Sign in to follow this  
Emerican360

Math behind gluLookAt

Recommended Posts

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 :) Edited by Emerican360

Share this post


Link to post
Share on other sites
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. Edited by Bacterius

Share this post


Link to post
Share on other sites
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. Edited by Emerican360

Share this post


Link to post
Share on other sites
[quote name='Emerican360' timestamp='1335776974' post='4936019']
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.
[/quote]
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 [url="http://stackoverflow.com/questions/349050/calculating-a-lookat-matrix"]StackOverflow[/url]):

[img]http://i46.tinypic.com/1611h0l.png[/img]

(automatic trimming is teh suck) Edited by Bacterius

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this