OpenGL ES Tutorials



Tutorials > OpenGL ES > Transformations

View Full Source


Transformations You may find yourself needing to transform your primitives in various ways.

OpenGL ES provides 3 ways of transforming your primitives :

  1. Scaling
  2. Translation
  3. Rotation

Scaling will enlarge or reduce the size of your primitives. Translation will move your primitives across the 3 axes in 3D space. Rotation obviously rotates your object along the 3 axes.

What else will be covered?

To show the effect of rotation, we will be introducing you to animation in this tutorial.

Contents of main.cpp :

2 variables are used to keep the current rotation along the x and y axes.

float xrot = 0.0f;
float yrot = 0.0f;

Below, we create an array to hold our triangle's vertices. Note that we create the shape centered on the origin. This is because transformations affect your models relative to the origin. This will be explained further below.

GLfloat triangle[] = {
	-0.25f, -0.25f, 0.0f,
	0.25f, -0.25f, 0.0f,
	-0.25f, 0.25f, 0.0f

An array for a square is also created. Note that we are only using two values for each vertex. This is because the z axis is not being used. This could have also been used above.

GLfloat square[] = {
	-0.25f, -0.25f,
	0.25f, -0.25f,
	-0.25f, 0.25f,
	0.25f, 0.25f

Our color array remains the same as before.

GLfloat colors[] = {
	1.0f, 0.0f, 0.0f, 1.0f,
	0.0f, 1.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f, 1.0f

Our init function contains only the glClearColor function call.

void init()
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

The display function starts off as per normal.

void display()

We will be drawing a triangle on the left of the screen and a square on the right-hand side. The triangle will be smooth shaded and the square will be flat shaded.

The setting up of the triangle is the same as before.

	// Triangle

	glVertexPointer(3, GL_FLOAT, 0, triangle);
	glColorPointer(4, GL_FLOAT, 0, colors);


Our transformation code follows. Remember in the reshape function that we set the modelview matrix as the current matrix. This matrix is now used for transformations. The 3 transformations are accomplished by using the glTranslatef, glScalef and glRotatef functions. The f on the end of the function indicates that all parameters must be floats. You could also place an x instead to require GLfixed variables. Many OpenGL ES functions are used in this way. Sometimes a v is also added to indicate that an array is being passed.

After drawing our triangle, we do not want all other shapes that will be drawn afterwards to also be affected by the transformations. The glPushMatrix and glPopMatrix functions can be used to push and pop the matrix onto and off of the stack. You can place your transformation code between these two functions to make sure that the modelview matrix is reset to its original value after the code segment.


We now move onto our 3 transformations. Each successive transformation affects the modelview matrix. Note that the order in which you place the transformation, affects the overall result as matrix multiplication is not the same when reversed.

If you translate something to the right and then rotate it, you will view a rotated shape sitting on the horizontal axis. If you first rotate the object and then translate it, you will view a rotated shape that has been moved out diagonally from the origin. Try changing the order and values of the functions below to see what affect each one has.

We pass 3 floats to the glTranslatef function, specifying the value to move the drawn objects in the x, y and z direction. Our first transformation is to move the triangle right 0.25 units and up 0.5 units.

		glTranslatef(0.25f, 0.5f, 0.0f);

Our next transformation scales the object. Remember we said that the object must be centered on the origin. This is because the scale transformation takes all 3 values of each vertex and multiplies them by the parameters passed onto the glScalef function. If the object was placed with its bottom-left corner on the origin, the scale transformation would cause the object to reduce in size but the bottom-left corner will remain on the origin.

The code below reduces the size of the triangle by half. You can scale an object a different amount in each axis.

		glScalef(0.5f, 0.5f, 0.5f);

Our rotation transformation is done below. The first parameter specifies the angle in degrees to rotate the objects.

The next 3 parameters are used to specify in what axis to rotate. These specify a vector. A value of 1.0 is normally used to specify an axis. You can think of rotation along the x axis being similar to a car tilting up and down on a hill with you looking forward. Rotation along the y axis is similar to how a drill bit rotates when you are drilling into a piece of wood. Rotation along the z axis is similar to a fan's rotation when looking at the blades head-on.

		glRotatef(xrot, 1.0f, 0.0f, 0.0f);

We then draw the triangle as per normal. The triangle will appear at half its size on the left-hand side of the screen.

		glDrawArrays(GL_TRIANGLES, 0, 3);

The previous matrix is now popped off the matrix to revert back to the original matrix for further drawing.


Our next shape will not use the color array, so we disable it by using the glDisableClientState function.


The square is next to be drawn. The square is flat shaded.

	// Square

Notice that when we initialize the vertex pointer, we pass 2 as the first parameter as we only have 2 values for each vertex.

	glVertexPointer(2, GL_FLOAT, 0, square);

Instead of using a color array, you can use the glColor4f or glColor4x functions. These functions change the currently selected color. All primitives drawn after this call will appear with the specified color unless the color array is enabled. The glColor4f function accepts 4 floats, being the RGBA values.

	glColor4f(0.25f, 0.25f, 0.75f, 1.0f);

The transformations made for the square are the same except that it is moved 0.75 units to the right instead of 0.25. The shape is also rotated along the y axis instead of the x axis.

		glTranslatef(0.75f, 0.5f ,0.0f);
		glScalef(0.5f, 0.5f, 0.5f);
		glRotatef(yrot, 0.0f, 1.0f, 0.0f);

A triangle strip is used to draw the square.

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

The remaining OpenGL commands are flushed and the buffer is swapped.


To allow animation to take place, we need to have an idle function. This function is called in the main loop when there are no other messages being processed. If you are using the UG library, this function must accept a handle to the OpenGL window.

We want this function to increase the angle that the shapes are rotated by in the x and y axes. We also want the screen to be redrawn after the angle values have been changed. This is done with a glutPostRedisplay or ugPostRedisplay function call.

void idle()
	xrot += 2.0f;
	yrot += 3.0f;


Our last step is to notify the GLUT|ES / UG library as to what idle function is being used. This is accomplished with a call to the glutIdleFunc / ugIdleFunc function. The UG version of this function takes two parameters. The first is a handle to the UG engine and the second parameter is the idle function. The GLUT|ES version only needs one parameter which is the idle function. This is placed in the same place as the call to the glutMainLoop / ugMainLoop function.


Well done. You now have the ability to tranform your primitives by scaling, translating and rotating them.

Please let me know of any comments you may have : Contact Me

GLUT|ES Source Files : Embedded Visual C++ 4.0
UG Source Files : Embedded Visual C++ 4.0

Last Updated : 20 November 2005

< Tutorial 09 - Window Resizing Tutorial 11 - Depth >

Back to Top

All Rights Reserved, © Zeus Communication, Multimedia & Development 2004-2005

Read the Disclaimer