I have a 3D camera with its current rotation stored as a quaternion, and I'm having trouble rotating it correctly. I want the camera to rotate incrementally around its local axes based on mouse movement each frame (first-person-shooter-style), but the rotation is wrong. It kind of works, but the camera seems to "roll" around its forward axis when it shouldn't.
I update the rotation each frame with this function:
void Camera::rotate(const Quat& q)
{
// m_rot is the current rotation
m_rot = m_rot * q;
}
Here's my quaternion multiplication function:
Quat Quat::operator*(const Quat &rhs) const
{
// quaternion elements in w,x,y,z order
Vector4d res;
res[0] = m_q[0]*rhs.m_q[0] - m_q[1]*rhs.m_q[1] -
m_q[2]*rhs.m_q[2] - m_q[3]*rhs.m_q[3];
res[1] = m_q[0]*rhs.m_q[1] + m_q[1]*rhs.m_q[0] +
m_q[2]*rhs.m_q[3] - m_q[3]*rhs.m_q[2];
res[2] = m_q[0]*rhs.m_q[2] - m_q[1]*rhs.m_q[3] +
m_q[2]*rhs.m_q[0] + m_q[3]*rhs.m_q[1];
res[3] = m_q[0]*rhs.m_q[3] + m_q[1]*rhs.m_q[2] -
m_q[2]*rhs.m_q[1] + m_q[3]*rhs.m_q[0];
return Quat(res);
}
Am I doing something wrong, or is this some kind of floating-point error thing?
For rotation quaternions, the inverse equals the conjugate. So for rotation quaternions, q−1 = q* = ( q0, −q1, −q2, −q3 ). Inverting or conjugating a rotation quaternion has the effect of reversing the axis of rotation, which modifies it to rotate in the opposite direction from the original.
Quaternions are an alternate way to describe orientation or rotations in 3D space using an ordered set of four numbers. They have the ability to uniquely describe any three-dimensional rotation about an arbitrary axis and do not suffer from gimbal lock.
Figured out the problem. For a mouse-controled first-person camera like the one I'm going for, I want to rotate around the local x-axis to look up and down, but the global y-axis for looking side to side.
So this is correct for the x-axis:
m_rot = m_rot * q;
But I need to do this for the y-axis:
m_rot = d * m_rot;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With