What I do is I calculate how far the mouse has moved this frame (from the center of the screen), convert it to radians, add those radians this frame to my member variables that keep track of the total radians to rotate about the y axis and strafe vectors. The latter is capped at PI/2 radians (looking straight up or straight down). The point (0, 0) is at the top left of your screen in screen coordinates, with the positive Y axis extending down towards the bottom of the screen.
To convert from screen change to radians use this proportion and cross multiply and divide to get the answer that solves for radians
radians / PI = deltaX / SCREEN_WIDTH/2;
radians / PI = deltaY / SCREEN_HEIGHT/2;
No gimbal lock, allows for role, I can even post some code that jinks the player in a helicopter like effect when strafing by rotating the Up vector about the View vector slightly
EDIT: it is also important to note that a rotation through a positive number of radians about an axis is in the counter clockwise direction, not clockwise. Keep that fact and what I said about screen coordinates in mind when performing these calculations.
EDIT1: also note the RotateVector prototype:
RotateVector(float Angle, Vector3 *VectorToRotateAbout, Vector3 *VectorToRotate)
Code:
bool Camera::CheckMouse()
{
POINT MousePos;
GetCursorPos(&MousePos);
SetCursorPos(MIDDLEX, MIDDLEY);
if(MousePos.x == MIDDLEX && MousePos.y == MIDDLEY)
return false;
float YDeviation = (MIDDLEY - MousePos.y);
float XDeviation = (MIDDLEX - MousePos.x);
XDegRad = (PI * YDeviation) / (SCREEN_WIDTH/2); //radians to rotate view vector about X axis
xRadians += XDegRad;
if(xRadians > HALFPI)
{
xRadians = HALFPI;
XDegRad = 0;
}
else if(xRadians < -HALFPI)
{
xRadians = -HALFPI;
XDegRad = 0;
}
YDegRad = (PI * XDeviation) / (SCREEN_HEIGHT/2); //radians to rotate view vector about Y axis
yRadians += YDegRad;
float cosXTheta = (float)cos(XDegRad);
float sinXTheta = (float)sin(XDegRad);
float cosYTheta = (float)cos(YDegRad);
float sinYTheta = (float)sin(YDegRad);
mView = Vector3(0, 0, 1);
mUp = Vector3(0, 1, 0);
RotateVector(yRadians, &mYAxis, &mView);
mStrafe = CrossProduct(mView, mYAxis);
RotateVector(xRadians, &mStrafe, &mView);
mUp = CrossProduct(mStrafe, mView);
return true;
}