How does gluLookAt work?

From my point of view,

gluLookAt( eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, up_y, up_z ); 

is equivalent to:

 glRotatef(B, 0.0, 0.0, 1.0); glRotatef(A, wx, wy, wz); glTranslatef(-eye_x, -eye_y, -eye_z); 

But when I print out the ModelView matrix, the call to glTranslatef() does not work properly. Here is the code snippet:

 #include <stdlib.h> #include <stdio.h> #include <GL/glut.h> #include <iomanip> #include <iostream> #include <string> using namespace std; static const int Rx = 0; static const int Ry = 1; static const int Rz = 2; static const int Ux = 4; static const int Uy = 5; static const int Uz = 6; static const int Ax = 8; static const int Ay = 9; static const int Az = 10; static const int Tx = 12; static const int Ty = 13; static const int Tz = 14; void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat lmodel_ambient[] = { 0.8, 0.0, 0.0, 0.0 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); } void displayModelviewMatrix(float MV[16]) { int SPACING = 12; cout << left; cout << "\tMODELVIEW MATRIX\n"; cout << "--------------------------------------------------" << endl; cout << setw(SPACING) << "R" << setw(SPACING) << "U" << setw(SPACING) << "A" << setw(SPACING) << "T" << endl; cout << "--------------------------------------------------" << endl; cout << setw(SPACING) << MV[Rx] << setw(SPACING) << MV[Ux] << setw(SPACING) << MV[Ax] << setw(SPACING) << MV[Tx] << endl; cout << setw(SPACING) << MV[Ry] << setw(SPACING) << MV[Uy] << setw(SPACING) << MV[Ay] << setw(SPACING) << MV[Ty] << endl; cout << setw(SPACING) << MV[Rz] << setw(SPACING) << MV[Uz] << setw(SPACING) << MV[Az] << setw(SPACING) << MV[Tz] << endl; cout << setw(SPACING) << MV[3] << setw(SPACING) << MV[7] << setw(SPACING) << MV[11] << setw(SPACING) << MV[15] << endl; cout << "--------------------------------------------------" << endl; cout << endl; } void reshape(int w, int h) { float ratio = static_cast<float>(w)/h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, ratio, 1.0, 425.0); } void draw() { float m[16]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX, m); gluLookAt( 300.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); glColor3f(1.0, 0.0, 0.0); glutSolidCube(100.0); glGetFloatv(GL_MODELVIEW_MATRIX, m); displayModelviewMatrix(m); glutSwapBuffers(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(400, 400); glutInitWindowPosition(100, 100); glutCreateWindow("Demo"); glutReshapeFunc(reshape); glutDisplayFunc(draw); init(); glutMainLoop(); return 0; } 

No matter what value I use for the eye vector:
300, 0, 0 or
0, 300, 0 or
0, 0, 300
the translation vector is the same, which does not make any sense, because the order of the code is in reverse order, so glTranslatef should be started first, and then 2 turns. In addition, the rotation matrix is โ€‹โ€‹completely independent of the translation column (in the ModelView matrix), what can cause this strange behavior? Here is the result with the eye vector (0.0f, 300.0f, 0.0f)

  MODELVIEW MATRIX -------------------------------------------------- RUAT -------------------------------------------------- 0 0 0 0 0 0 0 0 0 1 0 -300 0 0 0 1 -------------------------------------------------- 

I would expect the column T be (0, -300, 0) ! So can someone help me explain this?

Implementation of gluLookAt from http://www.mesa3d.org

 void GLAPIENTRY gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz) { float forward[3], side[3], up[3]; GLfloat m[4][4]; forward[0] = centerx - eyex; forward[1] = centery - eyey; forward[2] = centerz - eyez; up[0] = upx; up[1] = upy; up[2] = upz; normalize(forward); /* Side = forward x up */ cross(forward, up, side); normalize(side); /* Recompute up as: up = side x forward */ cross(side, forward, up); __gluMakeIdentityf(&m[0][0]); m[0][0] = side[0]; m[1][0] = side[1]; m[2][0] = side[2]; m[0][1] = up[0]; m[1][1] = up[1]; m[2][1] = up[2]; m[0][2] = -forward[0]; m[1][2] = -forward[1]; m[2][2] = -forward[2]; glMultMatrixf(&m[0][0]); glTranslated(-eyex, -eyey, -eyez); } 
+6
source share
3 answers

If we give a rotation and translation matrix such as your model matrix

 Rxx Rxy Rxz Tx Ryx Ryy Ryz Ty Rzx Rzy Rzz Tz 0 0 0 1 

act on an arbitrary vector

 x y z 1 

we get

 Rxx x + Rxy y + Rxz z + Tx Ryx x + Ryy y + Ryz z + Ty Rzx x + Rzy y + Rzz z + Tz 1 

(I write things, so vectors are obtained multiplied by matrices on the left).

This shows that the translation components of the matrix give the translation that is applied after performing the rotation. This is why they do not match your (-eye_x, -eye_y, -eye_z) vector, because since you indicate that the translation is done before rotation.

The reason the translation is always in the -z direction is because, in the -z view, the direction is centered. Since you always have a center 300 units from your eyes, all of your eye positions put the center at (0, 0, -300) in the view frame. Therefore, since the center begins at the origin before we perform any translation, the translation, in order to give it the correct co-orindates, must be (0, 0, -300).

In addition, you may have noticed this, but the viewing matrix of the model you are showing is pathological because you have a vector up pointing along the viewing direction (from the eye to the center). This explains why it has two full lines of zeros.

+6
source

"I am very confused about how the rotations are performed using the forward, up and side vectors in this code ..." I think you should know something about the UVN camera. There is some theory about coordinates translatable between two coordinate systems. In the above example, two coordinates are world coordinates and camera coordinates. And the result: x enter image description here

N is the vector from the target to the camera. Also known as a โ€œlook atโ€ a vector in any three-dimensional literature. This vector corresponds to -Z ax.

V - When you are standing upright, this is a vector from head to sky. If you are writing a flight simulator and the plane is reverse, this vector can very well point to the ground. This vector corresponds to Y ax.

U - This vector points from the camera to its "right" side. It corresponds to X ax.

0
source

@ Endon M. Coleman - what does the above diagram look like? The presence of the main matrix in a row or column refers to the representation of the memory of two-dimensional structures in 1D memory and has nothing to do with the above 4x4 transformation matrix diagram.

If the vectors U, V, N were written in columns, as you seem to suggest, then you will have camera space to convert the space into the world.

However, the entrance to the matrix is โ€‹โ€‹a space around the world, and the output is a position in the camera space, so the matrix is โ€‹โ€‹the space of the world of transformation into camera space.

The reason U, V, N is transposed, because it is the inverse matrix that you propose, and using the property of orthogonal matrices, where their inverse is also its transpose. That is, we write the vectors U, V, N into rows to get the space-to-space to space-to-space conversion and U, V, N to columns to get the camera space into the space-time transformation.

In addition, the choice of multiplying by world position on the right is that the chart uses column vectors. We would leave it many times if we used row vectors. NOTHING has anything to do with how we store the matrix in memory, and everything has to do with how we multiply the two matrices together, that is, we convert the vector into a 1X4 or 4X1 matrix before we multiply it by a 4x4 matrix.

In short, the above diagram is in order, it is just a transformation from one space to another, please do not confuse the issue with the conversation about the memory layout, which is a programming detail.

0
source

All Articles