How is the gimbal locked problem solved using accumulative matrix transformations
- by Luke San Antonio
I am reading the online "Learning Modern 3D Graphics Programming" book by Jason L. McKesson
As of now, I am up to the gimbal lock problem and how to solve it using quaternions.
However right here, at the Quaternions page.
Part of the problem is that we are trying to store an orientation as a series of 3 accumulated axial rotations. Orientations are orientations, not rotations. And orientations are certainly not a series of rotations. So we need to treat the orientation of the ship as an orientation, as a specific quantity.
I guess this is the first spot I start to get confused, the reason is because I don't see the dramatic difference between orientations and rotations. I also don't understand why an orientation cannot be represented by a series of rotations...
Also:
The first thought towards this end would be to keep the orientation as a matrix. When the time comes to modify the orientation, we simply apply a transformation to this matrix, storing the result as the new current orientation.
This means that every yaw, pitch, and roll applied to the current orientation will be relative to that current orientation. Which is precisely what we need. If the user applies a positive yaw, you want that yaw to rotate them relative to where they are current pointing, not relative to some fixed coordinate system.
The concept, I understand, however I don't understand how if accumulating matrix transformations is a solution to this problem, how the code given in the previous page isn't just that.
Here's the code:
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutil::MatrixStack currMatrix;
currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
currMatrix.RotateX(g_angles.fAngleX);
DrawGimbal(currMatrix, GIMBAL_X_AXIS, glm::vec4(0.4f, 0.4f, 1.0f, 1.0f));
currMatrix.RotateY(g_angles.fAngleY);
DrawGimbal(currMatrix, GIMBAL_Y_AXIS, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
currMatrix.RotateZ(g_angles.fAngleZ);
DrawGimbal(currMatrix, GIMBAL_Z_AXIS, glm::vec4(1.0f, 0.3f, 0.3f, 1.0f));
glUseProgram(theProgram);
currMatrix.Scale(3.0, 3.0, 3.0);
currMatrix.RotateX(-90);
//Set the base color for this object.
glUniform4f(baseColorUnif, 1.0, 1.0, 1.0, 1.0);
glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));
g_pObject->Render("tint");
glUseProgram(0);
glutSwapBuffers();
}
To my understanding, isn't what he is doing (modifying a matrix on a stack) considered accumulating matrices, since the author combined all the individual rotation transformations into one matrix which is being stored on the top of the stack.
My understanding of a matrix is that they are used to take a point which is relative to an origin (let's say... the model), and make it relative to another origin (the camera). I'm pretty sure this is a safe definition, however I feel like there is something missing which is blocking me from understanding this gimbal lock problem.
One thing that doesn't make sense to me is: If a matrix determines the difference relative between two "spaces," how come a rotation around the Y axis for, let's say, roll, doesn't put the point in "roll space" which can then be transformed once again in relation to this roll... In other words shouldn't any further transformations to this point be in relation to this new "roll space" and therefore not have the rotation be relative to the previous "model space" which is causing the gimbal lock.
That's why gimbal lock occurs right? It's because we are rotating the object around set X, Y, and Z axes rather than rotating the object around it's own, relative axes. Or am I wrong?
Since apparently this code I linked in isn't an accumulation of matrix transformations can you please give an example of a solution using this method.
So in summary:
What is the difference between a rotation and an orientation?
Why is the code linked in not an example of accumulation of matrix transformations?
What is the real, specific purpose of a matrix, if I had it wrong?
How could a solution to the gimbal lock problem be implemented using accumulation of matrix transformations?
Also, as a bonus: Why are the transformations after the rotation still relative to "model space?"
Another bonus: Am I wrong in the assumption that after a transformation, further transformations will occur relative to the current?
Also, if it wasn't implied, I am using OpenGL, GLSL, C++, and GLM, so examples and explanations in terms of these are greatly appreciated, if not necessary.
The more the detail the better!
Thanks in advance...