Composing quaternions

649 views Asked by At

I'm currently working on a 3D scene which has to be rotated by dragging the mouse. To do this, I'm utilizing a ArcBall implementation.

The used framework, immediately transformed the resulting quaternion into a rotation matrix. Any subsequent rotations would also be converted into a matrix. These matrices in turn are multiplied.

I wanted to optimize this by simply multiplying the rotation quaternions. Now the scene seems to be spinning uncontrollably while the original version worked okay(ish).

My code for multiplying quaternions:

public static Quat4f mul(Quat4f q1, Quat4f q2) {
    float x =  q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x;
    float y = -q1.x * q2.z + q1.y * q2.w + q1.z * q2.x + q1.w * q2.y;
    float z =  q1.x * q2.y - q1.y * q2.x + q1.z * q2.w + q1.w * q2.z;
    float w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w;

    return new Quat4f(x,y,z,w);
}

The multiplication is done as (the result is normalized for good measure):

currentRotation = Quat4f.mul(newRotation, currentRotation);

An finally, the rotation is applied as:

glMultMatrixf(currentRotation.toMatrix());

Does anyone know what I'm doing wrong?

1

There are 1 answers

1
Andon M. Coleman On BEST ANSWER

glMultMatrixf (...) multiplies the current matrix by the one you pass it. Now here is where things get kind of funny, you have a Quaternion that also seems to be cumulative (named currentRotation). You are accumulating the rotation in two different places.

Chances are, what you actually want is glLoadMatrixf (...). Rather than multiplying the current matrix by your rotation matrix, that will replace the matrix. You could achieve the same result by calling glLoadIdentity (...) immediately before glMultMatrixf (...); the bottom line is you need to discard any old rotation in your matrix before applying this.

It is not clear whether the behavior you are after is such that GL's matrix is reset every time it is updated or if the quaternion is reset, but you really need to reset one of the two or you will spin endlessly.