CS 4465 - Lab
(5)

Translation, Rotation, Scaling, etc

Translation, Rotation, Scaling, etc

Our goals in this lab are:

- To learn about different transformations

Try to use the same computer you have used before. You will complete all the activities during the lab.

Different Transformations in
OpenGL

Today we look at homogeneous coordinates and
the basic translation, scaling and rotation transformations. Translation and
rotation are *rigid body* transformations which preserve lengths and
angles. The general *affine* *transformation* which multiplies a point
in homogeneous coordinates (3rd coordinate = 1) by a matrix with arbitrary
values in the first two rows (but last row 0, 0 , 1 as always) preserves
parallel lines but not lengths or angles.

Here are the 3D versions of these transformations (Note that these are matrices, so they have [ and ] brackets around them). Also, note that this transformation is the same for a point and a vector:

Translation:

1 0 0 d_{x}0 1 0 d_{y}0 0 1 d_{z}0 0 0 1

Scaling:

s_{x}0 0 0

0 s_{y}0 0

0 0 s_{z}0

0 0 0 1

Rotation about z-axis:

cos(t) -sin(t) 0 0

sin(t) cos(t) 0 0

0 0 1 0

0 0 0 1

Rotation about x-axis:

0 0 1 0

0 cos(t) -sin(t) 0

0 sin(t) cos(t) 0

0 0 0 1

Rotation about y-axis:

cos(t) 0 sin(t) 0

0 1 0 0

-sin(t) 0 cos(t) 0

0 0 0 1

These transformations are on the object, not the viewer, but the coordinate
frame is always at the viewer. For example, if we translate an object -4 units
in the z direction, the transformation is the same as:

- the object moves in the negative z direction, or

- the camera moves in the positive direction.

The OpenGL functions for these transformations (rotation) is (e.g.):

void **glRotatef**(GLfloat *angle*, GLfloat
*x*,
GLfloat *y*, GLfloat *z*)

So for example, to rotate by 30 degrees around the y-axis we could call glRotatef(30,0,1,0);

voidSpecifies scale factors along the

glTranslatef

glTranslate

We will begin our OpenGL 3D viewing by constructing a cube. We have to
specify 6 polygonal faces (A, B, C, D, E, and F on the figure below), but each
vertex will be repeated three times (since it is shared by three faces). If we
do a brute-force construction listing all the points our code will repetitious
and hard to change. We will list the 8 vertices in an array and then refer to
them only by index. These 8 vertices are identified by 8 (x,y)
pairs as shown under Vertices in the figure below.

We'll also make a unit cube whose vertex coordinates play a two roles as the coordinate of the vertex and as the (r, g, b) component of the colors of the vertex. Here is idea:

typedef GLfloat point3[3];

//Vertices and the color they represent

point3 p[8]={

{0,0,0}, //black

{0,0,1}, //blue

{1,0,1}, //red+blue - Magenta

{1,0,0}, //red

{0,1,0}, //green

{0,1,1}, //green+blue - Cyan

{1,1,1}, //white

{1,1,0} //red+green - Yellow

};

//Draw a single point

void drawPoint(int i){

glVertex3fv(p[i]);

}

//Draw a faces of the cube - square

void drawFace(int i1,int i2,int i3,int i4){

glBegin(GL_POLYGON);

glColor3fv(p[i1]);

drawPoint(i1);

drawPoint(i2);

drawPoint(i3);

drawPoint(i4);

glEnd();

}

Our display function will include the code:

drawFace(0,3,2,1); //bottom = black,

drawFace(1,2,6,5); //front = blue

drawFace(2,3,7,6); //right side = magenta

drawFace(3,0,4,7); //back side = red

drawFace(4,5,6,7); //top = white

drawFace(5,4,0,1); //left side = yellow

Below is the progrm that creates the cube similar to the one explained
above:

#include <GL/glut.h>

#include
<math.h>

typedef GLfloat point3[3];

point3 p[8]={

{0,0,0}, //black

{0,0,1}, //blue

{1,0,1}, //magenta

{1,0,0}, //red

{0,1,0}, //green

{0,1,1}, //green+blue

{1,1,1}, //white

{1,1,0} //yellow

};

void drawPoint(int
i){

glVertex3fv(p[i]);

}

void drawFace(int i1,int i2,int i3,int
i4){

glBegin(GL_POLYGON);

glColor3fv(p[i1]);

drawPoint(i1);

drawPoint(i2);

drawPoint(i3);

drawPoint(i4);

glEnd();

}

void
myinit(void)

{

/* attributes */

glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */

glColor3f(0.0, 0.0, 0.0); /* draw in black */

/* set up viewing */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(-1, 1, -1, 1,-10,10);

glMatrixMode(GL_MODELVIEW);

glEnable(GL_DEPTH_TEST);

}

void drawCube(){

drawFace(0,3,2,1);

drawFace(1,2,6,5);

drawFace(2,3,7,6);

drawFace(3,0,4,7);

drawFace(4,5,6,7);

drawFace(5,4,0,1);

}

void display( void
)

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window
*/

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glTranslatef(-.5,-.5,-.5);

drawCube();

glFlush(); /* clear buffers */

}

void main(int
argc, char** argv)

{

/* Standard GLUT initialization */

glutInit(&argc,argv);

glutInitDisplayMode (GLUT_SINGLE| GLUT_RGB|GLUT_DEPTH);

glutInitWindowSize(500,500); /* 500 x 500 pixel window */

glutInitWindowPosition(0,0); /* place window top left on display */

glutCreateWindow("Cube"); /* window title */

glutDisplayFunc(display); /* display callback invoked when window opened
*/

myinit();
/* set attributes */

glutMainLoop(); /* enter event loop */

}

Lab Activity
(1)

Before you run this program I want you to do something on the
paper. Either print this image or
get a hard copy from the instructor. This is a blank
cube. Look at the code segments I have shown above in font
red. Mark each corner with numbers 0 through 7 in the same order that the
vertices are assigned in your program. Then, mark the color on each of the
6 sides. Try your best to figure this out as best as you can.

Cut and
paste the above program and run it. You will see a cube on your
screen. It might be hard to see that the image on the screen is really a
cube, because you are looking at one of its side directly from the
front. This is the front side of the cube. You drew that
at: drawFace(1,2,6,5);

You used the first argument for the color,
since the color is blue, then 1 corresponds to (0, 0, 1). You have to
remeber the right-hand rule, so you are going counter-clock-wise in this order:
1 -> 2 -> 6 -> 5.

I am sure
now you can determine whether you have correctly identify all the colors and
corners. But with the above program, you still need to do a few things to
confirm your answer. Hold on and we get to this very
soon.

There is a
glTranslatef(-0.5,-0.5,-0.5);
before the drawCube function call. Why do
we have that? Does that call move the cube to the center of the screen?
Comment that line and run your program again. I
am sure you now can verify what this translation was doing.

Rotation

Suppose we want to rotate the cube by 45 degree around
the y-axis. Based on what we
mentioned at the beginning of the lab, the call for this rotation looks like
this: glRotatef(45, 0, 1,
0);

Did we rotate
the cube around the center of the cube or around the origin (I suppose 0, 0,
0)? Let's run an experiment to answer some of the questions you might have
(write on a piece of paper for yourself). Important: make sure
to comment the glTranslatef line before
you proceed. Pay attention to the location where the cube will appear on
the screen.

a) Run the program as is
(after commenting the glTranslatf), what is the color of the side you are seeing
on the screen? Side 1: -----------

b) Rotate the cube by 90 degree around y-axis, glRotatef(90, 0, 1,
0); What is the color of the
side you see? Side 2: -----------

c) Rotate
the cube by 90 degree around y-axis once more, now you have
two 90 degree rotations, What is the color now? Side 3:
--------

d) Rotate the cube by 90 degree around y-axis
once more, now you have three 90 degree rotations, What is the
color now? Side 4: ---------

e) Rotate the cube by
90 degree around y-axis once more, What is the
color now? Side ?: ---------

The last rotation should have put you back where you were as by that rotation
you have have rotated 360 degrees. If this didn't happen, then there can
be two different problems?

Problem 1: You thought
you have rotated by 90 around y-axis every time, but somehow that was not the
case, i.e., you had a wrong value or incorrect number of
rotations, or incorrect rotation axis.

Problem 2: ___________________

I hope you know what the second problem is. What if you had used
the same color for more than one face.

Did you notice the way the cube appeared on the screen after each
rotation. Basically the cube appeared on the top-right-hand-side twice (a,
b) and on the top-left-hand-side twice (c,d). This should tell you where
the access of rotation was. So, now you can make sure that all your marks
on the paper is correct.

One more experiment. Try to remove all the rotation statements
but keep one:

glRotatef(270, 0, 1,
0);

This rotation is
equivalent to which one of the a, b, c, or d above?

Lab Activity
(2)

Let's try something new. Remove all the
rotations and keep only one rotation around y-axis by 90 degree. Conduct a new
experiment by placing the rotation

a) once by placing it before the
glTranslatef(-0.5, -0.5,
-0.5);

b) and another time by placing it after the
glTranslatef(-0.5, -0.5,
-0.5);

Did you
notice a difference?

Lab Activity
(3)

The glTranslatef(1.0, 0.5, 1.0) will scale the cube by 1/2 on the y-axis and will keep the rest of the
dimensions unchanged. Place this call in your program before the drawCube
function call to see its effect.

Lab Activity
(4)

Before you try start this activity, remove or comment
all the rotation and scaling transformation calls. Please keep the

glTranslatef(-0.5,-0.5,-0.5); in
the program.

Then try the following experiment and compare the results:

1) Rotate the cube by 45 degree
around y-axis

2)
then rotate the resulting cube by 35 degree around z-axis, and

3) then
rotate the resulting cube by 15 around x-axis.

Do you
think the result would have been different if you would reverse these steps,
i.e, you would do 3, then 2, and finally 1?

Lab Activity
(5)

Before you try start this activity, remove or comment
all the rotation and scaling transformation calls. Please only keep the

glTranslatef(-0.5,-0.5,-0.5); in the program.

Then try the following experiment and compare the results:

1) Rotate the cube by 45 degree
around y-axis

2)
Translate the resulting cube by 0.5 on y
axis

3) then rotate the resulting cube by 30 aroud
z-axis