0

I have some problems understanding the specification for gluLookAt. For example the z-axis is defined as:

F = ( centerX - eyeX, centerY - eyeY, centerZ - eyeZ )

with center being the point the camera looks at and eye being the position the camera is at.

f = F / |F|

and the View-Matrix M is defined as:

( x[0]   x[1]   x[2]  0 )
( y[0]   y[1]   y[2]  0 )
(-f[0]  -f[1]  -f[2]  0 )
( 0        0      0   1 )

with x and y being the x,y-axis and f being the z-axis

If my camera is positioned at (0, 0, 5) and the camera looks at the center. Then f would look along the negative z-axis because of the first equation (center - eye) the f-vector would be: (0,0,0) - (0,0,5) = (0,0,-5)

So far everything makes sense to me, but then the f-vector is multiplied by -1 in the M-Matrix above. That way the f-vector looks along the positive z-axis and away from the center.

I found that the perspective matrix gluPerspective will also multiply the z-axis of the camrea with -1 which turns the z-axis again and makes it look toward the world's negative z-axis.

So what is the point of multiplying it with -1?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Joe
  • 1
  • 1

2 Answers2

1

Because gluLookAt is a View Matrix for a right-handed system. In this space, Z-coordinate increments as it goes out of screen, or behind the camera. So all objects that the camera can see have negative Z in view space.

EDIT

You should review your maths. The matrix you exposed lacks the translation to camera position.

Following this notation let's do:

Obtain f normalized, up normalized, s normalized, and u=sn x f. Notice that s must be normalized because f and up may be not be perpendicular and then their cross-product is not a vector of length=1. This is not mentioned in the link above.

Form the matrix and pre-multiply by the translation to camera position, L= M · T

The resulting lookAt matrix is:

 s.x   s.y   s.z  -dot(s, eye)
 u.x   u.y   u.z  -dot(u, eye)
-f.x  -f.y  -f.z  dot(f, eye)
  0     0     0      1

With your data: camera=(0,0,5), target=(0,0,0), and up=(0,1,0), the matrix is:

1  0  0  0
0 -1  0  0
0  0  1 -5
0  0  0  1

Let's apply this transformation a the point A=(0,0,4). We get A'=(0,0,-1).
Again for B=(0,0,20), B'=(0,0,15).
A' has a negative Z, so the camera sees it. B' has a positive value, the camera can not see it.

Jose Luis Blanco
  • 705
  • 6
  • 10
Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • That is obvious and was not my question. What you describe is already automatically achieved by switching to Camera-Coordinates. But that additional -1 multiplication is not necessary for that. – Joe Mar 23 '17 at 13:49
  • x,y,f in the matrix transformation are the axis in view space. If you don't use that "-1" then the transformation does not "move" the objects to be in front of the camera. – Ripi2 Mar 23 '17 at 15:59
  • Example: eye-position = (0,0,5), center = (0,0,0), up = (0,1,0) which leads to x = (1,0,0,0), y = (0,1,0,0), z = f =(0,0,-1,0) and w = (0,0,5,1). The point p = (0,0,1,1) is obviously between the camera and the center. So once you change p to camera-coordinates you get p' = (0,0,4,1). – Joe Mar 23 '17 at 17:13
  • If the near and far plane are well chosen this will lead to p being rendered. But still there is no need for the -1 multiplication. I left it out in this example and it worked anyway because the camera's z-axis is already negative. You are free to do the math too. I checked "Real-Time-Rendering 3rd Edition" by Möller-Haines-Hoffman and they just note that opengl does it that way but they do not explain why. – Joe Mar 23 '17 at 17:13
  • Thanks for trying to help me but I found the error in my understanding of the camera concept. I was under the impression that the camera looks along its own positive z-axis, which would be the world's negative z-axis. But since it's the other way around I will have to check about that in some tutorial. – Joe Mar 23 '17 at 19:09
0

I know this isn't a direct answer to the question but it might help someone who is looking for an equivalent function without using GLU, for example, if they are porting old OpenGL2 code to modern OpenGL.

Here is an equivalent function to gluLookAt(...):

void gluLookAt(float eyeX, float eyeY, float eyeZ,
               float centreX, float centreY, float centreZ,
               float upX, float upY, float upZ) {
    GLfloat mat[16];
    float forwardX = centreX - eyeX;
    float forwardY = centreY - eyeY;
    float forwardZ = centreZ - eyeZ;

    glm::vec3 forward = glm::normalize(glm::vec3(forwardX, forwardY, forwardZ));

    glm::vec3 right = glm::cross(glm::vec3(forwardX, forwardY, forwardZ),
                                 glm::vec3(upX, upY, upZ));
    right = glm::normalize(right);

    mat[0] = right.x;
    mat[1] = right.y;
    mat[2] = right.z;
    mat[3] = 0.0f;
    mat[4] = upX;
    mat[5] = upY;
    mat[6] = upZ;
    mat[7] = 0.0f;
    mat[8] =  -forward.x;
    mat[9] =  -forward.y;
    mat[10] =  -forward.z;
    mat[11] = 0.0f;
    mat[12] =  0.0f;
    mat[13] =  0.0f;
    mat[14] =  0.0f;
    mat[15] = 1.0f;

    glMultMatrixf(mat);
    glTranslatef (-eyeX, -eyeY, -eyeZ);
}
jackw11111
  • 1,457
  • 1
  • 17
  • 34