I calculate the deviation of the mouse from the center of the screen. I then reset the cursor position back to the center of the screen.
I convert this deviations in the x and y directions into changes in angles.
SetCursorPos and GetCursorPos are the windows functions I use to get the mouse change.
Here is the function I wrote to do this. x and y radians are the pitch and yaw of the camera.
Note this is for a first person shooter style camera, it prevents you from looking further than directly 'up' or 'down' (pi/2 radians or + or - 90 degrees)
Once I have these angles gathered from the first function, an easy way to apply it to OpenGL is to use the second function to build the appropriate lookat matrix, using the angles and the position of the camera. You call the second function before drawing anything, and it will reflect the camera position and orientation. Keep in mind there are many ways to do this, this is just the most straightforward and basic approach.
Code:
void FPSCam::GatherInputOverframes()
{
POINT MousePos;
GetCursorPos(&MousePos);
static POINT NewPos;
if(MousePos.x == Export.mVars.MiddleX && MousePos.y == Export.mVars.MiddleY)
{
Export.DisableState(MOUSEMOVED);
return;
}
SetCursorPos(Export.mVars.MiddleX, Export.mVars.MiddleY);
Export.SetState(MOUSEMOVED);
float YDeviation = (Export.mVars.MiddleY - MousePos.y);
float XDeviation = (Export.mVars.MiddleX - MousePos.x);
float framespeed = (Export.mVars.TWOPI*8) * .01;
//fixme: i know this used to use screenheight, changed on purpose so it goes same speed along each axis
float XDegRad = (Export.mVars.PI * YDeviation) * (1/(Export.mVars.Width*.5)); //radians to rotate view vector about X axis
if(XDegRad > 0 && XDegRad > framespeed)
XDegRad = framespeed;
else if(XDegRad < 0 && XDegRad < -framespeed)
XDegRad = -framespeed;
xRadians += XDegRad;
/*
this is actually 89 degrees, gimbal lock is impossible in this scenario
however in order to have a valid move direction i sorta need to have X and Z components which is impossible
if you are looking straight upward
*/
if(xRadians > 1.553343)
{
xRadians = 1.553343;
XDegRad = 0;
}
else if(xRadians < -1.553343)
{
xRadians = -1.553343;
XDegRad = 0;
}
float YDegRad = (Export.mVars.PI * XDeviation) * (1/(Export.mVars.Width*.5)); //radians to rotate view vector about Y axis
if(YDegRad > 0 && YDegRad > framespeed)
YDegRad = framespeed;
else if(YDegRad < 0 && YDegRad < -framespeed)
YDegRad = -framespeed;
yRadians += YDegRad;
}
the second function. Note that I use radians in my camera and OpenGL takes degrees. You must convert somewhere along these lines (or just save the degrees, rather than radians, in the Camera setup).
Code:
void R_GenerateViewMatrix(float pitch, float yaw, float roll, Vector3 & translation)
{
if(pitch)
{
NT_GL(glRotatef(-pitch,1,0,0));
}
if(yaw)
{
NT_GL(glRotatef(-yaw,0,1,0));
}
if(roll)
{
NT_GL(glRotatef(-roll,0,0,1));
}
NT_GL(glTranslatef(-translation.x,-translation.y,-translation.z));
}