Large delay in wm_input

Started by
9 comments, last by MJP 16 years ago
I've written a small program in directx that just displays a model I've made in blender, and shows the x and y pos of the mouse that I get from wm_input. It takes the x coord and feeds it into a rotation of the model. The problem I'm having is that there is a huge delay in between the mouse movement and what happens on the screen. The model seems to move very, very smoothly, but if I move the mouse back and forth several times and then stop it takes the model several seconds stop wiggling as well as for the x and y coords to settle. I capture the mouse with this case WM_INPUT: { UINT dwSize = 40; static BYTE lpb[40]; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); RAWINPUT* raw = (RAWINPUT*)lpb; if (raw->header.dwType == RIM_TYPEMOUSE) { xPosRelative = raw->data.mouse.lLastX; yPosRelative = raw->data.mouse.lLastY; } break; } i process the input with just a few lines of code to give me a more static number absx += xPosRelative; absy += yPosRelative; if (absx >= 640 || absx <= -640){absx = 0;} if (absy >= 480 || absy <= -480){absy = 0;} xPosRelative = 0; yPosRelative = 0; I render some text with this std::wstring stemp = s2ws(itos(absx)); LPCWSTR result = stemp.c_str(); SetRect( &rc, 10, 450, 0, 0 ); g_pFont->DrawText( NULL, result , -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f )); SetRect( &rc, 50, 450, 0, 0 ); g_pFont->DrawText( NULL, L"Xpos", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f )); SetRect( &rc, 110, 450, 0, 0 ); stemp = s2ws(itos(absy)); result = stemp.c_str(); g_pFont->DrawText( NULL, result , -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f )); SetRect( &rc, 150, 450, 0, 0 ); g_pFont->DrawText( NULL, L"Ypos", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f )); and finally I do the rotation of the model with this line D3DXMatrixRotationY(&matRotateY, (absx/100.0f)); any clues? do I need buffered input or a seperate thread for input?
Advertisement
you have to handle all input before rendering...

MSG msg;while( 1 ){   if( PeekMessage( ... ) )   {       //handle input       ...   }   else   {       //render, app update       ...   }}
I dont think i understand. I already have my input before my render code.
Yes, but you still have your input bound to your render code. When you push a key, you handle the input, and then you render. Given this example, lets say you rapidly mash a whole bunch of keys really fast. Each input message will result in a render, and thus there will be a delay between each key getting handled that is at least the time it takes you to render something. As an alternative, if you soaked up all the keys pressed, then rendered, you wouldn't have this bound.

It's unlikely that you can even press keys that fast, but seeing this sort of structure in your input code is a pretty decent hint that you have these same sorts of problems elsewhere, which would definitely show up as a problem, or rather a slowdown.
I'm kind of at a loss. I'm looking over a few tutorials on wm_input as well as msdn, but none of them seem quite complete. anyone know of any really good resources?
Here is a way to look at it. When you check for input, you read in ALL of the input, keep reading in input until there is no input left to read, and logically make the changes that this input will result in. For example, if each key on the keyboard corresponds to a unit moving, then move the unit when you read a key is pressed.

Don't render any of the units. Don't render anything at all. Just update your game data.

When you're totally done reading in the input, then render everything in one bang. Repeat this cycle as needed. If you go to read input, and there is no input, just go straight to the render step.
well I'm pretty new to both Directx and windows gui programming so I'm pretty much hacking together tutorials and snippits from msdn. The part that I seem to be having trhoubles with now is that peekmesage needs MSG which is in:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
...

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
...
}

but my wm_input code relies on LPARAM which is in this sub:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){

UINT dwSize = 40;
static BYTE lpb[40];

GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));

RAWINPUT* raw = (RAWINPUT*)lpb;

if (raw->header.dwType == RIM_TYPEMOUSE)
{
xPosRelative = raw->data.mouse.lLastX;
yPosRelative = raw->data.mouse.lLastY;
}
}



How would I go about getting things to mesh nicely?
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
You should be responding to WM_INPUT and other messages in your window procedure. This is the exact purpose of that function: to handle messages. The code where you pump the message queue (AKA call PeekMessage or GetMessage) should be in a different function, where it's in a loop that runs until your program is finished.
I'm still lost. Here is what I have.

#ifndef WINVER
#define WINVER 0x0501
#endif

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0410
#endif

#ifndef _WIN32_IE
#define _WIN32_IE 0x0600
#endif

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <commdlg.h>
#include <sstream>

#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

RAWINPUTDEVICE Rid[1];
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer
LPDIRECT3DSURFACE9 z_buffer = NULL; // the pointer to the z-buffer
LPD3DXMESH meshSpaceship; // define the mesh pointer
D3DMATERIAL9* material; // define the material object
DWORD numMaterials; // stores the number of materials in the mesh
LPD3DXFONT pFontNew = NULL;
ID3DXFont* g_pFont = pFontNew;
RECT rc;
TCHAR g_strFont[LF_FACESIZE];
int absx = 0;
int absy = 0;
int xPosRelative;
int yPosRelative;
UINT dwSize = 40;
static BYTE lpb[40];

void initD3D(HWND hWnd);
void render_frame(void);
void cleanD3D(void);
void init_graphics(void);
void init_light(void);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

std::string itos(int arg)
{
std::ostringstream buffer;
buffer << arg;
return buffer.str();
}

std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass1";

RegisterClassEx(&wc);

hWnd = CreateWindowEx(NULL,
L"WindowClass1",
L"3D Test",
WS_OVERLAPPEDWINDOW,
0, 0,
SCREEN_WIDTH, SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hWnd, nCmdShow);

Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
initD3D(hWnd);

MSG msg;

while(TRUE)
{
DWORD starting_point = GetTickCount();

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
// while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)){
absx += xPosRelative;
absy += yPosRelative;
if (absx >= 640 || absx <= -640){absx = 0;}
if (absy >= 480 || absy <= -480){absy = 0;}
xPosRelative = 0;
yPosRelative = 0;
// }
TranslateMessage(&msg);
DispatchMessage(&msg);
}

render_frame();

if(KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);

while ((GetTickCount() - starting_point) < 25);
}
cleanD3D();

return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
case WM_INPUT:
{
GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
xPosRelative = raw->data.mouse.lLastX;
yPosRelative = raw->data.mouse.lLastY;
}
break;
}
}

return DefWindowProc (hWnd, message, wParam, lParam);
}


void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

d3ddev->BeginScene();

D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (0.0f, 4.0f, 8.0f), // the camera position
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView

D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45),
SCREEN_WIDTH / SCREEN_HEIGHT,
1.0f,
100.0f);
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);

//static float index = 0.0f; index+=0.13;
D3DXMATRIX matRotateY;
// D3DXMatrixRotationY(&matRotateY, index);
D3DXMatrixRotationY(&matRotateY, (absx/100.0f));
d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY));

for(DWORD i = 0; i < numMaterials; i++)
{
d3ddev->SetMaterial(&material);
meshSpaceship->DrawSubset(i);
}

std::wstring stemp = s2ws(itos(absx));
LPCWSTR result = stemp.c_str();
SetRect( &rc, 10, 450, 0, 0 );
g_pFont->DrawText( NULL, result , -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
SetRect( &rc, 50, 450, 0, 0 );
g_pFont->DrawText( NULL, L"Xpos", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
SetRect( &rc, 110, 450, 0, 0 );
stemp = s2ws(itos(absy));
result = stemp.c_str();
g_pFont->DrawText( NULL, result , -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
SetRect( &rc, 150, 450, 0, 0 );
g_pFont->DrawText( NULL, L"Ypos", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);

return;
}

...
...
...

This topic is closed to new replies.

Advertisement