Chapter 5 Transformations of Objects
 


5.1  INTRODUCTION

Affine transformations are the fundamental cornerstone of computer graphics and are central to OpenGL as well as most other graphics systems.

As discussed in Chapter 4, we need to understand the difference between points and vectors.   We will do this using the coordinate frames and appropriate homogeneous coordinates.

5.2  INTRODUCTION TO TRANSFORMATIONS

One example of transformation we have seen earlier was the mapping of world coordinates to screen or viewport coordiantes.  In this section, we will develop the required tools to be able to translate, scale, and rotate both 2D and 3D objects using affine transformations.

In OpenGL, a sequence of points are sent to the OpenGL graphics pipeline.  These points are then subjected to the current transformation (CT) and the resulting image is displayed on the screen.

Object Transformations versus Coordinate Transformations

There are two ways to view a transformation; as an object transformation or as a coordinate transformation.

An object transformation alters the coordinates of each point on the object according to some rule, leaving the underlining coordinate system fixed.

A coordinate transformation defines a new coordinate system in terms of the old one and then represents all of the object's points in this new system.

We will first develop the central ideas in terms of object transformation and then relate them to coordinate transformations.

5.2.1 Transforming Points and Objects

Given a set of points that define an object, a transformation maps each to the points to a set of new points.  If P is the point to be mapped by transformation T, the resulting point Q is the image of P under the mapping T.


With affine transformations, a straight line is mapped to a straight line, etc.

Recall from Chapter 4, that a coordinate frame consists of a particular point O called the origin and some mutually perpendicular vectors ( called i and j in 2D and i, j, and k in 3D) that serve as the axes of the coordinate frame.

In 2D  points P and Q, have the representation

The point P then would be represented as .

Appyling T to P we get

or Q = T(P)

5.5.2 The Affine Transformations

Affine transformations have a simple form: The coordinates of Q are linear combinations of those of P. That is,

The affine can be represented as a matrix multiplication as


 

Vectors can be transformed as

5.2.3 Geometric Effects of Elementary 2D Affine Transformations

Translation
The translation part of the affine transformation arises from the third column of the matrix

Scaling

Scaling changes the size of a picture and involves two scale factors, Sx and Sy for x- and y-coordinates respectively.  The matrix multiplication for scaling by Sx and Sy is simply

.

Scaling in this fashion is more accurately called scaling about the origin, because each point P is moved S times farther from the origin in the x-direction and Sy  times farther from the origin in the y-direction.

If a scale factor is negative, then there is also a reflection about a coordinate axis.  The figure below shows the scaling (Sx , Sy  ) = (-1 , 2).

Pure reflections would be using -1 for one or both of the scale factors.

If the two scale factors are the same, the transformation is a uniform scaling, or a magnification about the origin.  If the scale factors are both negative and equal, then the image is  a reflection about both axis (about the origin).  If the scale factors are not the same, the scaling is called a differential scaling.

Rotation

To rotate an image counter clockwise about the origin, the matrix is


 

Derivation of Rotation Mapping


Shearing

Shearing can be in the x-direction, y-direction, or along an aribitrary line.  The determinant of a shear matrix is unity.

In the figure the shearing is in the x-direction.


 

A shear in the x-direction is given by

The matrix associated with this type of shear is

Here h can be either positive or negative.
 

Shearing is sometimes used to make italic letters out of regular letters. One can also have a shear in the y-direction  by using the equations

The matrix for this transformation is


 

5.2.4  The Inverse of an Affine Transformation

Most affine transformations of interest are nonsingular.   A matrix is nonsingular if its determinant is nonzero.

Of the affine transformations, M,  we have consider the  determinant of M is given by

This determinant is the result of the two zero values in the third row of M.

If point P is mapped to Q by M, we have Q = MP.  If a matrix is nonsingular then we can find an inverse mapping so that we can undo the mapping of P to Q by mapping Q to P.  In this case,
P = M-1Q.

The inverse of M is given by

The following matrices are inverses of the matrices above.

Scaling:


Rotation:

Shearing:

Scaling:


 
 
 

5.2.5 Composing Affine Transformations

Most of the time we will need to do several transformations to an object.  For example,  if we want to rotate an object about a specific point.  To do this, the object would have to be translated to the origin rotated about the origin and then translated back to its original position.

The process of applying several transformations in succession to to form one overall transformation is called composing or concatenating the transformations.   The composition of two affine transformations is an affine transformation.

Consider the two transformations of the figure.

The point P is mapped to the point Q by transformation T1 and the point Q is mapped to W by transformation T2 .  If  matrix M 1 represents transformation T1 and matrix M2 represents transformation T2 then the order of matrix operations on the point P is M2M 1P .

The transformation T can be represented by a single matrix M where
M = M2M 1.

5.2.7  Some Useful Properties of Affine Transformations

Affine Transformations Preserve Affine Combinations of Points
 

Affine Transformations Preserve Lines and Planes
 

Parallelism of Lines and Planes is Preserved
 

The Columns of the Matrix Reveal the Transformed Coordinate Frame

The columns of the transformation matrix reveal the coordinate frame.  The first two columns are vectors and the last column is a point.

The vector i is transformed to the vector m1, the vector j is transformed to the vector m2, and the origin O is transformed to point m3.










Note the axes of the new coordinate frame are not necessarily perpendicular, nor must they be of unit length.  The axes will be perpendicular if the transformation involves only rotation and uniform scalings.

Relative Ratios are Preserved

Given the points A and B and the point P which is a fraction t of the way between A and B.  The affine transformation T(P) is also lies the same fraction t of the way between T(A) and T(B).





Effect of Transformations on the Areas of Figures

Translation and rotation do no affect the area or volume of a figure, but scaling does.  In 2D and 3D scaling, the area and volume of  the figure is scaled by the absolute value of the determinant of the transformation matrix M.

Every Affine Transformation Is Composed of Elementary Operations
 
 

5.3  3D AFFINE TRANSFORMATIONS

The same ideas apply to 3D affine transformations as apply to 2D affine transformations.

Given an affine transformation T() with matrix representation M, we can tranform the point P to point Q as in the 2D case.

5.3.1 The Elementary 3D Transformations

Translation
For a pure translation, the matrix M has the simple form

Check that Q = MP is simply a shift in Q by the vector m = ( m14  , m24  , m34  )

Scaling

Scaling in 3D is a direct extension of the 2D case, with a matrix

As in the 2D case, scaling is about the origin.

Shearing

Three-dimensional shears appear in greater variety than do their two-dimensional counterparts.  The matrix for the simplest elementary shear is the identity matrix with one zero term replace by some value, as in


 

Rotation

Rotations in three dimensions are common in graphics.  We may want to rotate an object or a camera in order to obtain different views.

Elementary rotations about a coordinate axis

The simplest rotation is a rotation about one of the coordinate axes.  This type of rotation is called roll, x-axis is an x-roll, y-axis is a y-roll, and z-axis is a z-roll.

For a positive angles, the rotation is counterclockwise (CCW) and clockwise for negative angles.


The following three matrices represent transformations that rotate about ponts through and angle b  about a coordinate axis:
Here c stands for cos b and s for sin b.
1.  An x-roll

2.  A y-roll


 

3.  A z-roll
 


 

The following figure depicts the rotation of a barn object about the three axes.








5.3.2  Composing 3D Affine Transformation

Any  number of affine transformations can be combined to form a single tranformation.  If M  and M are affine transformations, applying M1 and then M2 to an object is the same as applying the transformation M = M2 M1 once.

Unlike 2D, the order in which rotations are done in 3D matters.  3D rotation matrices do not commute.

It is common to perform a rotation in 3D by composing three elementary rotations such as an x-roll, followed by a y-roll, and last a z-roll.   The matrix M might be
M = R z( b3 ) Ry (b2 ) Rx (b1 ).

In this context,  the angles  b1 , b , and b3 are often called Euler angles.  One form of Euler's theorem asserts that any 3D rotation can be obtained by three rolls about the x- , y-, and z-axes, so any rotation can be written as a particular product of five matrices for the appropriate choice of Euler angles.   (See equation 5.32).
 

Rotation about an Arbitrary Axis

Euler's Theorem:  Any rotation (or sequence of rotations) about a point is equivalent to a single rotation about some axis through the point.

The figure shows an axis represented by a vector u and an arbitrary point P that is to be rotated through angle b about u to produce point Q.

There are two different ways to solve this problem, a classic way and a constructive way.

The Classic Way is to compose the rotation into a sequence of known steps:
1. Perform two rotations so that u becomes aligned with the x-axis.
2. Do an x-roll through the angle b.
3. Undo the two alignment rotations to restore u to it original direction.

The transformation requires the multiplication of five matrices:

The Constructive Way derivation is covered in Case Study 5.5.

The final result is the matrix








Here c = cos b , s = sin b  , and u = (ux , uy  , uz  ).
 

OpenGL provides a function to create a rotation about an arbitrary axis:

glRotated(angle,ux,uy,uz);
 

5.3.4  Summary of Properties of 3D Affine Transformations

Given a 3D transformation T(.) with matrix M, the following hold:
 


5.4  CHANGING COORDINATES SYSTEMS

Instead of thinking of an affine transformation as producing a new point in a fixed coordinate system, we can think of it as producing a new coordinate system in which to represent points.

Consider this figure.






Suppose that T(.) transforms coordinate frame #1 into coordinate frame #2.  This means that

Suppose that M is the matrix of the transformation T(.).  P has point representation (c,d,1)T  in the new system #2.   It follows that the values of a and b in system #1 are found by  multiplying (c,d,1)T   by M:

Proof:



Theorem:
Suppose coordinate system #2 is formed from coordinate system #1 by the affine transformation M.  Suppose further that point P = (Px , Py , 1) are the coordinates of a point P expressed in system #2.  Then the coordinates of P expressed in system #1 are MP.

Succesive Changes in a Coordinate Plane

Consider forming a transformation by making two successive changes of the coordinate system.

System #1 is converted to system #2 by T1 (.) and system #2 is converted to system #3 by T2 (.).

If follows that P coordinates for system #1 can be found by working backward from system #3; that is,

The following summarizes the case of three successive transformations:

Transforming Points
To apply a sequence of transformations T1 (.), T2 (.), T3 (.) ( in that order) to a point P, form a matrix

M = M3 x M2 x M1 .

Then P is transformed to MP.  To compose each successive transformation Mi , you must premultiply by Mi .

Transforming the Coordinate System
To apply a sequence of transformations T1 (.), T2 (.), T3 (.) ( in that order) to the coordinate system, for the matrix

M = M1 x M2 x M3 .

Then a point P expressed in the transformed system has coordinates MP in the original system.  To compose each additional transformation Mi , you must post-multiply by Mi .

How OpenGL Operates

OpenGL is organized so as to postmultiply each new transformation matrix in order to combine it with the current transformation.  Because of this, it seems more natural to the modeler to think in terms of successively transforming the coordinate system involved, since the order in which these transformations are carried out is the same as the order in which OpenGL computes them.

5.5  USING AFFINE TRANSFORMATIONS IN A PROGRAM

In this section, we will apply the theory of affine transformations in a program to carry out the scaling, rotating, and translaton of graphical objects.  We will investigate how this is done using OpenGL.

Suppose we have house represented in 2D by a set of points.  See Figure.

The Hard Way

This house was contructed by moveTo and lineTo commands.  To rotate the house through an angle of -30 degrees and translate it to (32,25), a tranformation matrix, M, would be defined and we could build a function transform2D(), that transforms one point into another, such that
Q = transform2D(M,P);

This would be apply to each point of the house #1 and the resulting points would then be used in moveTo and lineTo commands to redraw the new house #2.   This is the hard way.

The Easy Way

The transformation is quietly applied to each vertex , just as the window-to-viewport mapping is quietly applied to each vertex as part of moveTo() and lineTo().

As part of the OpenGL pipeline,  a vertex V, it is passed through the Current Transformation, CT, and comes out as Q.  This point Q is then passed to the window-to-viewport transformation and becomes S in the viewport.

In OpenGL, this transformtion is done with each point automatically.  OpenGL maintains a so-called modelview matrix, and every vertex that is passed down the graphics pipeline is multiplied by this matrix. We need only set up the modelview matrix to embody the desired transformation.

OpenGL works entirely in 3D, so its modelview matrix produces 3D transformation.  To do 2D drawing we restrict the view to be in the xy-plane with z=0.  Rotating about the origin in 2D, is the same as rotating about the z-axis in 3D.  Scaling is done by letting the z scale factor to be 1.

The principal routines for altering the modelview matrix are glRotated(), glScaled(), and glTranslated().  These do not set the CT directly, instead each postmultiplies the CT (the modelview matrix) by a particular matrix, say, M, and puts the result back into the CT.  Each routine creates a matrix M required for the new transformation and performs the operation

CT = CT*M.

CT*M applied to a point is equivalent to first performing the tranfomation embodied in M, followed by performing the tranformation dictated by the previous value of CT.

The following are OpenGL routines for applying transformations in the 2D case:


To start, we need to initialize the CT to the identity matrix.  This is done by using
glLoadIdentity().

These function affect any of the modes, GL_MODELVIEW or GL_PROJECTION.

To inform OpenGL that we want to change the matrix associated with CT, we need to specify
glMatrixModel(GL_MODELVIEW).

To rotated and translate the house, we need only do a glRotated(-30,0,0,1) and glTranslated(32,25,0).  Then call the routine to draw the house.

To implement these functions in the Canvas class, we add new methods initCT(), scale2D(double sx, double sy), translate2D(double dx, double dy), and rotate2D(double angle);

5.5.1  Saving the CT for later Use

A previous transformation can be saved on the the stack of transformations.  To do this, the functions glPushMatrix() and glPopMatrix() are used.  The top matrix on the stack.  A glPushMatrix(),  pushes a copy of the CT on the stack.  So the top two matrices on the stack are identitical.  If an operation such as a translate2D is done, then it would be multiplied times the matrix on the top of the stack.  Consider the following figure.  Two more function pushCT() and popCT() are added to the Canvas class.
 


 
 

5.6 DRAWING 3D SCENES WITH OPENGL

In this section, we examine how 3D transformations are used in an OpenGL-based program.  The main emphasis is on transforming objects in order to orient and position them as desire in a 3D scene.

5.6.1  An Overview of the Viewing Process and the Graphics Pipeline

Consider the Figure.   All the 2D drawing we have done is a special case of 3D viewing, based on a simple "parallel projection."

The "eye" that is viewing the scene looks along the z-axis at the "window", a rectangle lying in the xy-plane.   The view volume of the camera is a rectangular parallelepiped, whose four sidewalls are determined by the border of the window and whose other two walls are determined by a near plane and a far plane.   Points lying inside the volume are projected onto the window along lines parallel to the z-axis.   This is equivalent to ignoring the z-coordinates of those points, so that the 3D point (x 1, y1, z 1) projects to  (x 1, y1).

A separate viewport tranformation maps the projected points from the window to the viewport on the display device.

OpenGL provides functions for defining the new view volume and its position in the scene.   Each vertex that passes through the graphics pipeline encounters three matrices:

The modelview matrix is one matrix, but we can think of it as two matrices, the modeling matrix M and the viewing matrix V.  The modelview matrix is what we have been calling CT.

The figure show the effect of the modelview matrix.

Part (a) shows a unit cube centered at the origin.   A modeling transform based upon M scales, rotates, and translates the cube into the block shown in Part (b), which also show the relative position of the camera's view volume.  The V matrix is now used to rotate and translate the block into a new position.  The specific transformation is that which would carry the camera from its positon in the scene to its "generic" position, with the eye at the origin and the view volume aligned with the z-axis, as shown in Part (c) of the figure.  The vertices of the block are now positioned so that projecting them onto the plane such the near plane yields the proper values for displaying the projected image.  So the matrix V in fact effects a change of coordiantes of the scene's vertices into the camera's coordinate system.

Camera coordinates are sometimes also called eye coordinates.  In the camer's coordiante system, the edges of the view volume are parallel to the x-, y-, and z-axis.   The view volume extends from left to right in x, from bottom to top in y, and from -near to -far in z.   When the vertices of the original cube have passed through the entire modelview matrix, they are located as show in Part (c).

The projection matrix scales and shifts each vertex in a particular way, so that all those vertices that lie inside the view volume will lie inside a standard cube that extends from -1 to 1 in each dimension.  The projection matrix effectively squashes the view volume in to the cube centered at the origin.  The projection matrix also reverses the sense of the z-axis, so that increasing values of z now represent increasing values of the depth of a point from the eye.

Clipping is now performed eliminating the parts of the block lies outside the standard cube.

The viewport matrix maps the surviving portion of the block into a "3D viewport."
The matrix maps the standard cube into a block shape whose x and y values extend across the viewport and whose z-components from 0 to 1 and retains a measure of the depth of point (the distance between the point and the eye of the camera).

5.6.2 Some OpenGL Toos for Modeling and Viewing
 

Three Functions Are Used to Set Modeling Transformations
 


Setting the Camera in OpenGL (for a Parallel Projection)

The function glOrtho(left, right, bott, top, near, far); establishes as a view volume a parallelipiped that extends from left to right in x, from bott to top in y, and from -near to -far in z.  Since this definition operates in eye coordinates the camer's eye is at the origin, looking down the negative z-axis.  The function creates a matrix and postmultiplies the current matrix by it.   The  negative values for near and far position the near and far planes down the z-axis in front of the eye looking down the negative z-axis.

The following code sets the projection matrix:

glMatrixMode(GL_PROJECTION);    //make the projection matrix the current
glLoadIdentity();                                   // set it to the identity matrix
glOrtho(left,right,bottom,top,near,far);  // multiply it by the new matrix
 

Positioning an Aiming the Camera

The function gluLookAt(.) creates the view matrix, V, and postmuliplies the current matrix by it.
The syntax is

gluLookAt(eye.x, eye.y, eye.z, look.x, look.y, look.z, up.x, up.y, up.z);

To use this function, we employ the following sequence:
glMatrixMode(GL_MODELVIEW);    //make the modelview matrix the current
glLoadIdentity();                                   // set it to the identity matrix
gluLookAt(eye.x, eye.y, eye.z, look.x, look.y, look.z, up.x, up.y, up.z);

In the Figure the vectors assoicated with the gluLookAt function are depicted.

The vector n = eye - look; u = up x n and v = n x u.  The function gluLookAt builds a matrix using these vectors normalized to unit length.

where the point d has components


 

5.6.3  Drawing Elementary Shapes Provided by OpenGL

The GLUT provides several ready-made objects in both wire-framed and solid view, all of which are centered at the origin:

The cube is one of the five Platonic solids, the other four are: Also there are


Both the cone and the tapered cyclinder have their base on the z=0 plane and extend to z = height.  The radius at base z= 0 is baseRad.  The radius of the tapered cylinder at z=height is topRad.
The tapered cylinder is actually a family of shapes, distinguished by the value of topRad.  When topRad is 1, there is no taper, and we have a classic right circular cylinder.  When topRad is 0, the tapered cylinder is identical to the cone.

To draw the tapered cylinder you must define a new qudric object, set the drawing style to GLU_LINE for a wire frame, GLU_FILL for a solid rendering.  The code is a follows:

GLUquadricObj * qobj = gluNewQuadric();        // make a quadric object
gluQuadricDrawStyle(qobj, GLU_LINE);            // set style to wireframe
gluCylinder(qobj, baseRad, topRad, height, nSlices, nStacks);    // draw the cylinder