# Why is my quaternion camera rotating around strange axes?

I can't get it to work for the life of me. Its rotating the camera in the global coordinate system, or some other random coordinate system, not the camera local coordinate system. WASDEC work perfectly, right until I start rotating. Here's the annotated code:

  //eye.r is the quat camera rotation
//eye.p is the vec3 camera position

// Get the local axes we're going to do transformations with
var axes = {
x: quat4.multiplyVec3(eye.r, [1, 0, 0]),
y: quat4.multiplyVec3(eye.r, [0, 1, 0]),
z: quat4.multiplyVec3(eye.r, [0, 0, 1])
};

// If a movement key is down, add the appropriately scaled local axis
// to our position

// If a rotation key is down, create a scaled rotation about the appropriate
// local axis, and multiply it into the current rotation
if(keystate[UP])    quat4.multiply(quat4.rotation(-0.05, axes.x), eye.r, eye.r);
if(keystate[DOWN])  quat4.multiply(quat4.rotation( 0.05, axes.x), eye.r, eye.r);
if(keystate[LEFT])  quat4.multiply(quat4.rotation(-0.05, axes.y), eye.r, eye.r);
if(keystate[RIGHT]) quat4.multiply(quat4.rotation( 0.05, axes.y), eye.r, eye.r);


Edit: Since it might not be clear what the functions do. This is javascript and the glmatrix linear algebra/quat library.

quat4.multiplyVec3(quat, vec) // vec = quat * vec

vec3.add(vec, vec2) // vec = vec + vec2

vec3.scale(vec, scalar, dest) // dest = vec * scalar

quat4.rotation(angle, axis) // creates a quaternion rotation about the given axis, by the given angle

quat4.multiply(quat, quat2, dest) // dest = quat * quat2


Hmm.. I suspect part of the problem might be that quaternion rotation transformations use a sandwiching product form.

If: v = vector to be rotated q = quaternion representing the intended rotation v' = v after rotation

The rotation should be described by:

v' = qvq^-1

where q^-1 is the the inverse or the conjugate of q.

specifically the second section "Describing rotations with quaternions"

So as a result, my local axis vectors are completely half-baked, and can't be used as such. Fortunately, all they need is another inverse quat multiplication.

EDIT: Or not. On close inspection it looks like the multiply function actually does the two multiplies, one with the quat and one with it's conjugate. The mystery continues...

Might be a pre-multiply/post-multiply issue. Sometimes the order in which you need to apply transformations can be a little counterintuitive.

I would try changing this:

quat4.multiply(quat4.rotation(-0.05, axes.x), eye.r, eye.r)


to one of two possible things:

quat4.multiply(eye.r, quat4.rotation(-0.05, axes.x), eye.r)


or maybe

quat4.multiply(quat4.rotation(-0.05,[1, 0, 0]), eye.r, eye.r)


(and obviously make similar changes for the other rotations).