Section 3.1. Coordinate Systems and Matrices


3.1. Coordinate Systems and Matrices

This section covers several important aspects of OpenGL transformations and matrix state.

This book assumes that you are familiar with linear algebra. If you need to refresh your knowledge on this subject, refer to Chapter 5, "Geometrical Transformations," of Computer Graphics: Principles and Practice or Chapter 1, "Mathematical Fundamentals of Computer Graphics," of 3D Computer Graphics. In addition to covering the application of linear algebra to 3D computer graphics, both books are excellent computer graphics texts.

Specifically, you should be familiar with the concept of homogeneous coordinates, which are composed of four values: x, y, z, and w. When your application specifies a 3D xyz vertex, OpenGL implicitly supplies a w value of 1.0 to create a homogeneous coordinate. Homogeneous coordinates allow graphics systems to implement translation, scale, and rotation as matrix transformations. Also, as part of the transformation pipeline discussed in this chapter, OpenGL uses the w value to effect perspective.

3.1.1. Handedness

Traditionally, graphics systems present a right-handed coordinate system to the application (Core 1979). In a right-handed coordinate system, viewed from the positive end of an axis, positive rotations around that axis proceed counterclockwise.

OpenGL doesn't restrict the application to a right- or left-handed coordinate system, yet many programmers find it easiest to think of OpenGL as exposing a right-handed coordinate system to the application. If your application specifies vertices in a right-handed coordinate system, you'll obtain good results by not using negative scales and by following the typical usage described in this chapter.

To operate in a left-handed system, applications can simply scale by a negative value using the model-view matrix. Applications commonly scale by negative values to create a mirror effect. A scene can be mirrored by rendering it twice with an intervening negative scale, for example. The resulting rendered image will show both a right- and a left-handed scene.

Programmers new to OpenGL should first master the OpenGL transformation pipeline using coordinates in a right-handed system.

3.1.2. Matrices

OpenGL transforms vertices using 4 x 4 matrices. Applications typically instantiate an OpenGL matrix in C/C++ as a 1D array of 16 floating-point values (either GLfloat or GLdouble). The following code declares an array variable m suitable for use as an OpenGL matrix:

 GLfloat m[16]; 


OpenGL® Programming Guide, OpenGL® Reference Manual, and The OpenGL Graphics System all follow standard mathematical notation convention and present OpenGL matrices as column major:

m[0]

m[4]

m[8]

m[12]

m[1]

m[5]

m[9]

m[13]

m[2]

m[6]

m[10]

m[14]

m[3]

m[7]

m[11]

m[15]


Correspondingly, OpenGL vectors are displayed as columns:

x

y

z

w


The OpenGL specification's use of column-major notation is the source of great confusion among some C/C++ programmers who are accustomed to working with row-major 2D arrays. Note that this is a notational convention only. If the convention were changed to transpose matrices and write vectors as rows, OpenGL's interface and internal operation would remain unchanged.[1]

[1] OpenGL version 1.3 allows applications to specify row-major matrices, which OpenGL internally transposes. See The OpenGL Graphics System for details.

Row- versus column-major ordering is not an issue if applications don't access matrix elements directly but instead restrict themselves to the suite of OpenGL and GLU routines for manipulating matrices. Applications commonly manipulate matrix elements directly, however, especially the view transformation matrix, as described in the section "Setting the Model-View Matrix" later in this chapter. In this case, applications should access the matrix as a 1D array of 16 elements to help prevent confusion between row- and column-major ordering.

An OpenGL matrix should be viewed as the basis for a new coordinate system. Multiplying a vector by a matrix transforms the vector into a new coordinate system defined by the matrix. A C/C++ matrix m with elements m[0] through m[15] defines a new coordinate system as follows:

  • The new x axis vector is [ m[0] m[1] m[2] ].

  • The new y axis vector is [ m[4] m[5] m[6] ].

  • The new z axis vector is [ m[8] m[9] m[10] ].

  • The new origin is [ m[12] m[13] m[14] ].

3.1.3. Matrix Stacks and Matrix State

OpenGL uses two matrices in geometry transformation and a texture matrix for each texture unit to transform texture coordinates.[2]

[2] OpenGL also uses a matrix for color transformation, which is not covered in this book. See Chapter 8, "Drawing Pixels, Bitmaps, Fonts, and Images," of OpenGL® Programming Guide for information on the color matrix.

OpenGL stores matrices in matrix stacks, one for each matrix mode and one for each texture unit. All OpenGL matrix operations described in this chapter affect the top of the active matrix stack. Select the active matrix stack by calling glMatrixMode().


void glMatrixMode( GLenum mode );


Selects the active matrix stack. Subsequent matrix commands affect the selected stack. mode is GL_MODELVIEW, GL_PROJECTION, or GL_TEXTURE to select the model-view, projection, or texture matrix stacks, respectively.

If mode is GL_TEXTURE, the selected stack depends on the current texture unit as set by the application with glActiveTexture(). See Chapter 6, "Texture Mapping," for further information.

Like the attribute stacks described in Chapter 1, applications can push the active matrix stack and make changes to it, and then pop it to return to the original matrix. Issue the commands glPushMatrix() and glPopMatrix() to push and pop the active matrix stack.

OpenGL initializes all matrix stacks to have the identity matrix as their single entry. Popping a matrix stack with only one entry generates the error GL_STACK_UNDERFLOW. Similarly, pushing a matrix stack that is already full generates the error GL_STACK_OVERFLOW. The size of each matrix stack is at least 2, except for the model-view stack, which must be at least 32.

The section "The Transformation Pipeline" later in this chapter describes how the top of the model-view and projection matrix stacks are used in OpenGL transformations. Chapter 6, "Texture Mapping," describes how the tops of the texture matrix stacks are used to transform texture coordinates.

3.1.4. Matrix Manipulation Commands

OpenGL provides a suite of commands that affect the top of the active matrix stack. Specify the active matrix stack by using glMatrixMode() as described previously; then issue matrix manipulation commands to modify the current top of that stack.


void glLoadIdentity( void );
void glLoadMatrix[fd]( const TYPEm );
void glMultMatrix[fd]( const TYPEm );
void glRotate[fd]( TYPE theta, TYPE x, TYPE y, TYPE z );
void glScale[fd]( TYPE x, TYPE y, TYPE z );
void glTranslate[fd]( TYPE x, TYPE y, TYPE z );


Use these commands to modify the top of the active matrix stack.

glLoadIdentity() replaces the top of the active matrix stack with the identity matrix.

glLoadMatrix*() replaces the top of the active matrix stack with m.

glMultMatrix*() postmultiplies m onto the top of the active matrix stack.

glRotate*() computes a matrix that effects a rotation of theta degrees around the axis specified by x, y, and z, and postmultiplies this matrix onto the top of the active matrix stack.

glScale*() creates a matrix that effects a scale in the x, y, and z axes, and postmultiplies this matrix onto the top of the active matrix stack.

glTranslate*() creates a matrix that effects a translation along the x, y, and z axes, and postmultiplies this matrix onto the top of the active matrix stack.

Many OpenGL implementations perform transformations using single precision regardless of the implied precision of the interface. Regardless, applications often specify double-precision matrices to maximize precision during concatenation.

Note that when using a command that multiplies a matrix onto the top of the active matrix stack, such as glMultMatrix*(), glRotate*(), glScale*(), or glTranslate*(), OpenGL uses postmultiplication to perform the matrix concatenation. The order in which applications issue matrix commands affects the resulting top of the active matrix stack. As an example, consider the following code:

 glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 2.f, 0.f, 0.f ); glRotatef( -120.f, 0.f, 1.f, 0.f ); 


The above code first selects the model-view matrix stack and sets the top of that stack to the identity matrix. Next, it post-multiplies two matrices: first, a translation along the positive x axis, and then a negative 120-degree rotation around the y axis. The resulting top of the model-view matrix stack positions geometry at a new origin (2.0, 0.0, 0.0 ) and then rotates it 120 degrees around the y axis at the new origin. In effect, the rotation occurs in the new coordinate system defined by the translation. The results are illustrated in Figure 3-1a.

Figure 3-1. The order of matrix operations affects geometry transformation. In both figures, a cylinder, defined at the origin, is transformed to a new position and orientation. In (a), it is translated first and then rotated. In (b), the rotation occurs first, followed by the translation.


The following code is identical to the above code, except that it reverses the order of the glTranslatef() and glRotatef() commands:

 glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glRotatef( -120.f, 0.f, 1.f, 0.f ); glTranslatef( 2.f, 0.f, 0.f ); 


The top of the model-view stack that results from this command sequence is quite different. OpenGL rotates subsequent geometry around the y axis at its origin, producing a new x and z axis, and then translates geometry along the new x axis. In effect, the translation occurs in the new coordinate system defined by the rotation. The results are illustrated in Figure 3-1b.

Many applications use postmultiplication to their advantage to position geometry relative to other geometry. See the Transformation example program (downloadable from this book's Web site) for an effective use of nested model transformations.




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