2
\$\begingroup\$

I've been trying to build a 3D camera system in SDL2 with OpenGL so that I can use the mouse to look around. With glfw it's possible to trap the mouse in the window, and keep it centered with a library call, so I was looking for something equivalent in SDL2.

In order to process mouse events in the main loop I'm checking for SDL_MOUSEMOTION. Searching around the web, I've found that SDL2 allows for mouse trapping with the call to SDL_SetRelativeMouseMode(). With this call, though, the mouse is trapped and limited to move within the window, and not just at the center. This causes the mouse to be able to move from the top left corner at (0,0) to the bottom right corner at (WIDTH,HEIGHT), and not any further.

I've tried to fix this by repositioning the cursor position with SDL_WarpMouseInWindow(), but this generates a SDL_MOUSEMOTION event as well, basically resetting any movement I might've tried to do.

How can I fix this?

\$\endgroup\$
  • \$\begingroup\$ Duplicate to gamedev.stackexchange.com/questions/54633/trap-mouse-in-sdl2 \$\endgroup\$ – rioki Apr 4 '17 at 9:04
  • \$\begingroup\$ Possible duplicate of Trap mouse in SDL2 \$\endgroup\$ – rioki Apr 4 '17 at 9:04
  • \$\begingroup\$ @rioki I'm quite sure that OP's question makes it quite obvious that the solutions given in those questions (the usage of SDL_SetRelativeMouseMode) don't work for OP. \$\endgroup\$ – Tyyppi_77 Apr 4 '17 at 9:08
  • 1
    \$\begingroup\$ That being said, how are you using the mouse motion event data? I get valid direction data in xrel and yrel even when the mouse is at the border of the window when SDL_SetRelativeMouseMode is set to true. Maybe you're using the mouse positions to calculate velocity instead? So, for me the solutions in the two linked questions work just fine. \$\endgroup\$ – Tyyppi_77 Apr 4 '17 at 9:10
  • \$\begingroup\$ As seen here github.com/rioki/pkzo/blob/master/pkzo/Mouse.cpp, the combination of SDL_ShowCursor(0); SDL_SetRelativeMouseMode(SDL_TRUE); Should do the trick. \$\endgroup\$ – rioki Apr 4 '17 at 9:35
2
\$\begingroup\$

So your issue seems to be that you are getting invalid data because you are calculating the motion amount yourself. That won't work, since the mouse won't move past the window's border.

So, indeed, start with SDL_SetRelativeMouseMode(SDL_TRUE);. This will make sure that you get relative motion data in SDL_MOUSEMOTION events.

Now, in your event loop, instead of calculating the offsets yourself, simply use event.motion.xrel and event.motion.yrel which provide valid offset data even at the border of the window, since you told SDL to use relative mouse mode.

\$\endgroup\$
1
\$\begingroup\$

You've to SDL_SetRelativeMouseMode(SDL_TRUE); then create static xpos and ypos variables

case SDL_MOUSEMOTION:
// assuming I have a 800x600 Game window, then the result would be:
    static int xpos = SCR_W / 2; // = 400 to center the cursor in the window
    static int ypos = SCR_H / 2; // = 300 to center the cursor in the window
    xpos += e->motion.xrel;
    ypos += e->motion.yrel;
    ...

When the Mouse is moved, they're incremented infinitely by how much they're moved relatively from the center which can be negative/positive values.

So, You can use these variables for your 3D Camera to look infinitely around the scene.

\$\endgroup\$
0
\$\begingroup\$

This is how i handled mouse events. Maybe it can help you to develop your own solution. This are snippets from my first try of getting SDL2 and OpenGL running.

// Setup 
bool Mousefirst  = true;
bool MouseMotion = false;

// Mouse moved ?
if (Event.type == SDL_MOUSEMOTION) {
  MouseMotion = true;
  if (!Mousefirst) {
    MouseRelX = Event.motion.xrel;
    MouseRelY = Event.motion.yrel;
  } else {
    Mousefirst = false;
    MouseRelX = 0;
    MouseRelY = 0;
  }
}

And here is how the mouse motion was processed: (MouseSense is a float to regulate the sensitivity of your mouse)

if (MouseMotion) {
  MouseMotion = false;
  CameraYaw += MouseRelX * MouseSense;
  CameraPitch += MouseRelY * MouseSense;

  // Stuff to limit the camera angles ...

  // Stuff to create the camera viewing matrix ...
}

BTW: MouseFirst = true prevents a sudden jump after SDL_SetRelativeMouseMode(SDL_TRUE)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.