方案
我有一个包含几个摄像头的场景,可能面向任何方向。我无法控制场景或摄像机的创建,但我需要确定摄像机朝向哪个方向才能正确对齐它们。
以下代码是基于简单数字的示例,我认为表明我缺少一些基本的东西。
我目前正在使用
从相机矩阵中提取前向矢量 Vector3 forward = new Vector3(-worldToCamera.M13, -worldToCamera.M23, -worldToCamera.M33);
但是,对于任何给定的旋转输入,它总是返回(0, 0, -1)
。我的问题是:
如何从相机矩阵中获取世界空间中的前向方向?
代码
using System;
using System.Numerics;
public class Program
{
private const double OneEightyOverPI = 180d / Math.PI;
private const double TwoPI = Math.PI * 2d;
private const double PIOverTwo = Math.PI / 2d;
private const double ThreePIOverTwo = 3d * Math.PI / 2d;
public static void Main()
{
Vector3 cameraPosition = new Vector3(5, 5, 5);
Matrix4x4 translate = Matrix4x4.CreateTranslation(-cameraPosition);
Matrix4x4 cameraMatrix = translate;
Test(cameraMatrix, cameraPosition, 0);
// Z-axis is vertical, so rotate around it to change the pan angle of the camera
cameraMatrix = Matrix4x4.CreateRotationZ((float)PIOverTwo) * translate;
Test(cameraMatrix, cameraPosition, 90);
cameraMatrix = Matrix4x4.CreateRotationZ((float)Math.PI) * translate;
Test(cameraMatrix, cameraPosition, 180);
cameraMatrix = Matrix4x4.CreateRotationZ((float)ThreePIOverTwo) * translate;
Test(cameraMatrix, cameraPosition, 270);
}
private static void Test(Matrix4x4 worldToCamera, Vector3 cameraPositionWorld, int expected) {
// http://roy-t.nl/2010/03/04/getting-the-left-forward-and-back-vectors-from-a-view-matrix-directly.html
Vector3 forward = new Vector3(-worldToCamera.M13, -worldToCamera.M23, -worldToCamera.M33);
// input always aligned such that:
Vector3 north = Vector3.UnitY;
double angle = Math.Atan2(north.Y, north.X) - Math.Atan2(forward.Y, forward.X);
if (angle < 0) {
angle += TwoPI;
}
int deg = (int)(angle * OneEightyOverPI);
Console.WriteLine("Expected: " + expected + ", actual: " + deg + ", diff: " + (expected - deg));
}