C# 在具有不同坐标轴的系统之间转换euler角度';s(统一与三JS)

C# 在具有不同坐标轴的系统之间转换euler角度';s(统一与三JS),c#,math,unity3d,three.js,euler-angles,C#,Math,Unity3d,Three.js,Euler Angles,我试图在Unity和Threejs之间转换euler角度旋转。这有两个主要问题 问题1: Unity和ThreeJ有不同的坐标系 团结: 三个 问题2: Unity按照ZXY的顺序进行euler数学运算,而Threejs默认为XYZ。我在Threejs侧找到了一些公式,用于使用不同的乘法顺序创建Euler角,但我想知道这背后的数学,这样我可以在两个系统之间来回移动。我也不确定不同的坐标系是如何在这个转换数学中起作用的 编辑1 我发现了这篇关于将一个单位四元数转换为三元数的堆栈溢出帖子: 但

我试图在Unity和Threejs之间转换euler角度旋转。这有两个主要问题

问题1:

Unity和ThreeJ有不同的坐标系

团结:

三个

问题2:

Unity按照ZXY的顺序进行euler数学运算,而Threejs默认为XYZ。我在Threejs侧找到了一些公式,用于使用不同的乘法顺序创建Euler角,但我想知道这背后的数学,这样我可以在两个系统之间来回移动。我也不确定不同的坐标系是如何在这个转换数学中起作用的

编辑1

我发现了这篇关于将一个单位四元数转换为三元数的堆栈溢出帖子:

但是,我无法让这段代码与我所需要的从Threejs到Unity的方向相反。

问题1:

当然,我只辅修数学,但我相信你应该能够对点进行如下的直接映射:

(X,Y,Z)=>(X,Y,-Z)

这应该是双向的


就我所记得的,一旦你在坐标之间转换,数学应该是一样的,只要确保你在一个系统或另一个系统中工作,使你的生活更容易。然后,您可以根据需要将结果导出回去。

我终于通过下面的链接找到了解决方案。也许有一个更简单的解决办法,但我尝试的其他方法都没有达到预期的效果。值得注意的是,这是用一个3JS相机测试的,它的-z朝向+y向上的位置。我的unity相机是-z朝向+y朝向上。如果你有一个面向+z的摄像头,这在Unity中很常见,只需将游戏对象子对象化为一个空游戏对象,然后对空游戏对象应用180度Euler旋转。这还假设Threejs Euler旋转是默认的XYZ顺序

//
///将从Threejs获取的给定XYZ euler旋转转换为Unity euler旋转
/// 
公共静态Vector3转换器三个JSeulerTounity(Vector3 eulerThreejs)
{
eulerThreejs.x*=-1;
eulerThreejs.z*=-1;
Matrix4x4 threejsMatrix=CreateRotationalMatrixThreejs(参考eulerThreejs);
Matrix4x4 unityMatrix=3JS矩阵;
unityMatrix.m02*=-1;
unityMatrix.m12*=-1;
unityMatrix.m20*=-1;
unityMatrix.m21*=-1;
四元数旋转=从矩阵中提取旋转(参考单位矩阵);
Vector3 eulerotation=rotation.eulerAngles;
回归方程;
}
/// 
///为给定的旋转创建旋转矩阵
/// 
专用静态矩阵x4x4 CreateRotationalMatrixThreejs(参考向量3 eulerThreejs)
{
float c1=数学Cos(eulerThreejs.x);
浮点数c2=数学Cos(eulerThreejs.y);
float c3=数学Cos(eulerThreejs.z);
float s1=数学Sin(eulerThreejs.x);
float s2=数学Sin(eulerThreejs.y);
float s3=数学Sin(eulerThreejs.z);
Matrix4x4 threejsMatrix=新Matrix4x4();
threejsMatrix.m00=c2*c3;
threejsMatrix.m01=-c2*s3;
threejsMatrix.m02=s2;
3JSMatrix.m10=c1*s3+c3*s1*s2;
threejsMatrix.m11=c1*c3-s1*s2*s3;
threejsMatrix.m12=-c2*s1;
3JSMatrix.m20=s1*s3-c1*c3*s2;
3JSMatrix.m21=c3*s1+c1*s2*s3;
3JSMatrix.m22=c1*c2;
threejsMatrix.m33=1;
返回矩阵;
}
/// 
///从变换矩阵中提取旋转四元数。
/// 
///变换矩阵。此参数通过引用传递
///提高绩效;不会对其进行任何更改。
/// 
///旋转变换的四元数表示。
/// 
公共静态四元数提取旋转自矩阵(参考矩阵x4x4矩阵)
{
矢量3向前;
正向.x=矩阵.m02;
正向。y=矩阵。m12;
forward.z=matrix.m22;
向量3向上;
向上。x=矩阵m01;
向上。y=矩阵m11;
向上。z=矩阵m21;
返回四元数。向前旋转(向前、向上);
}

是否在Z*-1这样简单的坐标系之间翻转?这不起作用,因为我们讨论的是这两个系统中的旋转。如果我们讨论的是位置差异,这可能会起作用,但对欧拉角旋转不起作用。你看过旋转矩阵了吗?我相信这可能是解决这两个冲突的好方法,因为它们可以用来抽象旋转的顺序。那么你应该只剩下简单的坐标转换了。我一直在研究旋转矩阵。我能够使用这个wiki将来自3JS的Euler角度转换为旋转矩阵:此时,我尝试将矩阵从右手坐标系转换为左手坐标系,使用:此时,我尝试将旋转作为四元数从矩阵中提取出来。然而,最后两个步骤中的一个不起作用,因为旋转没有对齐。如果可以,请检查我的编辑
    /// <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);
    }