如何使用3x3旋转矩阵和平移矢量应用变换?

时间:2018-11-23 12:53:33

标签: unity3d matrix transformation arcore accord.net

我正在使用ARCore进行增强现实项目。每次启动应用程序时,ARCore的坐标系都会更改,并将初始位置作为原点。我在另一个坐标系中有5个点,我可以使用ARCore增强图像在Unity世界空间中找到这些位置中的4个。当然,这些点在我的其他坐标系中具有不同的值。我必须使用其在其他坐标系中的位置来找到第5个点在Unity世界空间中的位置。

我已遵循此tutorial来实现这一目标。但是由于Unity不支持3x3矩阵,因此我使用了Accord.NET框架。使用教程和Accord矩阵,我可以计算3x3 Rotation矩阵和Translation向量。

但是,当我尝试使用TestObject.transform.Translate(AccordtoUnity(Translation),Space.World)将其应用于我的第五点时,我遇到了麻烦。当最初的4个对象和参考对象处于相同方向时,我的翻译效果很好。但是,当旋转参考对象时,此平移不起作用。这当然很有意义,因为我只做了翻译。我的问题是我该如何对第五点进行旋转和平移。还是有一种方法可以将我的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));

2 个答案:

答案 0 :(得分: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点在世界上的位置时,这才有用...

如果轮换和翻译还有其他意义,则您需要做更多的事情。如果您可以准确定义此旋转和平移的含义,我们将为您提供进一步的帮助。

答案 1 :(得分:1)

如果我正确理解您的问题,则希望能够从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

这将创建一个与您的矩阵相对应的四元数。根据您的实际情况,您可能需要使用四元数的倒数,但这实际上就是您所需要的。

请注意,您只需要前进和前进,因为正确的选择永远是这两者的叉积,并且不添加任何信息。另外请注意,矩阵是纯旋转矩阵(即没有缩放或倾斜),否则可能会得到意外的结果。