freeglut - a smooth camera rotation using mouse

2019-05-31 18:03发布

When I rotate my fps camera using mouse the animation is not smooth. When I use a keyboard everything works nice. For keyboard I use an array of type bool to buffer keys. What Can I do to make the animation smooth when using mouse ?

void MousePassiveMotion(int x, int y)
{
     int centerX = glutGet(GLUT_WINDOW_WIDTH) / 2;
     int centerY = glutGet(GLUT_WINDOW_HEIGHT) / 2;

     int deltaX =  x - centerX;
     int deltaY =  y - centerY;

     if(deltaX != 0 || deltaY != 0) 
     {
          heading = deltaX * 0.2f;
          pitch = deltaY  * 0.2f;
          glutWarpPointer(centerX, centerY);
     }
}

2条回答
霸刀☆藐视天下
2楼-- · 2019-05-31 18:12

Sometimes when the mouse polling rate and the screen refresh rate are not of a good ratio, updating the display based on the mouse position can result in a jerky effect.

You have vertical sync on, correct? And if you turn it of the mouse movement is smoother at the expense of tearing?

One option is to use a smoothing function, that "lags" the values you use for the mouse position just a tiny bit behind the real mouse position

The gist of it goes like this:

float use_x,use_y;      // position to use for displaying
float springiness = 50; // tweak to taste.

void smooth_mouse(float time_d,float realx,float realy) {
    double d = 1-exp(log(0.5)*springiness*time_d);

    use_x += (realx-use_x)*d;
    use_y += (realy-use_y)*d;
}

This is an exponential decay function. You call it every frame to establish what to use for a mouse position. The trick is getting the right value for springiness. To be pedantic, springiness is the number of times the distance between the real mouse position and the used position will halve. For smoothing mouse movement, a good value for springiness is probably 50-100.

time_d is the interval since the last mouse poll. Pass it the real time delta (in fractional seconds) if you can, but you can get away with just passing it 1.0/fps.

If you have a WebGL-capable browser you can see a live version here - look for a class called GLDraggable in viewer.js.

查看更多
家丑人穷心不美
3楼-- · 2019-05-31 18:35

You should use something like this instead where the camera angles are calculated with the last position of your mouse instead of the center point of your screen.

void mouseMove( int x, int y )
{
   theta += (lastx-x) / 100.0;
   phi += (lasty-y) / 50.0;
   lastx = x;
   lasty = y;

   if ( phi >= M_PI )
      phi = M_PI - 0.001;
   else if ( phi <= 0 )
      phi = 0.001;
}

Here 100.0 and 50.0 are factors that influence the speed of the movement (sensitivity) and the if / else statement limits the movement to certain angles.

查看更多
登录 后发表回答