OpenGL Camera

What is a Graphics Camera?

The concept of a camera in a Graphics application is simple. Just imagine that what you see is the view of the camera. So adjusting the camera lens or moving\rotating it should affect your view.

The gluLookAt function

In the base OpenGL library, there is no concept of a camera. However, it can be simulated by applying the inverse of the camera transformation on the objects\pixels in the scene. Instead of having to build the matrix and invert it ourselves, the GLU library provides the gluLookAt function, which would do the work for us. This function takes as a parameter the location (x, y, z) of the camera\eye, the location (x, y, z) of the point to look at, and the coordinates (x, y, z) of the Up vector (rotation of the camera around its origin). Note that this function should be called on the ModelView matrix before any transformation is applied on objects in the scene. Avoid calling this function on the Projection matrix (more details here).

Given the description above, after specifying the camera attributes with a call to gluLookAt then drawing the objects in the scene, one would expect to see the objects in the scene based on the view of the camera. This expectation is completely valid, however, there is one more variable that affects what we see: the viewing volume (similar to real-world camera focus), which is controlled by calls on the projection matrix. Try to imagine what you’ll see if you run the code below:

GLdouble eyeX = 0, eyeY = 0, eyeZ = 2;
GLdouble centerX = 0, centerY = 0, centerZ = 0;
GLdouble upX = 0, upY = 1, pZ = 0;

void display()
{
    //  Set up camera properties
    glMatrixMode (GL_MODELVIEW);
    gluLookAt (eyeX, eyeY, eyeZ,
               centerX, centerY, centerZ,
               upX, upY, upZ);

    //  Draw an Object at the origin
    drawObject ();
}

The answer to the question above is that you’ll see nothing! The reason is that eyeZ = 2, the viewing volume is glOrtho(-1, 1, -1, 1, -1, 1) by default, and the object is drawn at the origin. Here is a visual demonstration using Nate Robin’s interactive OpenGL tutorial (projection.exe).

If we change zFar (last parameter of glOrtho) of projection to 3 or if we change eyeZ of the camera to 0.5, then we’ll be able to see the object.

To summarize all of this, I am taking advantage of one of the slides of the Siggraph OpenGL tutorial.

What are we building?

If you’ve used one of those 3D modeling software out there (like 3ds Max, Maya, etc…), then you’ve certainly seen multiple orthogonal views (Front, Back, Top, Bottom, Left, Right) of your 3D drawing. Here is a screenshot from 3ds Max.

Using the OpenGL camera, I’m going to create an OpenGL app that has 6 sub-windows each displaying the same object, but from a different camera angle. The world coordinates will be glOrtho(-1, 1, -1, 1, -2, 2) and the views will be: Front, Back, Top, Bottom, Left, and Right. The parameters that are going to be passed to gluLookAt will vary based on the view:

The Program

Controls (Keyboard, Mouse)

Note that you can use the left mouse button to rotate the object, right mouse button to translate the object, and middle mouse button to scale it. Also, the ‘r’ key will reset the object transformations in the scene.

Code

REPL

C code leveraging freeglut, runs on Linux within a repl.it. This is the easiest way possible to run the code and experiment with it. The first time you run, it might take a little bit of time for Replit to install the GLUT libraries.

Windows

C code within a C++ Visual Studio project that should run on Windows.

You can find the full source code on my GitHub page. If you have any issues compiling or running the app, check out this blog post for details about compiling and running an OpenGL app that uses the GLUT library.

Comments

Leave a comment