• 11
• 9
• 10
• 9
• 11

# How Do You Test/check If Lookat Matrix Is Correct?

This topic is 624 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I wrote a code snippet made to generate a Camera LookAt matrix, depending if the user wants a left-handed matrix, or a right-handed matrix.

void Mtx_LookAt(C3D_Mtx* out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded)
{
//Left-handed and Right-handed Look-At matrix functions are DirectX implementations.
//Left-handed: https://msdn.microsoft.com/en-us/library/windows/desktop/bb281710
//Right-handed: https://msdn.microsoft.com/en-us/library/windows/desktop/bb281711
C3D_FVec xaxis, yaxis, zaxis;

//Order of operations is crucial.
zaxis = FVec3_Normalize(FVec3_Subtract(cameraPosition, cameraTarget));
xaxis = FVec3_Normalize(FVec3_Cross(cameraUpVector, zaxis));
yaxis = FVec3_Cross(zaxis, xaxis);

out->r[0].x = xaxis.x;
out->r[0].y = yaxis.x;
out->r[0].z = zaxis.x;
out->r[0].w = 0.0f;

if (isLeftHanded)
{
//In LH matrix, the Y is in Row 2 of 4 and the Z is in Row 3 of 4.
out->r[1].x = xaxis.y;
out->r[1].y = yaxis.y;
out->r[1].z = zaxis.y;
out->r[1].w = 0.0f;

out->r[2].x = xaxis.z;
out->r[2].y = yaxis.z;
out->r[2].z = zaxis.z;
out->r[2].w = 0.0f;
}
else
{
//In RH matrix, the Z is in Row 2 of 4, and the Y is in Row 3 of 4.
out->r[1].x = xaxis.z;
out->r[1].y = yaxis.z;
out->r[1].z = zaxis.z;
out->r[1].w = 0.0f;

out->r[2].x = xaxis.y;
out->r[2].y = yaxis.y;
out->r[2].z = zaxis.y;
out->r[2].w = 0.0f;
}

out->r[3].x = -FVec3_Dot(xaxis, cameraPosition);
out->r[3].y = -FVec3_Dot(yaxis, cameraPosition);
out->r[3].z = -FVec3_Dot(zaxis, cameraPosition);
out->r[3].w = 1.0f;
}



Where:

C3D_Mtx is a row-major matrix, C3D_FVec is a Vector4 struct. FVec3_(...) are Vector3 math operations with left and right operands respectively.

I got this matrix generated, but I have no idea how to test or check to see if the matrix is correct.

I'm hoping for a mathematical method to check it. For example, I can check an inverse matrix, by multiplying it with the original matrix to see if the result is an identity matrix.

What methods can I use to check this? Thanks!

##### Share on other sites

If you invert the matrix, you'll get three rows with each of the three basis axes of the camera (xaxis, yaxis, zaxis as labeled in your code) and the cameraPosition in the fourth row.

##### Share on other sites
A quick check you can do is make sure the determinant of the matrix is nonzero.

##### Share on other sites

A quick check you can do is make sure the determinant of the matrix is nonzero.

Checked. The determinant of my look at matrix is non-zero. I guess this is working?

If you invert the matrix, you'll get three rows with each of the three basis axes of the camera (xaxis, yaxis, zaxis as labeled in your code) and the cameraPosition in the fourth row.

In the three basis axes, does having a -1.0f diagonally means this look at matrix is normal? I can see the cameraPosition correctly matching with the original cameraPosition vector after inverting the look at matrix. But I'm wondering about the diagonal -1.0f.

EDIT:

I was told by someone else saying just by checking the determinant for non-zero values is not an indication that the look at matrix is correct. Since det(M) == det(transpose(M)).

In fact, they said I also need to be aware of left-handed matrix and right-handed matrix, which I may have implemented it incorrectly, despite the documentations.

There is a way to check it, but I have no knowledge of the algorithms behind it. They said to check the RH look at matrix to the OpenGL Mathematics library, or GLM, and see if both of the matrices are equal. Not sure about left-handed matrix though.

I feel there is more to this, than just simply checking the determinant and the camera position vector.

Edited by tom_mai78101

##### Share on other sites

The determinant of the rotational part of the matrix (3x3) must be exactly 1 (or approximately 1 due to floating point drifts).

##### Share on other sites

The determinant of the rotational part of the matrix (3x3) must be exactly 1 (or approximately 1 due to floating point drifts).

What is the rotational part referring to in the Look At matrix?

EDIT: Also, the Look At matrix is 4x4, so I'm very confused as to what the 3x3 part of the matrix is which portion of the 4x4 matrix.

Edited by tom_mai78101

##### Share on other sites

Toss out the last row and column vectors from the original matrix and create a 3x3 matrix from the remaining numbers.

##### Share on other sites

I'd make a few test cases, where you can predict the outcome, and use that as unit tests.

Eg looking straight from one of the axes to (0, 0, 0), doing the same but add +1 to Z to camera position and look at coordinate (not sure if doing that for each axis is useful).

Other options are to compare two setups where the second is a simple change from the first.

##### Share on other sites

I'd make a few test cases, where you can predict the outcome, and use that as unit tests.

Eg looking straight from one of the axes to (0, 0, 0), doing the same but add +1 to Z to camera position and look at coordinate (not sure if doing that for each axis is useful).

Other options are to compare two setups where the second is a simple change from the first.

I already tried that. I have compared the camera position to the inverse of the look at matrix, and those values match up nicely.

However, when applied to a test game, the perspective of the world is completely awkward, as if the world was slanted so bad, it flips itself over in a fish-lens space.

I'm not fully buying this method to test if it works. And I don't know any test cases where the results are obvious for a look at matrix. I'll still ask around.

##### Share on other sites

Update:

I made a mistake when it comes to creating a look at matrix. I had assumed the matrix structure I am using is row-major left to right, column-aligned top to bottom. Apparently, the correct matrix structure I should be using is row-major left to right, reverse column aligned bottom to top.

In other words, when accessing all 16 values in a 4x4 matrix, from the first index to the last, You would get:

 0     1     2     3
4     5     6     7
8     9    10    11
12    13    14    15


I should be reversing the columns around:

 3     2     1     0
7     6     5     4
11    10     9     8
15    14    13    12


I have this thought where I can verify it via rotations and translations (and not relying on camera position vector), and match them up if they are correct. Going to try that out.

Edited by tom_mai78101