Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

SharpDX.Quaternion Multiply method #333

Closed
mogg3939 opened this issue Apr 6, 2014 · 2 comments
Closed

SharpDX.Quaternion Multiply method #333

mogg3939 opened this issue Apr 6, 2014 · 2 comments
Labels

Comments

@mogg3939
Copy link

mogg3939 commented Apr 6, 2014

SharpDX.Quaternion Multiply two quaternion method is incorrect.

line 445-447
Current (incorrect):
float a = (ly * rz - lz * ry);
float b = (lz * rx - lx * rz);
float c = (lx * ry - ly * rx);

Correct:
float a = (lz * ry - ly * rz);
float b = (lx * rz - lz * rx);
float c = (ly * rx - lx * ry);

@ArtiomCiumac
Copy link
Contributor

Can you please provide more details? Maybe some links, unit tests or some reference implementation? The formulas here, here, here and here seem to match the SharpDX implementation, therefore I am not sure if it is incorrect.

Also this code:

var q1 = new Quaternion(2, 3, 4, 5);
var q2 = new Quaternion(5, 4, 3, 2);
var q3 = Quaternion.Multiply(q1, q2);

Produces the result q3 = {X:22 Y:40 Z:16 W:-24} that matches the same result from a wolfram alpha query.

Based on the description above, I am closing this bug. I will be happy to reopen it and integrate a fix if you will provide arguments that I am wrong.

@mogg3939
Copy link
Author

mogg3939 commented Apr 7, 2014

Sorry, I provide more my evidence.

I think the current code is maybe right-hand coordinate.
As you know, Direct3D is left-hand coordinate normally.

The monoxna and euclideanspace(here) are right-hand.
Left-hand SlimDX is the same code I provided.(Code)

And I tested by the following code.

public void main()
{
    Vector3 result;
    Quaternion left, right, multiplied;

    left = Quaternion.RotationAxis(Vector3.UnitY, (float)(Math.PI / 2.0));
    right = Quaternion.RotationAxis(Vector3.UnitZ, (float)(Math.PI / 2.0));

    // Case1 : Matrix(Quaternion * Quaternion)
    multiplied = left * right;

    result = Vector3.TransformCoordinate(Vector3.UnitZ, Matrix.RotationQuaternion(multiplied));
    System.Diagnostics.Debug.WriteLine(result.ToString());
    //result X:0.9999999 Y:0 Z:1.192093E-07

    // Case2 : Matrix(Quaternion) * Matrix(Quaternion)
    result = Vector3.TransformCoordinate(Vector3.UnitZ, Matrix.RotationQuaternion(left) * Matrix.RotationQuaternion(right));
    System.Diagnostics.Debug.WriteLine(result.ToString());
    //result X:5.960464E-08 Y:0.9999999 Z:5.960464E-08

    // Case3 : Matrix(Multiply(Quaternion, Quaternion)) by using revised method
    multiplied = Multiply(left, right);

    result = Vector3.TransformCoordinate(Vector3.UnitZ, Matrix.RotationQuaternion(multiplied));
    System.Diagnostics.Debug.WriteLine(result.ToString());
    //result X:0 Y:0.9999999 Z:1.192093E-07
}

public Quaternion Multiply(Quaternion left, Quaternion right)
{
    Quaternion result;

    float lx = left.X;
    float ly = left.Y;
    float lz = left.Z;
    float lw = left.W;
    float rx = right.X;
    float ry = right.Y;
    float rz = right.Z;
    float rw = right.W;
    float a = (lz * ry - ly * rz);
    float b = (lx * rz - lz * rx);
    float c = (ly * rx - lx * ry);
    float d = (lx * rx + ly * ry + lz * rz);
    result.X = (lx * rw + rx * lw) + a;
    result.Y = (ly * rw + ry * lw) + b;
    result.Z = (lz * rw + rz * lw) + c;
    result.W = lw * rw - d;

    return result;
}

Vector (0, 0, 1) rotetes Y-90 degree and Z-90 degree, the result should be Vector (0, 1, 0).
Case1 is SharpDX Quaternion * Quaternion.
Case2 is SharpDX Matrix * Matrix.
Case3 is using Multiply method I provided.

Case1 result (1, 0, 0) is incorrect.
Case2 result (0, 1, 0) is correct.
Case3 result (0, 1, 0) is correct.

Thank you.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants