Skip to main content
GameDev.net gamedev.net
🔒 Locked

Math behind gluLookAt

Started by Emerican360 Apr 29, 2012 at 6:27 PM 3 replies 6.6k views
Original Post
Emerican360
Emerican360
Hello,

I'm studying CS and taking second year linear algebra, so i though a cool thing to do would be to learn computer graphics. I wrote my own 4x4 row-major matrix class and a 3D vector class. I understand how rotation, scaling and translation work.

Here's my problem:

[source]

// Calculate the orthogonal basis for the camera.
Math::Vector3Df forward = look - pos;
forward.normalise();

Math::Vector3Df right = forward.crossProduct(upVector);
right.normalise();

Math::Vector3Df up = right.crossProduct(forward);
up.normalise();

Math::Matrix4Df viewMatrix;
viewMatrix.m[0] = right.x;
viewMatrix.m[1] = right.y;
viewMatrix.m[2] = right.z;

viewMatrix.m[4] = up.x;
viewMatrix.m[5] = up.y;
viewMatrix.m[6] = up.z;

viewMatrix.m[8] = -forward.x;
viewMatrix.m[9] = -forward.y;
viewMatrix.m[10] = -forward.z;

viewMatrix.m[12] = 0.0f;
viewMatrix.m[13] = 0.0f;
viewMatrix.m[14] = 0.0f;

viewMatrix.m[3] = -right.dotProduct(pos);
viewMatrix.m[7] = -up.dotProduct(pos);
viewMatrix.m[11] = forward.dotProduct(pos);
viewMatrix.m[15] = 1.0f;

viewMatrix = translate(-pos.x, -pos.y, -pos.z) * viewMatrix;
[/source]

I understand what the first bit of the code does. Namely computing an orthogonal basis for the camera. I don't understand the second part.

So my question is:

Why are the entries of the matrix assigned the values they are assigned?

Edit: I was just reading up about orthogonal bases and discovered that an orthogonal basis made up of normalized vectors is called an orthonormal basis. So the first part of the algorithm computes an orthonormal basis for the camera! Cool
Bacterius
Bacterius
Well yes, the matrix is basically an orthogonal basis for the camera, using the camera's forward, up, and right direction (by convention). This is obtained by means of a couple cross products as you worked out. The last part basically translates the basis so that the pivot of rotation is located on the camera. If you think about it, the first part of the code basically computes a form of rotation matrix, and as such only uses the direction vector of the camera, which means that all cameras facing the same direction would have the same view matrix which is obviously not true, since the camera position needs to come into play at some point. If you look at the last line carefully, it means that if you were to multiply a vertex with the resulting matrix, it would be translated first so that it would be in reference to the camera at the origin, and then rotated (using the origin, which is then the camera's position) as pivot. This is why the translation vector is multiplied by the view matrix, and not the opposite.

EDIT: and as for the entries, you could look up tangent/bitangent/normal matrices which are essentially the same thing. The entries are arranged in the order shown because of how matrix multiplication is done, so that the vertex to be multiplied is dotted against each row, each row being a coordinate axis of the basis, which yields 4 numbers which then correspond to the X, Y, Z and W coordinates of the resulting vector respectively.

It's easier if you write down the matrix (taking care to get the row/column order right) and walk through the multiplication with some vertex manually.
“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”
Emerican360
Emerican360
Thanks for your response. Why add the dot products here tho?

[source]
viewMatrix.m[3] = -right.dotProduct(pos);
viewMatrix.m[7] = -up.dotProduct(pos);
viewMatrix.m[11] = forward.dotProduct(pos);
viewMatrix.m[15] = 1.0f;
[/source]

I feel like I'm missing something basic.
Bacterius
Bacterius

Thanks for your response. Why add the dot products here tho?

[source]
viewMatrix.m[3] = -right.dotProduct(pos);
viewMatrix.m[7] = -up.dotProduct(pos);
viewMatrix.m[11] = forward.dotProduct(pos);
viewMatrix.m[15] = 1.0f;
[/source]

I feel like I'm missing something basic.

Good question. Essentially, the dot products are there to perform the translation (it's basically a precomputed matrix multiplication, simplified since you are multiplying your basis which is an orthogonal rotation matrix with a translation matrix, which boils down to three dot products). In fact, in your first post you did the translation twice: the dot products handle the translation implicitly so the final step is redundant.

This explains it better (taken from StackOverflow):

1611h0l.png

(automatic trimming is teh suck)
“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”
Emerican360
Emerican360
Thank you! I finally get it! +1

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.