Jump to content
  • Advertisement
Sign in to follow this  
mojobojo

Framerate Independent Mouse Movement

This topic is 943 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am polling for input every frame from my application using SDL_PollEvent. When I recieve a mouse motion event I set the relative mouse position

// Other input code      
PlayerInput->RelMousePos.x = (f32)SdlEvent->motion.xrel;
PlayerInput->RelMousePos.y = (f32)SdlEvent->motion.yrel;
// Other input code

In my game loop I handle the input like so

f32 MouseXRatio = PlayerInput->RelMousePos.x / GameState->CurrentResolution.Width;
f32 MouseYRatio = PlayerInput->RelMousePos.y / GameState->CurrentResolution.Height;

f32 Units = 64.0f;
v3 Amount = v3(-MouseYRatio, MouseXRatio, 0.0f) * Units;
GameState->CameraRot += Amount;
// Rotate the view matrix

The camera rotates fine, feels good to move, etc. However, when I turn on vsync the sensitivity of the camera goes down. I am a little stuck on how to handle this.

Share this post


Link to post
Share on other sites
Advertisement

You're probably adding the mouse motion to camera's rotation multiple times per frame? It should be done just once, so you could try resetting RelMousePos to zero after you've used it.

Share this post


Link to post
Share on other sites

You're probably adding the mouse motion to camera's rotation multiple times per frame? It should be done just once, so you could try resetting RelMousePos to zero after you've used it.

It gets reset to zero before the input poll.

internal void
ProcessEvents(game_state *GameState) {
    SDL_Event SdlEvent;
    player_input *PlayerInput = &GameState->Input.PlayerInputs[0];
    PlayerInput->RelMousePos = v3(0.0f, 0.0f, 0.0f);

    while (SDL_PollEvent(&SdlEvent)) {
        ProcessSdlInputEvents(PlayerInput, &SdlEvent);
        switch (SdlEvent.type) {
            case SDL_QUIT: {
                GlobalRunning = false;
                break;
            }
            case SDL_WINDOWEVENT: {
                if (SdlEvent.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    i32 Width = SdlEvent.window.data1;
                    i32 Height = SdlEvent.window.data2;
                    GameState->CurrentResolution.Width = Width;
                    GameState->CurrentResolution.Height = Height;
                }
                break;
            }
            default: {
                break;
            }
        }
    }
}

I know why I am getting the extra motion I am just drawing a blank on how to compensate for it. For example say I am running 60fps and move the mouse for 1 second,

if the input poll puts RelMousePos to 5 that's 60*5 I am going to process, if its 120fps that is 120*5 which means its going to move farther. Initial thought was compensating for time with my frame dt (Units * DeltaTime) which makes the mouse motion feel really bad.

Edited by mojobojo

Share this post


Link to post
Share on other sites

Yeah, but you're still applying the motion multiple times, and you shouldn't even use delta time for that. If I move my mouse by X amount, I want it to rotate my camera by Y degrees, it doesn't matter how many frames or seconds it took. You can even try it by moving the rotation code directly in the event handling. And you could still add some lerping on top of that code if that's what you're looking for. Like smoothed_rotation = slerp(smoothed_rotation, actual_rotation, delta) or something, and that should happen in the frame update.

Share this post


Link to post
Share on other sites

So what you are saying is I should get the relative mouse position on a frame and move a certain amount and once that amount has been moved that is when I look at the mouse relative position again? So even if sdl gives me another xrel and yrel on the second frame, ignore it?

Share this post


Link to post
Share on other sites

You don't ignore it, it's an event. You get the event and you process the values from it.

void events() {
    SDL_Event event;
    while(SDL_PollEvent(&event)) {
        switch(event.type) {
            case SDL_MOUSEMOTION: {
                // Ooh, the mouse was moved, let's apply the motion.
                GameState->CameraRot += v3(event.motion.yrel, event.motion.xrel, 0.0f);
            } break;
        }
    }
}

void update() { ... }
void render() { ... }

void mainloop() {
    while(running) {
        events();
        update();
        render();
    }
}

Share this post


Link to post
Share on other sites

What you put there is what I am doing. I am saying SDL gives me back a non zero value for more than one frame.

 

EDIT: Correction, similar to what I am doing. I am setting the rotation inside the update loop, does that matter?

Edited by mojobojo

Share this post


Link to post
Share on other sites

I am setting the rotation inside the update loop, does that matter?

 

That's what I've been trying to say, I don't know about all the code you have but I'm guessing you're adding the same input multiple times.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!