When using and ortho camera, ProjectionMatrix * viewMatrix skew objects on rotation, but viewMatrix * ProjectionMatrix fix the problem

232 views Asked by At

I'm implementing a 3D graphics app for fun.

To create an orthographic camera following the "theory", you need to have a view projection Matrix implemented in this way:

ViewProjectionMatrix = ProjectionMatrix * _viewMatrix;

But when doing this, objects get skewed when the camera is rotated on the Z axis (translation works well).

If I do this instead:

ViewProjectionMatrix = _viewMatrix * ProjectionMatrix

That fixes the problem (Rotation and Translation work well), going against the theory of how to implement this matrix, what I'm doing wrong?

**This is what I tried: ** My implementation uses OpenGL (via Silk.Net bindings), C# .NET 7, and System.Numerics for matrices and vectors.

I'm calculating the Orthographic camera (Projection Matrix) like this:

float aspectRatio = (float)_window.Width / (float)_window.Height;
float left = -aspectRatio;
float right = aspectRatio;
float bottom = -1f;
float top = 1f;
float nearPlane = -1f;
float farPlane = 1;
ProjectionMatrix = Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, nearPlane, farPlane);

Then, I'm calculating the view matrix as the inverse of the camera Model Matrix:

float radiansZ = _angleZ * MathF.PI / 180f;
Matrix4x4 cameraModelMatrix =
    Matrix4x4.CreateTranslation(_position) *
    Matrix4x4.CreateRotationZ(_angleZ);

    Matrix4x4.Invert(
        cameraModelMatrix, out _viewMatrix); // _viewMatrix is the inverse of cameraModelMatrix
    ViewProjectionMatrix = ProjectionMatrix * _viewMatrix; // here is my problem :(

These are pictures of the different outputs:

Using ViewProjectionMatrix = ProjectionMatrix * _viewMatrix (Theory Correct, Result Wrong) Image: Using ViewProjectionMatrix = ProjectionMatrix * _viewMatrix

Using ViewProjectionMatrix = _viewMatrix * ProjectionMatrix (Theory Wrong, Result Correct) Image: Using ViewProjectionMatrix = _viewMatrix * ProjectionMatrix

System.Numerics is Column-Major, so when passing the Matrix to the uniform, I use transponse = false.

*** Extra Tests ***

I did this just to check problems with multiplication:

Matrix4x4 A = new Matrix4x4(
    1, 2, 3, 4,
    5, 6, 7, 8,
    9, 10, 11, 12,
    13, 14, 15, 16
);

Matrix4x4 B = new Matrix4x4(
    17, 18, 19, 20,
    21, 22, 23, 24,
    25, 26, 27, 28,
    29, 30, 31, 32
);
Debug.Info("A: {0}",A);
Debug.Info("B: {0}", B);
Debug.Info("A * B: {0}", A * B);
Debug.Info("B * A: {0}", B * A);

This outputs the following:

A: { {M11:1 M12:2 M13:3 M14:4} {M21:5 M22:6 M23:7 M24:8} {M31:9 M32:10 M33:11 M34:12} {M41:13 M42:14 M43:15 M44:16} }

B: { {M11:17 M12:18 M13:19 M14:20} {M21:21 M22:22 M23:23 M24:24} {M31:25 M32:26 M33:27 M34:28} {M41:29 M42:30 M43:31 M44:32} }

A * B: { {M11:250 M12:260 M13:270 M14:280} {M21:618 M22:644 M23:670 M24:696} {M31:986 M32:1028 M33:1070 M34:1112} {M41:1354 M42:1412 M43:1470 M44:1528} }

B * A: { {M11:538 M12:612 M13:686 M14:760} {M21:650 M22:740 M23:830 M24:920} {M31:762 M32:868 M33:974 M34:1080} {M41:874 M42:996 M43:1118 M44:1240} }

This looks expected from a mathematical perspective.

0

There are 0 answers