0% found this document useful (0 votes)
28 views63 pages

@vtucode - in 21CS63 Module 2 Textbook 2021 Scheme

Uploaded by

mrharshitha793
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views63 pages

@vtucode - in 21CS63 Module 2 Textbook 2021 Scheme

Uploaded by

mrharshitha793
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

MODULE-2

Two-Dimensional Geometric
Transformations

1 Basic Two-Dimensional Geometric


Transformations
2 Matrix Representations and
Homogeneous Coordinates
3 Inverse Transformations
4 Two-Dimensional Composite
Transformations
5 Other Two-Dimensional
Transformations
6 Raster Methods for Geometric
Transformations
7 OpenGL Raster Transformations
8 Transformations between
Two-Dimensional Coordinate
Systems
9 OpenGL Functions for
Two-Dimensional Geometric
Transformations

S
10 OpenGL Geometric-Transformation
o far, we have seen how we can describe a scene in
Programming Examples
11 Summary terms of graphics primitives, such as line segments and fill
areas, and the attributes associated with these primitives.
Also, we have explored the scan-line algorithms for displaying output
primitives on a raster device. Now, we take a look at transformation
operations that we can apply to objects to reposition or resize them.
These operations are also used in the viewing routines that convert a
world-coordinate scene description to a display for an output device.
In addition, they are used in a variety of other applications, such as
computer-aided design (CAD) and computer animation. An architect,
for example, creates a layout by arranging the orientation and size of
the component parts of a design, and a computer animator develops
a video sequence by moving the “camera” position or the objects
in a scene along specified paths. Operations that are applied to the
geometric description of an object to change its position, orientation,
or size are called geometric transformations.
Sometimes geometric transformations are also referred to as
modeling transformations, but some graphics packages make a

From Chapter 7 of Computer Graphics with OpenGL®, Fourth Edition, Donald Hearn, M. Pauline Baker, Warren R. Carithers.
Copyright © 2011 by Pearson Education, Inc. Published by Pearson Prentice Hall. All rights reserved.
189
Two-Dimensional Geometric Transformations

distinction between the two. In general, modeling transformations are used to con-
struct a scene or to give the hierarchical description of a complex object that is com-
posed of several parts, which in turn could be composed of simpler parts, and so
forth. For example, an aircraft consists of wings, tail, fuselage, engine, and other com-
ponents, each of which can be specified in terms of second-level components, and
so on, down the hierarchy of component parts. Thus, the aircraft can be described
in terms of these components and an associated “modeling” transformation for each
one that describes how that component is to be fitted into the overall aircraft design.
Geometric transformations, on the other hand, can be used to describe how objects
might move around in a scene during an animation sequence or simply to view them
from another angle. Therefore, some graphics packages provide two sets of transforma-
tion routines, while other packages have a single set of functions that can be used for
both geometric transformations and modeling transformations.

1 Basic Two-Dimensional Geometric


Transformations
The geometric-transformation functions that are available in all graphics pack-
ages are those for translation, rotation, and scaling. Other useful transformation
routines that are sometimes included in a package are reflection and shearing
operations. To introduce the general concepts associated with geometric trans-
formations, we first consider operations in two dimensions. Once we under-
stand the basic concepts, we can easily write routines to perform geometric trans-
formations on objects in a two-dimensional scene.

Two-Dimensional Translation
y We perform a translation on a single coordinate point by adding offsets to its
coordinates so as to generate a new coordinate position. In effect, we are moving
the original point position along a straight-line path to its new location. Simi-
larly, a translation is applied to an object that is defined with multiple coordinate
P positions, such as a quadrilateral, by relocating all the coordinate positions by the
same displacement along parallel paths. Then the complete object is displayed at
T
the new location.
To translate a two-dimensional position, we add translation distances tx and
P
ty to the original coordinates (x, y) to obtain the new coordinate position (x  , y )
x as shown in Figure 1.
FIGURE 1
x  = x + tx , y = y + ty (1)
Translating a point from position P to The translation distance pair (tx , ty ) is called a translation vector or shift vector.
position P using a translation
vector T. We can express Equations 1 as a single matrix equation by using the follow-
ing column vectors to represent coordinate positions and the translation vector:
     
x x tx
P= , P = , T = (2)
y y ty

This allows us to write the two-dimensional translation equations in the matrix


form
P = P + T (3)

190
Two-Dimensional Geometric Transformations

y
10

0 5 10 15 20 x
(a)

y
10

FIGURE 2
0 5 10 15 20 x Moving a polygon from position (a) to position (b) with the
(b) translation vector (−5.50, 3.75).

Translation is a rigid-body transformation that moves objects without defor-


mation. That is, every point on the object is translated by the same amount.
A straight-line segment is translated by applying Equation 3 to each of the
two line endpoints and redrawing the line between the new endpoint positions.
A polygon is translated similarly. We add a translation vector to the coordinate
position of each vertex and then regenerate the polygon using the new set of
vertex coordinates. Figure 2 illustrates the application of a specified translation
vector to move an object from one position to another.
The following routine illustrates the translation operations. An input transla-
tion vector is used to move the n vertices of a polygon from one world-coordinate
position to another, and OpenGL routines are used to regenerate the translated
polygon.

class wcPt2D {
public:
GLfloat x, y;
};

void translatePolygon (wcPt2D * verts, GLint nVerts, GLfloat tx, GLfloat ty)
{
GLint k;

for (k = 0; k < nVerts; k++) {


verts [k].x = verts [k].x + tx;
verts [k].y = verts [k].y + ty;
}
glBegin (GL_POLYGON);
for (k = 0; k < nVerts; k++)
glVertex2f (verts [k].x, verts [k].y);
glEnd ( );
}

If we want to delete the original polygon, we could display it in the back-


ground color before translating it. Other methods for deleting picture components

191
Two-Dimensional Geometric Transformations

are available in some graphics packages. Also, if we want to save the original poly-
gon position, we can store the translated positions in a different array.
Similar methods are used to translate other objects. To change the position of
a circle or ellipse, we translate the center coordinates and redraw the figure in the
new location. For a spline curve, we translate the points that define the curve path
and then reconstruct the curve sections between the new coordinate positions.

Two-Dimensional Rotation
We generate a rotation transformation of an object by specifying a rotation axis
and a rotation angle. All points of the object are then transformed to new positions
u by rotating the points through the specified angle about the rotation axis.
yr A two-dimensional rotation of an object is obtained by repositioning the object
along a circular path in the xy plane. In this case, we are rotating the object about
a rotation axis that is perpendicular to the xy plane (parallel to the coordinate
xr z axis). Parameters for the two-dimensional rotation are the rotation angle θ and
a position (xr , yr ), called the rotation point (or pivot point), about which the
FIGURE 3
object is to be rotated (Figure 3). The pivot point is the intersection position
Rotation of an object through angle θ
about the pivot point (x r , y r ). of the rotation axis with the xy plane. A positive value for the angle θ defines a
counterclockwise rotation about the pivot point, as in Figure 3, and a negative
value rotates objects in the clockwise direction.
To simplify the explanation of the basic method, we first determine the trans-
formation equations for rotation of a point position P when the pivot point is
at the coordinate origin. The angular and coordinate relationships of the origi-
nal and transformed point positions are shown in Figure 4. In this figure, r is
the constant distance of the point from the origin, angle φ is the original angu-
(x, y) lar position of the point from the horizontal, and θ is the rotation angle. Using
standard trigonometric identities, we can express the transformed coordinates in
r terms of angles θ and φ as
u
r (x, y) x  = r cos(φ + θ) = r cos φ cos θ − r sin φ sin θ
(4)
f
y = r sin(φ + θ) = r cos φ sin θ + r sin φ cos θ
The original coordinates of the point in polar coordinates are
FIGURE 4 x = r cos φ, y = r sin φ (5)
Rotation of a point from position (x , y )
to position (x  , y  ) through an angle θ Substituting expressions 5 into 4, we obtain the transformation equations for
relative to the coordinate origin. The rotating a point at position (x, y) through an angle θ about the origin:
original angular displacement of the
point from the x axis is φ. x  = x cos θ − y sin θ
(6)
y = x sin θ + y cos θ
With the column-vector representations 2 for coordinate positions, we can write
the rotation equations in the matrix form
P = R · P (7)

where the rotation matrix is


 
cos θ − sin θ
R= (8)
sin θ cos θ
A column-vector representation for a coordinate position P, as in Equa-
tions 2, is standard mathematical notation. However, early graphics systems
sometimes used a row-vector representation for point positions. This changes the
order in which the matrix multiplication for a rotation would be performed. But
now, graphics packages such as OpenGL, Java, PHIGS, and GKS all follow the
standard column-vector convention.

192
Two-Dimensional Geometric Transformations

Rotation of a point about an arbitrary pivot position is illustrated in


Figure 5. Using the trigonometric relationships indicated by the two right trian-
gles in this figure, we can generalize Equations 6 to obtain the transformation
equations for rotation of a point about any specified rotation position (xr , yr ): (x, y)
x  = xr + (x − xr ) cos θ − (y − yr ) sin θ
(9)
y = yr + (x − xr ) sin θ + (y − yr ) cos θ r
r (x, y)
u
These general rotation equations differ from Equations 6 by the inclusion of (xr , yr ) f
additive terms, as well as the multiplicative factors on the coordinate values.
The matrix expression 7 could be modified to include pivot coordinates by
including the matrix addition of a column vector whose elements contain the
FIGURE 5
additive (translational) terms in Equations 9. There are better ways, however, to
Rotating a point from position (x , y )
formulate such matrix equations, and in Section 2, we discuss a more consistent to position (x  , y  ) through an angle θ
scheme for representing the transformation equations. about rotation point (x r , y r ).
As with translations, rotations are rigid-body transformations that move
objects without deformation. Every point on an object is rotated through the same
angle. A straight-line segment is rotated by applying Equations 9 to each of the
two line endpoints and redrawing the line between the new endpoint positions.
A polygon is rotated by displacing each vertex using the specified rotation angle
and then regenerating the polygon using the new vertices. We rotate a curve by
repositioning the defining points for the curve and then redrawing it. A circle or
an ellipse, for instance, can be rotated about a noncentral pivot point by moving
the center position through the arc that subtends the specified rotation angle. In
addition, we could rotate an ellipse about its center coordinates simply by rotating
the major and minor axes.
In the following code example, a polygon is rotated about a specified world-
coordinate pivot point. Parameters input to the rotation procedure are the original
vertices of the polygon, the pivot-point coordinates, and the rotation angle theta
specified in radians. Following the transformation of the vertex positions, the
polygon is regenerated using OpenGL routines.

class wcPt2D {
public:
GLfloat x, y;
};

void rotatePolygon (wcPt2D * verts, GLint nVerts, wcPt2D pivPt,


GLdouble theta)
{
wcPt2D * vertsRot;
GLint k;

for (k = 0; k < nVerts; k++) {


vertsRot [k].x = pivPt.x + (verts [k].x - pivPt.x) * cos (theta)
- (verts [k].y - pivPt.y) * sin (theta);
vertsRot [k].y = pivPt.y + (verts [k].x - pivPt.x) * sin (theta)
+ (verts [k].y - pivPt.y) * cos (theta);
}
glBegin {GL_POLYGON};
for (k = 0; k < nVerts; k++)
glVertex2f (vertsRot [k].x, vertsRot [k].y);
glEnd ( );
}

193
Two-Dimensional Geometric Transformations

Two-Dimensional Scaling
To alter the size of an object, we apply a scaling transformation. A simple two-
dimensional scaling operation is performed by multiplying object positions (x, y)
by scaling factors sx and s y to produce the transformed coordinates (x  , y ):

x  = x · sx , y = y · s y (10)

Scaling factor sx scales an object in the x direction, while s y scales in the y direc-
tion. The basic two-dimensional scaling equations 10 can also be written in the
following matrix form:
     
x sx 0 x
= · (11)
y 0 sy y
(a)
or

P = S · P (12)

where S is the 2 × 2 scaling matrix in Equation 11.


(b) Any positive values can be assigned to the scaling factors sx and s y . Values
FIGURE 6 less than 1 reduce the size of objects; values greater than 1 produce enlargements.
Turning a square (a) into a rectangle Specifying a value of 1 for both sx and s y leaves the size of objects unchanged.
(b) with scaling factors s x = 2 and When sx and s y are assigned the same value, a uniform scaling is produced,
s y = 1.
which maintains relative object proportions. Unequal values for sx and s y result
in a differential scaling that is often used in design applications, where pictures
are constructed from a few basic shapes that can be adjusted by scaling and
positioning transformations (Figure 6). In some systems, negative values can
also be specified for the scaling parameters. This not only resizes an object, it
reflects it about one or more of the coordinate axes.
Objects transformed with Equation 11 are both scaled and repositioned.
Scaling factors with absolute values less than 1 move objects closer to the
coordinate origin, while absolute values greater than 1 move coordinate posi-
x x tions farther from the origin. Figure 7 illustrates scaling of a line by assigning
FIGURE 7 the value 0.5 to both sx and s y in Equation 11. Both the line length and the
A line scaled with Equation 12 using distance from the origin are reduced by a factor of 12 .
s x = s y = 0.5 is reduced in size and We can control the location of a scaled object by choosing a position, called the
moved closer to the coordinate origin. fixed point, that is to remain unchanged after the scaling transformation. Coor-
dinates for the fixed point, (x f , y f ), are often chosen at some object position, such
as its centroid (see Appendix A), but any other spatial position can be selected.
Objects are now resized by scaling the distances between object points and the
y
fixed point (Figure 8). For a coordinate position (x, y), the scaled coordinates
(x  , y ) are then calculated from the following relationships:
P1
x  − x f = (x − x f )sx , y − y f = (y − y f )s y (13)
P2
(xf , yf) We can rewrite Equations 13 to separate the multiplicative and additive
terms as
P3
x  = x · sx + x f (1 − sx )
(14)
x y = y · s y + y f (1 − s y )
FIGURE 8
where the additive terms x f (1 − sx ) and y f (1 − s y ) are constants for all points in
Scaling relative to a chosen fixed point
(x f , y f ). The distance from each the object.
polygon vertex to the fixed point is Including coordinates for a fixed point in the scaling equations is similar to
scaled by Equations 13. including coordinates for a pivot point in the rotation equations. We can set up

194
Two-Dimensional Geometric Transformations

a column vector whose elements are the constant terms in Equations 14, then
add this column vector to the product S · P in Equation 12. In the next section,
we discuss a matrix formulation for the transformation equations that involves
only matrix multiplication.
Polygons are scaled by applying transformations 14 to each vertex, then
regenerating the polygon using the transformed vertices. For other objects,
we apply the scaling transformation equations to the parameters defining the
objects. To change the size of a circle, we can scale its radius and calculate the
new coordinate positions around the circumference. And to change the size of an
ellipse, we apply scaling parameters to its two axes and then plot the new ellipse
positions about its center coordinates.
The following procedure illustrates an application of the scaling calculations
for a polygon. Coordinates for the polygon vertices and for the fixed point are
input parameters, along with the scaling factors. After the coordinate transforma-
tions, OpenGL routines are used to generate the scaled polygon.

class wcPt2D {
public:
GLfloat x, y;
};

void scalePolygon (wcPt2D * verts, GLint nVerts, wcPt2D fixedPt,


GLfloat sx, GLfloat sy)
{
wcPt2D vertsNew;
GLint k;

for (k = 0; k < nVerts; k++) {


vertsNew [k].x = verts [k].x * sx + fixedPt.x * (1 - sx);
vertsNew [k].y = verts [k].y * sy + fixedPt.y * (1 - sy);
}
glBegin {GL_POLYGON};
for (k = 0; k < nVerts; k++)
glVertex2f (vertsNew [k].x, vertsNew [k].y);
glEnd ( );
}

2 Matrix Representations and


Homogeneous Coordinates
Many graphics applications involve sequences of geometric transformations. An
animation might require an object to be translated and rotated at each increment
of the motion. In design and picture construction applications, we perform trans-
lations, rotations, and scalings to fit the picture components into their proper
positions. The viewing transformations involve sequences of translations and
rotations to take us from the original scene specification to the display on an out-
put device. Here, we consider how the matrix representations discussed in the
previous sections can be reformulated so that such transformation sequences can
be processed efficiently.

195
Two-Dimensional Geometric Transformations

We have seen in Section 1 that each of the three basic two-dimensional


transformations (translation, rotation, and scaling) can be expressed in the general
matrix form
P  = M1 · P + M 2 (15)

with coordinate positions P and P represented as column vectors. Matrix M1 is


a 2 × 2 array containing multiplicative factors, and M2 is a two-element column
matrix containing translational terms. For translation, M1 is the identity matrix.
For rotation or scaling, M2 contains the translational terms associated with the
pivot point or scaling fixed point. To produce a sequence of transformations with
these equations, such as scaling followed by rotation and then translation, we
could calculate the transformed coordinates one step at a time. First, coordinate
positions are scaled, then these scaled coordinates are rotated, and finally, the
rotated coordinates are translated. A more efficient approach, however, is to com-
bine the transformations so that the final coordinate positions are obtained directly
from the initial coordinates, without calculating intermediate coordinate values.
We can do this by reformulating Equation 15 to eliminate the matrix addition
operation.

Homogeneous Coordinates
Multiplicative and translational terms for a two-dimensional geometric transfor-
mation can be combined into a single matrix if we expand the representations
to 3 × 3 matrices. Then we can use the third column of a transformation matrix
for the translation terms, and all transformation equations can be expressed as
matrix multiplications. But to do so, we also need to expand the matrix repre-
sentation for a two-dimensional coordinate position to a three-element column
matrix. A standard technique for accomplishing this is to expand each two-
dimensional coordinate-position representation (x, y) to a three-element repre-
sentation (xh , yh , h), called homogeneous coordinates, where the homogeneous
parameter h is a nonzero value such that
xh yh
x= , y= (16)
h h
Therefore, a general two-dimensional homogeneous coordinate representation
could also be written as (h·x, h·y, h). For geometric transformations, we can choose
the homogeneous parameter h to be any nonzero value. Thus, each coordinate
point (x, y) has an infinite number of equivalent homogeneous representations.
A convenient choice is simply to set h = 1. Each two-dimensional position is then
represented with homogeneous coordinates (x, y, 1). Other values for parameter
h are needed, for example, in matrix formulations of three-dimensional viewing
transformations.
The term homogeneous coordinates is used in mathematics to refer to the effect
of this representation on Cartesian equations. When a Cartesian point (x, y) is
converted to a homogeneous representation (xh , yh , h), equations containing x and
y, such as f (x, y) = 0, become homogeneous equations in the three parameters
xh , yh , and h. This just means that if each of the three parameters is replaced by
any value v times that parameter, the value v can be factored out of the equations.
Expressing positions in homogeneous coordinates allows us to represent all
geometric transformation equations as matrix multiplications, which is the stan-
dard method used in graphics systems. Two-dimensional coordinate positions
are represented with three-element column vectors, and two-dimensional trans-
formation operations are expressed as 3 × 3 matrices.

196
Two-Dimensional Geometric Transformations

Two-Dimensional Translation Matrix


Using a homogeneous-coordinate approach, we can represent the equations for a
two-dimensional translation of a coordinate position using the following matrix
multiplication:
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x 1 0 tx x
⎣ y ⎦ = ⎣ 0 1 ty ⎦ · ⎣ y ⎦ (17)
1 0 0 1 1
This translation operation can be written in the abbreviated form
P = T(tx , ty ) · P (18)
with T(tx , ty ) as the 3 × 3 translation matrix in Equation 17. In situations where
there is no ambiguity about the translation parameters, we can simply represent
the translation matrix as T.

Two-Dimensional Rotation Matrix


Similarly, two-dimensional rotation transformation equations about the coordi-
nate origin can be expressed in the matrix form
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x cos θ −sinθ 0 x
⎣ y ⎦ = ⎣ sin θ cos θ 0 ⎦ · ⎣ y ⎦ (19)
1 0 0 1 1
or as
P = R(θ ) · P (20)

The rotation transformation operator R(θ ) is the 3 × 3 matrix in Equation 19


with rotation parameter θ . We can also write this rotation matrix simply as R.
In some graphics libraries, a two-dimensional rotation function generates
only rotations about the coordinate origin, as in Equation 19. A rotation about
any other pivot point must then be performed as a sequence of transformation
operations. An alternative approach in a graphics package is to provide additional
parameters in the rotation routine for the pivot-point coordinates. A rotation
routine that includes a pivot-point parameter then sets up a general rotation
matrix without the need to invoke a succession of transformation functions.

Two-Dimensional Scaling Matrix


Finally, a scaling transformation relative to the coordinate origin can now be
expressed as the matrix multiplication
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x sx 0 0 x
⎣ y ⎦ = ⎣ 0 s y 0 ⎦ · ⎣ y ⎦ (21)
1 0 0 1 1
or
P = S(sx , s y ) · P (22)

The scaling operator S(sx , s y ) is the 3 × 3 matrix in Equation 21 with parameters


sx and s y . And, in most cases, we can represent the scaling matrix simply as S.
Some libraries provide a scaling function that can generate only scaling with
respect to the coordinate origin, as in Equation 21. In this case, a scaling trans-
formation relative to another reference position is handled as a succession of
transformation operations. However, other systems do include a general scaling
routine that can construct the homogeneous matrix for scaling with respect to a
designated fixed point.

197
Two-Dimensional Geometric Transformations

3 Inverse Transformations
For translation, we obtain the inverse matrix by negating the translation distances.
Thus, if we have two-dimensional translation distances tx and ty , the inverse
translation matrix is
⎡ ⎤
1 0 −tx
T−1 = ⎣ 0 1 −ty ⎦ (23)
0 0 1
This produces a translation in the opposite direction, and the product of a trans-
lation matrix and its inverse produces the identity matrix.
An inverse rotation is accomplished by replacing the rotation angle by its
negative. For example, a two-dimensional rotation through an angle θ about the
coordinate origin has the inverse transformation matrix
⎡ ⎤
cos θ sin θ 0
R−1 = ⎣ − sin θ cos θ 0 ⎦ (24)
0 0 1
Negative values for rotation angles generate rotations in a clockwise direction,
so the identity matrix is produced when any rotation matrix is multiplied by its
inverse. Because only the sine function is affected by the change in sign of the
rotation angle, the inverse matrix can also be obtained by interchanging rows
and columns. That is, we can calculate the inverse of any rotation matrix R by
evaluating its transpose (R−1 = RT ).
We form the inverse matrix for any scaling transformation by replacing
the scaling parameters with their reciprocals. For two-dimensional scaling with
parameters sx and s y applied relative to the coordinate origin, the inverse trans-
formation matrix is
⎡ ⎤
1
0 0
⎢ sx ⎥
⎢ ⎥
−1
S =⎢ 0 ⎢ 1 ⎥ (25)
0⎥
⎣ sy ⎦
0 0 1
The inverse matrix generates an opposite scaling transformation, so the multipli-
cation of any scaling matrix with its inverse produces the identity matrix.

4 Two-Dimensional Composite
Transformations
Using matrix representations, we can set up a sequence of transformations as a
composite transformation matrix by calculating the product of the individual
transformations. Forming products of transformation matrices is often referred
to as a concatenation, or composition, of matrices. Because a coordinate posi-
tion is represented with a homogeneous column matrix, we must premultiply
the column matrix by the matrices representing any transformation sequence.
Also, because many positions in a scene are typically transformed by the same
sequence, it is more efficient to first multiply the transformation matrices to form
a single composite matrix. Thus, if we want to apply two transformations to point
position P, the transformed location would be calculated as
P  = M2 · M1 · P
= M·P (26)

198
Two-Dimensional Geometric Transformations

The coordinate position is transformed using the composite matrix M, rather than
applying the individual transformations M1 and then M2 .

Composite Two-Dimensional Translations


If two successive translation vectors (t1x , t1y ) and (t2x , t2y ) are applied to a two-
dimensional coordinate position P, the final transformed location P is calcu-
lated as
P = T(t2x , t2y ) · {T(t1x , t1y ) · P}
= {T(t2x , t2y ) · T(t1x , t1y )} · P (27)

where P and P are represented as three-element, homogeneous-coordinate col-


umn vectors. We can verify this result by calculating the matrix product for the
two associative groupings. Also, the composite transformation matrix for this
sequence of translations is
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
1 0 t2x 1 0 t1x 1 0 t1x + t2x
⎣ 0 1 t2y ⎦ · ⎣ 0 1 t1y ⎦ = ⎣ 0 1 t1y + t2y ⎦ (28)
0 0 1 0 0 1 0 0 1
or
T(t2x , t2y ) · T(t1x , t1y ) = T(t1x + t2x , t1y + t2y ) (29)
which demonstrates that two successive translations are additive.

Composite Two-Dimensional Rotations


Two successive rotations applied to a point P produce the transformed position
P = R(θ2 ) · {R(θ1 ) · P}
= {R(θ2 ) · R(θ1 )} · P (30)

By multiplying the two rotation matrices, we can verify that two successive rota-
tions are additive:
R(θ2 ) · R(θ1 ) = R(θ1 + θ2 ) (31)

so that the final rotated coordinates of a point can be calculated with the composite
rotation matrix as

P = R(θ1 + θ2 ) · P (32)

Composite Two-Dimensional Scalings


Concatenating transformation matrices for two successive scaling operations in
two dimensions produces the following composite scaling matrix:
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
s2x 0 0 s1x 0 0 s1x · s2x 0 0
⎣ 0 s2y 0 ⎦ · ⎣ 0 s1y 0 ⎦ = ⎣ 0 s1y · s2y 0 ⎦ (33)
0 0 1 0 0 1 0 0 1
or

S(s2x , s2y ) · S(s1x , s1y ) = S(s1x · s2x , s1y · s2y ) (34)

The resulting matrix in this case indicates that successive scaling operations are
multiplicative. That is, if we were to triple the size of an object twice in succession,
the final size would be nine times that of the original.

199
Two-Dimensional Geometric Transformations

(xr , yr ) (xr , yr)

(a) (b) (c) (d)


Original Position Translation of Rotation Translation of
FIGURE 9 of Object and Object so that about Object so that
A transformation sequence for rotating Pivot Point Pivot Point Origin the Pivot Point
an object about a specified pivot point (xr , yr) is at is Returned
using the rotation matrix R(θ ) of Origin to Position
transformation 19. (xr , yr)

General Two-Dimensional Pivot-Point Rotation


When a graphics package provides only a rotate function with respect to the coor-
dinate origin, we can generate a two-dimensional rotation about any other pivot
point (xr , yr ) by performing the following sequence of translate-rotate-translate
operations:
1. Translate the object so that the pivot-point position is moved to the coor-
dinate origin.
2. Rotate the object about the coordinate origin.
3. Translate the object so that the pivot point is returned to its original
position.
This transformation sequence is illustrated in Figure 9. The composite trans-
formation matrix for this sequence is obtained with the concatenation
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
1 0 xr cos θ −sin θ 0 1 0 −xr
⎣ 0 1 yr ⎦ · ⎣ sin θ cos θ 0 ⎦ · ⎣ 0 1 −yr ⎦
0 0 1 0 0 1 0 0 1
⎡ ⎤
cos θ −sin θ xr (1 − cos θ) + yr sin θ
= ⎣ sin θ cos θ yr (1 − cos θ) − xr sin θ ⎦ (35)
0 0 1
which can be expressed in the form
T(xr , yr ) · R(θ ) · T(−xr , −yr ) = R(xr , yr , θ) (36)

where T(−xr , −yr ) = T−1 (xr , yr ). In general, a rotate function in a graphics


library could be structured to accept parameters for pivot-point coordinates, as
well as the rotation angle, and to generate automatically the rotation matrix of
Equation 35.

General Two-Dimensional Fixed-Point Scaling


Figure 10 illustrates a transformation sequence to produce a two-dimensional
scaling with respect to a selected fixed position (x f , y f ), when we have a function
that can scale relative to the coordinate origin only. This sequence is
1. Translate the object so that the fixed point coincides with the coordinate
origin.

200
Two-Dimensional Geometric Transformations

(xf , yf) (xf , yf)

(a) (b) (c) (d) FIGURE 10


Original Position Translate Object Scale Object Translate Object A transformation sequence for scaling
of Object and so that Fixed Point with Respect so that the Fixed an object with respect to a specified
Fixed Point (xf , yf) is at Origin to Origin Point is Returned fixed position using the scaling matrix
to Position (xf , yf) S(s x , s y ) of transformation 21.

2. Scale the object with respect to the coordinate origin.


3. Use the inverse of the translation in step (1) to return the object to its
original position.
Concatenating the matrices for these three operations produces the required
scaling matrix:
⎡ ⎤ ⎡ ⎤ ⎡ ⎤ ⎡ ⎤
1 0 xf sx 0 0 1 0 −x f sx 0 x f (1 − sx )
⎣ 0 1 y f ⎦ · ⎣ 0 s y 0 ⎦ · ⎣ 0 1 −y f ⎦ = ⎣ 0 s y y f (1 − s y ) ⎦ (37)
0 0 1 0 0 1 0 0 1 0 0 1
or
T(x f , y f ) · S(sx , s y ) · T(−x f , −y f ) = S(x f , y f , sx , s y ) (38)

This transformation is generated automatically in systems that provide a scale


function that accepts coordinates for the fixed point.

General Two-Dimensional Scaling Directions


Parameters sx and s y scale objects along the x and y directions. We can scale y
s2
an object in other directions by rotating the object to align the desired scaling
directions with the coordinate axes before applying the scaling transformation.
Suppose we want to apply scaling factors with values specified by parameters
s1 and s2 in the directions shown in Figure 11. To accomplish the scaling without
changing the orientation of the object, we first perform a rotation so that the
directions for s1 and s2 coincide with the x and y axes, respectively. Then the
scaling transformation S(s1 , s2 ) is applied, followed by an opposite rotation to
u x
return points to their original orientations. The composite matrix resulting from
the product of these three transformations is s1
⎡ ⎤
s1 cos2 θ + s2 sin2 θ (s2 − s1 ) cos θ sin θ 0 FIGURE 11
R−1 (θ ) · S(s1 , s2 ) · R(θ ) = ⎣ (s2 − s1 ) cos θ sin θ s1 sin2 θ + s2 cos2 θ 0 ⎦ (39) Scaling parameters s 1 and s 2 along
orthogonal directions defined
0 0 1 by the angular displacement θ.
As an example of this scaling transformation, we turn a unit square into a
parallelogram (Figure 12) by stretching it along the diagonal from (0, 0) to (1, 1).
We first rotate the diagonal onto the y axis using θ = 45◦ , then we double its length
with the scaling values s1 = 1 and s2 = 2, and then we rotate again to return the
diagonal to its original orientation.
In Equation 39, we assumed that scaling was to be performed relative to
the origin. We could take this scaling operation one step further and concatenate
the matrix with translation operators, so that the composite matrix would include
parameters for the specification of a scaling fixed position.

201
Two-Dimensional Geometric Transformations

y y
(2, 2)

(1/2, 3/2)

(0, 1) (1, 1)

FIGURE 12
A square (a) is converted to a (3/2, 1/2)
parallelogram (b) using the composite
(0, 0) (1, 0) x (0, 0) x
transformation matrix 39, with
s 1 = 1, s 2 = 2, and θ = 45◦ . (a) (b)

Matrix Concatenation Properties


Multiplication of matrices is associative. For any three matrices, M1 , M2 , and M3 ,
the matrix product M3 · M2 · M1 can be performed by first multiplying M3 and
M2 or by first multiplying M2 and M1 :
M3 · M2 · M1 = (M3 · M2 ) · M1 = M3 · (M2 · M1 ) (40)
Therefore, depending upon the order in which the transformations are specified,
we can construct a composite matrix either by multiplying from left to right
(premultiplying) or by multiplying from right to left (postmultiplying). Some
graphics packages require that transformations be specified in the order in which
they are to be applied. In that case, we would first invoke transformation M1 ,
then M2 , then M3 . As each successive transformation routine is called, its matrix
is concatenated on the left of the previous matrix product. Other graphics systems,
however, postmultiply matrices, so that this transformation sequence would have
to be invoked in the reverse order: the last transformation invoked (which is M1
for this example) is the first to be applied, and the first transformation that is
called (M3 in this case) is the last to be applied.
Transformation products, on the other hand, may not be commutative. The
matrix product M2 · M1 is not equal to M1 · M2 , in general. This means that if we
want to translate and rotate an object, we must be careful about the order in which
the composite matrix is evaluated (Figure 13). For some special cases—such as
a sequence of transformations that are all of the same kind—the multiplication of
transformation matrices is commutative. As an example, two successive rotations
could be performed in either order and the final position would be the same. This
commutative property holds also for two successive translations or two successive
scalings. Another commutative pair of operations is rotation and uniform scaling
(sx = s y ).

Final Final
Position Position

(a) (b)
FIGURE 13
Reversing the order in which a sequence of transformations is performed may affect the transformed position of
an object. In (a), an object is first translated in the x direction, then rotated counterclockwise through an angle
of 45◦ . In (b), the object is first rotated 45◦ counterclockwise, then translated in the x direction.

202
Two-Dimensional Geometric Transformations

General Two-Dimensional Composite Transformations


and Computational Efficiency
A two-dimensional transformation, representing any combination of translations,
rotations, and scalings, can be expressed as
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x r sxx r sxy tr sx x
⎣ y ⎦ = ⎣ r s yx r s yy tr s y ⎦ · ⎣ y ⎦ (41)
1 0 0 1 1
The four elements r s jk are the multiplicative rotation-scaling terms in the transfor-
mation, which involve only rotation angles and scaling factors. Elements tr sx and
tr s y are the translational terms, containing combinations of translation distances,
pivot-point and fixed-point coordinates, rotation angles, and scaling parameters.
For example, if an object is to be scaled and rotated about its centroid coordi-
nates (xc , yc ) and then translated, the values for the elements of the composite
transformation matrix are
T(tx , ty ) · R(xc , yc , θ ) · S(xc , yc , sx , s y )
⎡ ⎤
sx cos θ −s y sin θ xc (1 − sx cos θ) + yc s y sin θ + tx
= ⎣ sx sin θ s y cos θ yc (1 − s y cos θ) − xc sx sin θ + ty ⎦ (42)
0 0 1
Although Equation 41 requires nine multiplications and six additions, the
explicit calculations for the transformed coordinates are
x  = x · r sxx + y · r sxy + tr sx , y = x · r s yx + y · r s yy + tr s y (43)

Thus, we need actually perform only four multiplications and four additions
to transform coordinate positions. This is the maximum number of computations
required for any transformation sequence, once the individual matrices have been
concatenated and the elements of the composite matrix evaluated. Without con-
catenation, the individual transformations would be applied one at a time, and the
number of calculations could be increased significantly. An efficient implementa-
tion for the transformation operations, therefore, is to formulate transformation
matrices, concatenate any transformation sequence, and calculate transformed co-
ordinates using Equations 43. On parallel systems, direct matrix multiplications
with the composite transformation matrix of Equation 41 can be equally efficient.
Because rotation calculations require trigonometric evaluations and sev-
eral multiplications for each transformed point, computational efficiency can
become an important consideration in rotation transformations. In animations and
other applications that involve many repeated transformations and small rotation
angles, we can use approximations and iterative calculations to reduce computa-
tions in the composite transformation equations. When the rotation angle is small,
the trigonometric functions can be replaced with approximation values based on
the first few terms of their power series expansions. For small-enough angles (less
than 10◦ ), cos θ is approximately 1.0 and sin θ has a value very close to the value of
θ in radians. If we are rotating in small angular steps about the origin, for instance,
we can set cos θ to 1.0 and reduce transformation calculations at each step to two
multiplications and two additions for each set of coordinates to be rotated. These
rotation calculations are
x  = x − y sin θ, y = x sin θ + y (44)

where sin θ is evaluated once for all steps, assuming the rotation angle does not
change. The error introduced by this approximation at each step decreases as the
rotation angle decreases; but even with small rotation angles, the accumulated

203
Two-Dimensional Geometric Transformations

error over many steps can become quite large. We can control the accumulated
error by estimating the error in x  and y at each step and resetting object posi-
tions when the error accumulation becomes too great. Some animation applica-
tions automatically reset object positions at fixed intervals, such as every 360◦ or
every 180◦ .
Composite transformations often involve inverse matrices. For example,
transformation sequences for general scaling directions and for some reflections
and shears (Section 5) require inverse rotations. As we have noted, the inverse
matrix representations for the basic geometric transformations can be generated
with simple procedures. An inverse translation matrix is obtained by changing
the signs of the translation distances, and an inverse rotation matrix is obtained
by performing a matrix transpose (or changing the sign of the sine terms). These
operations are much simpler than direct inverse matrix calculations.

Two-Dimensional Rigid-Body Transformation


If a transformation matrix includes only translation and rotation parameters, it
is a rigid-body transformation matrix. The general form for a two-dimensional
rigid-body transformation matrix is
⎡ ⎤
r xx r xy tr x
⎣ r yx r yy tr y ⎦ (45)
0 0 1
where the four elements r jk are the multiplicative rotation terms, and the elements
tr x and tr y are the translational terms. A rigid-body change in coordinate position
is also sometimes referred to as a rigid-motion transformation. All angles and
distances between coordinate positions are unchanged by the transformation. In
addition, matrix 45 has the property that its upper-left 2 × 2 submatrix is an
orthogonal matrix. This means that if we consider each row (or each column) of the
submatrix as a vector, then the two row vectors (r xx , r xy ) and (r yx , r yy ) (or the two
column vectors) form an orthogonal set of unit vectors. Such a set of vectors is
also referred to as an orthonormal vector set. Each vector has unit length as follows:
2
r xx + r xy
2
= r yx
2
+ r yy
2
=1 (46)

and the vectors are perpendicular (their dot product is 0):


r xx r yx + r xyr yy = 0 (47)

Therefore, if these unit vectors are transformed by the rotation submatrix, then
the vector (r xx , r xy ) is converted to a unit vector along the x axis and the vector (r yx ,
r yy ) is transformed into a unit vector along the y axis of the coordinate system:
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
r xx r xy 0 r xx 1
⎣ r yx r yy 0 ⎦ · ⎣ r xy ⎦ = ⎣ 0 ⎦ (48)
0 0 1 1 1
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
r xx r xy 0 r yx 0
⎣ r yx r yy 0 ⎦ · ⎣ r yy ⎦ = ⎣ 1 ⎦ (49)
0 0 1 1 1
For example, the following rigid-body transformation first rotates an object
through an angle θ about a pivot point (xr , yr ) and then translates the object:
⎡ ⎤
cos θ − sin θ xr (1 − cos θ) + yr sin θ + tx
T(tx , ty ) · R(xr , yr , θ) = ⎣ sin θ cos θ yr (1 − cos θ) − xr sin θ + ty ⎦ (50)
0 0 1

204
Two-Dimensional Geometric Transformations

y v y

u
FIGURE 14
The rotation matrix for revolving an
x x object from position (a) to position (b)
can be constructed with the values of
the unit orientation vectors u and v
(a) (b) relative to the original orientation.

Here, orthogonal unit vectors in the upper-left 2 × 2 submatrix are (cos θ, − sin θ)
and (sin θ, cos θ ), and
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
cos θ − sin θ 0 cos θ 1
⎣ sin θ cos θ 0 ⎦ · ⎣ − sin θ ⎦ = ⎣ 0 ⎦ (51)
0 0 1 1 1
Similarly, unit vector (sin θ , cos θ ) is converted by the preceding transformation
matrix to the unit vector (0, 1) in the y direction.

Constructing Two-Dimensional Rotation Matrices


The orthogonal property of rotation matrices is useful for constructing the matrix
when we know the final orientation of an object, rather than the amount of angular
rotation necessary to put the object into that position. This orientation information
could be determined by the alignment of certain objects in a scene or by reference
positions within the coordinate system. For example, we might want to rotate an
object to align its axis of symmetry with the viewing (camera) direction, or we
might want to rotate one object so that it is above another object. Figure 14 shows
an object that is to be aligned with the unit direction vectors u and v . Assuming
that the original object orientation, as shown in Figure 14(a), is aligned with
the coordinate axes, we construct the desired transformation by assigning the
elements of u to the first row of the rotation matrix and the elements of v to the
second row. In a modeling application, for instance, we can use this method to
obtain the transformation matrix within an object’s local coordinate system when
we know what its orientation is to be within the overall world-coordinate scene. A
similar transformation is the conversion of object descriptions from one coordinate
system to another, and we take up these methods in more detail in Section 8.

Two-Dimensional Composite-Matrix Programming Example


An implementation example for a sequence of geometric transformations is given
in the following program. Initially, the composite matrix, compMatrix, is con-
structed as the identity matrix. For this example, a left-to-right concatenation
order is used to construct the composite transformation matrix, and we invoke
the transformation routines in the order that they are to be executed. As each of
the basic transformation routines (scale, rotate, and translate) is invoked, a matrix
is set up for that transformation and left-concatenated with the composite matrix.
When all transformations have been specified, the composite transformation is
applied to transform a triangle. The triangle is first scaled with respect to its cen-
troid position, then the triangle is rotated about its centroid, and, lastly, it is
translated. Figure 15 shows the original and final positions of the triangle that
is transformed by this sequence. Routines in OpenGL are used to dispaly the
initial and final position of the triangle.

205
Two-Dimensional Geometric Transformations

y y
200 200

150 150

100 100

Centroid Centroid
50 50
FIGURE 15
A triangle (a) is transformed into
position (b) using the composite-
matrix calculations in procedure 50 100 150 200 x 50 100 150 200 x
transformVerts2D. (a) (b)

#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>

/* Set initial display-window size. */


GLsizei winWidth = 600, winHeight = 600;

/* Set range for world coordinates. */


GLfloat xwcMin = 0.0, xwcMax = 225.0;
GLfloat ywcMin = 0.0, ywcMax = 225.0;

class wcPt2D {
public:
GLfloat x, y;
};

typedef GLfloat Matrix3x3 [3][3];

Matrix3x3 matComposite;

const GLdouble pi = 3.14159;

void init (void)


{
/* Set color of display window to white. */
glClearColor (1.0, 1.0, 1.0, 0.0);
}

/* Construct the 3 x 3 identity matrix. */


void matrix3x3SetIdentity (Matrix3x3 matIdent3x3)
{
GLint row, col;

for (row = 0; row < 3; row++)


for (col = 0; col < 3; col++)
matIdent3x3 [row][col] = (row == col);
}

206
Two-Dimensional Geometric Transformations

/* Premultiply matrix m1 times matrix m2, store result in m2. */


void matrix3x3PreMultiply (Matrix3x3 m1, Matrix3x3 m2)
{
GLint row, col;
Matrix3x3 matTemp;

for (row = 0; row < 3; row++)


for (col = 0; col < 3 ; col++)
matTemp [row][col] = m1 [row][0] * m2 [0][col] + m1 [row][1] *
m2 [1][col] + m1 [row][2] * m2 [2][col];

for (row = 0; row < 3; row++)


for (col = 0; col < 3; col++)
m2 [row][col] = matTemp [row][col];
}

void translate2D (GLfloat tx, GLfloat ty)


{
Matrix3x3 matTransl;

/* Initialize translation matrix to identity. */


matrix3x3SetIdentity (matTransl);

matTransl [0][2] = tx;


matTransl [1][2] = ty;

/* Concatenate matTransl with the composite matrix. */


matrix3x3PreMultiply (matTransl, matComposite);
}

void rotate2D (wcPt2D pivotPt, GLfloat theta)


{
Matrix3x3 matRot;

/* Initialize rotation matrix to identity. */


matrix3x3SetIdentity (matRot);

matRot [0][0] = cos (theta);


matRot [0][1] = -sin (theta);
matRot [0][2] = pivotPt.x * (1 - cos (theta)) +
pivotPt.y * sin (theta);
matRot [1][0] = sin (theta);
matRot [1][1] = cos (theta);
matRot [1][2] = pivotPt.y * (1 - cos (theta)) -
pivotPt.x * sin (theta);

/* Concatenate matRot with the composite matrix. */


matrix3x3PreMultiply (matRot, matComposite);
}

void scale2D (GLfloat sx, GLfloat sy, wcPt2D fixedPt)


{
Matrix3x3 matScale;

207
Two-Dimensional Geometric Transformations

/* Set geometric transformation parameters. */


wcPt2D pivPt, fixedPt;
pivPt = centroidPt;
fixedPt = centroidPt;

GLfloat tx = 0.0, ty = 100.0;


GLfloat sx = 0.5, sy = 0.5;
GLdouble theta = pi/2.0;

glClear (GL_COLOR_BUFFER_BIT); // Clear display window.

glColor3f (0.0, 0.0, 1.0); // Set initial fill color to blue.


triangle (verts); // Display blue triangle.

/* Initialize composite matrix to identity. */


matrix3x3SetIdentity (matComposite);

/* Construct composite matrix for transformation sequence. */


scale2D (sx, sy, fixedPt); // First transformation: Scale.
rotate2D (pivPt, theta); // Second transformation: Rotate
translate2D (tx, ty); // Final transformation: Translate.

/* Apply composite matrix to triangle vertices. */


transformVerts2D (nVerts, verts);

glColor3f (1.0, 0.0, 0.0); // Set color for transformed triangle.


triangle (verts); // Display red transformed triangle.

glFlush ( );
}

void winReshapeFcn (GLint newWidth, GLint newHeight)


{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
gluOrtho2D (xwcMin, xwcMax, ywcMin, ywcMax);

glClear (GL_COLOR_BUFFER_BIT);
}

void main (int argc, char ** argv)


{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (50, 50);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Geometric Transformation Sequence");

init ( );
glutDisplayFunc (displayFcn);
glutReshapeFunc (winReshapeFcn);

glutMainLoop ( );
}

209
Two-Dimensional Geometric Transformations

/* Initialize scaling matrix to identity. */


matrix3x3SetIdentity (matScale);

matScale [0][0] = sx;


matScale [0][2] = (1 - sx) * fixedPt.x;
matScale [1][1] = sy;
matScale [1][2] = (1 - sy) * fixedPt.y;

/* Concatenate matScale with the composite matrix. */


matrix3x3PreMultiply (matScale, matComposite);
}

/* Using the composite matrix, calculate transformed coordinates. */


void transformVerts2D (GLint nVerts, wcPt2D * verts)
{
GLint k;
GLfloat temp;

for (k = 0; k < nVerts; k++) {


temp = matComposite [0][0] * verts [k].x + matComposite [0][1] *
verts [k].y + matComposite [0][2];
verts [k].y = matComposite [1][0] * verts [k].x + matComposite [1][1] *
verts [k].y + matComposite [1][2];
verts [k].x = temp;
}
}

void triangle (wcPt2D *verts)


{
GLint k;

glBegin (GL_TRIANGLES);
for (k = 0; k < 3; k++)
glVertex2f (verts [k].x, verts [k].y);
glEnd ( );
}

void displayFcn (void)


{
/* Define initial position for triangle. */
GLint nVerts = 3;
wcPt2D verts [3] = { {50.0, 25.0}, {150.0, 25.0}, {100.0, 100.0} };

/* Calculate position of triangle centroid. */


wcPt2D centroidPt;

GLint k, xSum = 0, ySum = 0;


for (k = 0; k < nVerts; k++) {
xSum += verts [k].x;
ySum += verts [k].y;
}
centroidPt.x = GLfloat (xSum) / GLfloat (nVerts);
centroidPt.y = GLfloat (ySum) / GLfloat (nVerts);

208
Two-Dimensional Geometric Transformations

5 Other Two-Dimensional Transformations


Basic transformations such as translation, rotation, and scaling are standard com-
ponents of graphics libraries. Some packages provide a few additional trans-
formations that are useful in certain applications. Two such transformations are
reflection and shear.

Reflection
1 A transformation that produces a mirror image of an object is called a reflection.
y
For a two-dimensional reflection, this image is generated relative to an axis of
Original reflection by rotating the object 180◦ about the reflection axis. We can choose
Position
an axis of reflection in the xy plane or perpendicular to the xy plane. When the
2 3 reflection axis is a line in the xy plane, the rotation path about this axis is in a plane
perpendicular to the xy plane. For reflection axes that are perpendicular to the xy
x plane, the rotation path is in the xy plane. Some examples of common reflections
2 3 follow.
Reflection about the line y = 0 (the x axis) is accomplished with the transfor-
Reflected mation matrix
Position
⎡ ⎤
1 0 0
1 ⎣ 0 −1 0 ⎦ (52)
FIGURE 16 0 0 1
Reflection of an object about the
x axis. This transformation retains x values, but “flips” the y values of coordinate posi-
tions. The resulting orientation of an object after it has been reflected about the x
axis is shown in Figure 16. To envision the rotation transformation path for this
reflection, we can think of the flat object moving out of the xy plane and rotating
180◦ through three-dimensional space about the x axis and back into the xy plane
on the other side of the x axis.
A reflection about the line x = 0 (the y axis) flips x coordinates while keeping
y coordinates the same. The matrix for this transformation is
⎡ ⎤
−1 0 0
⎣ 0 1 0⎦ (53)
0 0 1

y Figure 17 illustrates the change in position of an object that has been reflected
about the line x = 0. The equivalent rotation in this case is 180◦ through three-
Original Reflected dimensional space about the y axis.
Position Position We flip both the x and y coordinates of a point by reflecting relative to an axis
2 2 that is perpendicular to the xy plane and that passes through the coordinate origin.
This reflection is sometimes referred to as a reflection relative to the coordinate
1 1 origin, and it is equivalent to reflecting with respect to both coordinate axes. The
3 3 matrix representation for this reflection is
⎡ ⎤
x −1 0 0
⎣ 0 −1 0 ⎦ (54)
FIGURE 17
Reflection of an object about the 0 0 1
y axis.
An example of reflection about the origin is shown in Figure 18. The reflection
matrix 54 is the same as the rotation matrix R(θ) with θ = 180 ◦. We are simply
rotating the object in the xy plane half a revolution about the origin.

210
Two-Dimensional Geometric Transformations

y
Reflected
y
Position
3
3

2
1 2
1 yrfl
2 1 Preflect
x
1
2
3

3
Original
Position xrfl x

FIGURE 18 FIGURE 19
Reflection of an object relative to the Reflection of an object relative to an axis
coordinate origin. This transformation can be perpendicular to the x y plane and passing
accomplished with a rotation in the x y plane through point Preflect .
about the coordinate origin.

Reflection 54 can be generalized to any reflection point in the xy plane


(Figure 19). This reflection is the same as a 180 ◦ rotation in the xy plane about
the reflection point.
If we choose the reflection axis as the diagonal line y = x (Figure 20), the
yx
reflection matrix is y
⎡ ⎤ 3 Original
0 1 0 Position
⎣1 0 0⎦ (55)
2
0 0 1
1 Reflected
1 Position
We can derive this matrix by concatenating a sequence of rotation and coordinate-
axis reflection matrices. One possible sequence is shown in Figure 21. Here, we
3
first perform a clockwise rotation with respect to the origin through a 45◦ angle,
which rotates the line y = x onto the x axis. Next, we perform a reflection with
2
respect to the x axis. The final step is to rotate the line y = x back to its orig- x
inal position with a counterclockwise rotation through 45◦ . Another equivalent
sequence of transformations is to first reflect the object about the x axis, then rotate FIGURE 20
it counterclockwise 90◦ . Reflection of an object with respect to
the line y = x .
To obtain a transformation matrix for reflection about the diagonal y = −x,
we could concatenate matrices for the transformation sequence: (1) clockwise
rotation by 45◦ , (2) reflection about the y axis, and (3) counterclockwise rotation
by 45◦ . The resulting transformation matrix is
⎡ ⎤
0 −1 0
⎣ −1 0 0 ⎦ (56)
0 0 1

Figure 22 shows the original and final positions for an object transformed with
this reflection matrix.
Reflections about any line y = mx + b in the xy plane can be accomplished
with a combination of translate-rotate-reflect transformations. In general, we

211
Two-Dimensional Geometric Transformations

yx
first translate the line so that it passes through the origin. Then we can rotate
the line onto one of the coordinate axes and reflect about that axis. Finally, we
restore the line to its original position with the inverse rotation and translation
transformations.
45 We can implement reflections with respect to the coordinate axes or coordinate
origin as scaling transformations with negative scaling factors. Also, elements of
the reflection matrix can be set to values other than ±1. A reflection parameter
(a) with a magnitude greater than 1 shifts the mirror image of a point farther from
the reflection axis, and a parameter with magnitude less than 1 brings the mirror
y image of a point closer to the reflection axis. Thus, a reflected object can also be
enlarged, reduced, or distorted.

Shear
x A transformation that distorts the shape of an object such that the trans-
formed shape appears as if the object were composed of internal layers that had
been caused to slide over each other is called a shear. Two common shearing
transformations are those that shift coordinate x values and those that shift y
(b)
values.
An x-direction shear relative to the x axis is produced with the transformation
matrix
⎡ ⎤
1 sh x 0
⎣0 1 0⎦ (57)
45 0 0 1

which transforms coordinate positions as


(c)
FIGURE 21 x  = x + sh x · y, y = y (58)
Sequence of transformations to
produce a reflection about the line Any real number can be assigned to the shear parameter sh x . A coordinate position
y = x : A clockwise rotation of 45◦
(x, y) is then shifted horizontally by an amount proportional to its perpendicular
(a), a reflection about the x axis (b),
and a counterclockwise rotation distance (y value) from the x axis. Setting parameter sh x to the value 2, for exam-
by 45◦ (c). ple, changes the square in Figure 23 into a parallelogram. Negative values for
sh x shift coordinate positions to the left.

2
Reflected
Position

1 3
y y
2 1

Original (2, 1) (3, 1)


Position 3 (0, 1) (1, 1)

y  x

(0, 0) (1, 0) x (0, 0) (1, 0) x


(a) (b)
FIGURE 22 FIGURE 23
Reflection with respect to the line A unit square (a) is converted to a parallelogram (b) using the x -direction shear
y = −x . matrix 57 with s hx = 2.

212
Two-Dimensional Geometric Transformations

y y

(0, 1) (1, 1) (1, 1) (2, 1)

(0, 0) (1, 0) x (1/2, 0) (3/2, 0) x


FIGURE 24
yref  1 yref  1 A unit square (a) is transformed to a
shifted parallelogram (b) with
s h x = 0.5 and y ref = −1 in the
(a) (b) shear matrix 59.

y y (1, 2)

(0, 3/2)

(0, 1) (1, 1) (1, 1)

(0, 1/2) FIGURE 25


A unit square (a) is turned into a
shifted parallelogram (b) with
xref = – 1 (0, 0) (1, 0) x xref = – 1 x
parameter values s h y = 0.5 and
x ref = −1 in the y -direction shearing
(a) (b) transformation 61.

We can generate x-direction shears relative to other reference lines with


⎡ ⎤
1 sh x −sh x · yref
⎣0 1 0 ⎦ (59)
0 0 1
Now, coordinate positions are transformed as
x  = x + sh x (y − yref ), y = y (60)
An example of this shearing transformation is given in Figure 24 for a shear
parameter value of 12 relative to the line yref = −1.
A y-direction shear relative to the line x = xref is generated with the transfor-
mation matrix ⎡ ⎤
1 0 0
⎣ sh y 1 −sh y · xref ⎦ (61)
0 0 1
which generates the transformed coordinate values
x  = x, y = y + sh y (x − xref ) (62)
This transformation shifts a coordinate position vertically by an amount propor-
tional to its distance from the reference line x = xref . Figure 25 illustrates the
conversion of a square into a parallelogram with sh y = 0.5 and xref = −1.
Shearing operations can be expressed as sequences of basic transformations.
The x-direction shear matrix 57, for example, can be represented as a composite
transformation involving a series of rotation and scaling matrices. This compos-
ite transformation scales the unit square of Figure 23 along its diagonal, while
maintaining the original lengths and orientations of edges parallel to the x axis.
Shifts in the positions of objects relative to shearing reference lines are equivalent
to translations.

213
Two-Dimensional Geometric Transformations

6 Raster Methods for Geometric


Transformations
Pmax The characteristics of raster systems suggest an alternate method for performing
certain two-dimensional transformations. Raster systems store picture informa-
tion as color patterns in the frame buffer. Therefore, some simple object transfor-
mations can be carried out rapidly by manipulating an array of pixel values. Few
Pmin arithmetic operations are needed, so the pixel transformations are particularly
efficient.
Functions that manipulate rectangular pixel arrays are called raster opera-
tions and moving a block of pixel values from one position to another is termed
a block transfer, a bitblt, or a pixblt. Routines for performing some raster opera-
tions are usually available in a graphics package.
(a) Figure 26 illustrates a two-dimensional translation implemented as a block
transfer of a refresh-buffer area. All bit settings in the rectangular area shown are
copied as a block into another part of the frame buffer. We can erase the pattern
at the original location by assigning the background color to all pixels within that
block (assuming that the pattern to be erased does not overlap other objects in
the scene).
Rotations in 90-degree increments are accomplished easily by rearranging
the elements of a pixel array. We can rotate a two-dimensional object or pattern
90◦ counterclockwise by reversing the pixel values in each row of the array, then
interchanging rows and columns. A 180◦ rotation is obtained by reversing the
order of the elements in each row of the array, then reversing the order of the rows.
Figure 27 demonstrates the array manipulations that can be used to rotate a pixel
P0
block by 90◦ and by 180◦ .
(b) For array rotations that are not multiples of 90◦ , we need to do some extra
processing. The general procedure is illustrated in Figure 28. Each destination
FIGURE 26
Translating an object from screen pixel area is mapped onto the rotated array and the amount of overlap with
position (a) to the destination position the rotated pixel areas is calculated. A color for a destination pixel can then be
shown in (b) by moving a rectangular computed by averaging the colors of the overlapped source pixels, weighted by
block of pixel values. Coordinate their percentage of area overlap. Alternatively, we could use an approximation
positions Pmin and Pmax specify the
method, as in antialiasing, to determine the color of the destination pixels.
limits of the rectangular block to be
moved, and P0 is the destination We can use similar methods to scale a block of pixels. Pixel areas in the original
reference position. block are scaled, using specified values for sx and s y , and then mapped onto a set of
destination pixels. The color of each destination pixel is then assigned according
to its area of overlap with the scaled pixel areas (Figure 29).
An object can be reflected using raster transformations that reverse row or
column values in a pixel block, combined with translations. Shears are produced
with shifts in the positions of array values along rows or columns.

1 2 3 12 11 10
4 5 6 3 6 9 12 9 8 7
7 8 9 2 5 8 11 6 5 4
10 11 12 1 4 7 10 3 2 1
(a) (b) (c)
FIGURE 27
Rotating an array of pixel values. The original array is shown in (a), the
positions of the array elements after a 90◦ counterclockwise rotation are
shown in (b), and the positions of the array elements after a 180◦ rotation
are shown in (c).

214
Two-Dimensional Geometric Transformations

Destination
Pixel Array
Destination
Rotated
Pixel Areas
Pixel
Array Scaled
Array
Destination
Pixel Array

u (xf , yf)

FIGURE 28 FIGURE 29
A raster rotation for a rectangular block of pixels can be accomplished by Mapping destination pixel areas onto a scaled array of pixel values. Scaling
mapping the destination pixel areas onto the rotated block. factors s x = s y = 0.5 are applied relative to fixed point (x f , y f ).

7 OpenGL Raster Transformations


You should already be familiar with most of the OpenGL functions for per-
forming raster operations. A translation of a rectangular array of pixel-color val-
ues from one buffer area to another can be accomplished in OpenGL as the fol-
lowing copy operation:

glCopyPixels (xmin, ymin, width, height, GL_COLOR);

The first four parameters in this function give the location and dimensions of the
pixel block; and the OpenGL symbolic constant GL COLOR specifies that it is color
values are to be copied. This array of pixels is to be copied to a rectangular area of
a refresh buffer whose lower-left corner is at the location specified by the current
raster position. Pixel-color values are copied as either RGBA values or color-table
indices, depending on the current setting for the color mode. Both the region
to be copied (the source) and the destination area should lie completely within
the bounds of the screen coordinates. This translation can be carried out on any
of the OpenGL buffers used for refreshing, or even between different buffers. A
source buffer for the glCopyPixels function is chosen with the glReadBuffer
routine, and a destination buffer is selected with the glDrawBuffer routine.
We can rotate a block of pixel-color values in 90-degree increments by first
saving the block in an array, then rearranging the elements of the array and placing
it back in the refresh buffer. A block of RGB color values in a buffer can be saved
in an array with the function

glReadPixels (xmin, ymin, width, height, GL_RGB,


GL_UNSIGNED_BYTE, colorArray);

If color-table indices are stored at the pixel positions, we replace the constant
GL RGB with GL COLOR INDEX. To rotate the color values, we rearrange the
rows and columns of the color array, as described in the previous section. Then
we put the rotated array back in the buffer with

glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE,


colorArray);

The lower-left corner of this array is placed at the current raster position.
We select the source buffer containing the original block of pixel values with
glReadBuffer, and we designate a destination buffer with glDrawBuffer.

215
Two-Dimensional Geometric Transformations

A two-dimensional scaling transformation can be performed as a raster


operation in OpenGL by specifying scaling factors and then invoking either
glCopyPixels or glDrawPixels. For the raster operations, we set the scal-
ing factors with

glPixelZoom (sx, sy);

where parameters sx and sy can be assigned any nonzero floating-point values.


Positive values greater than 1.0 increase the size of an element in the source array,
and positive values less than 1.0 decrease element size. A negative value for sx or
sy, or both, produces a reflection and scales the array elements. Thus, if sx = sy
= −3.0, the source array is reflected with respect to the current raster position and
each color element of the array is mapped to a 3 × 3 block of destination pixels. If
the center of a destination pixel lies within the rectangular area of a scaled color
element of an array, it is assigned the color of that array element. Destination pixels
whose centers are on the left or top boundary of the scaled array element are also
assigned the color of that element. The default value for both sx and sy is 1.0.
We can also combine raster transformations with logical operations to pro-
duce various effects. With the exclusive or operator, for example, two successive
copies of a pixel array to the same buffer area restores the values that were origi-
nally present in that area. This technique can be used in an animation application
to translate an object across a scene without altering the background pixels.

8 Transformations between
Two-Dimensional Coordinate Systems
Computer-graphics applications involve coordinate transformations from one ref-
erence frame to another during various stages of scene processing. The viewing
routines transform object descriptions from world coordinates to device coor-
dinates. For modeling and design applications, individual objects are typically
defined in their own local Cartesian references. These local-coordinate descrip-
tions must then be transformed into positions and orientations within the overall
scene coordinate system. A facility-management program for office layouts, for
instance, has individual coordinate descriptions for chairs and tables and other
furniture that can be placed into a floor plan, with multiple copies of the chairs
and other items in different positions.
Also, scenes are sometimes described in non-Cartesian reference frames that
y axis
take advantage of object symmetries. Coordinate descriptions in these systems
must be converted to Cartesian world coordinates for processing. Some examples
axis of non-Cartesian systems are polar coordinates, spherical coordinates, elliptical
y is
ax coordinates, and parabolic coordinates. Here, we consider only the transforma-
x
u tions involved in converting from one two- dimensional Cartesian frame to another.
y0
Figure 30 shows a Cartesian x  y  system specified with coordinate origin
(x0 , y0 ) and orientation angle θ in a Cartesian xy reference frame. To transform
object descriptions from xy coordinates to x  y coordinates, we set up a transfor-
0 x0 x axis
mation that superimposes the x  y axes onto the xy axes. This is done in two steps:
FIGURE 30
1. Translate so that the origin (x0 , y0 ) of the x  y system is moved to the origin
A Cartesian x  y  system positioned at
(x 0 , y 0 ) with orientation θ in an x y (0, 0) of the xy system.
Cartesian system. 2. Rotate the x  axis onto the x axis.

216
Two-Dimensional Geometric Transformations

Translation of the coordinate origin is accomplished with the matrix y axis


transformation ⎡ ⎤
1 0 −x0
T(−x0 , −y0 ) = ⎣ 0 1 −y0 ⎦ (63)
0 0 1 y P
is is
The orientation of the two systems after the translation operation would then ax ax
y x
appear as in Figure 31. To get the axes of the two systems into coincidence, we y
x
then perform the clockwise rotation u
⎡ ⎤ x x axis
cos θ sin θ 0
R(−θ ) = ⎣ −sin θ cos θ 0 ⎦ (64) FIGURE 31
Position of the reference frames shown
0 0 1 in Figure 30 after translating the
origin of the x  y  system to the
Concatenating these two transformation matrices gives us the complete composite
coordinate origin of the x y system.
matrix for transforming object descriptions from the xy system to the x  y system:
Mxy, x y = R(−θ) · T(−x0 , −y0 ) (65)

An alternate method for describing the orientation of the x  y coordinate sys-


tem is to specify a vector V that indicates the direction for the positive y axis, as
shown in Figure 32. We can specify vector V as a point in the xy reference frame
relative to the origin of the xy system, which we can convert to the unit vector
V
v= = (vx , v y ) (66)
|V|
We obtain the unit vector u along the x  axis by applying a 90◦ clockwise rotation
to vector v:
u = (v y , −vx )
= (ux , u y ) (67)

In Section 4, we noted that the elements of any rotation matrix could be expressed
as elements of a set of orthonormal vectors. Therefore, the matrix to rotate the
x  y system into coincidence with the xy system can be written as
⎡ ⎤
ux u y 0
R = ⎣ vx v y 0 ⎦ (68)
0 0 1
For example, suppose that we choose the orientation for the y axis as V = (−1, 0).
Then the x  axis is in the positive y direction, and the rotation transformation
matrix is ⎡ ⎤
0 1 0
⎣ −1 0 0 ⎦
0 0 1

y axis
is
ax xis
y a
x
V P0
y0

FIGURE 32
Cartesian system x  y  with origin at
0 x0 x axis P0 = ( x 0 , y 0 ) and y  axis parallel to vector V.

217
Two-Dimensional Geometric Transformations

y axis

is V  P1  P0 is
ax ax
y x
P1

y0
P0
FIGURE 33
A Cartesian x  y  system defined with two coordinate
positions, P0 and P1 , within an x y reference frame. 0 x0 x axis

Equivalently, we can obtain this rotation matrix from Equation 64 by setting the
orientation angle as θ = 90◦ .
In an interactive application, it may be more convenient to choose the direc-
tion of V relative to position P0 than to specify it relative to the xy-coordinate
origin. Unit vectors u and v would then be oriented as shown in Figure 33. The
components of v are now calculated as
P1 − P 0
v= (69)
|P1 − P0 |
and u is obtained as the perpendicular to v that forms a right-handed Cartesian
system.

9 OpenGL Functions for Two-Dimensional


Geometric Transformations
In the core library of OpenGL, a separate function is available for each of the basic
geometric transformations. Because OpenGL is designed as a three-dimensional
graphics application programming interface (API), all transformations are spec-
ified in three dimensions. Internally, all coordinate positions are represented
as four-element column vectors, and all transformations are represented using
4 × 4 matrices. Fortunately, performing two-dimensional transformations within
OpenGL is generally just a matter of using a value for the transformation in the
third (z) dimension that causes no change in that dimension.
To perform a translation, we invoke the translation routine and set the com-
ponents for the three-dimensional translation vector. In the rotation function, we
specify the angle and the orientation for a rotation axis that intersects the coor-
dinate origin. In addition, a scaling function is used to set the three coordinate
scaling factors relative to the coordinate origin. In each case, the transformation
routine sets up a 4 × 4 matrix that is applied to the coordinates of objects that are
referenced after the transformation call.

Basic OpenGL Geometric Transformations


A 4 × 4 translation matrix is constructed with the following routine:

glTranslate* (tx, ty, tz);

Translation parameters tx, ty, and tz can be assigned any real-number values,
and the single suffix code to be affixed to this function is either f (float) or d (dou-
ble). For two-dimensional applications, we set tz = 0.0; and a two-dimensional
position is represented as a four-element column matrix with the z component
equal to 0.0. The translation matrix generated by this function is used to transform

218
Two-Dimensional Geometric Transformations

positions of objects defined after this function is invoked. For example, we trans-
late subsequently defined coordinate positions 25 units in the x direction and −10
units in the y direction with the statement

glTranslatef (25.0, -10.0, 0.0);

Similarly, a 4 × 4 rotation matrix is generated with

glRotate* (theta, vx, vy, vz);

where the vector v = (vx, vy, vz) can have any floating-point values for its com-
ponents. This vector defines the orientation for a rotation axis that passes through
the coordinate origin. If v is not specified as a unit vector, then it is normalized
automatically before the elements of the rotation matrix are computed. The suffix
code can be either f or d, and parameter theta is to be assigned a rotation angle in
degrees, which the routine converts to radians for the trigonometric calculations.
The rotation specified here will be applied to positions defined after this function
call. Rotation in two-dimensional systems is rotation about the z axis, specified
as a unit vector with x and y components of zero, and a z component of 1.0. For
example, the statement

glRotatef (90.0, 0.0, 0.0, 1.0);

sets up the matrix for a 90◦ rotation about the z axis. We should note here that
internally, this function generates a rotation matrix using quaternions. This method
is more efficient when rotation is about an arbitrarily-specific axis.
We obtain a 4 × 4 scaling matrix with respect to the coordinate origin with
the following routine:

glScale* (sx, sy, sz);

The suffix code is again either f or d, and the scaling parameters can be assigned
any real-number values. Scaling in a two-dimensional system involves changes
in the x and y dimensions, so a typical two-dimensional scaling operation has a
z scaling factor of 1.0 (which causes no change in the z coordinate of positions).
Because the scaling parameters can be any real-number value, this function will
also generate reflections when negative values are assigned to the scaling param-
eters. For example, the following statement produces a matrix that scales by a
factor of 2 in the x direction, scales by a factor of 3 in the y direction, and reflects
with respect to the x axis:

glScalef (2.0, -3.0, 1.0);

A zero value for any scaling parameter can cause a processing error because an
inverse matrix cannot be calculated. The scale-reflect matrix is applied to subse-
quently defined objects.
It is important to note that internally OpenGL uses composite matrices to hold
transformations. As a result, transformations are cumulative—that is, if we apply
a translation and then apply a rotation, objects whose positions are specified after
that will have both transformations applied to them. If that is not the behavior we
desired, we must be able to remove the effects of previous transformations. This
requires additional functions for manipulating the composite matrices.

219
Two-Dimensional Geometric Transformations

OpenGL Matrix Operations


The glMatrixMode routine is used to set the projection mode, which desig-
nates the matrix that is to be used for the projection transformation. This trans-
formation. This transformation determines how a scene is to be projected onto
the screen. We use the same routine to set up a matrix for the geometric trans-
formations. In this case, however, the matrix is referred to as the modelview
matrix, and it is used to store and combine the geometric transformations. It is
also used to combine the geometric transformations with the transformation to a
viewing-coordinate system. We specify the modelview mode with the statement

glMatrixMode (GL_MODELVIEW);

which designates the 4 × 4 modelview matrix as the current matrix. The OpenGL
transformation routines discussed in the previous section are all applied to what-
ever composite matrix is the current matrix, so it is important to use glMatrix-
Mode to change to the modelview matrix before applying geometric transforma-
tions. Following this call, OpenGL transformation routines are used to modify
the modelview matrix, which is then applied to transform coordinate positions
in a scene. Two other modes that we can set with the glMatrixMode function
are the texture mode and the color mode. The texture matrix is used for mapping
texture patterns to surfaces, and the color matrix is used to convert from one
color model to another. We discuss viewing, projection, texture, and color trans-
formations in later chapters. For now, we limit our discussion to the details of the
geometric transformations. The default argument for the glMatrixMode func-
tion is GL MODELVIEW.
Once we are in the modelview mode (or any other mode), a call to a transfor-
mation routine generates a matrix that is multiplied by the current matrix for that
mode. In addition, we can assign values to the elements of the current matrix, and
there are two functions in the OpenGL library for this purpose. With the following
function, we assign the identity matrix to the current matrix:

glLoadIdentity ( );

Alternatively, we can assign other values to the elements of the current matrix
using

glLoadMatrix* (elements16);

A single-subscripted, 16-element array of floating-point values is specified with


parameter elements16, and a suffix code of either f or d is used to designate
the data type. The elements in this array must be specified in column-major order.
That is, we first list the four elements in the first column, and then we list the four
elements in the second column, the third column, and finally the fourth column.
To illustrate this ordering, we initialize the modelview matrix with the following
code:

glMatrixMode (GL_MODELVIEW);

GLfloat elems [16];


GLint k;

for (k = 0; k < 16; k++)


elems [k] = float (k);
glLoadMatrixf (elems);

220
Two-Dimensional Geometric Transformations

which produces the matrix

⎡ ⎤
0.0 4.0 8.0 12.0
⎢ 1.0 5.0 9.0 13.0 ⎥
M=⎢
⎣ 2.0

6.0 10.0 14.0 ⎦
3.0 7.0 11.0 15.0

We can also concatenate a specified matrix with the current matrix as follows:

glMultMatrix* (otherElements16);

Again, the suffix code is either f or d, and parameter otherElements16 is a


16-element, single-subscripted array that lists the elements of some other matrix
in column-major order. The current matrix is postmultiplied by the matrix specified
in glMultMatrix, and this product replaces the current matrix. Thus, assuming
that the current matrix is the modelview matrix, which we designate as M, then
the updated modelview matrix is computed as

M = M · M

where M represents the matrix whose elements are specified by parameter


otherElements16 in the preceding glMultMatrix statement.
The glMultMatrix function can also be used to set up any transformation
sequence with individually defined matrices. For example,

glMatrixMode (GL_MODELVIEW);

glLoadIdentity ( ); // Set current matrix to the identity.


glMultMatrixf (elemsM2); // Postmultiply identity with matrix M2.
glMultMatrixf (elemsM1); // Postmultiply M2 with matrix M1.

produces the following current modelview matrix:

M = M 2 · M1

The first transformation to be applied in this sequence is the last one specified in
the code. Thus, if we set up a transformation sequence in an OpenGL program,
we can think of the individual transformations as being loaded onto a stack, so the
last operation specified is the first one applied. This is not what actually happens,
but the stack analogy may help you remember that in an OpenGL program, a
transformation sequence is applied in the opposite order from which it is specified.
It is also important to keep in mind that OpenGL stores matrices in column-
major order. In addition, a reference to a matrix element such as m jk in OpenGL is
a reference to the element in column j and row k. This is the reverse of the standard
mathematical convention, where the row number is referenced first. However, we
can usually avoid errors in row-column references by always specifying matrices
in OpenGL as 16-element, single-subscript arrays and listing the elements in a
column-major order.

221
Two-Dimensional Geometric Transformations

OpenGL actually maintains a stack of composite matrices for each of the four
modes that we can select with the glMatrixMode routine.

10 OpenGL Geometric-Transformation
Programming Examples
In the following code segment, we apply each of the basic geometric transforma-
tions, one at a time, to a rectangle. Initially, the modelview matrix is the identity
matrix and we display a blue rectangle. Next, we reset the current color to red,
specify two-dimensional translation parameters, and display the red translated
rectangle (Figure 34). Because we do not want to combine transformations, we
next reset the current matrix to the identity. Then a rotation matrix is constructed
and concatenated with the current matrix (the identity matrix). When the origi-
nal rectangle is again referenced, it is rotated about the z axis and displayed in
red (Figure 35). We repeat this process once more to generate the scaled and
reflected rectangle shown in Figure 36.

glMatrixMode (GL_MODELVIEW);

glColor3f (0.0, 0.0, 1.0);


glRecti (50, 100, 200, 150); // Display blue rectangle.

glColor3f (1.0, 0.0, 0.0);


glTranslatef (-200.0, -50.0, 0.0); // Set translation parameters.
glRecti (50, 100, 200, 150); // Display red, translated rectangle.

glLoadIdentity ( ); // Reset current matrix to identity.


glRotatef (90.0, 0.0, 0.0, 1.0); // Set 90-deg. rotation about z axis.
glRecti (50, 100, 200, 150); // Display red, rotated rectangle.

glLoadIdentity ( ); // Reset current matrix to identity.


glScalef (-0.5, 1.0, 1.0); // Set scale-reflection parameters.
glRecti (50, 100, 200, 150); // Display red, transformed rectangle.

200

150

100
Translated Original Position
Position
50

FIGURE 34
Translating a rectangle using the
150 100 50 50 100 150 200
OpenGL function glTranslatef
(−200.0, −50.0, 0.0).

222
Two-Dimensional Geometric Transformations

200

150

100
Original Position

50
Rotated Position
FIGURE 35
Rotating a rectangle about the z axis
using the OpenGL function
150 100 50 50 100 150 200 glRotatef (90.0, 0.0,
0.0, 1.0).

200

150
Scaled-Reflected
Position

Original Position

50

FIGURE 36
Scaling and reflecting a rectangle using
150 100 50 50 100 150 200 the OpenGL function glScalef
(−0.5, 1.0, 1.0).

11 Summary
The basic geometric transformations are translation, rotation, and scaling. Transla-
tion moves an object in a straight-line path from one position to another. Rotation
moves an object from one position to another along a circular path around a spec-
ified rotation axis. For two-dimensional applications, the rotation path is in the xy
plane about an axis that is parallel to the z axis. Scaling transformations change
the dimensions of an object relative to a fixed position.
We can express two-dimensional transformations as 3 × 3 matrix operators,
so that sequences of transformations can be concatenated into a single composite
matrix. Performing geometric transformations with matrices is an efficient for-
mulation because it allows us to reduce computations by applying a composite
matrix to an object description to obtain its transformed position. To do this, we
express coordinate positions as column matrices. We choose a column-matrix rep-
resentation for coordinate points because this is the standard mathematical con-
vention, and most graphics packages now follow this convention. A three-element
column matrix (vector) is referred to as a homogeneous-coordinate representa-
tion. For geometric transformations, the homogeneous coefficient is assigned the
value 1.
As with two-dimensional systems, transformations between three-
dimensional Cartesian coordinate systems are accomplished with a sequence of
translate-rotate transformations that brings the two systems into coincidence.

223
Two-Dimensional Geometric Transformations

T A B L E 1
Summary of OpenGL Geometric Transformation Functions

Function Description

glTranslate* Specifies translation parameters.

glRotate* Specifies parameters for rotation about any axis


through the origin.
glScale* Specifies scaling parameters with respect to
coordinate origin.
glMatrixMode Specifies current matrix for geometric-viewing
transformations, projection transformations,
texture transformations, or color transformations.
glLoadIdentity Sets current matrix to identity.

glLoadMatrix* (elems); Sets elements of current matrix.


glMultMatrix* (elems); Postmultiplies the current matrix by the
specified matrix.
glPixelZoom Specifies two-dimensional scaling parameters for
raster operations.

However, in a three-dimensional system, we must specify two of the three axis


directions, not just one (as in a two-dimensional system).
The OpenGL basic library contains three functions for applying individual
translate, rotate, and scale transformations to coordinate positions. Each func-
tion generates a matrix that is premultiplied by the modelview matrix. Thus,
a sequence of geometric-transformation functions must be specified in reverse
order: the last transformation invoked is the first to be applied to coordinate
positions. Transformation matrices are applied to subsequently defined objects.
In addition to accumulating transformation sequences in the modelview matrix,
we can set this matrix to the identity or some other matrix. We can also form
products with the modelview matrix and any specified matrices. Several opera-
tions are available in OpenGL for performing raster transformations. A block of
pixels can be translated, rotated, scaled, or reflected with these OpenGL raster
operations.
Table 1 summarizes the OpenGL geometric-transformation functions and
matrix routines discussed in this chapter.

REFERENCES
For additional techniques involving matrices and geo- Woo, et al. (1999). Programming examples for
metric transformations, see Glassner (1990), Arvo (1991), the OpenGL geometric-transformation functions
Kirk (1992), Heckbert (1994), and Paeth (1995). Discus- are also available at Nate Robins’s tutorial web-
sions of homogeneous coordinates in computer graphics site: http://www.xmission.com/∼nate/opengl.html.
can be found in Blinn and Newell (1978) and in Blinn Finally, a complete listing of OpenGL geometric-
(1993, 1996, and 1998). transformation functions is provided in Shreiner
Additional programming examples using OpenGL (2000).
geometric-transformation functions are given in

224
Three-Dimensional
Geometric Transformations

1 Three-Dimensional Translation
2 Three-Dimensional Rotation
3 Three-Dimensional Scaling
4 Composite Three-Dimensional
Transformations
5 Other Three-Dimensional
Transformations
6 Transformations between
Three-Dimensional Coordinate
Systems
7 Affine Transformations
8 OpenGL Geometric-Transformation
Functions
9 OpenGL Three-Dimensional
Geometric- Transformation
Programming Examples
10 Summary

M ethods for geometric transformations in three dimensions


are extended from two-dimensional methods by includ-
ing considerations for the z coordinate. In most cases, this
extension is relatively straighforward. However, in some cases—
particularly, rotation—the extension to three dimensions is less
obvious.
When we discussed two-dimensional rotations in the xy plane,
we needed to consider only rotations about axes that were perpendic-
ular to the xy plane. In three-dimensional space, we can now select
any spatial orientation for the rotation axis. Some graphics packages
handle three-dimensional rotation as a composite of three rotations,
one for each of the three Cartesian axes. Alternatively, we can set up
general rotation equations, given the orientation of a rotation axis
and the required rotation angle.
A three-dimensional position, expressed in homogeneous coor-
dinates, is represented as a four-element column vector. Thus, each
geometric transformation operator is now a 4 × 4 matrix, which

From Chapter 9 of Computer Graphics with OpenGL®, Fourth Edition, Donald Hearn, M. Pauline Baker, Warren R. Carithers.
Copyright © 2011 by Pearson Education, Inc. Published by Pearson Prentice Hall. All rights reserved.
273
Three-Dimensional Geometric Transformations

premultiplies a coordinate column vector. In addition, as in two dimensions, any sequence


of transformations is represented as a single matrix, formed by concatenating the matri-
ces for the individual transformations in the sequence. Each successive matrix in a trans-
formation sequence is concatenated to the left of previous transformation matrices.

1 Three-Dimensional Translation
A position P = (x, y, z) in three-dimensional space is translated to a location P =
(x  , y , z ) by adding translation distances tx , ty , and tz to the Cartesian coordinates
of P:

x  = x + tx , y = y + ty , z = z + tz (1)

Figure 1 illustrates three-dimensional point translation.


We can express these three-dimensional translation operations in matrix form.
But now the coordinate positions, P and P , are represented in homogeneous
coordinates with four- element column matrices, and the translation operator T
is a 4 × 4 matrix:

⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x 1 0 0 tx x
⎢ y ⎥ ⎢ 0 1 0 ty ⎥ ⎢ y ⎥
⎢ ⎥=⎢ ⎥ ⎢ ⎥
⎣ z ⎦ ⎣ 0 0 1 tz ⎦ · ⎣ z ⎦ (2)
1 0 0 0 1 1

or

P = T · P (3)

An object is translated in three dimensions by transforming each of the defin-


ing coordinate positions for the object, then reconstructing the object at the new
location. For an object represented as a set of polygon surfaces, we translate each
vertex for each surface (Figure 2) and redisplay the polygon facets at the trans-
lated positions.
The following program segment illustrates construction of a translation
matrix, given an input set of translation parameters.

y axis

(x, y, z)

(x, y, z) T  (tx, ty, tz)

FIGURE 1
Moving a coordinate position with translation vector x axis
T = ( t x , t y , tz ) . z axis

274
Three-Dimensional Geometric Transformations

y axis

(x, y, z)


T  (tx, ty, tz)
(x, y, z)
FIGURE 2
x axis Shifting the position of a three-dimensional object
z axis using translation vector T.

typedef GLfloat Matrix4x4 [4][4];

/* Construct the 4 x 4 identity matrix. */


void matrix4x4SetIdentity (Matrix4x4 matIdent4x4)
{
GLint row, col;

for (row = 0; row < 4; row++)


for (col = 0; col < 4 ; col++)
matIdent4x4 [row][col] = (row == col);
}

void translate3D (GLfloat tx, GLfloat ty, GLfloat tz)


{
Matrix4x4 matTransl3D;

/* Initialize translation matrix to identity. */


matrix4x4SetIdentity (matTransl3D);

matTransl3D [0][3] = tx;


matTransl3D [1][3] = ty;
matTransl3D [2][3] = tz;
}

An inverse of a three-dimensional translation matrix is obtained using the


same procedures that we applied in a two-dimensional translation. That is,
we negate the translation distances tx , ty , and tz . This produces a translation in the
opposite direction, and the product of a translation matrix and its inverse is the
identity matrix.

2 Three-Dimensional Rotation
We can rotate an object about any axis in space, but the easiest rotation axes to
handle are those that are parallel to the Cartesian-coordinate axes. Also, we can use
combinations of coordinate-axis rotations (along with appropriate translations)
to specify a rotation about any other line in space. Therefore, we first consider the
operations involved in coordinate-axis rotations, then we discuss the calculations
needed for other rotation axes.
By convention, positive rotation angles produce counterclockwise rotations
about a coordinate axis, assuming that we are looking in the negative direction
along that coordinate axis (Figure 3). This agrees with our earlier discussion of

275
Three-Dimensional Geometric Transformations

(a)

z
(b)

FIGURE 3 x
Positive rotations about a coordinate axis are
counterclockwise, when looking along the positive z
half of the axis toward the origin. (c)

rotations in two dimensions, where positive rotations in the xy plane are counter-
clockwise about a pivot point (an axis that is parallel to the z axis).

Three-Dimensional Coordinate-Axis Rotations


The two-dimensional z-axis rotation equations are easily extended to three
dimensions, as follows:
x  = x cos θ − y sin θ
y = x sin θ + y cos θ (4)
z = z
Parameter θ specifies the rotation angle about the z axis, and z-coordinate val-
ues are unchanged by this transformation. In homogeneous-coordinate form, the
three-dimensional z-axis rotation equations are
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x cos θ − sin θ 0 0 x
⎢ y ⎥ ⎢ sin θ cos θ 0 0 ⎥ ⎢ y⎥
⎢ ⎥=⎢ ⎥·⎢ ⎥ (5)
⎣z ⎦ ⎣ 0 0 1 0⎦ ⎣ z ⎦
1 0 0 0 1 1

276
Three-Dimensional Geometric Transformations

FIGURE 4
z Rotation of an object about the z axis.

which we can write more compactly as


P = Rz (θ ) · P (6)

Figure 4 illustrates rotation of an object about the z axis.


Transformation equations for rotations about the other two coordinate axes
can be obtained with a cyclic permutation of the coordinate parameters x, y, and
z in Equations 4:
x→y→z→x (7)

Thus, to obtain the x-axis and y-axis rotation transformations, we cyclically


replace x with y, y with z, and z with x, as illustrated in Figure 5.
Substituting permutations 7 into Equations 4, we get the equations for an
x-axis rotation:
y = y cos θ − z sin θ
z = y sin θ + z cos θ (8)

x =x
Rotation of an object around the x axis is demonstrated in Figure 6.
A cyclic permutation of coordinates in Equations 8 gives us the transforma-
tion equations for a y-axis rotation:
z = z cos θ − x sin θ
x  = z sin θ + x cos θ (9)

y =y
An example of y-axis rotation is shown in Figure 7.
An inverse three-dimensional rotation matrix is obtained in the same way
as the inverse rotations in two dimensions. We just replace the angle θ with −θ.

y z x

x y z

z x y
FIGURE 5
Cyclic permutation of the Cartesian-coordinate axes to produce the three sets of coordinate-axis rotation
equations.

277
Three-Dimensional Geometric Transformations

y y

x
x z
FIGURE 6 FIGURE 7
Rotation of an object about the x axis. Rotation of an object about the y axis.

Negative values for rotation angles generate rotations in a clockwise direction,


and the identity matrix is produced when we multiply any rotation matrix by its
inverse. Because only the sine function is affected by the change in sign of the
rotation angle, the inverse matrix can also be obtained by interchanging rows and
columns. That is, we can calculate the inverse of any rotation matrix R by forming
its transpose (R−1 = RT ).

General Three-Dimensional Rotations


A rotation matrix for any axis that does not coincide with a coordinate axis can
be set up as a composite transformation involving combinations of translations
and the coordinate-axis rotations. We first move the designated rotation axis onto
one of the coordinate axes. Then we apply the appropriate rotation matrix for
that coordinate axis. The last step in the transformation sequence is to return the
rotation axis to its original position.
In the special case where an object is to be rotated about an axis that is parallel
to one of the coordinate axes, we attain the desired rotation with the following
transformation sequence:
1. Translate the object so that the rotation axis coincides with the parallel
coordinate axis.
2. Perform the specified rotation about that axis.
3. Translate the object so that the rotation axis is moved back to its original
position.
The steps in this sequence are illustrated in Figure 8. A coordinate position P is
transformed with the sequence shown in this figure as
P = T−1 · Rx (θ ) · T · P (10)

where the composite rotation matrix for the transformation is


R(θ ) = T−1 · Rx (θ ) · T (11)

This composite matrix is of the same form as the two-dimensional transformation


sequence for rotation about an axis that is parallel to the z axis (a pivot point that
is not at the coordinate origin).
When an object is to be rotated about an axis that is not parallel to one of
the coordinate axes, we must perform some additional transformations. In this

278
Three-Dimensional Geometric Transformations

y y

Rot
atio
n Ax u
is

z x z x
(a)
(c)
Original Position of Object
Rotate Object Through Angle u

y y

Rot
atio
n Ax
is

z x z x
FIGURE 8
(b) (d) Sequence of transformations for
Translate Rotation Axis onto x Axis Translate Rotation rotating an object about an axis that is
Axis to Original Position parallel to the x axis.

case, we also need rotations to align the rotation axis with a selected coordinate
axis and then to bring the rotation axis back to its original orientation. Given the
specifications for the rotation axis and the rotation angle, we can accomplish the
required rotation in five steps:
1. Translate the object so that the rotation axis passes through the coordinate
origin.
2. Rotate the object so that the axis of rotation coincides with one of the
coordinate axes.
3. Perform the specified rotation about the selected coordinate axis.
4. Apply inverse rotations to bring the rotation axis back to its original
orientation.
5. Apply the inverse translation to bring the rotation axis back to its original
spatial position.
We can transform the rotation axis onto any one of the three coordinate axes.
The z axis is often a convenient choice, and we next consider a transformation
sequence using the z-axis rotation matrix (Figure 9).
A rotation axis can be defined with two coordinate positions, as in Figure 10,
or with one coordinate point and direction angles (or direction cosines) between
the rotation axis and two of the coordinate axes. We assume that the rotation axis
is defined by two points, as illustrated, and that the direction of rotation is to be
counterclockwise when looking along the axis from P2 to P1 . The components of
the rotation-axis vector are then computed as
V = P2 − P1
= (x2 − x1 , y2 − y1 , z2 − z1 ) (12)

The unit rotation-axis vector u is


V
u= = (a , b, c) (13)
|V|

279
Three-Dimensional Geometric Transformations

y y y
P2 P2

P1 P1 P1
x x P x
2
z z
Initial Step 1 z Step 2
Position Translate Rotate P2
P1 to the Origin onto the z Axis

y y y
P2 P2

P1
P1 P1
u
P x x x
2
z z
FIGURE 9 z Step 3 Step 4 Step 5
Five transformation steps for obtaining Rotate the Rotate the Axis Translate the
a composite matrix for rotation about Object Around the to Its Original Rotation Axis
an arbitrary axis, with the rotation axis z Axis Orientation to Its Original
projected onto the z axis. Position

where the components a , b, and c are the direction cosines for the rotation axis:
y x2 − x1 y2 − y1 z2 − z1
P2 a= , b= , c= (14)
u
|V| |V| |V|
If the rotation is to be in the opposite direction (clockwise when viewing from P2
P1
x
to P1 ), then we would reverse axis vector V and unit vector u so that they point
in the direction from P2 to P1 .
z
The first step in the rotation sequence is to set up the translation matrix
FIGURE 10 that repositions the rotation axis so that it passes through the coordinate ori-
An axis of rotation (dashed line) gin. Because we want a counterclockwise rotation when viewing along the axis
defined with points P1 and P2 . The
from P2 to P1 (Figure 10), we move the point P1 to the origin. (If the rotation had
direction for the unit axis vector u is
determined by the specified rotation been specified in the opposite direction, we would move P2 to the origin.) This
direction. translation matrix is
⎡ ⎤
1 0 0 −x1
⎢ 0 1 0 −y1 ⎥
T=⎢⎣ 0 0 1 −z1 ⎦
⎥ (15)
y
0 0 0 1
which repositions the rotation axis and the object as shown in Figure 11.
u
Next, we formulate the transformations that will put the rotation axis onto
x the z axis. We can use the coordinate-axis rotations to accomplish this alignment
z in two steps, and there are a number of ways to perform these two steps. For this
example, we first rotate about the x axis, then rotate about the y axis. The x-axis
FIGURE 11
Translation of the rotation axis to the
rotation gets vector u into the xz plane, and the y-axis rotation swings u around
coordinate origin. to the z axis. These two rotations are illustrated in Figure 12 for one possible
orientation of vector u.
Because rotation calculations involve sine and cosine functions, we can use
standard vector operations to obtain elements of the two rotation matrices.
A vector dot product can be used to determine the cosine term, and a vector
cross product- can be used to calculate the sine term.

280
Three-Dimensional Geometric Transformations

y y

a
x x
u
z z
(a) (b)
FIGURE 12
Unit vector u is rotated about the x axis to bring it into the x z plane
(a), then it is rotated around the y axis to align it with the z axis (b).

y
We establish the transformation matrix for rotation around the x axis by
determining the values for the sine and cosine of the rotation angle necessary
to get u into the xz plane. This rotation angle is the angle between the projection u u
of u in the yz plane and the positive z axis (Figure 13). If we represent the projec- a
tion of u in the yz plane as the vector u = (0, b, c), then the cosine of the rotation x
angle α can be determined from the dot product of u and the unit vector uz along uz  (0, 0, 1)
z
the z axis:
FIGURE 13
u · uz c Rotation of u around the x axis into
cos α =  = (16)
|u | |uz | d the x z plane is accomplished by
rotating u (the projection of u in the
where d is the magnitude of u : y z plane) through angle α onto the z
 axis.
d= b2 + c2 (17)

Similarly, we can determine the sine of α from the cross-product of u and uz . The
coordinate-independent form of this cross-product is
u × uz = ux |u | |uz | sin α (18)

and the Cartesian form for the cross-product gives us


u × uz = ux · b (19)

Equating the right sides of Equations 18 and 19, and noting that |u | = 1z and
|u | = d, we have
d sin α = b
or
b
sin α = (20)
d
Now that we have determined the values for cos α and sin α in terms of the
components of vector u, we can set up the matrix elements for rotation of this
vector about the x axis and into the xz plane: y
⎡ ⎤
1 0 0 0
⎢ c b ⎥
⎢0 − 0⎥ b
⎢ d d ⎥
Rx (α) = ⎢


⎥ (21)
uz  (0, 0, 1)
⎢0 b c
0 ⎥ x
⎣ d d ⎦ z u  (a, 0, d)
0 0 0 1 FIGURE 14
Rotation of unit vector u (vector u
The next step in the formulation of the transformation sequence is to deter- after rotation into the x z plane) about
mine the matrix that will swing the unit vector in the xz plane counterclockwise the y axis. Positive rotation angle β
around the y axis onto the positive z axis. Figure 14 shows the orientation of aligns u with vector uz .

281
Three-Dimensional Geometric Transformations

the unit vector in the xz plane, resulting from the rotation about the x axis. This
vector, labeled u , has the value a for its x component, because rotation about the
x axis leaves the x component unchanged. Its z component is d (the magnitude of
u ), because vector u has been rotated onto the z axis. Also, the y component of
u is 0 because it now lies in the xz plane. Again, we can determine the cosine
of rotation angle β from the dot product of unit vectors u and uz . Thus,
u · uz
cos β = =d (22)
|u | |uz |
because |uz | = |u | = 1. Comparing the coordinate-independent form of the
cross-product

u × uz = u y |u | |uz | sin β (23)

with the Cartesian form

u × uz = u y · (−a ) (24)

we find that

sin β = −a (25)

Therefore, the transformation matrix for rotation of u about the y axis is
⎡ ⎤
d 0 −a 0
⎢0 1 0 0⎥

R y (β) = ⎣ ⎥ (26)
a 0 d 0⎦
0 0 0 1
With transformation matrices 15, 21, and 26, we have aligned the rota-
tion axis with the positive z axis. The specified rotation angle θ can now be applied
as a rotation about the z axis as follows:
⎡ ⎤
cos θ − sin θ 0 0
⎢ sin θ cos θ 0 0⎥
Rz (θ ) = ⎢
⎣ 0
⎥ (27)
0 1 0⎦
0 0 0 1
To complete the required rotation about the given axis, we need to transform
the rotation axis back to its original position. This is done by applying the inverse
of transformations 15, 21, and 26. The transformation matrix for rotation
about an arbitrary axis can then be expressed as the composition of these seven
individual transformations:

R(θ ) = T−1 · R−1 −1


x (α) · R y (β) · Rz (θ ) · R y (β) · Rx (α) · T (28)

A somewhat quicker, but perhaps less intuitive, method for obtaining the
composite rotation matrix R y (β)·Rx (α) is to use the fact that the composite matrix
for any sequence of three-dimensional rotations is of the form
⎡ ⎤
r11 r12 r13 0
⎢ r21 r22 r23 0 ⎥
R=⎢ ⎣ r31 r32 r33 0 ⎦
⎥ (29)
0 0 0 1
The upper-left 3 × 3 submatrix of this matrix is orthogonal. This means that the
rows (or the columns) of this submatrix form a set of orthogonal unit vectors that

282
Three-Dimensional Geometric Transformations

are rotated by matrix R onto the x, y, and z axes, respectively:


⎡ ⎤ ⎡ ⎤ ⎡ ⎤ ⎡ ⎤ ⎡ ⎤ ⎡ ⎤
r11 1 r21 0 r31 0
⎢ r12 ⎥ ⎢ 0 ⎥ ⎢ r22 ⎥ ⎢ 1 ⎥ ⎢ r32 ⎥ ⎢ 0 ⎥
R·⎢ ⎥ ⎢ ⎥
⎣ r13 ⎦ = ⎣ 0 ⎦ , R·⎢ ⎥ ⎢ ⎥
⎣ r23 ⎦ = ⎣ 0 ⎦ , R·⎢ ⎥ ⎢ ⎥
⎣ r33 ⎦ = ⎣ 1 ⎦ (30)
1 1 1 1 1 1 y
uz  u
uy
Therefore, we can set up a local coordinate system with one of its axes aligned on
the rotation axis. Then the unit vectors for the three coordinate axes are used to
ux
construct the columns of the rotation matrix. Assuming that the rotation axis is
not parallel to any coordinate axis, we could form the following set of local unit x
vectors (Figure 15). z

uz = u FIGURE 15
Local coordinate system for a rotation
u × ux
uy = (31)
axis defined by unit vector u.
|u × ux |
ux = uy × uz
If we express the elements of the unit local vectors for the rotation axis as
ux = (ux1 , ux2 , ux3 )
uy = (uy1 , uy2 , uy3 ) (32)
uz = (uz1 , uz2 , uz3 )
then the required composite matrix, which is equal to the product R y (β) · Rx (α),
is
⎡  ⎤
ux1 ux2 ux3 0
⎢ u uy2 uy3 0 ⎥
⎢ ⎥
R = ⎢ y1 ⎥ (33)
⎣ uz1 uz2 uz3 0 ⎦
0 0 0 1
This matrix transforms the unit vectors ux , uy ,
and uz onto the x, y, and z axes,
respectively. This aligns the rotation axis with the z axis, because uz = u.

Quaternion Methods for Three-Dimensional Rotations


A more efficient method for generating a rotation about an arbitrarily selected axis
is to use a quaternion representation for the rotation transformation. Quaternions,
which are extensions of two-dimensional complex numbers, are useful in a num-
ber of computer-graphics procedures, including the generation of fractal objects.
They require less storage space than 4 × 4 matrices, and it is simpler to write
quaternion procedures for transformation sequences. This is particularly important
in animations, which often require complicated motion sequences and motion
interpolations between two given positions of an object.
One way to characterize a quaternion is as an ordered pair, consisting of a
scalar part and a vector part:
q = (s, v)
We can also think of a quaternion as a higher-order complex number with one
real part (the scalar part) and three complex parts (the elements of vector v). A
rotation about any axis passing through the coordinate origin is accomplished by
first setting up a unit quaternion with the scalar and vector parts as follows:
θ θ
s = cos , v = u sin (34)
2 2

283
Three-Dimensional Geometric Transformations

y
where u is a unit vector along the selected rotation axis and θ is the specified
u rotation angle about this axis (Figure 16). Any point position P that is to be
u rotated by this quaternion can be represented in quaternion notation as
P = (0, p)
x

z with the coordinates of the point as the vector part p = (x, y, z). The rotation of
the point is then carried out with the quaternion operation
F I G U R E 16
Unit quaternion parameters θ and u P = q Pq −1 (35)
for rotation about a specified axis.
where q −1 = (s, −v) is the inverse of the unit quaternion q with the scalar and
vector parts given in Equations 34. This transformation produces the following
new quaternion:
P = (0, p ) (36)

The second term in this ordered pair is the rotated point position p , which is
evaluated with vector dot and cross-products as
p = s 2 p + v(p · v) + 2s(v × p) + v × (v × p) (37)

Values for parameters s and v are obtained from the expressions in 34. Many
computer graphics systems use efficient hardware implementations of these vec-
tor calculations to perform rapid three-dimensional object rotations.
Transformation 35 is equivalent to rotation about an axis that passes through
the coordinate origin. This is the same as the sequence of rotation transformations
in Equation 28 that aligns the rotation axis with the z axis, rotates about z, and
then returns the rotation axis to its original orientation at the coordinate origin.
We can evaluate the terms in Equation 37 using the definition for quaternion
multiplication. Also, designating the components of the vector part of q as v =
(a , b, c) , we obtain the elements for the composite rotation matrix R−1 −1
x (α) · R y (β)
· Rz (θ) · R y (β) · Rx (α) in a 3 × 3 form as
⎡ ⎤
1 − 2b 2 − 2c 2 2a b − 2sc 2a c + 2sb
M R (θ) = ⎣ 2a b + 2sc 1 − 2a 2 − 2c 2 2bc − 2sa ⎦ (38)
2a c − 2sb 2bc + 2sa 1 − 2a 2 − 2b 2
The calculations involved in this matrix can be greatly reduced by substituting
explicit values for parameters a , b, c, and s, and then using the following trigono-
metric identities to simplify the terms:
θ θ θ θ θ
cos2 − sin2 = 1 − 2 sin2 = cos θ, 2 cos sin = sin θ
2 2 2 2 2
Thus, we can rewrite Matrix 38 as
M R (θ ) =
⎡ ⎤
u2x (1 − cos θ) + cos θ ux u y (1 − cos θ) − uz sin θ ux uz (1 − cos θ) + u y sin θ
⎣ u y ux (1 − cos θ) + uz sin θ u2y (1 − cos θ) + cos θ u y uz (1 − cos θ) − ux sin θ ⎦
uz ux (1 − cos θ) − u y sin θ uz u y (1 − cos θ) + ux sin θ u2z (1 − cos θ) + cos θ
(39)
where ux , u y , and uz are the components of the unit axis vector u.
To complete the transformation sequence for rotating about an arbitrarily
placed rotation axis, we need to include the translations that move the rotation
axis to the coordinate axis and return it to its original position. Thus, the complete
quaternion rotation expression, corresponding to Equation 28, is
R(θ) = T−1 · M R · T (40)

284
Three-Dimensional Geometric Transformations

For example, we can perform a rotation about the z axis by setting rotation-
axis vector u to the unit z-axis vector (0, 0, 1). Substituting the components of this
vector into Matrix 39, we get the 3 × 3 version of the z-axis rotation matrix R z (θ )
in Equation 5. Similarly, substituting the unit-quaternion rotation values into
Equation 35 produces the rotated coordinate values in Equations 4.
In the following code, we give examples of procedures that could be used to
construct a three-dimensional rotation matrix. The quaternion representation in
Equation 40 is used to set up the matrix elements for a general three-dimensional
rotation.

class wcPt3D {
public:
GLfloat x, y, z;
};
typedef float Matrix4x4 [4][4];

Matrix4x4 matRot;

/* Construct the 4 x 4 identity matrix. */


void matrix4x4SetIdentity (Matrix4x4 matIdent4x4)
{
GLint row, col;

for (row = 0; row < 4; row++)


for (col = 0; col < 4 ; col++)
matIdent4x4 [row][col] = (row == col);
}

/* Premultiply matrix m1 by matrix m2, store result in m2. */


void matrix4x4PreMultiply (Matrix4x4 m1, Matrix4x4 m2)
{
GLint row, col;
Matrix4x4 matTemp;

for (row = 0; row < 4; row++)


for (col = 0; col < 4 ; col++)
matTemp [row][col] = m1 [row][0] * m2 [0][col] + m1 [row][1] *
m2 [1][col] + m1 [row][2] * m2 [2][col] +
m1 [row][3] * m2 [3][col];
for (row = 0; row < 4; row++)
for (col = 0; col < 4; col++)
m2 [row][col] = matTemp [row][col];
}

void translate3D (GLfloat tx, GLfloat ty, GLfloat tz)


{
Matrix4x4 matTransl3D;

/* Initialize translation matrix to identity. */


matrix4x4SetIdentity (matTransl3D);

matTransl3D [0][3] = tx;


matTransl3D [1][3] = ty;
matTransl3D [2][3] = tz;

285
Three-Dimensional Geometric Transformations

/* Concatenate translation matrix with matRot. */


matrix4x4PreMultiply (matTransl3D, matRot);
}

void rotate3D (wcPt3D p1, wcPt3D p2, GLfloat radianAngle)


{
Matrix4x4 matQuaternionRot;

GLfloat axisVectLength = sqrt ((p2.x - p1.x) * (p2.x - p1.x) +


(p2.y - p1.y) * (p2.y - p1.y) +
(p2.z - p1.z) * (p2.z - p1.z));
GLfloat cosA = cos (radianAngle);
GLfloat oneC = 1 - cosA;
GLfloat sinA = sin (radianAngle);
GLfloat ux = (p2.x - p1.x) / axisVectLength;
GLfloat uy = (p2.y - p1.y) / axisVectLength;
GLfloat uz = (p2.z - p1.z) / axisVectLength;

/* Set up translation matrix for moving p1 to origin. */


translate3D (-p1.x, -p1.y, -p1.z);

/* Initialize matQuaternionRot to identity matrix. */


matrix4x4SetIdentity (matQuaternionRot);

matQuaternionRot [0][0] = ux*ux*oneC + cosA;


matQuaternionRot [0][1] = ux*uy*oneC - uz*sinA;
matQuaternionRot [0][2] = ux*uz*oneC + uy*sinA;
matQuaternionRot [1][0] = uy*ux*oneC + uz*sinA;
matQuaternionRot [1][1] = uy*uy*oneC + cosA;
matQuaternionRot [1][2] = uy*uz*oneC - ux*sinA;
matQuaternionRot [2][0] = uz*ux*oneC - uy*sinA;
matQuaternionRot [2][1] = uz*uy*oneC + ux*sinA;
matQuaternionRot [2][2] = uz*uz*oneC + cosA;

/* Combine matQuaternionRot with translation matrix. */


matrix4x4PreMultiply (matQuaternionRot, matRot);

/* Set up inverse matTransl3D and concatenate with


* product of previous two matrices.
*/
translate3D (p1.x, p1.y, p1.z);
}

void displayFcn (void)


{
/* Input rotation parameters. */

/* Initialize matRot to identity matrix: */


matrix4x4SetIdentity (matRot);

/* Pass rotation parameters to procedure rotate3D. */

/* Display rotated object. */


}

286
Three-Dimensional Geometric Transformations

FIGURE 17
Doubling the size of an object with transformation 41 also
x
moves the object farther from the origin. z

3 Three-Dimensional Scaling
The matrix expression for the three-dimensional scaling transformation of a
position P = (x, y, z) relative to the coordinate origin is a simple extension of
two-dimensional scaling. We just include the parameter for z-coordinate scaling
in the transformation matrix:
⎡ ⎤ ⎡ ⎤ ⎡ ⎤
x sx 0 0 0 x
⎢ y ⎥ ⎢ 0 s y 0 0 ⎥ ⎢ y ⎥
⎢ ⎥=⎢ ⎥ ⎢ ⎥
⎣ z ⎦ ⎣ 0 0 sz 0 ⎦ · ⎣ z ⎦ (41)
1 0 0 0 1 1

The three-dimensional scaling transformation for a point position can be repre-


sented as
P = S · P (42)

where scaling parameters sx , s y , and sz are assigned any positive values. Explicit
expressions for the scaling transformation relative to the origin are

x  = x · sx , y = y · s y , z = z · sz (43)

Scaling an object with transformation 41 changes the position of the object


relative to the coordinate origin. A parameter value greater than 1 moves a point
farther from the origin in the corresponding coordinate direction. Similarly, a
parameter value less than 1 moves a point closer to the origin in that coordinate
direction. Also, if the scaling parameters are not all equal, relative dimensions of a
transformed object are changed. We preserve the original shape of an object with
a uniform scaling: sx = s y = sz . The result of scaling an object uniformly, with each
scaling parameter set to 2, is illustrated in Figure 17 .
Because some graphics packages provide only a routine that scales relative
to the coordinate origin, we can always construct a scaling transformation with
respect to any selected fixed position (x f , y f , z f ) using the following transformation
sequence:

1. Translate the fixed point to the origin.


2. Apply the scaling transformation relative to the coordinate origin using
Equation 41.
3. Translate the fixed point back to its original position.

This sequence of transformations is demonstrated in Figure 18. The matrix


representation for an arbitrary fixed-point scaling can then be expressed as the

287
Three-Dimensional Geometric Transformations

y concatenation of these translate-scale-translate transformations:

⎡ ⎤
sx 0 0 (1 − sx )x f
⎢0 sy 0 (1 − s y )y f ⎥
T(x f , y f , z f ) · S(sx , s y , sz ) · T(−x f , −y f , −z f ) = ⎢
⎣0
⎥ (44)
(1 − sz )z f ⎦
(xF, yF, zF)
0 sz
0 0 0 1
z x
Original Position
(a) We can set up programming procedures for constructing a three-dimensional
scaling matrix using either a translate-scale-translate sequence or a direct incorpo-
ration of the fixed-point coordinates. In the following code example, we demon-
y strate a direct construction of a three-dimensional scaling matrix relative to a
selected fixed point using the calculations in Equation 44:

(xF, yF, zF) class wcPt3D


{
z x private:
Translate GLfloat x, y, z;
(b)
public:
/* Default Constructor:
y * Initialize position as (0.0, 0.0, 0.0).
*/
wcPt3D ( ) {
x = y = z = 0.0;
(xF, yF, zF)
}

setCoords (GLfloat xCoord, GLfloat yCoord, GLfloat zCoord) {


z x
Scale x = xCoord;
(c) y = yCoord;
z = zCoord;
}
y
GLfloat getx ( ) const {
return x;
}

(xF, yF, zF) GLfloat gety ( ) const {


return y;
z x }
Inverse Translate
(d) GLfloat getz ( ) const {
FIGURE 18 return z;
A sequence of transformations for }
scaling an object relative to a selected };
fixed point, using Equation 41.
typedef float Matrix4x4 [4][4];

void scale3D (GLfloat sx, GLfloat sy, GLfloat sz, wcPt3D fixedPt)
{
Matrix4x4 matScale3D;

/* Initialize scaling matrix to identity. */


matrix4x4SetIdentity (matScale3D);

288
Three-Dimensional Geometric Transformations

matScale3D [0][0] = sx;


matScale3D [0][3] = (1 - sx) * fixedPt.getx ( );
matScale3D [1][1] = sy;
matScale3D [1][3] = (1 - sy) * fixedPt.gety ( );
matScale3D [2][2] = sz;
matScale3D [2][3] = (1 - sz) * fixedPt.getz ( );
}

An inverse, three-dimensional scaling matrix is set up for either Equation 41


or Equation 44 by replacing each scaling parameter (s x, s y , and sz )with its recip-
rocal. However, this inverse transformation is undefined if any scaling parameter
is assigned the value 0. The inverse matrix generates an opposite scaling trans-
formation, and the concatenation of a three-dimensional scaling matrix with its
inverse yields the identity matrix.

4 Composite Three-Dimensional
Transformations
As with two-dimensional transformations, we form a composite three-
dimensional transformation by multiplying the matrix representations for
the individual operations in the transformation sequence. Any of the two-
dimensional transformation sequences, such as scaling in noncoordinate direct-
ions, can be carried out in three-dimensional space.
We can implement a transformation sequence by concatenating the individual
matrices from right to left or from left to right, depending on the order in which
the matrix representations are specified. Of course, the rightmost term in a matrix
product is always the first transformation to be applied to an object and the
leftmost term is always the last transformation. We need to use this ordering for
the matrix product because coordinate positions are represented as four-element
column vectors, which are premultiplied by the composite 4 × 4 transformation
matrix.
The following program provides example routines for constructing a three-
dimensional composite transformation matrix. The three basic geometric trans-
formations are combined in a selected order to produce a single composite matrix,
which is initialized to the identity matrix. For this example, we first rotate, then
scale, then translate. We choose a left-to-right evaluation of the composite matrix
so that the transformations are called in the order that they are to be applied.
Thus, as each matrix is constructed, it is concatenated on the left of the current
composite matrix to form the updated product matrix.

class wcPt3D {
public:
GLfloat x, y, z;
};
typedef GLfloat Matrix4x4 [4][4];

Matrix4x4 matComposite;

/* Construct the 4 x 4 identity matrix. */


void matrix4x4SetIdentity (Matrix4x4 matIdent4x4)

289
Three-Dimensional Geometric Transformations

{
GLint row, col;

for (row = 0; row < 4; row++)


for (col = 0; col < 4 ; col++)
matIdent4x4 [row][col] = (row == col);
}

/* Premultiply matrix m1 by matrix m2, store result in m2. */


void matrix4x4PreMultiply (Matrix4x4 m1, Matrix4x4 m2)
{
GLint row, col;
Matrix4x4 matTemp;

for (row = 0; row < 4; row++)


for (col = 0; col < 4 ; col++)
matTemp [row][col] = m1 [row][0] * m2 [0][col] + m1 [row][1] *
m2 [1][col] + m1 [row][2] * m2 [2][col] +
m1 [row][3] * m2 [3][col];
for (row = 0; row < 4; row++)
for (col = 0; col < 4; col++)
m2 [row][col] = matTemp [row][col];
}

/* Procedure for generating 3-D translation matrix. */


void translate3D (GLfloat tx, GLfloat ty, GLfloat tz)
{
Matrix4x4 matTransl3D;

/* Initialize translation matrix to identity. */


matrix4x4SetIdentity (matTransl3D);

matTransl3D [0][3] = tx;


matTransl3D [1][3] = ty;
matTransl3D [2][3] = tz;

/* Concatenate matTransl3D with composite matrix. */


matrix4x4PreMultiply (matTransl3D, matComposite);
}

/* Procedure for generating a quaternion rotation matrix. */


void rotate3D (wcPt3D p1, wcPt3D p2, GLfloat radianAngle)
{
Matrix4x4 matQuatRot;

float axisVectLength = sqrt ((p2.x - p1.x) * (p2.x - p1.x) +


(p2.y - p1.y) * (p2.y - p1.y) +
(p2.z - p1.z) * (p2.z - p1.z));
float cosA = cosf (radianAngle);
float oneC = 1 - cosA;
float sinA = sinf (radianAngle);
float ux = (p2.x - p1.x) / axisVectLength;
float uy = (p2.y - p1.y) / axisVectLength;
float uz = (p2.z - p1.z) / axisVectLength;

/* Set up translation matrix for moving p1 to origin,

290
Three-Dimensional Geometric Transformations

* and concatenate translation matrix with matComposite.


*/
translate3D (-p1.x, -p1.y, -p1.z);

/* Initialize matQuatRot to identity matrix. */


matrix4x4SetIdentity (matQuatRot);

matQuatRot [0][0] = ux*ux*oneC + cosA;


matQuatRot [0][1] = ux*uy*oneC - uz*sinA;
matQuatRot [0][2] = ux*uz*oneC + uy*sinA;
matQuatRot [1][0] = uy*ux*oneC + uz*sinA;
matQuatRot [1][1] = uy*uy*oneC + cosA;
matQuatRot [1][2] = uy*uz*oneC - ux*sinA;
matQuatRot [2][0] = uz*ux*oneC - uy*sinA;
matQuatRot [2][1] = uz*uy*oneC + ux*sinA;
matQuatRot [2][2] = uz*uz*oneC + cosA;

/* Concatenate matQuatRot with composite matrix. */


matrix4x4PreMultiply (matQuatRot, matComposite);

/* Construct inverse translation matrix for p1 and


* concatenate with composite matrix.
*/
translate3D (p1.x, p1.y, p1.z);
}

/* Procedure for generating a 3-D scaling matrix. */


void scale3D (Gfloat sx, GLfloat sy, GLfloat sz, wcPt3D fixedPt)
{
Matrix4x4 matScale3D;

/* Initialize scaling matrix to identity. */


matrix4x4SetIdentity (matScale3D);

matScale3D [0][0] = sx;


matScale3D [0][3] = (1 - sx) * fixedPt.x;
matScale3D [1][1] = sy;
matScale3D [1][3] = (1 - sy) * fixedPt.y;
matScale3D [2][2] = sz;
matScale3D [2][3] = (1 - sz) * fixedPt.z;

/* Concatenate matScale3D with composite matrix. */


matrix4x4PreMultiply (matScale3D, matComposite);
}

void displayFcn (void)


{
/* Input object description. */
/* Input translation, rotation, and scaling parameters. */

/* Set up 3-D viewing-transformation routines. */

/* Initialize matComposite to identity matrix: */


matrix4x4SetIdentity (matComposite);

/* Invoke transformation routines in the order they

291
Three-Dimensional Geometric Transformations

* are to be applied:
*/
rotate3D (p1, p2, radianAngle); // First transformation: Rotate.
scale3D (sx, sy, sz, fixedPt); // Second transformation: Scale.
translate3D (tx, ty, tz); // Final transformation: Translate.

/* Call routines for displaying transformed objects. */


}

5 Other Three-Dimensional Transformations


In addition to translation, rotation, and scaling, the other transformations
discussed for two-dimensional applications are also useful in many three-
dimensional situations. These additional transformations include reflection,
shear, and transformations between coordinate-reference frames.

Three-Dimensional Reflections
A reflection in a three-dimensional space can be performed relative to a selected
reflection axis or with respect to a reflection plane. In general, three-dimensional
reflection matrices are set up similarly to those for two dimensions. Reflections rel-
ative to a given axis are equivalent to 180◦ rotations about that axis. Reflections
with respect to a plane are similar; when the reflection plane is a coordinate
plane (xy, xz, or yz), we can think of the transformation as a 180◦ rotation in
four-dimensional space with a conversion between a left-handed frame and a
right-handed frame.
An example of a reflection that converts coordinate specifications from a right-
handed system to a left-handed system (or vice versa) is shown in Figure 19. This
transformation changes the sign of z coordinates, leaving the values for the x and
y coordinates unchanged. The matrix representation for this reflection relative to
the xy plane is
⎡ ⎤
1 0 0 0
⎢0 1 0 0⎥
Mzreflect = ⎢
⎣ 0 0 −1 0 ⎦
⎥ (45)
0 0 0 1

Transformation matrices for inverting x coordinates or y coordinates are


defined similarly, as reflections relative to the yz plane or to the xz plane,
respectively. Reflections about other planes can be obtained as a combination
of rotations and coordinate-plane reflections.

Reflection
y Relative to the y
xy Plane
FIGURE 19
Conversion of coordinate
specifications between a right-handed z
and a left-handed system can be
x x
carried out with the reflection
transformation 45. z

292
Three-Dimensional Geometric Transformations

Three-Dimensional Shears y
These transformations can be used to modify object shapes, just as in two-
dimensional applications. They are also applied in three-dimensional viewing
transformations for perspective projections. For three-dimensional applications,
we can also generate shears relative to the z axis.
A general z-axis shearing transformation relative to a selected reference x
position is produced with the following matrix:
z
⎡ ⎤ (a)
1 0 shzx −shzx · zref
⎢ 0 1 shzy −shzy · zref ⎥
Mzshear =⎢
⎣0 0

⎦ (46) y
1 0
0 0 0 1

Shearing parameters shzx and shzy can be assigned any real values. The effect of
this transformation matrix is to alter the values for the x and y coordinates by an
amount that is proportional to the distance from zref , while leaving the z coordinate x
unchanged. Plane areas that are perpendicular to the z axis are thus shifted by an z
amount equal to z − zref . An example of the effect of this shearing matrix on a unit (b)
cube is shown in Figure 20 for shearing values sh zx = shzy = 1 and a reference FIGURE 20
position zref = 0. Three-dimensional transformation matrices for an x-axis shear A unit cube (a) is sheared relative to
and a y-axis shear are similar to the two-dimensional matrices. We just need to the origin (b) by Matrix 46, with
add a row and a column for the z-coordinate shearing parameters. shzx = shzy = 1.

6 Transformations between
Three-Dimensional Coordinate Systems
Coordinate-system trans formations are employed in computer-graphics pack-
ages to construct (model) scenes and to implement viewing routines for both
two-dimensional and three-dimensional applications. A transformation matrix for
transferring a two-dimensional scene description from one coordinate system to
another is constructed with operations for superimposing the coordinate axes of
the two systems. The same procedures apply to three-dimensional scene transfers.
We again consider only Cartesian reference frames, and we assume that an
x  y z system is defined with respect to an xyz system. To transfer the xyz coor-
dinate descriptions to the x  y z system, we first set up a translation that brings
the x  y z coordinate origin to the position of the xyz origin. This is followed by a
sequence of rotations that align corresponding coordinate axes. If different scales
are used in the two coordinate systems, a scaling transformation may also be
necessary to compensate for the differences in coordinate intervals.
Figure 21 shows an x  y z coordinate system with origin (x0, y0, z0 ) and unit
axis vectors defined relative to an xyz reference frame. The coordinate origin of

y
y⬘
FIGURE 21
u⬘y
An x  y  z  coordinate system defined within
an x y z system. A scene description is x⬘
(x0, y0, z0) u⬘x
transferred to the new coordinate reference
x
using a transformation sequence that (0, 0, 0) u⬘z
superimposes the x  y  z  frame on the z
x y z axes. z⬘

293
Three-Dimensional Geometric Transformations

the x  y z system is brought into coincidence with the xyz origin using the trans-
lation matrix T(−x0 , −y0 , −z0 ). Also, we can use the unit axis vectors to form the
coordinate-axis rotation matrix
⎡  ⎤
ux1 ux2 ux3 0
⎢ u uy2 uy3 0 ⎥
⎢ ⎥
R = ⎢ y1 ⎥ (47)
⎣ uz1 uz2 uz3 0 ⎦
0 0 0 1
which transforms unit vectors ux , uy , and uz onto the x, y, and z axes, respectively.
The complete coordinate transformation sequence is then given by the composite
matrix R · T. This matrix correctly transforms coordinate descriptions from one
Cartesian system to another, even if one system is left-handed and the other is
right-handed.

7 Affine Transformations
A coordinate transformation of the form
x  = a xx x + a xy y + a xz z + b x
y = a yx x + a yy y + a yz z + b y (48)
z = a zx x + a zy y + a zz z + b z
is called an affine transformation. Each of the transformed coordinates x  , y , and
z is a linear function of the original coordinates x, y, and z, and parameters a i j and
b k are constants determined by the transformation type. Affine transformations
(in two dimensions, three dimensions, or higher dimensions) have the general
properties that parallel lines are transformed into parallel lines, and finite points
map to finite points.
Translation, rotation, scaling, reflection, and shear are examples of affine trans-
formations. We can always express any affine transformation as some composition
of these five transformations. Another example of an affine transformation is the
conversion of coordinate descriptions for a scene from one reference system to
another because this transformation can be described as a combination of trans-
lation and rotation. An affine transformation involving only translation, rotation,
and reflection preserves angles and lengths, as well as parallel lines. For each of
these three transformations, line lengths and the angle between any two lines
remain the same after the transformation.

8 OpenGL Geometric-Transformation
Functions
The basic OpenGL functions for performing geometric transformations are the
same functions used to perform transformations in three dimensions. For con-
venience, those functions are listed in Table 1 at the end of the chapter.

OpenGL Matrix Stacks


You are already familiar with the OpenGL modelview mode. This mode is se-
lected with the glMatrixMode routine and is used to select the modelview

294
Three-Dimensional Geometric Transformations

composite transformation matrix as the target of subsequent OpenGL transfor-


mation calls.
For each of the four modes (modelview, projection, texture, and color) that we
can select with the glMatrixMode function, OpenGL maintains a matrix stack.
Initially, each stack contains only the identity matrix. At any time during the pro-
cessing of a scene, the top matrix on each stack is called the “current matrix”
for that mode. After we specify the viewing and geometric transformations, the
top of the modelview matrix stack is the 4 × 4 composite matrix that combines
the viewing transformations and the various geometric transformations that we
want to apply to a scene. In some cases, we may want to create multiple views and
transformation sequences, and then save the composite matrix for each. Therefore,
OpenGL supports a modelview stack depth of at least 32, and some implemen-
tations may allow more than 32 matrices to be saved on the modelview stack.
We can determine the number of positions available in the modelview stack for a
particular implementation of OpenGL with

glGetIntegerv (GL_MAX_MODELVIEW_STACK_DEPTH, stackSize);

which returns a single integer value to array stackSize. The other three matrix
modes have a minimum stack depth of 2, and we can determine the maxi-
mum available depth of each for a particular implementation using one of the
following OpenGL symbolic constants: GL MAX PROJECTION STACK DEPTH,
GL MAX TEXTURE STACK DEPTH, or GL MAX COLOR STACK DEPTH.
We can also find out how many matrices are currently in the stack with

glGetIntegerv (GL_MODELVIEW_STACK_DEPTH, numMats);

Initially, the modelview stack contains only the identity matrix, so the value 1 is
returned by this function if we issue the query before any stack processing has
occurred. Similar symbolic constants are available for determining the number of
matrices currently in the other three stacks.
We have two functions available in OpenGL for processing the matrices in
a stack. These stack-processing functions are more efficient than manipulating
the stack matrices individually, particularly when the stack functions are imple-
mented in hardware. For example, a hardware implementation can copy multiple
matrix elements simultaneously. And we can maintain an identity matrix on the
stack, so that initializations of the current matrix can be performed faster than by
using repeated calls to glLoadIdentity.
With the following function, we copy the current matrix at the top of the active
stack and store that copy in the second stack position:

glPushMatrix ( );

This gives us duplicate matrices at the top two positions of the stack. The other
stack function is

glPopMatrix ( );

which destroys the matrix at the top of the stack, and the second matrix in the
stack becomes the current matrix. To “pop” the top of the stack, there must be at
least two matrices in the stack. Otherwise, we generate an error.

295
Three-Dimensional Geometric Transformations

9 OpenGL Three-Dimensional Geometric-


Transformation Programming Examples
Usually, it is more efficient to use the stack-processing functions than to use the
matrix-manipulation functions. This is particularly true when we want to make
several changes in the viewing or geometric transformations. In the following
code, we perform rectangle transformations using stack processing instead of the
glLoadIdentity function:

glMatrixMode (GL_MODELVIEW);

glColor3f (0.0, 0.0, 1.0); // Set current color to blue.


glRecti (50, 100, 200, 150); // Display blue rectangle.

glPushMatrix ( ); // Make copy of identity (top) matrix.


glColor3f (1.0, 0.0, 0.0); // Set current color to red.

glTranslatef (-200.0, -50.0, 0.0); // Set translation parameters.


glRecti (50, 100, 200, 150); // Display red, translated rectangle.

glPopMatrix ( ); // Throw away the translation matrix.


glPushMatrix ( ); // Make copy of identity (top) matrix.

glRotatef (90.0, 0.0, 0.0, 1.0); // Set 90-deg. rotation about z axis.
glRecti (50, 100, 200, 150); // Display red, rotated rectangle.

glPopMatrix ( ); // Throw away the rotation matrix.


glScalef (-0.5, 1.0, 1.0); // Set scale-reflection parameters.
glRecti (50, 100, 200, 150); // Display red, transformed rectangle.

For our next geometric-transformation programming example, we give an


OpenGL version of the three-dimensional, composite-transformation code in Sec-
tion 4. Because OpenGL postmultiplies transformation matrices as they are
called, we must now invoke the transformations in the opposite order from which
they are to be applied. Thus, each subsequent transformation call concatenates the
designated transformation matrix on the right of the composite matrix. Because
we have not yet explored the three-dimensional OpenGL viewing routines, this
p rogram could be completed using two-dimensional OpenGL viewing operations
and applying the geometric transformations to objects in the xy plane.

class wcPt3D {
public:
GLfloat x, y, z;
};

/* Procedure for generating a matrix for rotation about

296
Three-Dimensional Geometric Transformations

* an axis defined with points p1 and p2.


*/
void rotate3D (wcPt3D p1, wcPt3D p2, GLfloat thetaDegrees)
{
/* Set up components for rotation-axis vector. */
float vx = (p2.x - p1.x);
float vy = (p2.y - p1.y);
float vz = (p2.z - p1.z);

/* Specify translate-rotate-translate sequence in reverse order: */


glTranslatef (p1.x, p1.y, p1.z); // Move p1 back to original position.
/* Rotate about axis through origin: */
glRotatef (thetaDegrees, vx, vy, vz);
glTranslatef (-p1.x, -p1.y, -p1.z); // Translate p1 to origin.
}

/* Procedure for generating a matrix for a scaling


* transformation with respect to an arbitrary fixed point.
*/
void scale3D (GLfloat sx, GLfloat sy, GLfloat sz, wcPt3D fixedPt)
{
/* Specify translate-scale-translate sequence in reverse order: */
/* (3) Translate fixed point back to original position: */
glTranslatef (fixedPt.x, fixedPt.y, fixedPt.z);
glScalef (sx, sy, sz); // (2) Scale with respect to origin.
/* (1) Translate fixed point to coordinate origin: */
glTranslatef (-fixedPt.x, -fixedPt.y, -fixedPt.z);
}

void displayFcn (void)


{
/* Input object description. */
/* Set up 3D viewing-transformation routines. */
/* Display object. */

glMatrixMode (GL_MODELVIEW);

/* Input translation parameters tx, ty, tz. */


/* Input the defining points, p1 and p2, for the rotation axis. */
/* Input rotation angle in degrees. */
/* Input scaling parameters: sx, sy, sz, and fixedPt. */

/* Invoke geometric transformations in reverse order: */


glTranslatef (tx, ty, tz); // Final transformation: Translate.
scale3D (sx, sy, sz, fixedPt); // Second transformation: Scale.
rotate3D (p1, p2, thetaDegrees); // First transformation: Rotate.

/* Call routines for displaying transformed objects. */


}

10 Summary
We can express three-dimensional transformations as 4 × 4 matrix operators, so
that sequences of transformations can be concatenated into a single composite

297
Three-Dimensional Geometric Transformations

T A B L E 1
Summary of OpenGL Geometric Transformation Functions

Function Description

glTranslate* Specifies translation parameters.

glRotate* Specifies parameters for rotation about any axis


through the origin.
glScale* Specifies scaling parameters with respect to
coordinate origin.
glMatrixMode Specifies current matrix for geometric-viewing
transformations, projection transformations,
texture transformations, or color transformations.
glLoadIdentity Sets current matrix to identity.

glLoadMatrix* (elems); Sets elements of current matrix.


glMultMatrix* (elems); Postmultiplies the current matrix by the
specified matrix.
glGetIntegerv Gets max stack depth or current number of matrices
in the stack for the selected matrix mode.
glPushMatrix Copies the top matrix in the stack and store copy in
the second stack position.
glPopMatrix Erases the top matrix in the stack and moves the
second matrix to the top of the stack.
glPixelZoom Specifies two-dimensional scaling parameters for
raster operations.

matrix to allow efficient application of multiple transformations. We use a four-


element column matrix (vector) representation for three-dimensional coordinate
points, representing them using a homogeneous coordinate representation.
We can create composite transformations through matrix multiplications of
translation, rotation, scaling, and other transformations. In general, matrix mul-
tiplications are not commutative. The upper-left 3 × 3 submatrix of a rigid-body
transformation is an orthogonal matrix. Thus, rotation matrices can be formed by
setting the upper-left, 3×3 submatrix equal to the elements of two orthogonal unit
vectors. When the angle is small, we can reduce rotation computations by using
first-order approximations for the sine and cosine functions. Over many rotational
steps, however, the approximation error can accumulate to a significant value.
Transformations between Cartesian coordinate systems in three dimensions
are accomplished with a sequence of translate-rotate transformations that brings
the two systems into coincidence. We specify the coordinate origin and axis vectors
for one reference frame relative to the original coordinate reference frame. The
transfer of object descriptions from the original coordinate system to the second
system is calculated as the matrix product of a translation that moves the new
origin to the old coordinate origin and a rotation to align the two sets of axes. The
rotation needed to align the two frames can be obtained from the orthonormal set
of axis vectors for the new system.

298
Three-Dimensional Geometric Transformations

The OpenGL library provides functions for applying individual translate,


rotate, and scale transformations to coordinate positions. Each function generates
a matrix that is premultiplied by the modelview matrix. Transformation matrices
are applied to subsequently defined objects. In addition to accumulating transfor-
mation sequences in the modelview matrix, we can set this matrix to the identity
or some other matrix, and can also form products with the modelview matrix
and any specified matrices. All matrices are stored in stacks, and OpenGL main-
tains four stacks for the various types of transformations that we use in graphics
applications. We can use an OpenGL query function to determine the current stack
size or the maximum allowable stack depth for a system. Two stack-processing
routines are available: one for copying the top matrix in a stack to the second
position, and one for removing the top matrix.
Table 1 summarizes the OpenGL geometric-transformation functions and
matrix routines discussed in this chapter.

REFERENCES
For additional techniques involving matrices and geo- initial position after each complete revolution
metric transformations, see Glassner (1990), Arvo (1991), about the axis.
Kirk (1992), Heckbert (1994), and Paeth (1995). Discus- 7 Derive the three-dimensional transformation
sions of homogeneous coordinates in computer graphics matrix for scaling an object by a scaling factor s in
can be found in Blinn and Newell (1978) and in Blinn a direction defined by the direction cosines α, β,
(1993, 1996, and 1998). and γ .
Additional programming examples using OpenGL
8 Develop a routine to reflect a three-dimensional
geometric-transformation functions are given in Woo,
object about an arbitrarily selected plane.
et al. (1999). Programming examples for the OpenGL
geometric-transformation functions are also available at 9 Write a procedure to shear a three-dimensional
Nate Robins’s tutorial website: http://www.xmission. object with respect to any specified axis, using in-
com/∼nate/opengl.html. Finally, a complete listing of put values for the shearing parameters.
OpenGL geometric-transformation functions is pro- 10 Develop a procedure for converting an object
vided in Shreiner (2000). definition in one three-dimensional coordinate ref-
erence to any other coordinate system defined rel-
ative to the first system.
EXERCISES 11 Develop a routine to scale an object by a given fac-
1 Show that rotation matrix 33 is equal to the com- tor in each dimension relative to a given point con-
posite matrix R y (β) · Rx (α). tained within the object.
2 By evaluating the terms in Equation 37, derive
the elements for the general rotation matrix given
in Equation 38.
3 Prove that the quaternion rotation matrix 38
reduces to the matrix representation in Equation
5 when the rotation axis is the coordinate z axis.
4 Prove that Equation 40 is equivalent to the
general rotation transformation given in Equa-
tion 28.
5 Using trigonometric identities, derive the elements
of the quaternion-rotation matrix 39 from 38.
6 Develop a procedure for animating a three-
dimensional object by incrementally rotating it
about any specified axis. Use appropriate approx-
imations to the trigonometric equations to speed
up the calculations, and reset the object to its

299

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy