Jan Schultke Jan Schultke - 1 month ago 12
Java Question

Invalid results when multiplying quaternions and no idea why

I am currently working on a 3D-library including quaternions. As every expert, I coded my methods based on what I found on Wikipedia and it doesn't work quite right.

This is the method for calculating the product between two quaternions:



public static Quaternion product(Quaternion a, Quaternion b) {
return a.clone().multiply(b);
}


And here is its implementation:



public Quaternion multiply(Quaternion q) {
float rx = q.getX(), ry = q.getY(), rz = q.getZ(), rw = q.getW();

this.w = w*rw - x*rx - y*ry - z*rz;
this.x = w*rx + x*rw + y*rz - z*ry;
this.y = w*ry - x*rz + y*rw + z*rx;
this.z = w*rz + x*ry - y*rx + z*rw;
return this;
}


And here is a small test that I wrote:



Quaternion a = Quaternion.create(1, 1, 1, Spatium.DEG_TO_RAD * 15);
Quaternion b = Quaternion.create(1, 1, 1, Spatium.DEG_TO_RAD * 15);
Quaternion c = Quaternion.product(a, b);
System.out.println(a + " * " + b + " = " + c);


Note that the
create()
method initializes quaternions with
x
,
y
,
z
,
w
.

Unfortunately, the tests yields results that don't make any sense despite my amazing skills of copying and pasting Wikipedia formulas:

(0.2617994 + 1.0i + 1.0j + 1.0k) * (0.2617994 + 1.0i + 1.0j + 1.0k) = (-2.931461 + -2.6696618i + 1.0j + -6.3393235k)


For comparison, Wolfram solves it correctly and returns
-2.93146 + 0.523599i + 0.523599j + 0.523599k
.

Here's the formulas I so skillfully copied from Wikipedia:
enter image description here

I don't really have anything to say other than please help me, Wikipedia couldn't.

Answer

I think you should store the current values of x, y, z and w in a temp variable before updating it with new values.

    public Quaternion multiply(Quaternion q) {
        float rx = q.getX(), ry = q.getY(), rz = q.getZ(), rw = q.getW();

        float cx = x; // cx = current X
        float cy = y;
        float cz = z;
        float cw = w;

        this.w = cw*rw - cx*rx - cy*ry - cz*rz;
        this.x = cw*rx + cx*rw + cy*rz - cz*ry;
        this.y = cw*ry - cx*rz + cy*rw + cz*rx;
        this.z = cw*rz + cx*ry - cy*rx + cz*rw;
        return this;
    }

In your code, when you use this.w = w*rw - x*rx - y*ry - z*rz;, you are override the current value o w, and the next 3 operations will be affect by this changes.