# Finding a suitable axis-angle to avoid gimbal lock

In OpenGL the camera faces the -z axis with the +y axis pointing up. I am using quaternions to represent the orientation of my objects (which works well) and am trying to do the same for the camera. I want the camera's initial orientation rotation to face the +x axis with the up vector being +z. I was attempting to initialize the camera's quaternion rotation by multiplying two 90 degree rotation quaternions in an effort to achieve this, but I believe I am experiencing gimbal lock because I cannot orient the camera properly (the first rotation works fine, the second one produces undesired results). I haven't been able to wrap my head around an axis-angle representation that will orient the camera the way I want.

In summary:

I'm searching for an axis angle (or anything that can be converted to a quaternion really) that will provide the following rotation:

inital camera orientation: facing -z axis, +y pointing up

desired orientation: facing +x axis, +z pointing up

Note: I am already aware of gluLookAt, this problem was my attempt at understanding more about how everything works.

The orientation you are looking for is:

Rotation Axis : 0.577, -0.577, -0.577
Rotation Angle: 2.094 radians or 120.0 degrees


The quaternion that represents that orientation is:

q: 0.500, -0.500, -0.500, 0.500


where the first 3 terms are the imaginary part (the rotation axis) and the last term commonly known as w, the encoded rotation angle.

Following is the code I used to calculate the orienation. If you don't have a linear algebra library yet, this is the point where you either want to roll your own or to download one. glm for instance.

Now back to the calculation. The first orientation frame you describe is basically the identity matrix for the opengl camera (facing -z axis, +y pointing up). The second orientation frame is our target orientation: facing +x axis, +z pointing up. Calculating the matrix from those 2 parameters is pretty straight forward, the following function is an example how to do it:

void gm33GetOrientationMatrix(
matrix33 result,
vector3 const dir,
vector3 const up )
{
gv3CopyNegated( result, dir );
gv3CrossProduct( result, up, result );
gv3Normalize( result );
gv3CrossProduct( result, result, result );
}


Once we have this matrix, its pretty simple to calculate a quaternion from it, here you can find the code for the matrix-quaternion conversion.

And voila, that's it, we have the quaternion. As an example, here is the full code I used to calculate it:

// calculate our target rotation matrix
vector3 target_dir = { 1.0f, 0.0f, 0.0f };
vector3 target_up = { 0.0f, 0.0f, 1.0f };
matrix33 target;
gm33GetOrientationMatrix( target, target_dir, target_up );

// convert it to a quaternion
quaternion rot;
gqFromM33( rot, target );

• I plugged in your axis-angle values directly but I didn't not get the proper rotation. I then tried plugging in your quaternion directly and got the same matrix (which didn't work). I am using functions built into LWJGL (OpenGL for Java). I ended up creating a matrix by hand using the source code of gluLook At. The working matrix for my desired orientation is (row by row) [0 -1 0 0] [0 0 1 0] [ -1 0 0 0] [0 0 0 1]. The matrix calculated from your values is [2.28E-4 2.28E-4 1 0] [-1 2.28E-4 2.28E-4 0] [-2.28E-4 -1 2.28E-4 0] [0 0 0 1] ... any insight is appreciated. Jul 23, 2012 at 22:41
• Well I converted the matrix that I calculated to a quaternion, and then converted that to an axis angle, and the values for the quat and axis-angle match what you specified. So I know now that your answer is correct, and I messed up somewhere in the process of multiplying the matrix with a translation matrix, and inverting the whole thing to load into the modelview matrix. Jul 23, 2012 at 23:00
• Finally I'd like to mention that what I have now (its working) is to take the quaternion rotation, and generate the matrix using a method I found here link. I must have been doing something wrong with the LWJGL functions. I create the matrix from the quaternion, multiply a translation matrix to it, and invert result. The information to calculate the quaternion orientation is indeed very useful, however all I needed was the initial rotation for the camera (which I can simply hardcode into the game). Jul 23, 2012 at 23:58