How to use glRotate for object with arbitrary known roll and pitch vectors?

Hello. I’m attempting to use glRotate to draw a rigid body with known roll and pitch vectors (here I am using an aeronautical analogy, the roll vector points toward the front of a plane and the pitch points to its left wing). My issue is that I can compute the angle and rotation axis to bring the roll axis to e.g. the z-axis (by atan2 and cross product respectively) but then my pitch vector generally isn’t where I want it e.g. the y axis. Here’s pseudocode for what I’ve attempted to do:

alpha = angle between roll vector and z axis
axis1 = cross product of roll and unit vector in z direction
wrong pitch = (vector you get when you rotate pitch vector around axis1 by alpha)
beta = angle between wrong-pitch and y
glRotate( alpha, axis1[0], axis2[1], axis3[2]);
glRotate( beta, 0, 0, 1)
draw stuff

This “kind of” works… I get the expected behavior as my plane turns, but then all of a sudden it spins 180 degrees and is flying backwards. I’m not sure what’s wonky about my solution, but I’d think there is a better way.

I’m aware of Euler’s rotation theorem, which implies I ought to be able to do this with just one call to glRotate. However, I have scoured the web and haven’t found a way to compute the needed angle and Euler axis, just lots of proofs of stuff about matrices. It may be a shot in the dark, but I suppose this is a common thing people want to do with opengl. Any help is greatly appreciated!

John

Do you actually need the angles? If you just need to set the appropriate transformation, it’s easier to construct the matrix directly from the two vectors and their cross-product, then use glLoadMatrix() or glMultMatrix() to apply it.

If you do need the angles, then examine the matrix generated by glRotate, and note that subtracting the matrix from its transpose gives:


   [  0 -z  y ]
   [          ]
2s [  z  0 -x ]
   [          ]
   [ -y  x  0 ]

Thus, for any orthonormal matrix m, each m[i,j]-m[j,i] (for i =/= j) gives you one component of the rotation vector, up to a common scale factor.

As you also know that x2+y2+z2=1, you can determine the normalised vector and s, and from s you can determine c.

Note that rotating by an angle a about the vector <x,y,z> is equivalent to rotating by an angle -a about the vector <-x,-y,-z>, so solutions come in pairs differing only in the signs.

Also note that for angles close to zero, the solution is ill-conditioned, as a rotation about any vector by an angle of zero produces an identity matrix.

Thanks very much for the reply. This suggestion sounds great, but I guess my calc 3 is failing me because I’m not clear on how to construct that rotation matrix. I’m not fixated on using glRotate by any means and I don’t need to know the angles.

Edit: Oh I see what you meant about the rotation matrix, its rows are just roll pitch and yaw. Now I just have to figure out glLoadMatrix…

Just wanted to say thanks to JClements, I got it working by following your suggestion.