Handout 3

Projection*


Introduction

Specifying the projection transformation is like choosing a lens for a camera. You can think of this transformation as determining the field of view and therefore which objects are inside it and, to some extent, how they should look. There are two basic types of projections provided for you by OpenGL, orthographic and perspective.

OpenGL Coordinate System

The default coordinate system in OpenGL(TM) is right-handed: the positive x and y axes point right and up, and the negative z axis points forward. Positive rotation is counterclockwise about the axis of rotation.

positive x rotation

positive y rotation

positive z rotation

This means that the positive x-axis and the positive y-axis are as normal, however the positive z-axis is pointing OUT OF the screen. To remember this take your right hand. Now with your palm facing upwards, point your fingers until they are in the direction of the positive x-axis (to the right). Now curl your fingers until they are in the direction of the positive y-axis (up). Your thumb is now pointing in the direction of the positive z-axis (out of).

Orthographic Projection

Orthographic projection maps objects directly onto the screen without affecting their relative sizes. This projection is used mainly in architectural and computer-aided design applications, where the actual measurements of the objects are more important than how they might look.

With an orthographic projection, the viewing volume is a rectangular parallelepiped, or more informally, a box. Unlike perspective projection, the size of the viewing volume doesn't change from one end to the other, so distance from the camera doesn't affect how large an object appears. This type of projection is used for applications such as creating architectural blueprints and computer-aided design, where it's crucial to maintain the actual sizes of objects and angles between them as they're projected.

void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);  // Assumes z within [�1.0,1.0] 

Perspective

We will use the perspective projection to get a more realistic rendering of an object. The object(s) will have the unmistakable characteristic of foreshortening: the further an object is from the camera, the smaller it appears in the final image. This is because the viewing volume of perspective projection is a frustum (a truncated pyramid whose top has been cut off by a plane parallel to its base). Objects that are closer to the apex of the pyramid appear smaller while objects closer to the base appear larger. The command to define this frustrum is glFrustum(), which takes the values for left, right, top, bottom, near and far edges. You could perform rotations or translations on this projection matrix to alter its orientation, by this is tricky and should be avoided.

The command to define a frustum, glFrustum(), calculates a matrix that accomplishes perspective projection and multiplies the current projection matrix (typically the identity matrix) by it. Recall that the viewing volume is used to clip objects that lie outside of it; the four sides of the frustum, its top, and its base correspond to the six clipping planes of the viewing volume, as shown below. Objects or parts of objects outside these planes are clipped from the final image. Note that glFrustum() doesn't require you to define a symmetric viewing volume.

void glFrustum( GLdouble left, GLdouble right,  GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);
Easier to use than glFrustum, but limited to symmetric, (not off axis)

Examples

Example 1 - Wireframe box using glFrustum

Example 2 - Wireframe box using glOrtho


Details

The command glFrustum() is used to set the projection transformation. The command glMatrixMode() is used, with the argument GL_PROJECTION is used to set up the matrix upon which this projection transformation (and subsequent transformations) is performed. Note that we use the glLoadIdentity() command to initialize the current projection matrix so that only the specified projection transformation(s) have an effect. Finally, we call the command glOrtho() to create an orthographic parallel viewing volume. The viewing volume is a box with the left, right, top, bottom, near and far edges specified in the glOrtho() command.

   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   glOrtho (-2.0, 2.0, -2.0, 2.0, 1.5, 20.0);
   glMatrixMode (GL_MODELVIEW);

The same set of commands to set the projection glMatrixMode(GL_PROJECTION) and glLoadIndentity() should be used to set up the projection transformation, but instead of using the glOrtho() command the glFrustum() command is given.

When it is time to perform transformations on the models that we have created, we will use the same glMatrixMode() command with GL_MODELVIEW as the argument. This indicates that the succeeding transformations now affect the modelview matrix instead of the projection matrix.

glOrtho() and glFrustum() End Notes

Although it's easy to understand conceptually, glFrustum() isn't intuitive to use. Instead, you might try the Utility Library routine gluPerspective(). This routine creates a viewing volume of the same shape as glFrustum() does, but you specify it in a different way. Rather than specifying corners of the near clipping plane, you specify the angle of the field of view in the x-z plane and the aspect ratio of the width to height (x/y). (For a square portion of the screen, the aspect ratio is 1.0.)
These two parameters are enough to determine an untruncated pyramid along the line of sight. You also specify the distance between the viewpoint and the near and far clipping planes, thereby truncating the pyramid. Note that gluPerspective() is limited to creating frustums that are symmetric in both the x- and y-axes along the line of sight, but this is usually what you want.

gluLookAt

gluLookAt creates a viewing matrix derived from an eye point, a reference point indicating the center of the scene, and an up vector. The matrix maps the reference point to the negative z axis and the eye point to the origin, so that, when a typical projection matrix is used, the center of the scene maps to the center of the viewport. Similarly, the direction described by the up vector projected onto the viewing plane is mapped to the positive y axis so that it points upward in the viewport. The up vector must not be parallel to the line of sight from the eye to the reference point.

The matrix generated by gluLookAt postmultiplies the current matrix.

void gluLookAt(GLdouble eyex,    GLdouble eyey,    GLdouble eyez, 
               GLdouble centerx, GLdouble centery, GLdouble centerz, 
               GLdouble upx,     GLdouble upy,     GLdouble upz)

eyex, eyey, eyez - Specifies the position of the eye point.
centerx, centery, centerz - Specifies the position of the reference point.
upx, upy, upz - Specifies the direction of the up vector.

In the default position, the camera is at the origin, is looking down the negative z-axis, and has the positive y-axis straight up. This is the same as:

gluLookAt (0.0, 0.0, 0.0, 	0.0, 0.0, -100.0, 0.0, 1.0, 0.0);

The centerz value is -100 but could be any negative value because the line of sight would be the same.

 

 

gluLookAt (0.0, 0.0, 5.0, 
			0.0, 0.0, 0.0, 
			0.0, 1.0, 0.0);
gluLookAt (0.0, 0.0, 5.0, 
			0.0, 0.0, 0.0, 
			1.0, 0.0, 0.0); 
gluLookAt (0.0, 0.0, 5.0, 
			0.0, 0.0, 0.0, 
			1.0, 1.0, 0.0); 


* portions from here, here, here.