Moving from dinput to RAW input (mouse)

Started by
26 comments, last by cozzie 9 years, 7 months ago

Hi,

I've been working on getting rid of DirectInput for handling keyboard and mouse input.

On the keyboard side I'm all good, but my current RAW mouse implementation (1st attempt) has two strange symptons:

1 - terrible 'lag' in movement, like it's 'dragging along' after the mouse physically stopped moving

2 - interference with keyboard input

Here's the code I use.

Any input is really appreciated.


// setting up the mouse
bool CInputHandler::SetupMouseRaw(const HWND pHwnd)
{
	Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; 
    Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; 
  
  Rid[0].dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_INPUTSINK | RIDEV_NOLEGACY
    Rid[0].hwndTarget = pHwnd;
    RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));

	mInitialized = true;
	return true;
}

// updating the mouse
void CInputHandler::UpdateMouse(const int pPosX, const int pPosY)
{
	mMousePosX = pPosX;
	mMousePosY = pPosY;
	mMouseMoved = true;
}	

// windows messaging (WNDPROC)
		// MOUSE INPUT: RAW
		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)
			{
				_input.UpdateMouse(raw->data.mouse.lLastX, raw->data.mouse.lLastY);
			}
		}
		break;

// handling game input
			if(_input.MouseMoved())
			{
				_d3dcam.FreeLook(_input.GetMousePosX(), _input.GetMousePosY(), _player.GetLookSpeed()); // * _timer.GetDelta());
				_input.SetMouseMoved(false);
			}

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

First: Is there a particular reason you're using raw input rather than WM_MOUSEMOVE messages?

Second: You don't check for errors. The functions you call provide an indication of success or failure, which you don't check. I.e., RegisterRawInputDevices returns TRUE or FALSE. You should use that for your return value of SetupMouseRaw. GetRawInputData also provides a return value which can be checked for error.

Have you correctly defined your HID_xxx constants? Have you tried just just RIDDEV_NOLEGACY? I.e., do you need _CAPTUREMOUSE and _INPUTSINK?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Make sure you are using:

while (PeekMessage(...)) { }

instead of

if (PeekMessage(...)) { }

/psychic debugging off

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

Also, do you pass the message on to DefWindowProc?

The MSDN is a bit misleading here, in the description of WPARAM it says that the message should be passed on to DefWindowProc for cleanup.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>


1 - terrible 'lag' in movement, like it's 'dragging along' after the mouse physically stopped moving

This could happen when you re-draw & present everything after every message from your message loop, with VSYNC on. Because Present waits for VSYNC, it causes your whole message loop (including raw input messages) to be delayed every frame.

Fiddler's recommendation should fix this...

Hi all. Thanks for the input.

- I've tried to use just the flag 'RIDEV_NOLEGACY', but unfortunately no difference

- WM_MOUSEMOVE I tried, but didn't work out because I'm trying to come close to using DirectInput in exclusive mode (also with the cursor outside the render window)

- my main message loop is:


	PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
	while(msg.message != WM_QUIT)
	{
		if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))	
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

I tried to change it to a 'while' instead for 'for'.

That solved most of the problems! Great.

Can someone explain what exactly happens there and what the cons are of doing it with a while loop?
(will this cause delay when there are no messages, since if waits?)

The only issue left if that there's some strange interference left with the keyboard input. Will look further into that (some testing with the flags etc.)

Add; flags don't change things, but I did notice that without V-sync mouse 'spreed' is much better then with V-sync. Do I need to make that speed dependent on V-sync, or are there better options?

On the left 'interference' it's really strange, I only get it with the 'VK_ESCAPE' key, all other input is OK. When I change back the the message loop to a 'if' instead of 'while' loop, the VK_ESCAPE reaction is back. Strange?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me


Can someone explain what exactly happens there and what the cons are of doing it with a while loop?
(will this cause delay when there are no messages, since if waits?)

No cons really. That's the way it's supposed to be handled:

You should process all pending messages before you run the game logic. Otherwise you will see the lagging that you described because the message queue will fill up with stale input data.

I personally never bother with Windows messages and use the API functions directly. Look up GetCursorPos() for mouse movement and GetAsyncKeyState() for keypresses. These will give you immediate values which you can process at your own will.

I personally never bother with Windows messages and use the API functions directly. Look up GetCursorPos() for mouse movement and GetAsyncKeyState() for keypresses. These will give you immediate values which you can process at your own will.

GetAsyncKeyState() can miss key presses when the framerate is low or the key was pressed very quickly.

I personally never bother with Windows messages and use the API functions directly. Look up GetCursorPos() for mouse movement and GetAsyncKeyState() for keypresses. These will give you immediate values which you can process at your own will.

GetAsyncKeyState() can miss key presses when the framerate is low or the key was pressed very quickly.

Usually that is not a problem in games since most of the time keys will be held down for some longer period. For example, when moving, you'll just want to know if key X is down or not, key-up is often not even relevant. You'd also have to have extremely low framerate to actually press-and-release in between frames.

For text input and such, it's a totally different scenario.

This topic is closed to new replies.

Advertisement