Scenario
I have a scene which contains several cameras, which may be facing any direction. I have no control over the creation of scene or cameras, but I need to work out which direction the cameras are facing in order to align them correctly.
The code below is a sample based on simple numbers, and I think shows that I'm missing something fundamental.
I am currently extracting the forward vector from the camera matrix using
Vector3 forward = new Vector3(-worldToCamera.M13, -worldToCamera.M23, -worldToCamera.M33);
as specified at http://roy-t.nl/2010/03/04/getting-the-left-forward-and-back-vectors-from-a-view-matrix-directly.html
However, for any given rotated input, this always returns (0, 0, -1)
. My question is:
How do I get the forward direction in world space from the camera matrix?
Code
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));
}