Section 3.3. Setting the Model-View Matrix


3.3. Setting the Model-View Matrix

As the name model-view implies, the model-view matrix stores both model and view transformations. Because OpenGL performs no operations in world coordinates, the model-view matrix transforms directly from object coordinates to eye coordinates. Nearly all applications, however, use a world-coordinate-system paradigm and maintain separate model and view transformations. Typically, applications start each frame by loading a view transformation onto the top of the model-view matrix stack and then post-multiplying model transformations, as in the following example:

 glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); gluLookAt( ... ); glPushMatrix(); glTranslatef( ... ); // Specify vertices and vertex data glPopMatrix(); 


The glMatrixMode( GL_MODELVIEW ) command tells OpenGL that subsequent matrix commands operate on the model-view matrix stack. The glLoadIdentity() command clears the top of the matrix stack, and gluLookAt() creates a matrix that positions and orients the viewer, and multiplies it onto the top of the matrix stack. At this point in the code, the model-view matrix contains only the view transformation.

The glPushMatrix() command pushes the stack and places a copy of the view transformation on the new top of the stack. Next, the code postmultiplies a model transformation onto the top of the matrix stack with a call to glTranslatef(). At this point in the code, the model-view matrix contains both view and model transformations. OpenGL uses this matrix to transform subsequent vertices and vertex data into eye coordinates.

The final glPopMatrix() call effectively erases the model transformation, leaving only the view transformation in the model-view matrix. Applications typically wrap model transformations and their associated geometry with calls to glPushMatrix() and glPopMatrix() to facilitate changes in model transformation while retaining the same view transformation.

3.3.1. Creating the View Transformation with gluLookAt()

The Picking example code, referred to in the preceding section, uses a GLU routine to position the view.


void gluLookAt( GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,
  GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble
  upX, GLdouble upY, GLdouble upZ );


Creates a view transformation and postmultiplies it onto the top of the active matrix stack. When used as the view transformation in the model-view matrix, this function effectively places the viewer at ( eyeX, eyeY, eyeZ ) and orients the viewer to face the point ( centerX, centerY, centerZ ), with the up vector ( upX, upY, upZ ).

The results are undefined if the up vector coincides with a vector from the eye point to the center point.

The up direction depends on your application's world-coordinate system. Some applications use positive y for up; others use positive z. Regardless, you might need to change it from your world-coordinate default if your application emulates, for example, a first-person view from inside a rolling aircraft.

Because OpenGL doesn't provide a viewer-centric interface for creating a view transformation, gluLookAt() is very popular and used by several applications. It's suitable only in cases where your application stores both the eye and center locations, however.

In practice, many applications store the eye location and view direction, or they store the view center location, view direction, and distance back to the eye. In these cases, creating a view transformation in application code can be slightly more efficient than using gluLookAt().

3.3.2. Creating the View Transformation Matrix

The view transformation transforms vertices into eye coordinates and is the inverse of a transformation to place and orient the viewer in world coordinates. The view transformation has two components: a 4 x 4 orientation matrix, O, and a 4 x 4 translation matrix, T. The view transformation matrix, V, is the concatenation of the two 4 x 4 matrices:

V = OT


The orientation matrix O is an orthonormal basis derived from the view direction and up vectors. Given an [ x y z ] view direction d and an [ x y z ] up vector u, compute their cross product c as:

c = d x u


Discard u and compute the actual up vector u' as:

u' = c x d


Normalize d, c, and u' to unit length, and create the orientation matrix O as follows:


The translation matrix T is simply the inverse translation to the eye location. If you already have the eye location stored in your application, you can use it directly in a call to glTranslated(), as shown in the code below. If you don't have the eye location, scale the view direction vector by the distance to the eye, negate it, and add it to the center location. The result is the eye location.

So if an application creates a double-precision orientation matrix called orientMatrix using the steps above and has the eye location stored in a double-precision [ x y z ] array called eye, the code to create the view transformation is

 glMatrixMode( GL_MODELVIEW ); glLoadMatrixd( orientMatrix ); glTranslated( -eye[0], -eye[1], -eye[2] ); 


In fact, gluLookAt() does essentially the same thing internally. It computes the view direction by subtracting eye from center and then follows the above method to create the orientation matrix. For this reason, if your application already stores the center location, view direction, and view distance, gluLookAt() is slightly less efficient than creating the view transformation in your application code.

3.3.3. View Transformations in the Example Code

The example code manages views with a View base class declared in OGLDView.h and defined in OGLDView.cpp.

The View base class manages a view direction vector, up vector, center location, and distance from the center to the eye location. To set the view transformation, the examples call the View::loadMatrix() and View::multMatrix() methods. These member functions create the two component matrices O and T, and multiply them onto the top of the active matrix stack, as described in the section "Creating the View Transformation Matrix" earlier in this chapter.

To handle mouse interaction, the example code derives two classes from the View base class: AltAzView and TrackballView. These are declared in OGLDAltAzView.h and OGLDTrackballView.h, and defined in OGLDAltAzView.cpp and OGLDTrackballView.cpp. These classes provide two different viewing interfaces to the user. Both classes allow the user to view geometry from any viewing angle, but AltAzView preserves the initial up vector, whereas TRackballView allows arbitrary orientation. Both also let the user change the eye distance by pressing the Shift key while dragging the mouse.

All example view code uses math routines in OGLDMath.h and OGLDMath.cpp for dot products, normalization, cross products, and so on.

Depending on your application, you might provide an alt-az or trackball view interface, or a completely different view interface. Many simulation applications require a first-person view interface that lets the user move the view position forward and backward, as well as change the view direction.

See the Viewing example (refer to Figure 3-3) to try out both the AltAzView and trackballView interfaces.




OpenGL Distilled
OpenGL Distilled
ISBN: 0321336798
EAN: 2147483647
Year: 2007
Pages: 123
Authors: Paul Martz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net