How to avoid gimbal lock

I am trying to write code with rotates an object.

I implemented it as:

Rotation about X-axis is given by the amount of change in y coordinates of a mouse and Rotation about Y-axis is given by the amount of change in x coordinates of a mouse.

This method is simple and work fine until on the the axis coincides with Z-axis, in short a gimble lock occurs.

How can I utilize the rotation arount Z-axis to avoid gimbal lock.

• Short answer: use quaternions Commented Mar 20, 2013 at 17:16
• Quaternions are still prone to gimbal lock if you use them wrong - it's not what you use to represent your rotations, it's concatenating multiple rotations that causes it. So don't concatenate rotations. Commented Mar 20, 2013 at 17:27
• Regarding my previous comment, see the comment from Maik Semder at gamedev.stackexchange.com/questions/23540/… Commented Mar 20, 2013 at 17:39
• I was about to write the same comment again, thanks for finding it @mh01 :) Commented Mar 20, 2013 at 17:53

The simple solution is not to store the orientation of the object as angles around axes (X-, Y-, Z-axis), as for instance in euler angles.

Store the orientation of the object as a matrix or a quaternion.

This can cause gimbal lock, using euler angles:

class Object
{
float m_angleAxisX;
float m_angleAxisY;
float m_angleAxisZ;
};


No gimbal lock:

class Object
{
matrix m_orientation;
};


No gimbal lock either:

class Object
{
quaternion m_orientation;
};


Now whenever the mouse is changed, multiply m_orientation with the orientation change coming from the mouse movement each frame.

This book (real-time rendering) helped me alot! See on page 66 and 70. It has very good graphics and explenation. Quaternions are on page 72 aswell! :)

Rotation about an Arbitrary Axis

This renders the camera with the rotation done by mouse input:

void Camera::getVectors(D3DXVECTOR3& up, D3DXVECTOR3& lookAt)
{
float yaw, pitch, roll;
D3DXMATRIX rotationMatrix;

// Setup the vector that points upwards.
up.x = 0.0f;
up.y = 1.0f;
up.z = 0.0f;

// Setup where the camera is looking by default.
lookAt.x = 0.0f;
lookAt.y = 0.0f;
lookAt.z = 1.0f;

// Set the yaw (Y axis), pitch (X axis), and roll (Z axis) rotations in radians.
pitch = m_rotation.x * 0.0174532925f;
yaw   = m_rotation.y * 0.0174532925f;
roll  = m_rotation.z * 0.0174532925f;

// Create the rotation matrix from the yaw, pitch, and roll values.
D3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll);

// Transform the lookAt and up vector by the rotation matrix so the view is correctly rotated at the origin.
D3DXVec3TransformCoord(&lookAt, &lookAt, &rotationMatrix);
D3DXVec3TransformCoord(&up, &up, &rotationMatrix);
}

// The Render function uses the position and rotation of the camera to build and update the view matrix
void Camera::render()
{
D3DXVECTOR3 up, position, lookAt;

// Setup the position of the camera in the world.
position = (D3DXVECTOR3)m_position;

getVectors(up, lookAt);

// Translate the rotated camera position to the location of the viewer.
lookAt = position + lookAt;

// Finally create the view matrix from the three updated vectors.
D3DXMatrixLookAtLH(&m_viewMatrix, &position, &lookAt, &up);

return;
}


With the mouse input you modify yaw(head), pitch and roll.

• -1 This does not solve the gimbal lock as it uses euler angles (m_rotation) for the internal orientation storage. This wiki explains why. Commented Mar 20, 2013 at 20:29