I'm making a simple openGL application and so far I can get the window to display, the update/render loop work, and it processes windows events (like WM_QUIT and WM_MOUSE). I've found though that there is a noticeable lag between, say, pressing the space bar, and receiving the event in the WndProc function (in this case, WM_KEYDOWN.) Is this a result of using WndProc and not some fancy direct input system? Is there a better way of getting, say, the mouse position?
I can even tie one of my objects to draw itself at the current mouse position (updated in that same WndProc function) and while it does so fine, to the proper coordinates, it's always behind the mouse. I can post some code if you guys are interested but it's about the most standard update loop / event processing code out there.
Thanks for the help!
EDIT: Since you're curious, here's the main():
int main(int argc, char **argv){
MSG msg;
if (!createEngineWindow("Expanse")){
destroyEngineWindow();
return 1;
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // sorry, other windows
initGL();
startup();
updatePreviousTime=updateCurrentTime
=renderPreviousTime
=renderCurrentTime
=static_cast<float>(clock())/CLOCKS_PER_SEC; // start the stopwatches
while (!done){
previousMousePosition=mousePosition;
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
updatePreviousTime=updateCurrentTime;
updateCurrentTime=static_cast<double>(clock())/CLOCKS_PER_SEC;
uDT=updateCurrentTime-updatePreviousTime;
updatePhase(uDT);
if (updateCurrentTime>0.01 && uDT>0.01){ // ignore the first few frames
double framerate=1.0/uDT;
averagedFrameRate=Lerp<double>(averagedFrameRate,
framerate,
0.3);
}
renderPreviousTime=renderCurrentTime;
renderCurrentTime=static_cast<double>(clock())/CLOCKS_PER_SEC;
rDT=renderCurrentTime-renderPreviousTime;
renderPhase(rDT);
SwapBuffers(hDC);
}
cleanUp();
}
And the WinProc, which handles the DispatchMessage thing (or TranslateMessage, or something.)
LRESULT CALLBACK WndProc(HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam){ // Additional Message Information
switch (uMsg){
case WM_CLOSE: // Did We Receive A Close Message?
PostQuitMessage(0); // Send A Quit Message (we're going, hold on already.)
done=true;
return 0; // Jump Back
case WM_ACTIVATE:
if (!HIWORD(wParam)) // Check Active state
windowActive=true; // Program Is Active
else
windowActive=false; // Program Is No Longer Active
return 0;
case WM_MOUSEMOVE:
if (!ignoreMouseMove)
mouseMove(LOWORD(lParam),
HIWORD(lParam));
else
ignoreMouseMove=false;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
and the window creation:
bool createEngineWindow(string title){
int PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
// Window Sizing and Position
screenWidth=GetSystemMetrics(SM_CXSCREEN);
screenHeight=GetSystemMetrics(SM_CYSCREEN);
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)screenWidth;
WindowRect.top=(long)0;
WindowRect.bottom=(long)screenHeight;
// Windows Style
hInstance=GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style=CS_OWNDC | // We want our own device context
CS_DBLCLKS; // We want double clicks too
wc.lpfnWndProc=(WNDPROC)WndProc; // Our WndProc handles events first.
wc.cbClsExtra=0; // No Extra Window Data
wc.cbWndExtra=0; // No Extra Window Data
wc.hInstance=hInstance; // Set The Instance
wc.hIcon=LoadIcon(NULL, // Load The Default Icon
IDI_WINLOGO);
wc.hCursor=LoadCursor(NULL, // Load The Arrow Pointer
IDC_ARROW);
wc.hbrBackground=NULL; // No Background Required For GL
wc.lpszMenuName=NULL; // We Don't Want A Menu
wc.lpszClassName="TorqWindow"; // Set The Class Name
if (!RegisterClass(&wc)){
return false;
}
// Fullscreen settings
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings, // Makes Sure Memory's Cleared
0,
sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth=WindowRect.right; // Selected Screen Width
dmScreenSettings.dmPelsHeight=WindowRect.bottom; // Selected Screen Height
dmScreenSettings.dmBitsPerPel=24; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL // What the Devmode will set (it could also work with printers.
| DM_PELSWIDTH
| DM_PELSHEIGHT;
if (!ChangeDisplaySettings(&dmScreenSettings,
CDS_FULLSCREEN))
return false;
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(TRUE); // Do not hide Mouse Pointer
AdjustWindowRectEx(&WindowRect, // Adjust Window to fit fullscreen
dwStyle,
FALSE,
dwExStyle);
hWnd=CreateWindowEx(dwExStyle, // Extended Style For The Window
"TorqWindow", // Class Name
title.c_str(), // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right, // Window Width
WindowRect.bottom, // Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL); // Dont Pass Anything To WM_CREATE
if (!hWnd) // If we didn't succeed with making a window
return false;
hDC=GetDC(hWnd);
if (!hDC) // Did We Get A Device Context?
return false;
// Grab a pixel format descriptor. This tells Windows what kind of buffer we want.
// see http://msdn.microsoft.com/en-us/library/dd368826(VS.85).aspx
static PIXELFORMATDESCRIPTOR pfd={ // pfd Tells Windows How We Want Things To Be
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
16, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
PixelFormat=ChoosePixelFormat(hDC,&pfd);
if (!PixelFormat)
return false;
if (!SetPixelFormat(hDC,PixelFormat,&pfd))
return false;
hRC=wglCreateContext(hDC);
if (!hRC)
return false;
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
return false;
GLenum err = glewInit();
if (GLEW_OK != err)
return false;
return true;
}
void destroyEngineWindow(){
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
if (hRC){
wglMakeCurrent(NULL,
NULL);
wglDeleteContext(hRC);
hRC=NULL;
}
if (hDC){
ReleaseDC(hWnd,hDC);
hDC=NULL;
}
if (hWnd){
DestroyWindow(hWnd);
hWnd=NULL;
}
UnregisterClass("TorqWindow",
hInstance);
hInstance=NULL;
}
Thanks for the help!