Advertisement

Quaternion multiplication

Started by September 05, 2016 05:43 PM
1 comment, last by Dirk Gregorius 8 years, 5 months ago

The code I see for Quaternion multiplication on System.Numerics.Vectors is different (reversed) from all the other code I see on the Internet. What gives?

http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/WIN_WINDOWS/lh_tools_devdiv_wpf/Windows/wcp/Core/System/Windows/Media3D/Quaternion@cs/1/Quaternion@cs

public static Quaternion operator *(Quaternion left, Quaternion right)
{
if (left.IsDistinguishedIdentity)
{
return right;
}
if (right.IsDistinguishedIdentity)
{
return left;
}
double x = left._w * right._x + left._x * right._w + left._y * right._z - left._z * right._y;
double y = left._w * right._y + left._y * right._w + left._z * right._x - left._x * right._z;
double z = left._w * right._z + left._z * right._w + left._x * right._y - left._y * right._x;
double w = left._w * right._w - left._x * right._x - left._y * right._y - left._z * right._z;
Quaternion result = new Quaternion(x,y,z,w);
return result;
}

https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/src/System/Numerics/Quaternion.cs

public static Quaternion operator *(Quaternion value1, Quaternion value2)
{
Quaternion ans;
float q1x = value1.X;
float q1y = value1.Y;
float q1z = value1.Z;
float q1w = value1.W;
float q2x = value2.X;
float q2y = value2.Y;
float q2z = value2.Z;
float q2w = value2.W;
// cross(av, bv)
float cx = q1y * q2z - q1z * q2y;
float cy = q1z * q2x - q1x * q2z;
float cz = q1x * q2y - q1y * q2x;
float dot = q1x * q2x + q1y * q2y + q1z * q2z;
ans.X = q1x * q2w + q2x * q1w + cx;
ans.Y = q1y * q2w + q2y * q1w + cy;
ans.Z = q1z * q2w + q2z * q1w + cz;
ans.W = q1w * q2w - dot;
return ans;
}
Quaternion multiplication is well defined in the Math literature. i*j = -j*i = k, j*k = -k*j = i, k*i = -i*k = j, and everything else can be deduced from the fact that 1 is the neutral element of multiplication and by linearity.

Try to multiply i*j and if you get something different than k, it's broken.
Advertisement

Let's define a quaternion like this:


struct Quaternion 
{
    Vector3 v; 
    float s;
};

Then the quaternion product is defined as:


Quaternion operator*( const Quaternion& q1, const Quaternion& q2 )
{
    Quaternion result;
    result.v = cross( q1.v, q2.v )+ q1.s * q2.v + q2.s * q1.v;
    result.s = q1.s * q2.s - dot( q1, q2 );

    return result;
}

Both your functions are equivalent. The vector'ish form is just less usual in literature in my experience. If you write the definition above component-wise you will get the same result!

This topic is closed to new replies.

Advertisement