如何使用 3x3 旋转矩阵和平移向量应用变换?
How to apply transformation using 3x3 rotation matrix and a translation vector?
我正在使用 ARCore 进行增强现实项目。每次启动应用程序时,ARCore 的坐标系都会发生变化,以初始位置为原点。我在另一个坐标系中有 5 个点,我可以使用 ARCore 增强图像在 Unity 世界 space 中找到其中的 4 个位置。当然,这些点在我的其他坐标系中具有不同的值。我必须使用它在其他坐标系中的位置在 Unity 世界 space 中找到第 5 个点的位置。
我遵循了这个tutorial to achieve this. But since Unity does not support 3x3 matrices i used Accord.NET 框架。使用教程和 Accord 矩阵,我可以计算一个 3x3 Rotation
矩阵和一个 Translation
向量。
但是,当我尝试使用 TestObject.transform.Translate(AccordtoUnity(Translation),Space.World)
将其应用到我的第 5 个点时,我遇到了麻烦。当最初的 4 个对象和参考对象处于同一方向时,我的翻译工作完美。但是,当我的参考对象旋转时,此翻译不起作用。这当然是有道理的,因为我只做了翻译。我的问题是如何对第 5 点应用旋转和平移。或者有没有办法将我的 3x3 旋转矩阵和转换转换为 Unity 4x4Matrix
,从那时起我就可以使用 Matrix4x4.MultiplyPoint3x4
。或者是否可以将我的 3x3 旋转矩阵转换为 Quaternion
让我使用 4x4Matrix.SetTRS
。我对这种转换有点困惑,因为 4x4Matrix
也包括缩放,但我没有进行任何缩放。
如果有人能给我一些提示或提供更好的方法来找到第 5 点,我会很高兴。谢谢!
编辑:
其实我是根据Daveloper的回答解决的。我像这样构建了一个 Unity 4x4 矩阵:
[ R00 R01 R02 T.x ]
[ R10 R11 R12 T.y ]
[ R20 R21 R22 T.z ]
[ 0 0 0 1 ]
我测试了在 Unity 中创建原始对象并使用上面的矩阵应用平移和旋转,如下所示:
TestObject.transform.position = TransformationMatrix.MultiplyPoint3x4(TestObject.transform.position);
TestObject.transform.rotation *= Quaternion.LookRotation(TransformationMatrix.GetColumn(2), TransformationMatrix.GetColumn(1));
要使用 3x3 旋转矩阵和平移向量来设置变换,请使用
// rotationMatrixCV = your 3x3 rotation matrix; translation = your translation vector
var rotationMatrix = new Matrix4x4();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
rotationMatrix[i, j] = rotationMatrixCV[i, j];
}
}
rotationMatrix[3, 3] = 1f;
var localToWorldMatrix = Matrix4x4.Translate(translation) * rotationMatrix);
Vector3 scale;
scale.x = new Vector4(localToWorldMatrix.m00, localToWorldMatrix.m10, matrix.m20, localToWorldMatrix.m30).magnitude;
scale.y = new Vector4(localToWorldMatrix.m01, localToWorldMatrix.m11, matrix.m21, localToWorldMatrix.m31).magnitude;
scale.z = new Vector4(localToWorldMatrix.m02, localToWorldMatrix.m12, matrix.m22, localToWorldMatrix.m32).magnitude;
transform.localScale = scale;
Vector3 position;
position.x = localToWorldMatrix.m03;
position.y = localToWorldMatrix.m13;
position.z = localToWorldMatrix.m23;
transform.position = position;
Vector3 forward;
forward.x = localToWorldMatrix.m02;
forward.y = localToWorldMatrix.m12;
forward.z = localToWorldMatrix.m22;
Vector3 upwards;
upwards.x = localToWorldMatrix.m01;
upwards.y = localToWorldMatrix.m11;
upwards.z = localToWorldMatrix.m21;
transform.rotation = Quaternion.LookRotation(forward, upwards);
注意:
仅当此旋转和平移在当前使用的坐标系中定义您的第 5 个点在世界中的位置时,这才有用...
如果您的旋转和平移还有其他意义,您将需要做更多的工作。如果您能准确定义这种旋转和平移的含义,我们很乐意提供进一步的帮助。
如果我正确理解你的问题,你希望能够从 3x3 矩阵创建旋转四元数。
您可以将 3x3 旋转矩阵想象成三个长度为 1 且彼此成 90 度的向量。例如:
| forward.x forward.y forward.z |
| up.x up.y up.z |
| right.x right.y right.z |
一种非常可靠的转换方法是从矩阵中取出前向和向上向量,并将它们应用于 Unity 方法 https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html
这将创建一个与您的矩阵相对应的四元数。根据您的实际情况,您可能需要使用四元数的倒数,但本质上这就是您所需要的。
请注意,您只需要向前和向上,因为向右始终是这两者的叉积,不添加任何信息。还要注意你的矩阵是一个纯旋转矩阵(即没有缩放或倾斜),否则你可能会得到意想不到的结果。
我正在使用 ARCore 进行增强现实项目。每次启动应用程序时,ARCore 的坐标系都会发生变化,以初始位置为原点。我在另一个坐标系中有 5 个点,我可以使用 ARCore 增强图像在 Unity 世界 space 中找到其中的 4 个位置。当然,这些点在我的其他坐标系中具有不同的值。我必须使用它在其他坐标系中的位置在 Unity 世界 space 中找到第 5 个点的位置。
我遵循了这个tutorial to achieve this. But since Unity does not support 3x3 matrices i used Accord.NET 框架。使用教程和 Accord 矩阵,我可以计算一个 3x3 Rotation
矩阵和一个 Translation
向量。
但是,当我尝试使用 TestObject.transform.Translate(AccordtoUnity(Translation),Space.World)
将其应用到我的第 5 个点时,我遇到了麻烦。当最初的 4 个对象和参考对象处于同一方向时,我的翻译工作完美。但是,当我的参考对象旋转时,此翻译不起作用。这当然是有道理的,因为我只做了翻译。我的问题是如何对第 5 点应用旋转和平移。或者有没有办法将我的 3x3 旋转矩阵和转换转换为 Unity 4x4Matrix
,从那时起我就可以使用 Matrix4x4.MultiplyPoint3x4
。或者是否可以将我的 3x3 旋转矩阵转换为 Quaternion
让我使用 4x4Matrix.SetTRS
。我对这种转换有点困惑,因为 4x4Matrix
也包括缩放,但我没有进行任何缩放。
如果有人能给我一些提示或提供更好的方法来找到第 5 点,我会很高兴。谢谢!
编辑:
其实我是根据Daveloper的回答解决的。我像这样构建了一个 Unity 4x4 矩阵:
[ R00 R01 R02 T.x ]
[ R10 R11 R12 T.y ]
[ R20 R21 R22 T.z ]
[ 0 0 0 1 ]
我测试了在 Unity 中创建原始对象并使用上面的矩阵应用平移和旋转,如下所示:
TestObject.transform.position = TransformationMatrix.MultiplyPoint3x4(TestObject.transform.position);
TestObject.transform.rotation *= Quaternion.LookRotation(TransformationMatrix.GetColumn(2), TransformationMatrix.GetColumn(1));
要使用 3x3 旋转矩阵和平移向量来设置变换,请使用
// rotationMatrixCV = your 3x3 rotation matrix; translation = your translation vector
var rotationMatrix = new Matrix4x4();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
rotationMatrix[i, j] = rotationMatrixCV[i, j];
}
}
rotationMatrix[3, 3] = 1f;
var localToWorldMatrix = Matrix4x4.Translate(translation) * rotationMatrix);
Vector3 scale;
scale.x = new Vector4(localToWorldMatrix.m00, localToWorldMatrix.m10, matrix.m20, localToWorldMatrix.m30).magnitude;
scale.y = new Vector4(localToWorldMatrix.m01, localToWorldMatrix.m11, matrix.m21, localToWorldMatrix.m31).magnitude;
scale.z = new Vector4(localToWorldMatrix.m02, localToWorldMatrix.m12, matrix.m22, localToWorldMatrix.m32).magnitude;
transform.localScale = scale;
Vector3 position;
position.x = localToWorldMatrix.m03;
position.y = localToWorldMatrix.m13;
position.z = localToWorldMatrix.m23;
transform.position = position;
Vector3 forward;
forward.x = localToWorldMatrix.m02;
forward.y = localToWorldMatrix.m12;
forward.z = localToWorldMatrix.m22;
Vector3 upwards;
upwards.x = localToWorldMatrix.m01;
upwards.y = localToWorldMatrix.m11;
upwards.z = localToWorldMatrix.m21;
transform.rotation = Quaternion.LookRotation(forward, upwards);
注意:
仅当此旋转和平移在当前使用的坐标系中定义您的第 5 个点在世界中的位置时,这才有用...
如果您的旋转和平移还有其他意义,您将需要做更多的工作。如果您能准确定义这种旋转和平移的含义,我们很乐意提供进一步的帮助。
如果我正确理解你的问题,你希望能够从 3x3 矩阵创建旋转四元数。
您可以将 3x3 旋转矩阵想象成三个长度为 1 且彼此成 90 度的向量。例如:
| forward.x forward.y forward.z |
| up.x up.y up.z |
| right.x right.y right.z |
一种非常可靠的转换方法是从矩阵中取出前向和向上向量,并将它们应用于 Unity 方法 https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html
这将创建一个与您的矩阵相对应的四元数。根据您的实际情况,您可能需要使用四元数的倒数,但本质上这就是您所需要的。
请注意,您只需要向前和向上,因为向右始终是这两者的叉积,不添加任何信息。还要注意你的矩阵是一个纯旋转矩阵(即没有缩放或倾斜),否则你可能会得到意想不到的结果。