Computer Graphics Lab 3: Last First
Computer Graphics Lab 3: Last First
2D Transformation
In this section, you will see OpenGL transformation functions. Then, you will implement your own
transformation functions.
Translation:
glTranslatef(tx, ty, tz). There is another variation of this function that takes doubles;
glTranslated(tx, ty, tz): [tx, ty and tz] is the translation vector.
Scaling:
glScalef(sx, sy, sz): where sx, sy and sz are scaling factors in the three directions.
Rotation:
glRotatef(angle, x, y, z): where angle is the angle of rotation in degrees, and x, y, z represent the axis
of rotation. The value that corresponds to the axis of rotation is set to 1. 2D transformation is the same
as a 3D transformation with the axis of rotation being the z-axis. So, to do 2D transformation, we set
x=0, y=0 and z=1
When we specify any transformation function, OpenGl multiplies the current transformation matrix by
the transformation matrix of the specified transformation. Every OpenGl primitive that comes up after
a transformation is specified is first transformed before being drawn. The basic transformation matrix
is the identity matrix. It is specified using the function glLoadIdentity().
The most important idea is that when the transformation matrices are specified, the last one
specified is the first one to multiply the current transformation matrix.
The function glLoadIdnetity() resets the current transformation matrix to the identity matrix!
glLoadIdentity()
glTranslatef(0.4, 0.3, 0.2);
glScalef(1,2,2);
In this specification, first the scaling matrix is applied on the identity matrix and then the translation
matrix is applied.
1/7
Your task for this lab:
1. Incase you don't have a sample OpenGL code, here is a main function and the basic things that go
into the display function. Our coordinate system for this lab will be from (-1,-1) to (1,1).
Sample code
#include <GL/glut.h>
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
….
….
glFlush();
}
As you can easily note, the data types of the vertices are given as GLfloat. Glfloat is the
OpenGL type definition for float. If you resolutely use the OpenGL defined data types
throughout your application, you will avoid mismatched types when porting your code between
different implementations. Here are other OpenGL defined data types.
2/7
Suffix Data Type Typical Corresponding C- OpenGL Type
Language type Definition
b 8-bit integer signed char GLbyte
s 16-bit integer short GLshort
i 32-bit integer Int or long Glint, GLsizei
f 32-bit floating point float Glfloat,GLclampf
d 64-bit floating point double Gldouble,GLclampd
ub 8-bit unsigned integer Unsigned char Glubyte, GLboolean
us 16-bit unsigned integer Unsigned short GLushort
ui 32-bit unsigned integer Unsigned int or GLunit, GLenum,
unsigned long GLbitfield
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
New code for drawing coordinate lines
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glFlush();
}
4. Draw a rectangle (not filled) with bottom left vertex (xmin, ymin)=(0.1, 0.1) and top right
vertex (xmax, ymax)=(0.5, 0.4) with a red color.
a) If you use GL_QUADS and GL_POLYGON, or glRectf(), u will get a filled rectangle
b) So, you can the drawLine() function to accomplish this.
c) Or you can make your own drawRectangle() function and use that :)
d) We will reuse this code in the following section; so let's label it drawRectangle().
Your display() function will look like:
3/7
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT); New code for drawing the rectangle
glDisable(GL_DEPTH_TEST);
glFlush();
}
5. Use the following code to translate the rectangle. Draw the rectangle with the color yellow
Show both the original and the translated rectangles.
glLoadIdentity()
glTranslatef(-0.2, -0.2, 0.0);
code_rectangle //this is the code u used to draw the original
rectangle
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glLoadIdentity()
New code for translating the rectangle
glTranslatef(-0.2, -0.2, 0.0);
drawRectangle(0.1, 0.1, 0.5, 0.4);
glFlush();
}
4/7
Has the translation been done correctly? If not, try to diagnose any mistakes you made before
proceeding. If you can not, please call for help :)
6. Now, move and resize the window (where the rectangle is drawn) with the mouse. Do you
observe anything odd? If yes, then, most probably, the original rectangle's place is different
now, or you can not see it at all. The quadrant forming lines may have also moved down a bit.
Can you explain what is happening? Take some time and think about it.
7. If you could not explain what is happening, then here is the explanation: Let's consider just the
rectangle.
The first time the rectangle was drawn, the current transformation matrix was the identity
matrix. Then, we specified a translation, glTranslatef(), which multiplied the current
transformation matrix by the translation matrix. When the rectangle was drawn after this, it
was translated.
As we know, the display() function is called whenever the objects need to be redrawn. So, when
you moved/resized the window, the display() function was called to draw them at the new
coordinates. Now, when it drew the first rectangle, it used the current transformation matrix,
which is not the same as it was before. So, this caused the original rectangle to be drawn in a
different position.
If your code is written following the above instructions, the two rectangles are drawn in the
same position, as the transformation matrices are the same for both of them. Can you explain
why the current transformation matrices used to draw both rectangles are the same?
Now, Try to suggest a solution to this problem. Think for a while before proceeding to the
solution given below.
8. If you have not yet solved it, there are at least two solutions for this problem. You may not be
able to get the second solution if you have not done some reading. But you can get the first
solution if you do a little thinking.
Solution 1: Since glIdentity() has the power to reset the current transformation matrix, we put it
at the beginning of the display() function along with the other initializers :)
Check if this solution works! Your display() function will look like:
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
New code to reset current transformation matrix
glLoadIdentity();
5/7
drawLine(-1.0, 0.0, 1.0, 0.0);
drawLine(0.0, 1.0, 0.0, -1.0);
glLoadIdentity()
glTranslatef(-0.2, -0.2, 0.0);
drawRectangle(0.1, 0.1, 0.5, 0.4);
glFlush();
}
Solution 2: OpenGL provides two functions glPushMatrix() and glPopMatrix(). The former
function puts the current transformation matrix to a stack and the latter function pops it from the
stack. So, now that you know this functions exist, can u suggest how to use them to solve the
problem?
If you can't, then this is how we use them: Before the glTranslate() function, use glPushMatrix()
to put the current transformation matrix in the stack. After drawing the rectangle, use
glPopMatrix() to set the current transformation matrix to what it was before doing the drawing.
Check if this solution works! Your display() function will look like:
void display(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glPushMatrix();
6/7
}
9. Now, use the following code to scale the original rectangle. Draw the rectangle with a
different color.
glLoadIdentity()
glScalef(1.5, 1.5, 0.0);
drawRectangle(0.1, 0.1, 0.5, 0.4)
10. Now, use the following code to rotate the original rectangle with 90 degree. Draw the
rectangle with a different color.
glLoadIdentity()
glRotatef(90, 0, 0, 1);
drawRectangle(0.1, 0.1, 0.5, 0.4);
Composite Transformation
To do composite transformation, we specify the transformations in a reverse order. This is
because the last one specified is applied first. So, to do translation followed by rotation
followed by scaling, u use the following;
glLoadIdentity()
glScalef(1.5, 1.5, 0.0);
glRotatef(90, 0, 0, 1);
glTranslatef(-0.2, -0.2, 0.0);
drawRectangle(0.1, 0.1, 0.5, 0.4);
11. Now, you will implement your own functions to do the above transformations.
7/7