2011-01-07

What matrix gluLookAt generates? (1)

gluLookAt function

I use OpenGL API to draw a 3D scene. This API is often used in games. If you only use OpenGL world, you usually don't need to know what kind of matrices are created underneath the API. However, if you want to overlay the OpenGL scene, for instance, if you write a own renderer and still want to render the scene with OpenGL and own, it is sometimes useful to know what kind of matrices are computed in the OpenGL API.

Therefore, this blog entry is quite specific. If you are not interested in such story, see you next time.

I would like to talk about a matrix that is computed by gluLookAt function.

gluLookAt puts a camera with a position and camera posture, e.g., which is up direction. Recently, I need to know how to generate this matrix by my own, however, I could not find a good page with a good explanation. At the end, I looked into the source code of Mesa 7.5.1 (Mesa-7.5.1/src/glu/sgi/libutil/project.c), OpenGL software implementation.

The code is quite readable and has useful comments. Here is the Mesa 7.5.1's gluLookAt() source code.


/*
 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
 */
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);
}


By the way, I am always confused by OpenGL coordinate system and matrix contents. You can even find the folloing in the OpenGL official we pages. http://www.opengl.org/resources/faq/technical/transformations.htm

Column-major notation suggests that matrices are not laid out in memory as a programmer would expect.
It explicitly said you will be probably confused.

I usually first think them with the standard math notation and then interpret to the implementation. Here I would like to use the same strategy. If you would like to implement this with C/C++, then you need to think about the memory layout of your matrices.

Figure 1 shows camera coordinates (up) and the bottom figure shows the camera coordinate has no relationship with the global/world coordinates.

We can assume a camera is a rigid body object, therefore, you can move and rotate the camera. You might be able to extend, shrink, or crash a camera, but, we don't think about such operation on a OpenGL camera.

Figure 1: Camera coordinates. Camera coordinates and other coordinates

Before going to create a matrix, I would like to say one more, about model and view duality. This is:

  • If the scene is static (doesn't move), but your camera goes to forward 1m.
  • If your camera doesn't move, but whole other scene moved 1m backword from the camera.

The camera see exactly the same scene in these two cases. You might experienced when you are at a station on a train, waiting for the departure, sometimes you mistook you are now moving or the other side train is moving. This is an example of the camera movement or the scene movement (the other side train moved). This object movement (model) and camera movement (view) are conbined to the matrix called model-view matrix in OpenGL.

This story is about camera position and posture matrix, therefore it should be 'view matrix,' however, OpenGL says this matrix is model-view matrix since model view duality. In a implementation it is called modelview matrix, though I only talk about a view matrix.

Next time, I would like to talk about the matrices generated by gluLookAt.

1 comment:

Mukund said...

Excellent article! Thanks a lot! It would be great if you could please provide a link to this:

http://www.opengl.org/resources/faq/technical/viewing.htm

That article highlights the fact that there is no "camera" as such, in OpenGL. However, it does go on to tell that a camera concept can be implemented.