Download as pdf or txt
Download as pdf or txt
You are on page 1of 41

Chapter Three

Transformations
Basic transformation

• Changes in orientation, size, and shape are accomplished with


geometric transformations that alter the coordinate descriptions of
objects.
• The basic geometric transformations are translation, rotation, and
scaling.
Translation

• A translation is applied to an object by repositioning it along a


straight-line path from one coordinate location to another.
• We translate a two-dimensional point by adding translation distances
tx and ty to the original coordinate position (x, y) to move the point to
a new position (x',y').
• x' = x + tx y' = y + ty…………………… equation 3-1
• The translation distance pair (tx, ty) is called a translation vector or
shift vector.
• We can express the translation equations 3-1 as a single matrix
equation by using column vectors to represent coordinate positions
and the translation vector:
• This allows us to write the two-dimensional translation equations in
the matrix form:
• P’=P+T…………….. equation 3-3
• Translation is a rigid-body transformation that moves objects without
deformation.
• That is, every point on the object is translated by the same amount.
glBegin(GL_LINE_STRIP);
//original star made up of line strip glVertex2f((tranX(0.37,i)),(tranY(0,i)));
#include <iostream.h>
glBegin(GL_LINE_STRIP); glVertex2f((tranX(-0.37,i)),(tranY(0,i)));
#include<GL/glut.h>
glVertex2f(0.37,0); glVertex2f((tranX(0.19,i)),(tranY(-0.37,i)));
#include<math.h> glVertex2f((tranX(0.0,i)),(tranY(0.37,i)));
glVertex2f(-0.37,0);
float tranX(float x,float i) glVertex2f((tranX(-0.19,i)),(tranY(-0.37,i)));
glVertex2f(0.19,-0.37);
{ float nx; glVertex2f((tranX(0.37,i)),(tranY(0,i)));
glVertex2f(0.0,0.37);
nx=x+i; glEnd();
glVertex2f(-0.19,-0.37); glFlush();}
return nx; }
glVertex2f(0.37,0); void init()
float tranY(float y,float i)
glEnd(); { glClearColor(0.2,0.4,0.7,0.0);}
{ float ny;
float i=0.6; int main(int argc, char **argv)
ny=y+i;
glColor3f(1.0,1.0,0.0); {
return ny; } glutInit(&argc,argv);
glLineWidth(2.0);
void display()
//translated star by 0.6 in the x and y direction glutCreateWindow("Star translation");
{ init();
glClear(GL_COLOR_BUFFER_BIT); glutDisplayFunc(display);
glColor3f(1.0,1.0,0.0); glutMainLoop();
glLineWidth(2.0); return 0;
}
Scaling
• A scaling transformation alters the size of an object.
• This operation can be carried out for polygons by multiplying the
coordinate values (x, y) of each vertex by scaling factors sx, and sy, to
produce the transformed coordinates (x', y'):
• x’=x* sx, y’=y*sy ……………….. Equation 3-4
• Scaling factor sx, scales objects in the x direction, while sy scales in the
y direction.
• Any positive numeric values can be assigned to the scaling factors sx,
and sy.
• Values less than 1 reduce the size of objects; values greater than 1
produce an enlargement.
• Specifying a value of 1 for both sx, and sy, leaves the size of objects
unchanged. When sx, and sy, are assigned the same value, a uniform
scaling is produced that maintains relative object proportions.
• Unequal values for sx, and sy, result in a differential scaling.
• We can control the location of a scaled object by choosing a position,
called the fixed point that is to remain unchanged after the scaling
transformation.
• Coordinates for the fixed point (xf,yf) can be chosen as one of the
vertices, the object centroid, or any other position.
• A polygon is then scaled relative to the fixed point by scaling the
distance from each vertex to the fixed point.
• For a vertex with coordinates (x, y) the scaled coordinates ( x ', y ') are
calculated as:
#include <iostream.h> void init()
#include<GL/glut.h> {glClearColor(0.2,0.4,0.7,0.0); }
#include<math.h> int main(int argc, char **argv)
float scaleX(float x,float xf=0) {
{ float nx; glVertex2f(0.5,0.5); glutInit(&argc,argv);
nx=(x*0.8)+(xf*(1-0.8)); glVertex2f(0.5,-0.5); glutCreateWindow("Scaling a square");
return nx; } glEnd(); init();
float scaleY(float y, float yf=0) glBegin(GL_LINES); glutDisplayFunc(display);
{ float ny; glVertex2f(0.0,1.0); glutMainLoop();
ny=(y*0.6)+(yf*(1-0.6)); glVertex2f(0.0,-1.0); return 0;
return ny; } glVertex2f(-1.0,0.0); }
void display() glVertex2f(1.0,0.0);
{ glClear(GL_COLOR_BUFFER_BIT); glEnd();
glColor3f(1.0,1.0,0.0); glColor3f(1.0,1.0,1.0);
glBegin(GL_POLYGON); glBegin(GL_POLYGON);
glVertex2f(-0.5,-0.5); glVertex2f((scaleX(-0.5,0.5)),(scaleY(-0.5,-0.5)));
glVertex2f(-0.5,0.5); glVertex2f((scaleX(-0.5,0.5)),(scaleY(0.5,-0.5)));
glVertex2f((scaleX(0.5,0.5)),(scaleY(0.5,-0.5)));
glVertex2f((scaleX(0.5,0.5)),(scaleY(-0.5,-0.5)));
glEnd();
glFlush();}
Rotation
• A two-dimensional rotation is applied to an object by repositioning it
along a circular path in the xy plane.
• To generate a rotation, we specify a rotation angle θ and the position
(xr, yr) of the rotation point (or pivot point) about which the object is
to be rotated.
• Positive values for the rotation angle define counterclockwise
rotations about the pivot point, and negative values rotate objects in
the clockwise direction.
Rotation of an object through angle θ about the pivot point (xr, yr)
• We first determine the transformation equations for rotation of a
point position P when the pivot point is at the coordinate origin.
• The angular and coordinate relationships of the original and
transformed point positions are shown in Fig below.
• In this figure, r is the constant distance of the point from the origin,
angle ∅ is the original angular position of the point from the
horizontal, and θ is the rotation angle.
• Using standard trigonometric identities, we can express the
transformed coordinates in terms of angles θ and ∅ as:
• The original coordinates of the point in polar coordinates are:

• Substituting the second equation into the first, we obtain the


transformation equations for rotating a point at position (x, y)
through an angle θ about the origin:
• Rotation of a point about an arbitrary pivot position is illustrated in
Fig below.
• Using the trigonometric relationships in this figure, we can generalize
the above equation to obtain the transformation equations for
rotation of a point about any specified rotation position (xr,yr).

• As with translations, rotations are rigid-body transformations that


move objects without deformation. Every point on an object is
rotated through the same angle.
glVertex2f(0.0,0.0);
#include <iostream.h> glVertex2f(0.5,0.5);
#include<GL/glut.h> glVertex2f(0.9,0.0);
#include<math.h> glEnd();
float traX(float x,float y, float angle) glBegin(GL_TRIANGLES);
{ float nx; glColor3f(0.3,0.3,0.5);
nx=((x*cos(angle))-(y*sin(angle))); glVertex2f((traX(0.0,0.0,90.0)),(traY(0.0,0.0,90.0)));
return nx; } glVertex2f((traX(0.5,0.5,90.0)),(traY(0.5,0.5,90.0)));
float traY(float x,float y, float angle) glVertex2f((traX(0.9,0.0,90.0)),(traY(0.9,0.0,90.0)));
{ float ny; glEnd();
ny=((x*sin(angle))+(y*cos(angle))); glFlush(); }
return ny; } void init()
void display() { glClearColor(0.2,0.4,0.7,0.0);}
{ int main(int argc, char **argv)
glClear(GL_COLOR_BUFFER_BIT); { glutInit(&argc,argv);
glBegin(GL_TRIANGLES); glutCreateWindow("Rotating triangle");
glColor3f(0.4,0.3,0.2); init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Identity matrix
• In OpenGL we usually work with 4x4 transformation matrices for
several reasons and one of them is that most of the vectors are of size
4.
• The most simple transformation matrix that we can think of is the
identity matrix.
• The identity matrix is an NxN matrix with only 0s except on its
diagonal.
• As you'll see, this transformation matrix leaves a vector completely
unharmed:
Scaling
• When we're scaling a vector we are increasing the length of the arrow
by the amount we'd like to scale, keeping its direction the same.
• Since we're working in either 2 or 3 dimensions we can define scaling
by a vector of 2 or 3 scaling variables, each scaling one axis (x, y or z).
• Let's try scaling the vector 𝑣=(3,2).
ҧ We will scale the vector along the
x-axis by 0.5, thus making it twice as narrow; and we'll scale the
vector by 2 along the y-axis, making it twice as high. Let's see what it
looks like if we scale the vector by (0.5,2) as 𝑠:ҧ
• Keep in mind that OpenGL usually operates in 3D space so for this 2D case we
could set the z-axis scale to 1, leaving it unharmed.
• The scaling operation we just performed is a non-uniform scale, because the
scaling factor is not the same for each axis.
• If the scalar would be equal on all axes it would be called a uniform scale.
• Let's start building a transformation matrix that does the scaling for us.
• We saw from the identity matrix that each of the diagonal elements were
multiplied with its corresponding vector element.
• What if we were to change the 1s in the identity matrix to 3s?
• In that case, we would be multiplying each of the vector elements by a value of 3 and thus effectively
uniformly scale the vector by 3.
• If we represent the scaling variables as (S1,S2,S3) we can define a scaling matrix
on any vector (x,y,z) as:
Note that we keep the 4th scaling value 1. The w component is used for other purposes
Example
• Assume a triangle with pints A(0,0) , B(5,0), C(5,5) and we want to
scale it 1.5 times in x direction and 2 times in y direction. What would
be the new vector (vertex) value of the above punts (A,B and C).
• The homogenous scaling matrix will look like:
1.5 0 0 0
0 2 0 0

0 0 1 0
0 0 0 1
0 5 5 0
0 0 5 0
• The object matrix will look like
1 1 1 1
1 1 1 1
• Resulting scaled matrix will be
1.5 0 0 0 0 5 5 0 0 7.5 7.5 0
0 2 0 0 0 0 5 0 0 0 10 0
• * =
0 0 1 0 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1 1 1

Old New
A(0,0) A(0,0)
B(5,0) B(7.5,0)
C(5,5) C(7.5,10)
Arbitrary Scaling Pivot

• To scale about an arbitrary pivot point P(px, py):


• Translate the object so that P will coincide with the origin: T(-px, -py)
• Scale the object: S(sx, sy)
• Translate the object back: T(px,py)
Translation
• Translation is the process of adding another vector on top of the
original vector to return a new vector with a different position, thus
moving the vector based on a translation vector.
• Just like the scaling matrix there are several locations on a 4-by-4
matrix that we can use to perform certain operations and for
translation those are the top-3 values of the 4th column.
• If we represent the translation vector as (Tx,Ty,Tz) we can define the
translation matrix by:
• This works because all of the translation values are multiplied by the
vector's w column and added to the vector's original values
(remember the matrix-multiplication rules).
• This wouldn't have been possible with a 3-by-3 matrix.
• Homogeneous coordinates
• The w component of a vector is also known as a homogeneous coordinate. To
get the 3D vector from a homogeneous vector we divide the x, y and z
coordinate by its w coordinate. We usually do not notice this since the w
component is 1.0 most of the time. Using homogeneous coordinates has
several advantages: it allows us to do matrix translations on 3D vectors
(without a w component we can't translate vectors)
Example
• To demonstrate the multiplication of two matrices, let's try scaling a
given vector by (2,2,2) and translating it by (1,2,3). Given the
translation and scaling matrices above, the following product is
calculated:
• Notice how we want to scale the vector first, but the scale
transformation comes last in the multiplication. Pay attention to this
when combining transformations or you'll get the opposite of what
you've asked for.
• Now, let's try to transform a vector and see if it worked:
Rotation

• A rotation in 2D or 3D is represented with an angle.


• An angle could be in degrees or radians where a whole circle has 360
degrees or 2 PI radians.
• Rotating half a circle rotates us 360/2 = 180 degrees and rotating
1/5th to the right means we rotate 360/5 = 72 degrees to the right.
This is demonstrated for a basic 2D vector where 𝑣ഥ is rotated 72
degrees to the right, or clockwise, from 𝑘ഥ
• A rotation matrix is defined for each unit axis in 3D space where the
angle is represented as the theta symbol θ.

Rotation around the X-axis


Arbitrary rotation Center

• Translate the object so that P will coincide with the origin(-px, -py)
• Rotate the object: R(q)
• Translate the object back: T(px,py)
• As a matrix multiplication
• p’ = T[px,py] * R[q] * T[-px, -py] * P
• OpenGL manages two 4 × 4 transformation matrices: the modelview
matrix (Model related operations: glBegin, glEnd,glTranslate, glRotate,
glScale, gluLookAt), and the projection
Matrix(glViewport,gluPerspective/glOrtho/glFrustum…).
• Whenever you specify geometry (using glVertex), the vertices are
transformed by the current modelview matrix and then the current
projection matrix.
• Hence, you don’t have to perform these transformations yourself. You
can modify the entries of these matrices at any time. OpenGL
provides several utilities for modifying these matrices.
• The modelview matrix is normally used to represent geometric
transformations of objects; the projection matrix is normally used to store
the camera transformation.
• To modify the current matrix, first specify which matrix is going to be
manipulated: use glMatrixMode(GL MODELVIEW) to modify the modelview
matrix.
• The modelview matrix can then be initialized to the identity with
glLoadIdentity().
• The matrix can be manipulated by directly filling its values, multiplying it by
an arbitrary matrix, or using the functions OpenGL provides to multiply the
matrix by specific transformation matrices (glRotate, glTranslate, and
glScale).
• OpenGL provides a stack to assist with hierarchical transformations.
There is one stack for the modelview matrix and one for the
projection matrix. OpenGL provides routines for pushing and popping
matrices on the stack.
Eg. The following example demonstrates using openGL transformation functions
#include<iostream.h> void display()
#include <GL/glut.h> //rotation of green rectangle specified by the angle
{ glClear(GL_COLOR_BUFFER_BIT);
#include<math.h> glPushMatrix();
//yellow triangle translated by (i,i)
float i=0.1; glLoadIdentity();
glPushMatrix();
float j=-0.1; glRotatef(angle, 0.0f, 0.0f, 1.0f);
glLoadIdentity();
float angle=30; glColor3f(0.0,1.0,0.0);
glTranslatef(i, i,0.0);
float scale =0.1; glBegin(GL_TRIANGLES);
glColor3f(0.8,0.8,0.0);
void update(int value) { glVertex2f(0,0.5);
glBegin(GL_TRIANGLES);
i += 0.2; glVertex2f(-0.5,0.0);
glVertex2f(0,0.5);
j-=0.2; glVertex2f(0.5,0.0);
glVertex2f(-0.5,0.0);
if(i>1) glEnd();
glVertex2f(0.5,0.0);
i=0; glPopMatrix();
glEnd();
if(j<-1) glPopMatrix();
j=0;
angle+=50;
if(angle>360)
angle-=360;
scale+=0.1;
if (scale>0.6)
scale=0.1;
glutPostRedisplay();
glutTimerFunc(1000, update, 0);}
//scaling of red triangle by the point scale
glPushMatrix();
glLoadIdentity(); //rotation ,translation and scaling of a triangle at once
glScalef(scale, scale, 0.0f);
glPushMatrix();
glColor3f(1.0,0.0,0.0);
glBegin(GL_TRIANGLES); glLoadIdentity();
glVertex2f(0,0.5); glRotatef(angle, 0.0f, 0.0f, 1.0f);
glVertex2f(-0.5,0.0); glTranslatef(i, i,0.0);
glVertex2f(0.5,0.0); void init()
glScalef(scale, scale, 0.0f);
glEnd(); {glClearColor(0.0, 0.0, 0.0, 0.0);}
glColor3f(1.0,1.0,1.0);
glPopMatrix(); int main(int argc, char** argv)
glBegin(GL_TRIANGLES);
{ glutInit(&argc,argv);
glVertex2f(0,0.5);
glutInitWindowSize(500, 500);
glVertex2f(-0.5,0.0);
glutCreateWindow("simple");
glVertex2f(0.5,0.0);
glutDisplayFunc(display);
glEnd();
init();
glPopMatrix();
glFlush();} glutTimerFunc(1000, update, 0);
glutMainLoop();}

You might also like