views:

988

answers:

1

I am trying to prototype a space flight sim in OpenGL, but after reading many articles online I still have difficulty with getting the rotations to work correctly (I did have a quaternion camera that I didn't understand well, but it drifts and has other odd behaviors).

I am trying to do the following:

1) Local rotation - when the user presses arrow keys, rotation occurs relative to the viewport (rotating "up" is toward the top of the screen, for example). Two keys, such as Z and X, will control the "roll" of the ship (rotation around the current view).

2) The rotations will be stored in Axis-angle format (which is most natural for OpenGL and a single rotate call with the camera vector should rotate the scene properly). Therefore, given the initial Angle-axis vector, and one or more of the local rotations noted above (we could locally call "X" the left/right axis, "Y" the top/bottom axis, and "Z" the roll axis), I would like the end result to be a new Axis-angle vector.

3) Avoid quarternions and minimize the use of matrices (for some reason I find both unintuitive). Instead of matrix notation please just show in psuedocode the vector components and what's happening.

4) You should be able to rotate in a direction (using the arrow keys) 360 degrees and return to the starting view without drifting. Preferably, if the user presses one combination and then reverses it, they would expect to be able to return to near their original orientation.

5) The starting state for the camera is at coordinates (0,0,0) facing the Axis-angle vector (0,0,1,0 - z-axis with no starting rotation). "up" is (0,1,0).

+2  A: 

Using Euler angles approach is wrong with spacesim. I have tried that approach and quickly had to give up. Player wants all degrees of freedom, and Euler's angles don't provide that, or complicate it enormously.

What you really, really want are quaternions. This is a part of my update code.

            Quaternion qtmp1, qtmp2, qtmp3;

            Rotation r(........);
            qtmp1.CreateFromAxisAngle(1., 0., 0., r.j*m_updatediff);
            qtmp2.CreateFromAxisAngle(0., 1., 0., r.i*m_updatediff);
            qtmp3.CreateFromAxisAngle(0., 0., 1., r.k*m_updatediff);
            m_rotq = qtmp1 * qtmp2 * qtmp3 * m_rotq;

r.i, r.j and r.k contain the current speed of rotation around a certain axis. Getting a spacesim-like feel is just a matter of multiplying these quaternions.

Everything else is just a complication. With Euler's angles, you can play all day long -- in fact, all year long -- but you will just make loads of messy code.

Your daily recommendation: quaternions.

Ivan Vučica