从相机矩阵中提取前向矢量

时间:2017-08-15 14:09:05

标签: c# math matrix vector 3d

方案

我有一个包含几个摄像头的场景,可能面向任何方向。我无法控制场景或摄像机的创建,但我需要确定摄像机朝向哪个方向才能正确对齐它们。

以下代码是基于简单数字的示例,我认为表明我缺少一些基本的东西。

我目前正在使用

从相机矩阵中提取前向矢量

Vector3 forward = new Vector3(-worldToCamera.M13, -worldToCamera.M23, -worldToCamera.M33);

按照规定 http://roy-t.nl/2010/03/04/getting-the-left-forward-and-back-vectors-from-a-view-matrix-directly.html

但是,对于任何给定的旋转输入,它总是返回(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));    
    }

0 个答案:

没有答案