I’m just starting my first OpenGL project, which is a (Windows) viewer for 3D wireframe models. It needs to load the model and let the user rotate, scale, and translate for viewing purposes. I’m at the point where I have a primitive working prototype to use for testing the individual functions I need to create.
So far, I’m able to load the data and display it (Ortho mode). I’m trying to get the rotation working correctly using up/down buttons for each axis. The intent is to rotate about a fixed axis system relative to the model - if it is rotated, say, 5 degrees about the Z axis then X and Y move with the model. Subsequent rotations about X need to account for this.
Clicking the buttons causes the correct rotation to occur (5 degrees each click), but with one major problem. If I rotate a few times about each axis and then click (e.g.) X+, then the model leaps to a whole new orientation before rotating about X.
The rotations are applied by a drawing routine as follows:
glPushMatrix(); // Dup current matrix onto stack (This will be the identity matrix)
glTranslated(Translate[XX], Translate[YY], Translate[ZZ]);
glRotated(Angle[XX], 1.0, 0.0, 0.0); // Apply Z rotations
glRotated(Angle[YY], 0.0, 1.0, 0.0);
glRotated(Angle[ZZ], 0.0, 0.0, 1.0);
else if ...
...do the others
for (i = 0; i < len; i++) // len is number of elements
xyzpos1 = bs[i]; // xyzpos1 is XYZ of first vertex
xyzpos2 = bs[i+1]; // xyzpos2 is XYZ of second vertex
I think I understand what’s happening (I don’t think I should be starting with
the identity matrix) and think there’s an obvious solution but have
spent many hours now and can’t find it. Can anyone point me in the right direction?
I think the problem you have is the “gimbal lock”… You should try and think in terms of the absolute orientation of the wireframes you are viewing, rather than applying incremental changes around axes. Applying succesive rotations through glRotated() tends to lead to gimbal lock. You can use quaternions to get over this problem. You only need to use one call to glMulMatrix() where the matrix is a rotation matrix representing the orientation you want. A handy quaternion / matrix link is http://www.j3d.org/matrix_faq/matrfaq_latest.html.
Steve, thanks. I think you’re correct and will try the quaternion method.
I have a question: JHC was applying the rotations about each of the axes seperately. If he were to figure out the axis that he would have to rotate about to get all three of those rotations and used just one glRotate*() call, would he still get a gimbal lock? That was a crazy sentence…What i mean is, since OpenGL allows you to specify an arbitrary rotation axis, can you do that and avoid the gimbal lock?
I mean that’s why quaternions work without gimbal lock right? because you get a single axis to rotate about.
I actually put on my site a few camera models using quaternions, euler angles and stuff… Check them out.
One of the methods (the one I use in my engine) I use quaternions to axis angles. This transformation can be passed directly to glRotatef in one call. Cool stuff…
Look under my camera.
And about gimbal lock… The problem is with a defficiency euler angles.
So the use of one glRotate compared to three does not fix the problem.
What fixes the problem??? You can create new quaternion with the new bit of rotation, and then multiply it with the camera quternion… What do I mean?
Well instead of using the ussual rotation ranging from 0-360, you rotate one unit at a time, say 1 or -1, and create a quaternion from it, then multiply it with the quternion that contains the previous rotation.
[This message has been edited by mancha (edited 04-03-2003).]