转换具有不同坐标轴(Unity和Three Js)的系统之间的欧拉角度

时间:2015-03-31 21:34:04

标签: c# math unity3d three.js euler-angles

我试图转换Unity和Threejs之间的欧拉角旋转。这有两个主要问题。

问题1:

Unity和Threejs有不同的坐标系

统一:

enter image description here

Threejs

enter image description here

问题2:

Unity以ZXY的顺序执行euler数学运算,而Threejs默认为XYZ。我在Threejs方面找到了一些使用不同乘法顺序创建欧拉角的公式,但我想知道这背后的数学因此我可以在两个系统之间来回切换。我也不确定不同的坐标系如何影响这种转换数学。

编辑1

我发现这个关于将Unity Quaternion转换为Threejs的堆栈溢出帖子:

Convert Unity transforms to THREE.js rotations

然而,我无法让这段代码与Threejs相反的方向工作,这是我需要的。

2 个答案:

答案 0 :(得分:1)

我终于使用下面的链接找到了解决方案。可能有一个更简单的解决方案,但我尝试的其他任何东西都没有给我预期的效果。值得注意的是,这是通过一个Threejs相机测试的,-z面向+ y向上。我的团结相机-z面向+ y朝上。如果您有一个面向+ z的摄像头,这在Unity中是常见的,只需将GameObject与一个空的GameObject相对应,并将180度欧拉旋转应用于空的GameObject。这也假设Threejs Euler旋转是默认的XYZ排序。

http://answers.unity3d.com/storage/temp/12048-lefthandedtorighthanded.pdf

http://en.wikipedia.org/wiki/Euler_angles

http://forum.unity3d.com/threads/how-to-assign-matrix4x4-to-transform.121966/

    /// <summary>
    /// Converts the given XYZ euler rotation taken from Threejs to a Unity Euler rotation
    /// </summary>
    public static Vector3 ConvertThreejsEulerToUnity(Vector3 eulerThreejs)
    {
        eulerThreejs.x *= -1;
        eulerThreejs.z *= -1;
        Matrix4x4 threejsMatrix = CreateRotationalMatrixThreejs(ref eulerThreejs);

        Matrix4x4 unityMatrix = threejsMatrix;
        unityMatrix.m02 *= -1;
        unityMatrix.m12 *= -1;
        unityMatrix.m20 *= -1;
        unityMatrix.m21 *= -1;

        Quaternion rotation = ExtractRotationFromMatrix(ref unityMatrix);
        Vector3 eulerRotation = rotation.eulerAngles;
        return eulerRotation;
    }

    /// <summary>
    /// Creates a rotation matrix for the given threejs euler rotation
    /// </summary>
    private static Matrix4x4 CreateRotationalMatrixThreejs(ref Vector3 eulerThreejs)
    {
        float c1 = Mathf.Cos(eulerThreejs.x);
        float c2 = Mathf.Cos(eulerThreejs.y);
        float c3 = Mathf.Cos(eulerThreejs.z);
        float s1 = Mathf.Sin(eulerThreejs.x);
        float s2 = Mathf.Sin(eulerThreejs.y);
        float s3 = Mathf.Sin(eulerThreejs.z);
        Matrix4x4 threejsMatrix = new Matrix4x4();
        threejsMatrix.m00 = c2 * c3;
        threejsMatrix.m01 = -c2 * s3;
        threejsMatrix.m02 = s2;
        threejsMatrix.m10 = c1 * s3 + c3 * s1 * s2;
        threejsMatrix.m11 = c1 * c3 - s1 * s2 * s3;
        threejsMatrix.m12 = -c2 * s1;
        threejsMatrix.m20 = s1 * s3 - c1 * c3 * s2;
        threejsMatrix.m21 = c3 * s1 + c1 * s2 * s3;
        threejsMatrix.m22 = c1 * c2;
        threejsMatrix.m33 = 1;
        return threejsMatrix;
    }

    /// <summary>
    /// Extract rotation quaternion from transform matrix.
    /// </summary>
    /// <param name="matrix">Transform matrix. This parameter is passed by reference
    /// to improve performance; no changes will be made to it.</param>
    /// <returns>
    /// Quaternion representation of rotation transform.
    /// </returns>
    public static Quaternion ExtractRotationFromMatrix(ref Matrix4x4 matrix)
    {
        Vector3 forward;
        forward.x = matrix.m02;
        forward.y = matrix.m12;
        forward.z = matrix.m22;

        Vector3 upwards;
        upwards.x = matrix.m01;
        upwards.y = matrix.m11;
        upwards.z = matrix.m21;

        return Quaternion.LookRotation(forward, upwards);
    }

答案 1 :(得分:0)

问题1:

当然,我只是辅修数学,但我相信你应该只需按照以下方式进行直接映射:

(X,Y,Z)=&gt; (X,Y,-Z)

这应该是双向的。

据我记得,一旦你在坐标之间进行转换,数学应该是相同的,只要确保你在一个系统或另一个系统中工作,以使你的生活更轻松。然后,您可以根据需要导出结果。