在具有不同坐标轴的系统之间转换欧拉角(Unity 和 Threejs)
Posted
技术标签:
【中文标题】在具有不同坐标轴的系统之间转换欧拉角(Unity 和 Threejs)【英文标题】:Convert euler angles between systems with different coordinate axis's (Unity and Threejs) 【发布时间】:2015-06-05 09:41:38 【问题描述】:我正在尝试在 Unity 和 Threejs 之间转换欧拉角旋转。这有两个主要问题。
问题一:
Unity 和 Threejs 有不同的坐标系
团结:
三个
问题 2:
Unity 以 ZXY 顺序进行欧拉数学运算,而 Threejs 默认为 XYZ。我在 Threejs 方面找到了一些公式,用于使用不同的乘法顺序创建欧拉角,但我想知道这背后的数学,以便我可以在两个系统之间来回切换。我也不确定不同的坐标系如何影响这个转换数学。
编辑 1
我发现这篇关于将 Unity 四元数转换为 Threejs 的堆栈溢出帖子:
Convert Unity transforms to THREE.js rotations
但是,我无法让这段代码工作,以便将 Threejs 的相反方向转向 Unity,而这正是我所需要的。
【问题讨论】:
坐标系之间的翻转是否像Z * -1那么简单? 【参考方案1】:我终于使用下面的链接找到了解决方案。可能有一个更简单的解决方案,但我尝试的其他任何方法都没有给我预期的效果。值得注意的是,这是使用 Threejs 相机进行的测试,该相机 -z 朝向 +y 向上的位置。我的统一相机是 -z 面向 +y 朝上。如果您有一个 +z 朝向的相机,这在 Unity 中很常见,只需将 GameObject 子化到一个空的 GameObject 并将 180 度 Euler 旋转应用于空的 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);
【讨论】:
【参考方案2】:问题一:
虽然我只辅修数学,但我相信您应该能够简单地为点进行如下直接映射:
(X, Y, Z) => (X, Y, -Z)
这应该是双向的。
据我所知,一旦您在坐标之间转换,数学应该是相同的,只要确保您在一个系统或另一个系统中工作,以使您的生活更轻松。然后您可以根据需要将结果导出回来。
【讨论】:
这不起作用,因为我们正在讨论这两个系统中的旋转。如果我们谈论的是位置差异,这可能有效,但不适用于欧拉角旋转。 你有没有研究过旋转矩阵?我相信这可能是解决这两种冲突的好方法,因为它们可以用来抽象旋转的顺序。那么你应该只剩下简单的坐标转换了。 我一直在研究旋转矩阵。我能够使用此 wiki 将 Threejs 的欧拉角转换为旋转矩阵:en.wikipedia.org/wiki/Euler_angles 此时我尝试使用以下方法将矩阵从右手坐标系转换为左手坐标系:***.com/questions/1263072/… 此时我尝试将旋转作为四元数从矩阵中提取出来。然而,最后两个步骤之一不起作用,因为旋转没有对齐。如果可以,请检查我的编辑以上是关于在具有不同坐标轴的系统之间转换欧拉角(Unity 和 Threejs)的主要内容,如果未能解决你的问题,请参考以下文章
Unity3D 灵巧小知识点☀️ | Unity 四元数欧拉角 与 方向向量 之间转换