Gimbal lock with Quaternions

I have a 3d object in the scene and I’m trying do pitch, yaw and roll. To avoid Gimbal lock, quaternions are used. It looks like I’m missing something fundamental about the implementation. I’m still getting Gimbal lock. Ideally, there should be an axis around which I should be doing the rotation, but I am not sure how to update the object’s orientation/axis.



glm::quat rotP = glm::angleAxis(glm::radians(doPitch), glm::vec3(1.0f, 0.0f, 0.0f)); //i believe the glm::vec3 should be updated with the new orientation, but not sure how

glm::quat rotY = glm::angleAxis(glm::radians(doYaw), glm::vec3(0.0f, 1.0f, 0.0f));

glm::quat rotR = glm::angleAxis(glm::radians(doRoll), glm::vec3(0.0f, 0.0f, 1.0f));


model = glm::mat4_cast(rotR) * glm::mat4_cast(rotY) * glm::mat4_cast(rotP) ;

doPitch, doYaw and doRoll are updated incrementally using keyboard.

I need to find a way to update the orientation after i do pitch, yaw or roll. Could someone help please?

I have a 3d object in the scene and I’m trying do pitch, yaw and roll. To avoid Gimbal lock, quaternions are used.

The long version can be found here. This is the TL;DR version:

Quaternions are not a magical salve that can be applied to make Gimbal lock go away.

The problem with Euler angles is that, when you compute the matrices, each angle is relative to the rotation of the matrix that came before it. What you want is to take an object’s current orientation, and apply a rotation along some axis, producing a new orientation.

You can’t do that with Euler angles. You can with matrices, and you can with quaternions (as they’re just the rotation part of a matrix). But you can’t do it by pretending they are Euler angles.

This is done by not storing angles at all. Instead, you just have a quaternion which represents the current orientation of the object. When you decide to apply a rotation to it (of some angle by some axis), you construct a quaternion that represents that rotation by an angle around that axis. Then you right-multiply that quaternion with the current orientation quaternion, producing a new current orientation.

When you render the object, you use the current orientation as… the orientation.

And therein lies your problem.

Assuming the usual order of application (yaw, pitch, roll), if the pitch is 90°, then yaw and roll do the same thing. Modifying either of them will rotate about the world’s vertical axis. This is the essence of gimbal lock. Changing the order of application just changes which flavour of gimbal lock you get. If the middle rotation is 90°, then the first and last rotations rotate about the same axis.

To avoid this, you need to replace those three variables with either a quaternion or a rotation matrix holding the current orientation. Instead of updating one of three variables using the keyboard, you apply an incremental rotation about one of the three axes to the current orientation. If you use current=currentincremental (post-multiply) the rotation is in the object’s (local) coordinate system, while current=incrementalcurrent (pre-multiply) uses the world’s (global) coordinate system.

[QUOTE=GClements;397960]And therein lies your problem.

Assuming the usual order of application (yaw, pitch, roll), if the pitch is 90°, then yaw and roll do the same thing. Modifying either of them will rotate about the world’s vertical axis. This is the essence of gimbal lock. Changing the order of application just changes which flavour of gimbal lock you get. If the middle rotation is 90°, then the first and last rotations rotate about the same axis.

To avoid this, you need to replace those three variables with either a quaternion or a rotation matrix holding the current orientation. Instead of updating one of three variables using the keyboard, you apply an incremental rotation about one of the three axes to the current orientation. If you use current=currentincremental (post-multiply) the rotation is in the object’s (local) coordinate system, while current=incrementalcurrent (pre-multiply) uses the world’s (global) coordinate system.[/QUOTE]

That’s spot on. I wasn’t holding the current orientation. Thanks!! It works now.