Skip to content

41. Viewing

Dated: 08-07-2025

Overview: the Camera Analogy

The viewing transformations must precede the modeling transformations in our code, but we can specify the projection and viewport transformations at any point before drawing occurs.

cs602_e_41_1.svg

Stages of Vertex Transformation

To specify the following transformations

  • viewing
  • modeling
  • projection

we construct \(4 \times 4\) matrix1 \(M\) such that

\[\vec v^\prime = M \vec v\]

Where \(\vec v\) are the coordinates of a vertex.

Modelview matrix1 is combination of viewing and modeling transformations.

We can manipulate the dimensions of the viewport to cause the final image to be enlarged, shrunk, or stretched.

A Simple Example: Drawing a Cube

The viewing transformation, gluLookAt(), positions and aims the camera towards where the cube is drawn.

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

void init(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    glLoadIdentity(); // clear the matrix

    // viewing transformation
    gluLookAt(
        0.0, 0.0, 5.0,   // eye position
        0.0, 0.0, 0.0,   // look-at point
        0.0, 1.0, 0.0    // up vector
    );

    glScalef(1.0, 2.0, 1.0); // modeling transformation
    glutWireCube(1.0);
    glFlush();
}

void reshape(int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
    glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

cs602_i_41_1.png

Transformed Cube

The Viewing Transformation

Recall that the viewing transformation is analogous to positioning and aiming a camera.

Setting the current matrix1 to \(I\) by calling glLoadIdentity() is important because most of the transformation commands multiply the current matrix1 by the specified matrix1 then set the result to be the current matrix.1

The gluLookAt() indicates where the camera is placed and if it is not defined, the camera is situated at the origin, points down the \(z^-\) axis. The up vector2 defines a unique orientation for the camera.

The Modeling Transformation

We use the modeling transformation to position and orient the model.

The Projection Transformation

Specifying the projection transformation is like choosing a lens for a camera. Two basic types of projections are provided for us by OpenGL.

  • Perspective projection specified by glFrustum()
  • Orthographic projection (used by architects to reflect the real measurements of the viewed object).

glMatrixMode() changes which matrix1 we are dealing with

  • GL_MODELVIEW matrix1
  • GL_PROJECTION matrix1

Thinking about Transformations

All viewing and modeling transformations are represented as \(4 \times 4\) matrices.1 Each successive call to glMultMatrix() or transformation command multiplies a new \(4 \times 4\) matrix1 \(M\) by current modelview matrix1 \(C\) to yield \(CM\). Finally, vertices \(v\) are multiplied by the current modelview matrix.1

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glMultMatrixf(N); // apply transformation N
glMultMatrixf(M); // apply transformation M
glMultMatrixf(L); // apply transformation L

glBegin(GL_POINTS);
glVertex3fv(v); // draw transformed vertex v
glEnd();

In this code, the modelview matrix1 successively contains

  • \(I\)
  • \(N\)
  • \(NM\)
  • \(NML\)

The transformed vertex \(v\) is \(NMLv\).

Moving a Local Coordinate System

A local coordinate system is tied relative to the object and the transformation matrices1 appear in their natural order in the code. Only problem with this approach is that a non uniform transformation (which changes the shape of the object) can cause the local coordinate system to be non perpendicular, hence making things confusing and tougher to deal with.
If there is no viewing transformation if camera should be left at its default position and there is no modeling transformation if the model isn't moved.

Modeling Transformations

OpenGL provides

  • glTranslate()
  • glRotate()
  • glScale()

Each matrix1 multiplication is described in terms of what it does to the vertices of a geometric object using the fixed coordinate system approach, and in terms of what it does to the local coordinate system that's attached to an object.

Translate

  • void glTranslatef(float x, float y, float z)
  • void glTranslated(double x, double y, double z)

Moves the local coordinate system by \((x, y, z)\).

Rotate

  • void glRotatef(float angle, float x, float y, float z)
  • void glRotated(float angle, double x, double y, double z)

Let \(O\) be the origin and \(\vec R = \langle x, y, z \rangle\) then these functions rotate the local coordinate system about \(\vec{OR}\) by angle amount in counter clockwise direction.

Scale

  • glScalef(float x, float y, float z)
  • glScaled(double x, double y, double z)

The \(x, y, z\) coordinates of each point of the object are multiplied by x, y and z.

Code Example

glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
draw_triangle(); /* solid lines */
glEnable(GL_LINE_STIPPLE); /* dashed lines */
glLineStipple(1, 0xF0F0);
glLoadIdentity();
glTranslatef(-20.0, 0.0, 0.0);
draw_triangle();
glLineStipple(1, 0xF00F); /*long dashed lines */
glLoadIdentity();
glScalef(1.5, 0.5, 1.0);
draw_triangle();
glLineStipple(1, 0x8888); /* dotted lines */
glLoadIdentity();
glRotatef (90.0, 0.0, 0.0, 1.0);
draw_triangle ();
glDisable (GL_LINE_STIPPLE);

Viewing Transformations

A viewing transformation changes the position and orientation of the viewpoint.

Keep in mind that the viewing transformation commands must be called before any modeling transformations are performed, so that the modeling transformations take effect on the objects first.

Emulating Viewing Transformations through Modeling Transformations

When we use modeling transformation commands to emulate viewing transformations, we're trying to move the viewpoint in a desired way while keeping the objects in the world stationary.
To put \(5\) units of distance between the viewpoint and the objects by moving the viewpoint, use glTranslatef(0.0, 0.0, -5.0); This routine moves the objects in the scene \(-5\) units along the \(z\) axis. This is also equivalent to moving the camera \(+5\) units along the \(z\) axis.

Comparisons

Imagine both camera and an object at the origin. We want to see the side of the object but how do we achieve it?

Fixed Coordinate System Approach

We could rotate the object first and then translate it but we know that in fixed coordinate system approach, the code has to have transformation matrices1 in the reverse order. Therefore, in the code, we have translate first, followed by rotation commands.

Local Coordinate System Approach

In this approach, the object may be translated first and then rotated using its local coordinate system. Also, the transformation matrices1 appear in the natural order in the code.

  1. glTranslatef(0.0, 0.0, -5.0);
  2. glRotatef(90.0, 0.0, 1.0, 0.0);

Using the gluLookAt() Utility Routine

Sometimes, we want to construct the scene around the origin and then orient the camera (viewpoint) to look at a certain position in the scene.

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

The camera is positioned at eye, it looks at center and the up vector2 defines which direction is up relative to the scene.

Manipulating the Matrix1 Stacks

ModelView matrix1 stacks \(32\) matrices1 meanwhile projection matrix1 stacks \(2\) matrices.1 These matrices1 are \(4 \times 4\) in dimension.

draw_wheel_and_bolts() {
    long i;
    draw_wheel();
    for(i = 0; i < 5; i++) {
        glPushMatrix();
        glRotatef(72.0 * i, 0.0, 0.0, 1.0);
        glTranslatef(3.0, 0.0, 0.0);
        draw_bolt();
        glPopMatrix();
    }
}

draw_body_and_wheel_and_bolts() {
    draw_car_body();
    glPushMatrix();
    glTranslatef(40,0,30); /*move to first wheel position*/
    draw_wheel_and_bolts();
    glPopMatrix();
    glPushMatrix();
    glTranslatef(40,0,-30); /*move to 2nd wheel position*/
    draw_wheel_and_bolts();
    glPopMatrix();
    ...
    /*draw last two wheels similarly*/
}

This code assumes the wheel and bolt axes are coincident with the \(z\) axis, that the bolts are evenly spaced every \(72\) degrees, \(3\) units (maybe inches) from the center of the wheel, and that the front wheels are \(40\) units in front of and \(30\) units to the right and left of the car's origin.

References