在Unity中,我们知道在inspector中修改Positon以及Rotation就可以更改相机的位置以及旋转信息,我们知道Rotation都是用Quaternion四元组进行表示的,在Unity中有个一个函数Matrix4x4.TRS可以根据Postion、Quaternion、Scale求得视图转换矩阵。
那这个TRS是怎样实现的呢?
查了很多资料,基本的实现的代码如下。我这里都是用数组来表示的,返回的是行优先,而Unity的Matrix4x4 ToString方法打印的是列优先,你可以把我返回的数组做一下转置。你可以比较一下是否一致。还要注意一点,Unity是左手坐标系。OpenGL是右手坐标系,求得的view matrix需要做一下左手换右手。这个需要注意一下。
public static void convertToViewMatrix(float[] postion, float[] orientation, float[] viewMatrix, int offset) {
float twoXSquared = 2 * orientation[0] * orientation[0];
float twoYSquared = 2 * orientation[1] * orientation[1];
float twoZSquared = 2 * orientation[2] * orientation[2];
float twoXY = 2 * orientation[0] * orientation[1];
float twoWZ = 2 * orientation[3] * orientation[2];
float twoXZ = 2 * orientation[0] * orientation[2];
float twoWY = 2 * orientation[3] * orientation[1];
float twoYZ = 2 * orientation[1] * orientation[2];
float twoWX = 2 * orientation[3] * orientation[0];
viewMatrix[offset + 0] = 1 - twoYSquared - twoZSquared;
viewMatrix[offset + 4] = twoXY + twoWZ;
viewMatrix[offset + 8] = twoXZ - twoWY;
viewMatrix[offset + 1] = twoXY - twoWZ;
viewMatrix[offset + 5] = 1 - twoXSquared - twoZSquared;
viewMatrix[offset + 9] = twoYZ + twoWX;
viewMatrix[offset + 2] = twoXZ + twoWY;
viewMatrix[offset + 6] = twoYZ - twoWX;
viewMatrix[offset + 10] = 1 - twoXSquared - twoYSquared;
Vector3 front = new Vector3(viewMatrix[0], viewMatrix[4], viewMatrix[8]);
normalize(front);
Vector3 up = new Vector3(viewMatrix[1], viewMatrix[5], viewMatrix[9]);
normalize(up);
Vector3 right = new Vector3(viewMatrix[2], viewMatrix[6], viewMatrix[10]);
normalize(right);
Vector3 postionVec = new Vector3(postion[0], postion[1], postion[2]);
viewMatrix[offset + 12] = -(float) Vector3.Vector3Dot(front, postionVec);
viewMatrix[offset + 13] = -(float) Vector3.Vector3Dot(up, postionVec);
viewMatrix[offset + 14] = -(float) Vector3.Vector3Dot(right, postionVec);
viewMatrix[offset + 4 - 1] = 0.0F;
viewMatrix[offset + 8 - 1] = 0.0F;
viewMatrix[offset + 12 - 1] = 0.0F;
viewMatrix[offset + 16 - 1] = 1.0F;
}