Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating a LookAt matrix

I'm in the midst of writing a 3d engine and I've come across the LookAt algorithm described in the DirectX documentation:

zaxis = normal(At - Eye) xaxis = normal(cross(Up, zaxis)) yaxis = cross(zaxis, xaxis)   xaxis.x           yaxis.x           zaxis.x          0  xaxis.y           yaxis.y           zaxis.y          0  xaxis.z           yaxis.z           zaxis.z          0 -dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1 

Now I get how it works on the rotation side, but what I don't quite get is why it puts the translation component of the matrix to be those dot products. Examining it a bit it seems that it's adjusting the camera position by a small amount based on a projection of the new basis vectors onto the position of the eye/camera.

The question is why does it need to do this? What does it accomplish?

like image 438
Daemin Avatar asked Dec 08 '08 10:12

Daemin


People also ask

What is a LookAt matrix?

The lookat matrix is a matrix that positions / rotates something to point to (look at) a point in space, from another point in space.

How do you find the view of a matrix?

If R represents the orientation of the camera, and T represents the translation of the camera in world space, then the camera's transform matrix M can be computed by multiplying the two matrices together.

What is GLM LookAt?

It provides the basis for your viewing vector space, in other words it defines all of the axes (X,Y,Z) of your coordinate system. You need three vectors in order to do this.


2 Answers

Note the example given is a left-handed, row major matrix.

So the operation is: Translate to the origin first (move by -eye), then rotate so that the vector from eye to At lines up with +z:

Basically you get the same result if you pre-multiply the rotation matrix by a translation -eye:

 [      1       0       0   0 ]   [ xaxis.x  yaxis.x  zaxis.x 0 ] [      0       1       0   0 ] * [ xaxis.y  yaxis.y  zaxis.y 0 ] [      0       0       1   0 ]   [ xaxis.z  yaxis.z  zaxis.z 0 ] [ -eye.x  -eye.y  -eye.z   1 ]   [       0        0        0 1 ]    [         xaxis.x          yaxis.x          zaxis.x  0 ] = [         xaxis.y          yaxis.y          zaxis.y  0 ]   [         xaxis.z          yaxis.z          zaxis.z  0 ]   [ dot(xaxis,-eye)  dot(yaxis,-eye)  dot(zaxis,-eye)  1 ] 

Additional notes:

Note that a viewing transformation is (intentionally) inverted: you multiply every vertex by this matrix to "move the world" so that the portion you want to see ends up in the canonical view volume.

Also note that the rotation matrix (call it R) component of the LookAt matrix is an inverted change of basis matrix where the rows of R are the new basis vectors in terms of the old basis vectors (hence the variable names xaxis.x, .. xaxis is the new x axis after the change of basis occurs). Because of the inversion, however, the rows and columns are transposed.

like image 193
bobobobo Avatar answered Sep 21 '22 10:09

bobobobo


I build a look-at matrix by creating a 3x3 rotation matrix as you have done here and then expanding it to a 4x4 with zeros and the single 1 in the bottom right corner. Then I build a 4x4 translation matrix using the negative eye point coordinates (no dot products), and multiply the two matrices together. My guess is that this multiplication yields the equivalent of the dot products in the bottom row of your example, but I would need to work it out on paper to make sure.

The 3D rotation transforms your axes. Therefore, you cannot use the eye point directly without also transforming it into this new coordinate system. That's what the matrix multiplications -- or in this case, the 3 dot-product values -- accomplish.

like image 30
Judge Maygarden Avatar answered Sep 20 '22 10:09

Judge Maygarden