Camera rotation problem

I know this is one of the most basic problems in 3D graphics, but as a self-taught programmer I admit I'm having some trouble working it out. What I'm trying to do is take an object's yaw, pitch and roll values and convert them to a correct matrix or axis/angle representation for submission to OpenGL. The problems I'm trying to avoid are gimbal lock, and rotation about world rather than local axes.

For the second problem, I understand that in principal the axes of the object need to be rotated as well as the object; that is, a 45 degree yaw should also rotate the x axis 45 degrees, so that the subsequent pitch rotation will occur around the local rather than world x axis. I could do this manually, or course, but I don't think that's the way it's usually done.

I'm reasonably well versed in quaternion and matrix math and have a class for each, but I'm having trouble putting all the pieces together. At the moment I'm trying to create a Descent-style 6DOF camera. I'm sure many of you have already done this, so any input would be appreciated.

Always use a quaternion or axis-angle representation (they're essentially equivalent; converting one to the other is trivial).

glRotatef takes the axis-angle form.

Ok, I'm listening. But how does one get from the user input stage to a quaternion/axis-angle representation? Mapping user input to yaw, pitch and roll is of course fairly trivial, but I'm not sure how to bypass that and go directly to the less intuitive mathematical form. If you could elaborate just a little I'd really appreciate it.

Quote:Originally posted by OneSadCookie I'd say at least every frame, more often as empirically necessary (if you notice jumps or jerks, or can't turn an exact circle, you may need to normalize more often).

In my implementation, quaternion corruption is very, very rare (every few minutes, sometimes), so you can probably get away with a quick non-square-root magnitude check each frame and normalize if it's diverged by more than, say, .00001.

Also, if you want "real" Descent-style movement, the camera rotation caused by the controls depends on the camera's current orientation, so you'll need to alter the axes of the Y/P/R quaternions before you add them to the camera.

Quote:Originally posted by Mark Levin In my implementation, quaternion corruption is very, very rare (every few minutes, sometimes), so you can probably get away with a quick non-square-root magnitude check each frame and normalize if it's diverged by more than, say, .00001.

Yeah, but the overhead of the branch is probably more than the overhead of normalizing the quaternion each time. And if you can notice the extra 0.000001 seconds per frame caused by normalizing a quaternion, you're much more observant than I am

Quote:Also, if you want "real" Descent-style movement, the camera rotation caused by the controls depends on the camera's current orientation, so you'll need to alter the axes of the Y/P/R quaternions before you add them to the camera.

Rotating the axis vectors (1, 0, 0), (0, 1, 0) and (0, 0, 1) by this quaternion (inverse(q) (0, v) q) will get you the new axes.

Yeah, I'd considered this, but guessed that the total cost would be more or less equivalent. I should find out for sure, though.

Quote:Also, if you want "real" Descent-style movement, the camera rotation caused by the controls depends on the camera's current orientation, so you'll need to alter the axes of the Y/P/R quaternions before you add them to the camera.

As OneSadCookie mentioned, I'm extracting the local axes from the rotation matrix, so I think I'm doing this part correctly.

If I can get away with the sqrt(), I may just normalize every frame for peace of mind. Mark, if I interpret what you're saying correctly, if I do want to normalize only when necessary I can just check the squared length, right (since it's a unit quaternion)?

Quote:Originally posted by Jesse Mark, if I interpret what you're saying correctly, if I do want to normalize only when necessary I can just check the squared length, right (since it's a unit quaternion)?

Right, numbers that close to 1 are so close to their roots/squares it really doesn't matter.