How to apply transformation using 3x3 rotation mat

2019-08-22 02:08发布

I am working on an Augmented Reality project using ARCore. Coordinate system of ARCore changes every time you launch the application making the initial position as origin. I have 5 points in another coordinate system and i can find 4 of these positions in Unity world space using ARCore Augmented Image. These points have different values in my other coordinate system of course. I have to find position of a 5th point in Unity world space using its position in other coordinate system.

I have followed this tutorial to achieve this. But since Unity does not support 3x3 matrices i used Accord.NET framework. Using the tutorial and Accord matrices i can calculate a 3x3 Rotation matrix and a Translation vector.

However, when i tried to apply this to my 5th point using TestObject.transform.Translate(AccordtoUnity(Translation),Space.World)i am having trouble. When the initial 4 objects and reference objects are at same orientation my translation works perfect. However, when my reference objects are rotated this translation does not work. This makes sense of course since i have only done a translation. My question is how can i apply rotation and translation to my 5th point. Or is there a way to convert my 3x3 rotation matrix and translation to Unity 4x4Matrix since then i can use Matrix4x4.MultiplyPoint3x4. Or is it possible to convert my 3x3 rotation matrix to a Quaternion which let me use4x4Matrix.SetTRS. I am a bit confused about this conversion because 4x4Matrix includes scaling as well but i am not doing any scaling.

I would be happy if someone can give me some hint or offer a better approach to find a way to find 5th point. Thanks!

EDIT:

I actually solved the problem based on Daveloper's answer. I constructed a Unity 4x4 matrix like this:

[ R00 R01 R02 T.x ]
[ R10 R11 R12 T.y ]
[ R20 R21 R22 T.z ]
[ 0    0   0   1  ]

I tested this creating primitive objects in Unity and apply translation and rotation using the matrix above like this:

 TestObject.transform.position  = TransformationMatrix.MultiplyPoint3x4(TestObject.transform.position);
 TestObject.transform.rotation *= Quaternion.LookRotation(TransformationMatrix.GetColumn(2), TransformationMatrix.GetColumn(1));

2条回答
倾城 Initia
2楼-- · 2019-08-22 02:36

If I understand your question correctly, you want to be able to create a rotation quaternion from a 3x3 matrix.

You can think of a 3x3 rotation matrix as three vectors of length 1 all at 90 degrees to each other. e.g.:

| forward.x    forward.y    forward.z |
| up.x         up.y         up.z      |
| right.x      right.y      right.z   |

A pretty reliable way to do the conversion is to take the forward and up vectors out of your matrix and applying them to the Unity method https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html

This will create a quaternion that corresponds to your matrix. Depending on your actual situation, you might need to use the inverse of the quaternion, but essentially this is what you need.

Note you only need the forward and up, because the right is always the cross product of those two and adds no information. Also take care that you matrix is a pure rotation matrix (i.e. no scaling or skewing), otherwise you might get unexpected results.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-08-22 02:40

to use a 3x3 rotation matrix and a translation vector to set a transform, use

// 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);

NOTICE:

This is only useful if this rotation and translation define your 5th point's location in the world in the coordinate system that is actively being used...

If your rotation and translation mean anything else, you'll have to do more. Glad to help further if you can define what this rotation and translation mean exactly.

查看更多
登录 后发表回答