I'm trying to achieve an object rotation about 3 axes by incrementing values of rotation angles for axes, and displaying those axes to make next rotation direction predictable for the viewer. But after a few rotations, only rotation about Z-axis is performed in accord with displayed axis. Is there a chance it can be done simply, without poring over quaternions?
glPushMatrix ();
glRotatef (angleX, 1.0, 0.0, 0.0);
glRotatef (angleY, 0.0, 1.0, 0.0);
glRotatef (angleZ, 0.0, 0.0, 1.0);
glBegin(GL_LINES);
glVertex3f(80.0, 0.0, 0.0); //x axis
glVertex3f(-80.0, 0.0, 0.0);
glVertex3f(0.0, 80.0, 0.0); //y axis
glVertex3f(0.0, -80.0, 0.0);
glVertex3f( 0.0, 0.0, 80.0); //z axis
glVertex3f( 0.0, 0.0, -80.0);
//here is some code for drawing arrows at axes ends
glEnd();
glPopMatrix();
Edit: I have axes like those: http://img841.imageshack.us/i/arrowsx.jpg/ angleX, angleY, angleZ are globals incremented on key press - e.g. after pressing 'A' angleX is incremented by 10, and I expect axis X won't move after that and axes Y and Z will rotate about axis X. But it is true only when I change only one of angle variables. After rotation ab开发者_如何学Pythonout more then one axis, when I change, e.g. angleX - all axes from picture will change their positions.
The code you posted essentially lumps all of your rotations about each axis into a single rotation about that axis. As you note, it works well as long as all you're doing is incremental rotations about a single axis. From your update, it also appears that you want the key strokes to apply rotations to the image as displayed, rather than in aggregate as you have coded. One way to achieve the behavior you're looking for is to store in a queue or resizable vector (std::vector, or std::queue or some other container if you're using C++) each of the rotations that you apply. Each time the user presses a key, add another rotation of the fixed angle size about the desired axis to the list. During playback, apply the rotations in the order they were entered (maybe reverse order, I'll have to give it more thought). This will then apply the rotations to the displayed geometry, rather than to the canonical (i.e. un-rotated) geometry.
There might be an easier and less memory intensive way to do this using quaternions; that's one area that I really need to get better versed on. Give what I know right now, though, this is the way I'd go about achieving the behavior I think you're after.
I did a bit of OpenGL programming in college. It seems like I ran into the same problem, and ended up applying the total sum of each angle each time any given angle was updated.
Quaternions are not that difficult. You essentially do something like this (it is pretty simple to implement the Quat class) -
Matrix yawMatrix = Quat(yawAxis, m_rx).matrix();
Matrix pitchMatrix = Quat(pitchAxis, m_ry).matrix();
Matrix rotMatrix = Matrix::multiply(yawMatrix, pitchMatrix);
and apply the rotation matrix to the eye point of your camera to rotate it about the target point.
精彩评论