Search code examples
c#mathunity-game-enginequaternionsslimdx

LookAt rotation in SlimMath with expected values from Unity3D


Assume that v1 = (36.5f, 10.7f, 15.9f), v2 = (29.4f, 10.8f, 19.7f), up = (0f, 1f, 0f).

I tried to use Matrix.LookAtLH and LookAtRH but all reasults are wrong:

Quaternion.RotationMatrix(Matrix.LookAtLH(v1, v2, up)) outputs

        w: 0.9    x: 0    y: 0.5    z: 0

Quaternion.RotationMatrix(Matrix.LookAtRH(v1, v2, up)) outputs

        w: 0.5    x: 0    y: -0.9   z: 0

But I expect (from Unity3D)

        w: 0.9   x: 0    y: -0.5     z: 0

Another example: v1 = (106.5f, 35.7f, 15.9f), v2 = (29.4f, 10.8f, 19.7f), up = (0f, 1f, 0f).

Quaternion.RotationMatrix(Matrix.LookAtLH(v1, v2, up)) outputs

       w: 0.7     x: -0.1 y: 0.7     z: -0.1

Quaternion.RotationMatrix(Matrix.LookAtRH(v1, v2, up)) outputs

       w: 0.7     x: 0.1  y: -0.7    z: -0.1

But I expect (from Unity3D)

       w: 0.7     x: 0.1  y: -0.7    z: 0.1

SlimMath Matrix.cs:

    /// <summary>
    /// Creates a left-handed, look-at matrix.
    /// </summary>
    /// <param name="eye">The position of the viewer's eye.</param>
    /// <param name="target">The camera look-at target.</param>
    /// <param name="up">The camera's up vector.</param>
    /// <param name="result">When the method completes, contains the created look-at matrix.</param>
    public static void LookAtLH(ref SlimVector3 eye, ref SlimVector3 target, ref SlimVector3 up, out SlimMatrix result)
    {
        SlimVector3 xaxis, yaxis, zaxis;
        SlimVector3.Subtract(ref target, ref eye, out zaxis); zaxis.Normalize();
        SlimVector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize();
        SlimVector3.Cross(ref zaxis, ref xaxis, out yaxis);

        result = SlimMatrix.Identity;
        result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z;
        result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z;
        result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z;

        SlimVector3.Dot(ref xaxis, ref eye, out result.M41);
        SlimVector3.Dot(ref yaxis, ref eye, out result.M42);
        SlimVector3.Dot(ref zaxis, ref eye, out result.M43);

        result.M41 = -result.M41;
        result.M42 = -result.M42;
        result.M43 = -result.M43;
    }

    /// <summary>
    /// Creates a right-handed, look-at matrix.
    /// </summary>
    /// <param name="eye">The position of the viewer's eye.</param>
    /// <param name="target">The camera look-at target.</param>
    /// <param name="up">The camera's up vector.</param>
    /// <param name="result">When the method completes, contains the created look-at matrix.</param>
    public static void LookAtRH(ref SlimVector3 eye, ref SlimVector3 target, ref SlimVector3 up, out SlimMatrix result)
    {
        SlimVector3 xaxis, yaxis, zaxis;
        SlimVector3.Subtract(ref eye, ref target, out zaxis); zaxis.Normalize();
        SlimVector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize();
        SlimVector3.Cross(ref zaxis, ref xaxis, out yaxis);

        result = SlimMatrix.Identity;
        result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z;
        result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z;
        result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z;

        SlimVector3.Dot(ref xaxis, ref eye, out result.M41);
        SlimVector3.Dot(ref yaxis, ref eye, out result.M42);
        SlimVector3.Dot(ref zaxis, ref eye, out result.M43);

        result.M41 = -result.M41;
        result.M42 = -result.M42;
        result.M43 = -result.M43;
    }

How can I modify it to receive the same results as from Unity3D?


Solution

  • I don't understand why it appears to be inverted. I invert axis values of LookAtLH back and it works now...