1.1 What Is Modeling Transformation?
1.1 What Is Modeling Transformation?
x∗ = tx + x (1)
∗
y = ty + y (2)
P∗ = T(tx , ty ) + P (3)
x∗ tx x
= + (4)
y∗ ty y
x∗ = sx ∗ x (5)
∗
y = sy ∗ y (6)
where sx and sy are the scaling factors along the x and y axes respectively. Uniform scaling occurs
when sx == sy , otherwise the scaling will be non–uniform resulting into shape distortion. For
example, using scaling factors of sx = 2 and sy = 1.5 on the sample square above will result into
a rectangular shape.
1
(x*, y*)
ty
(x, y)
tx
Figure 1: 2D Translation
Figure 2: 2D Scaling
2
(x*, y*)
(x, y)
Figure 3: 2D Rotation
Enlargement occurs when sx > 1.0 or sy > 1.0. Reduction results when 0.0 < sx < 1.0 or
0.0 < sy < 1.0.
Scaling is expressed in matrix form as
P∗ = S(sx , sy ) P (7)
x∗ sx 0 x
= (8)
y∗ 0 sy y
x = r cos φ (9)
y = r sin φ (10)
Although r and φ are not explicity given, they are determined simply by:
r = x2 + y 2 (11)
y
φ = arctan( ) (12)
x
The unknown coordinates (x∗ , y ∗ ) can then be computed in a similar manner:
x∗ = r cos(φ + θ) (13)
∗
y = r sin(φ + θ) (14)
3
Via sum of angles 1 , we can rewrite the last two equations as:
In matrix form
P∗ = R(θ) P (19)
x∗ cos θ − sin θ x
= (20)
y∗ sin θ cos θ y
The matrix R(θ) is referred to as rotation matrix. Just like in translation and scaling, if there are
n points making up the object, then n rotations need to be applied – one for each point.
P = T(tx , ty ) + P
P = S(sx , sy ) P
P = R(θ) P
• Translation
P∗ = T(tx , ty , tz ) + P (21)
x∗ tx x
y∗ = ty + y (22)
z∗ tz z
1 cos(α± β) = cos α cos β ∓ sin α sin β
sin(α ± β) = sin α cos β ± cos α sin β
4
• Scaling
P∗ = S(sx , sy , sz ) P (23)
x∗ sx 0 0 x
y∗ = 0 sy 0 y (24)
z∗ 0 0 sz z
• Rotation. A 3D point can be rotated about any of the three principal axes (i.e., x, y, z axes)
as indicated below.
P∗ = Rz (θ) P (25)
x∗ cos θ − sin θ 0 x
y∗ = sin θ cos θ 0 y (26)
z∗ 0 0 1 z
P∗ = Rx (θ) P (27)
x∗ 1 0 0 x
y∗ = 0 cos θ − sin θ y (28)
z∗ 0 sin θ cos θ z
P∗ = Ry (θ) P (29)
x∗ cos θ 0 sin θ x
y∗ = 0 1 0 y (30)
z∗ − sin θ 0 cos θ z
• Rotation
Notice that translation involves matrix addition, while the other two transformations involve ma-
trix multiplication. At first glance, the difference in the nature of matrix operation for the said
transformations do not cause any concern. However, the fact that translation is a matrix addition
actually leads to computational inefficiency!
Consider the following scenario. We would like to perform multiple 2D transformations on an
object. For this particular case, first we would like to scale the object by S(sx , sy ); thereafter, the
scaled object will be rotated by R(θ). Assume that point P is one of the points on the object.
5
We perform the transformations sequentially. First, we scale the object:
P = S(sx , sy ) P
x sx 0 x
=
y 0 sy y
sx ∗ x
=
sy ∗ y
P = R(θ) P
x cos θ − sin θ x
=
y sin θ cos θ y
cos θ − sin θ sx ∗ x
=
sin θ cos θ sy ∗ y
(sx ∗ x) cos θ − (sy ∗ y) sin θ
= (31)
(sx ∗ x) sin θ + (sy ∗ y) cos θ
We repeat these two–step transformation for all the points in the object to achieve the desired
effect.
An alternative way to express the two–step transformations described above is as follows:
P = S(sx , sy ) P
P = R(θ)P
The difference here is that instead of multiplying matrix S(sx , sy ) with P as in the previous
discussion, we first substitute P yielding:
The result of pre–multiplying matrices R(θ) and S(sx , sy ) is another matrix. We use the term
concatenate for such pre–multiplication (of transformation matrices), and the term concatenated
matrix to refer to the resulting matrix.
Finally, multiplying the concatenated transformation matrix with P yields:
x sx ∗ x cos θ − sy ∗ y sin θ
= (32)
y sx ∗ x sin θ + sy ∗ y cos θ
The net result as shown in equations (31) and (32) are actually the same. However, the sec-
ond approach (i.e., pre-multiplying the transformation matrices) is more computationally efficient
compared with the first approach when multiple transformations are to be performed on several
points.
Let us prove this claim simply by using as a basis the number of arithmetic operations involved
in the matrix operations.
• First approach:
6
– Multiplying matrix S(sx , sy ) with matrix P requires 4 multiplications and 2 additions
(for a total of 6 arithmetic operations).
– Multiplying matrix R(θ) with matrix P requires 4 multiplications and 2 additions (for
a total of 6 arithemetic operations).
– Thus, there are 12 arithmetic operations involved.
• Second approach:
– Multiplying matrix R(θ) with S(sx , sy ) requires 8 multiplications and 4 additions (for a
total of 12 arithemetic operations).
– Multiplying the concatenated matrix R(θ) S(sx , sy ) with P requires 4 multiplications
and 2 additions (for a total of 6 arithemetic operations).
– Thus, there are 18 arithmetic operations involved.
It seems that the numbers above are contradictory to our claim. However, note that the numbers
are for a single point only. What happens when there are 2 points, 3 points, or more?
For the first approach, 10 arithmetic operations need to be performed for each point. Thus if
there are n points, the total number of operations will be 10 * n.
For the second approach, the concatenated matrix R(θ)S(sx , sy ) needs to be computed only
once! It’s the same for all the points that need to be transformed. Thus if there are n points, the
total number of operations will be 12 + 6 * n which is much less than the number of operations
required compared with that of the first approach as n gets larger. Note that it is not unusual to
transform hundreds or even thousands of points in computer animations.
Unfortunately, we cannot pre–multiply the transformation matrices if there is a translation
involved due to the fact that translation is expressed as a matrix addition!
We know now that the transformation matrices are better pre-multipled for computational effi-
ciency. The problem is, “Is there a way to express translation instead as a matrix multiplication?”
The solution to this problem is to represent the points in homogeneous coordinates.
7
Question. Is the quadruple (5, 10, 15, 0) valid? Think about it! Ask me for the answer in
case I forgot to mention it in our class.
P∗ = T(tx , ty ) P
x∗ 1 0 tx x
y∗ = 0 1 ty y
1 0 0 1 1
x + tx
= y + ty
1
P∗ = T(tx , ty , tz ) P (36)
x∗ 1 0 0 tx x
y∗ 0 1 0 ty y
∗ = (37)
z 0 0 1 tz z
1 0 0 0 1 1
• Scaling
P∗ = S(sx , sy , sz ) P (38)
x∗ sx 0 0 0 x
y∗ 0 sy 0 0 y
∗ = (39)
z 0 0 sz 0 z
1 0 0 0 1 1
• Rotation. A point can be rotated about any of the three principal axes (i.e., x, y, z axes) as
indicated below.
P∗ = Rz (θ) P (40)
x∗ cos θ − sin θ 0 0 x
y∗ sin θ cos θ 0 0 y
∗ = (41)
z 0 0 1 0 z
1 0 0 0 1 1
8
– Rotation of a point about the x axis by an angle θ
P∗ = Rx (θ) P (42)
x∗ 1 0 0 0 x
y∗ 0 cos θ − sin θ 0 y
∗ = (43)
z 0 sin θ cos θ 0 z
1 0 0 0 1 1
P∗ = Ry (θ) P (44)
∗
x cos θ 0 sin θ 0 x
y∗ 0 1 0 0 y
∗ = (45)
z − sin θ 0 cos θ 0 z
1 0 0 0 1 1
P = T(−qx , −qy ) P
P = R(θ) P
P = T(qx , qy ) P
P∗ = M P
where M is used to represent the transformation matrix. M may correspond to a primitive trans-
formation matrix or it maybe a concatenation of several transformation matrices.
In the case of the problem above:
P∗ = P = M P
where
M = T(qx , qy ) R(θ) T(−qx , −qy )
9
1.12 How do you rotate a point about a line parallel to a primary axis?
This problem is the 3D version of the previous subsection. Imagine, for example a line that is
parallel with the a primary axis, say for example, the x axis. Imagine also that this line passes
through a point Q = (qx , qy , qz ). What we want is to rotate an arbitrary point, say P = (px , py , pz ),
about the said line by an angle θ. How do you achieve this?
The solution is again similar in the previous section. First we must do a translation such that
the line passing through Q is collinear with the x axis – moving along with it P. Thereafter, the
rotation about the x axis can then be performed on the translated point P. Finally, an inverse
translation that will reposition the line to its original location should be performed – moving along
with it the rotated point. Expressed mathematically,
glLoadIdentity();
glTranslatef(1, -2, 3);
The semantic of the code is to translate by tx = 1, ty = −2, and tz = 3 the object – in this
case a point with coordinates (1, 1, 1). Thus, the coordinates of the translated point will (2, -1,
4).
Note that the glTranslate*() command should be written before the object to be translated.
Exercise:
• What is the effect of glTranslatef(0.0, 0.0, 0.0)?
• Translate the line along the x axis (maintain the y factor at 0.25).
10
glScalef(0.5, 0.25, 1.0);
glBegin(GL_LINES);
glVertex3f(0.0, 0.25, 0.0);
glVertex3f(0.5, 0.25, 0.0);
glEnd();
Note that the glScale*() command should be written before the object to be scaled.
glLoadIdentity();
gRotatef(45, 0, 0, 1); /* rotate by 45 degrees about the z axis */
glBegin(GL_POINTS);
glVertex(1, 1, 1);
glEnd();
Note that the glRotate*() command should be written before the object to be rotated.
Exercise:
• Try glRotatef(45.0, 1.0, 0.0, 0.0). What is the effect?
• Try glRotatef(45.0, 0.0, 1.0, 0.0). What is the effect?
• Try glRotatef(-45.0, 0.0, 0.0, 1.0). What is the effect?
• Try glRotatef(90.0, 0.0, 0.0, 1.0). What is the effect?
• Try glRotatef(360.0, 0.0, 0.0, 1.0). What is the effect?
11
Determining the proper sequencing of the function, (in the case above – which should be written
first glTranslate*() or glRotate*() in the program code?), is actually the main stumbling block
for the beginning programmer.
The convention is actually very easy, instead of writing the equation horizontally, rewrite it
vertically, i.e.:
Rz (30)
T(1, −2, 3)
P
This is also the sequence in which the commands should be written in the program code, as shown
in the following:
glLoadIdentity();
glRotatef(30, 0, 0, 1);
glTranslatef(1, -2, 3);
glBegin(GL_POINTS);
glVertex(1, 1, 1);
glEnd();
Let us do the inverse. Given the following codes, what is the corresponding mathematical
formulation?
glLoadIdentity();
glScalef(2, 2, 2);
glTranslatef(1, -2, 3);
glRotatef(-45, 0, 1, 0);
glBegin(GL_POINTS);
glVertex(1, 1, 1);
glEnd();
The corresponding equation is:
12
EXERCISE SET 1: Modeling Transformations
I. SIMPLE TRANSFORMATIONS
Assume a point in Cartesian coordinates P = (0.5, 1.0, 2.0). Compute P∗ corresponding to
the following transformations:
(1) P∗ = T(1, 2, 3) P
(2) P∗ = T(−5, 3, −4) P
(3) P∗ = S(0.5, 1.5, 2.0) P
(4) P∗ = S(5, 2, 3) P
(5) P∗ = Rx (45) P
(6) P∗ = Ry (−30) P
(7) P∗ = Rz (10) P
Next, assume a point in homogeneous coordinates Q = (2.0, 4.0, −6.0, 2.0). Compute Q∗
corresponding to the following transformations:
(9) Q∗ = T(1, 2, 3) Q
(10) Q∗ = T(−5, 3, −4) Q
(11) Q∗ = S(0.5, 1.5, 2.0) Q
(12) Q∗ = S(5, 2, 3) Q
(13) Q∗ = Rx (45) Q
(14) Q∗ = Ry (−30) Q
(15) Q∗ = Rz (10) Q
13
(7) first, rotate by Rx (45); then rotate by Rx (15)
(8) first, rotate by Rx (15); then rotate by Rx (45)
• What do you notice about the resulting transformation matrix compared with the
result from the previous problem?
(9) first, rotate by Rx (15); then rotate by Rx (20); and then rotate by Rx (35)
• What do you notice about the resulting transformation matrix compared with the
result from the TWO previous problems?
(10) first, rotate by Ry (45); then rotate by Ry (−45)
• What kind of matrix is the resulting concatenated transformation matrix?
• What do you notice about the rotation angle of the second rotation compared with
that of the first rotation?
(11) first, translate by T(1, 2, 3); then scale by S(2, −4, 0.5)
(12) first, scale by S(2, −4, 0.5); then translate by T(1, 2, 3)
(13) first, translate by T(tx, ty, tz); then rotate by Rz (α); and finally rotate by Rx (β)
(1) Assume a line segment starting from the origin O = (0, 0, 0) to a point P = (1, 1, 0).
Determine the transformation matrix that will rotate this line segment such that after
the transformation:
• the starting point O∗ will still be at the origin
• the end point P∗ will lie on the positive X axis (i.e., the transformed line segment
will be collinear with the X axis)
(2) Assume the same line segment from O = (0, 0, 0) to P = (1, 1, 0). Determine the trans-
formation matrix that will rotate this line segment such that after the transformation:
• the starting point O∗ will still be at the origin
• the end point P∗ will lie on the positive Y axis (i.e., the transformed line segment
will be collinear with the Y axis)
(3) Assume the same line segment from O = (0, 0, 0) to P = (1, 1, 0). Determine the
CONCATENATED transformation matrix that will transform line segment OP such
that after the transformation:
• the starting point O∗ will still be at the origin
14
• the end point P∗ will lie on the positive Z axis (i.e. the transformed line segment
will be collinear with the Z axis)
Hint: you need two rotations to achieve these requirements.
(4) Do the following with reference to the last three problems:
• Compute the length of the line segment from O to P.
• Compute the length of the line segment from O∗ to P∗ for problems 1, 2, and 3.
Does the length of the line segment OP change after each rotation?
(5) Assume a line segment with the following characteristics:
• its starting point, which we denote as O, is at the origin
• its end point, which we denote as P lies on the Y-Z plane (i.e., the x coordinate of
the line segment is zero)
• its length is 1
• the angle between the line segment OP and the Y axis is 30 degrees
a. Draw the X, Y, Z axes and the line segment OP.
b. What are the values of the x, y and z coordinates of P?
c. What is the transformation matrix that will transform OP such that it will start
from the origin, and P∗ will lie on the positive Y axis?
d. What is the transformation matrix that will transform OP such that it will start
from the origin, and P∗ will lie on the positive Z axis?
e. What is the CONCATENATED transformation matrix will transform OP such
that it will start from the origin, and P∗ will lie on the positive X axis (Hint: you
need two rotations in this case)
(6) Note: I gave the following problem in a previous examination at DLSU.
Assume an equilateral triangle with vertices Q0 , Q1 and Q2 positioned on the x-y plane.
(Note: an equilateral triangle is a triangle with three sides having the same length.
Moreover, the angle between two adjacent sides is 60 degrees.). Let the 3D Cartesian
coordinates of point Q0 = (3, 5, 0) while that of Q1 = (5, 5, 0). Q2 is positioned above
Q0 and Q1 (i.e., its y coordinate is greater than that of Q0 and Q1 ). Assume also an
arbitrary point P = (x, y, z).
• Write down the sequence of modeling transformations that will rotate the point P
by an angle of 45 degrees about an axis passing through points Q0 and Q2 .
• Write the contents of the modeling transformation matrix for each step you speci-
fied. Use the actual constant values, not just representative variables. For example,
for a rotation, you have to specify the actual rotation angle and not just any an-
gle (variable) name. You are NOT required to concatenate the matrices in this
problem.
V. PROVING (Hint: set up the corresponding matrices on the left hand side, and on the right
hand side of the equality/inequality).
15
(4) Prove: S(a, b, c) S(e, f, g) = S(a ∗ e, b ∗ f, c ∗ g)
We want to prove that two consecutive scaling is equivalent to a single scaling with
scaling factors are equivalent to the product of the scaling factors (with respect to X, Y
and Z axes respectively) of the two scalings.
(5) Prove: Rx (b) Rx (a) = Rx (a) Rx (b)
We want to prove that two consecutive rotations on the same AXIS is commutative.
(6) Prove: Rx (b) Ry (a) = Ry (a) Rx (b)
We want to prove that two consecutive rotations on different AXES is NOT commuta-
tive.
(7) Prove: Rx (b) Rx (a) = Rx (a + b)
We want to prove that two consecutive rotations on the same AXIS, is equivalent to a
single rotation with a rotation angle equivalent to the sum of the rotation angles of the
two rotations.
VI. OpenGL PROGRAMMING (Note: I hope that youve been trying to learn how to program in
OpenGL. If thats the case, the following problems should prove to be easy.)
(1) This problem is concerned with SIMPLE modeling transformations only. Let a triangle
be defined by the following vertices P0 = (1, 1, 0, 1), P1 = (2, 1, 0, 1) and P2 = (2, 2, 0, 1)
in homogeneous coordinates. Write the OpenGL codes (for the event display() func-
tion) that will transform and draw this triangle as indicated below. Please note that
each item is independent from each other. That is, the effect of item (a) does not carry
over to item (b) and so on . . .
a. Translate with tx = 1, ty = 2, and tz = 3
b. Translate with tx = -5, ty = 3, tz = -4
c. Scale with sx = 5, sy = 2, sz = 3
d. Scale with sx = 0.25, sy = 1.5, sz = 2.5
e. Rotate about x axis clockwise by angle equivalent to π/4 radians
f. Rotate about the z axis counterclockwise by an angle equivalent to 3π/4 radians
g. Rotate about the y axis clockwise by an angle equivalent to 15 degrees
Note: do not write all transformations required above in just one program. Write, and
save one program for each transformation requirement. Thus, you will have SEVEN
separate programs, with the first translating the triangle by tx = 1, ty = 2, and tz = 3,
and with the last program rotating the triangle about the y-axis.
Do not forget to initialize first the current transformation matrix to an identity matrix
before any modeling transformation is applied. You need to do this to avoid accumu-
lation of transformation effects when the event display() function is invoked several
times.
void event_display(void)
{
/* supply the body of this function */
16
a. first translate by T(1, −2, 3); then translate by T(2, 4, −2)
b. first translate by T(2, 4, −2); then translate by T(1, −2, 3)
c. first scale by S(0.5, 1.0, 1.5); then scale by S(2, 3, 4)
d. first scale by S(2, 3, 4); then scale by S(0.5, 1.0, 1.5)
e. first translate by T(2, −3, 4); then rotate by Rx (−45)
f. first rotate by Rx (−45); then translate by T(2, −3, 4)
g. first rotate by Rx (15); then rotate by Ry (−30)
h. first rotate by Ry (−30); then rotate by Rx (15)
i. first rotate by Rx (15); then rotate by Ry (30); and finally rotate by Rz (45)
j. first translate by T(1, 2, 1.5); then rotate by Rz (45); then scale by S(2, 2, 2); and
finally Ry (30)
Note: do not write all transformations required above in just one program. Write,
and save one program for each transformation requirement. Thus, you will have TEN
separate programs.
Do not forget to initialize first the current transformation matrix to an identity matrix
before any modeling transformation is applied. You need to do this to avoid accumu-
lation of transformation effects when the event display() function is invoked several
times.
void event_display(void)
{
/* supply the body of this function */
(3) The following is not really a programming problem. Its more of an OpenGL program
tracing problem. Assume that you are given the following OpenGL code segment:
glTranslatef(1, 2, 3);
glScalef(2, -2, 3);
glRotatef(45, 1, 0, 0);
glLoadIdentity(); /* BE CAREFUL HERE! */
glRotatef(-90, 0, 1, 0); /* note angle is negative */
glTranslatef(1, -1, 1);
glScalef(2, 3, 4);
glBegin(GL_POINTS);
glVertex4f(4, 4, 4, 2); /* note: w = 2 */
glEnd();
a. Compute the contents of the concatenated transformation matrix that will be ap-
plied to the vertex.
b. What are the final CARTESIAN coordinates (not homogeneous coordinates) of the
point when subjected to the concatenated transformation?
17