OpenGL ES Tutorial for Android – Part III – Transformations

转载 2011年01月17日 23:29:00



Last tutorial was about building your polygons. This tutorial is all about transformations, how to move the polygons around. I will continue this tutorial from where the previous ended so you can use that source code or make a copy of it.

I am not going to bore you with a lot of mathematics but I believe it is important to know that when OpenGL render a mesh it multiplies all vertices with a matrix. All the transformations you do are about manipulating the vertices in different ways by modifying this matrix. You can think of the matrix as a paper and that you never move the pen before you start to draw. You always draw in the center. But by doing a translation on the matrix you are moving the paper and also the center. A rotation is like rotating the paper around the center. And a scale is a bit harder to visualize with the paper view but it is like changing the unit size regarding to how you translate your meshes. Usually you talk about transformations according to the mesh not the world, but it is still important to know about.

Coordinate System

OpenGL uses a so called right-handed coordinate system. A system is called right-handed if you look from the positive end towards the origin of the axis the counter-clockwise rotation is considered to be a positive rotation.

When you have started up your view and haven't applied any transformations the axis are aligned like this: The x-axis goes from left to right, the y-axis comes from the bottom and goes up and the z-axis is moving from the back of the screen towards the front of the screen.

Coordinate System


public abstract void glTranslatef
 (float x, float y, float z) //OpenGL docs.

Coordinate System A translations added to the matrix makes the mesh appear as it has been moved. Translations are made along the axis and with no rotation added the axis are in there default state. Translation affects all the vertices in a polygon the same amount over the same axis. Translations are simply additions and subtractions to a current value. The image to the right shows a translation in 2 dimensions.
The start point is {x:-2, y:1} we like to go to {x:1, y:3} so we add {x:3, y:2}.

A simple addition: {x:-2, y:1} + {x:3, y:2} = {x:-2 + 3, y:1 + 2} = {x:1, y:3}.

In 3 dimensions we do the same, if we are located at position: {x:1, y:1, z:0} and we like to move 3 units into the screen we add {x:0, y:0, z:-3} and end up at: {x:1, y:1, z:-3}.

In the last tutorial we moved the square 4 units into the screen just to be able to see the square. What we did was that we added {x:0, y:0, z:-4} to the current position. This is the code we used for the translation:

// Translates 4 units into the screen.
gl.glTranslatef (0, 0, -4); OpenGL docs.

If you do several translations after each other the order of the movement is along the X, Y and Z axis, in that order. On translate the order isn't so important but when we do a rotation it's really important.

It can be quite tricky to remember how the axis are aligned. Fortunate there is a good trick to remember the direction of the axis. Hold your left hand like the photo below. The point on each finger represents the positive direction on one axis. Your thumb is y-axis, index finger is x-axis and your middle finger would represent the z-axis. When I first started with 3D programming I actually wrote the letters, x, y and z on my fingers :)

Help with the axis.


public abstract void glRotatef
(float angle, float x, float y, float z)//OpenGL docs.
Rotating is what it sounds like. You add a rotation to the matrix making it appears like the mesh are rotated. With no translation before the rotation is around the origo. The x, y and z values defines the vector to rotate around. The angle value is the number of degrees to rotate. Coordinate System

If you remember these three things you will manage rotation quite easy.

1. The rotation value are in degrees.
Most frameworks and math functions on computers use radians but OpenGL use degrees.

2. When doing several rotations the order are important.
If you like to restore a rotation you negate the angle or all the axis like this: glRotatef(angle, x, y, z) is restored with glRotatef(angle, -x, -y, -z) or glRotatef(-angle, x, y, z).

But if you do several rotations after each other like this:

(90f, 1.0f, 0.0f, 0.0f); // OpenGL docs.

gl.glRotatef (90f, 0.0f, 1.0f, 0.0f); // OpenGL docs.
gl.glRotatef (90f, 0.0f, 0.0f, 1.0f); // OpenGL docs.
gl.gRotatef(90f, 1.0f, 1.0f, 1.0f)

And want to restore the mesh to it's original position you can't just negate the angle like this:

(90f, -1.0f, 0.0f, 0.0f); // OpenGL docs.

gl.glRotatef (90f, 0.0f, -1.0f, 0.0f); // OpenGL docs.
gl.glRotatef (90f, 0.0f, 0.0f, -1.0f); // OpenGL docs.
gl.gRotatef(90f, -1.0f, -1.0f, -1.0f)

You have to revert the order of the rotations as well like this:

(90f, 0.0f, 0.0f, -1.0f); // OpenGL docs.

gl.glRotatef (90f, 0.0f, -1.0f, 0.0f); // OpenGL docs.
gl.glRotatef (90f, -1.0f, 0.0f, 0.0f); // OpenGL docs.

The order of several rotations is important.

3. If you look from the positive end towards the origin of the axis the positive rotation is counter-clockwise.
If you take a pencil in your hand, let the point be in the same direction as your thumb, as in the picture below, then aligns the pencil with the x-axis. Let the pencil's point be aligned with the positive direction of the axis. Your other fingers will now point in the positive direction of the rotation over that axis.

Positive rotation.

Translate & Rotate

Since both rotation and translations are made within each mesh own coordinate system it is important to remember that the order you do the translation and rotation are very important.

If you do a translation on the mesh first and then rotate it, the translation is made on the current state of the mesh coordinate system and then rotated at the new location.

Translate Rotate

If you first rotate and the move the mesh it will be moved accordingly to its own rotated coordinate system.

Translate Rotate


public abstract void glScalef
 (float x, float y, float z) // OpenGL docs.

Scaling is just as it sounds and it is possible to scale over each axis separately. Scaling is the same as multiplying all vertexes with the same scalar. In the image below we scale with: gl.glScalef(2f, 2f, 2f). That means that we multiply all vertixes with 2.


Translate & Scale

The order of scaling and translating does matter. If you translate before scaling the transformation is intact. Like this example, first a translation of 2 units and then scale it by 0.5.

(2, 0, 0); // OpenGL docs.

gl.glScalef (0.5f, 0.5f, 0.5f); // OpenGL docs.
Translate scale.

But if you scale before the translation you get a different result. Since you scale the mesh coordinate system then do the translation you will not move the mesh the same amount as you would before the scaling. So if you first scale with 0.5 and then do a translation of 2 units the result will appear as a translation of 1 unit.

(0.5f, 0.5f, 0.5f); // OpenGL docs.

gl.glTranslatef (2, 0, 0); // OpenGL docs.
Scale translate.

Load Identity, push and pop matrix

When you translate, rotate or scaling you are not applying the transformation from the same preconditions, you are applying them to the previous transition. You need to be able to reset the position.


public abstract void glLoadIdentity
() // OpenGL docs.

glLoadIdentity replaces the current matrix with the identity matrix. It is the same as calling glLoadMatrix with the identity matrix:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

There are situations where you don't want to reset the model matrix, you rather want to go back to how it was just before your latest transformation.


public abstract void glPushMatrix
() // OpenGL docs.

glPushMatrix makes a copy of the current matrix and put it on the stack. This means that when you do any kind of translations after glPushMatrix you are doing them on a copy.


public abstract void glPopMatrix
() // OpenGL docs.

To get back to the previous matrix you use the glPushMatrix command.

A good practice can be to have one glLoadIdentity in the begining of each frame and after that use glPushMatrix and glPopMatrix.

Putting it all togetter

So to make something with this new knowlege let us do 3 squares call them A, B and C. Scale them so that B is 50% smaller then A and C is 50% smaller then B. Then let A rotate counter-clockwise in the center of the screen. B should rotate clockwise around A and finaly C rotating clockwise around B and counter-clockwise in a high speed around it's own center.

public void onDrawFrame(GL10 gl) {
// Clears the screen and depth buffer.
// Replace the current matrix with the identity matrix
// Translates 10 units into the screen.
gl.glTranslatef(0, 0, -10);

// Save the current matrix.
// Rotate square A counter-clockwise.
gl.glRotatef(angle, 0, 0, 1);
// Draw square A.
// Restore the last matrix.

// Save the current matrix
// Rotate square B before moving it, making it rotate around A.
gl.glRotatef(-angle, 0, 0, 1);
// Move square B.
gl.glTranslatef(2, 0, 0);
// Scale it to 50% of square A
gl.glScalef(.5f, .5f, .5f);
// Draw square B.

// Save the current matrix
// Make the rotation around B
gl.glRotatef(-angle, 0, 0, 1);
gl.glTranslatef(2, 0, 0);
// Scale it to 50% of square B
gl.glScalef(.5f, .5f, .5f);
// Rotate around it's own center.
gl.glRotatef(angle*10, 0, 0, 1);
// Draw square C.

// Restore to the matrix as it was before C.
// Restore to the matrix as it was before B.

// Increse the angle.

And don't forget to add angel as a variable as well. Thanks Tim!

public class OpenGLRenderer implements Renderer {
private Square square;
private float angle; // Don't forget to add this.


The info used in this tutorial is collected from:
Android Developers
OpenGL ES 1.1 Reference Pages

[译] --- OpenGL ES 2.0 for iPhone Tutorial Part 2: Textures

本文译自:OpenGL ES 2.0 for iPhone Tutorial Part 2: Textures。其中主要介绍了OpenGLES纹理相关的内容。...
  • icetime17
  • icetime17
  • 2016年01月11日 21:16
  • 842

OpenGL ES Tutorial for Android – Part VI – Textures

这篇文章花费的时间最长,从这里了解的UV mapping, Last tutorial we worked a bit more on meshes and we have also talked ...
  • virus026
  • virus026
  • 2011年01月17日 23:42
  • 1146

OpenGL ES Tutorial for Android

OpenGL ES Tutorial for Android
  • androidwifi
  • androidwifi
  • 2014年08月28日 21:06
  • 367

Android OpenGL ES2.0基础(一、最简单的使用)

Android OpenGL ES2.0基础(一、最简单的使用)一、OpenGL ES是什么OpenGL(Open Graphics Library)是一个跨编程语言、跨平台的3D图形库。广泛应用于游...
  • tianzhaoai
  • tianzhaoai
  • 2017年03月09日 17:14
  • 1465

Android OpenGL ES 入门系列(二) --- 环境搭建

转载请注明出处 本文出自Hansion的博客 本章介绍如何使用GLSurfaceView和GLSurfaceView.Renderer完成在Activity中的最简单实现。 1....
  • hansion3333
  • hansion3333
  • 2018年01月08日 10:50
  • 848

Android OpenGL ES学习笔记之材质概念和添加光照

一、光照概念 观察一个真实的3D物体,在不同的部位必然有不同的光照效果,有的地方暗一点,有的地方亮一点。而这种视觉差异是由光源和材质(物体的材料)共同决定的。光源强度由红、绿、蓝三色光强度共同决定,...
  • qq_31530015
  • qq_31530015
  • 2016年08月10日 10:33
  • 3641

Android OpenGL ES(一)----必备知识

1.手机的坐标空间 我们都知道要想在手机上随心所欲的绘制图形,就必须了解手机的坐标体系。下图就是将坐标映射到手机屏幕的坐标。  图1 手机屏幕基本坐标系 2.OpenGL基本图形 在Op...
  • liyuanjinglyj
  • liyuanjinglyj
  • 2015年06月21日 20:35
  • 5268

Android API Guide for Animation and Graphics(六)—— 动画与图形(OpenGL ES)

OpenGL ESAndroid包含支持高性能2D和3D图形绘制开源库(OpenGL),尤其是OpenGL ES API. OpenGL是一个跨平台的图形API,它为硬件处理3D图形指定了一个标准的软...
  • u014011112
  • u014011112
  • 2016年12月20日 01:44
  • 975

android opengl es 位图字体

  • Simdanfeg
  • Simdanfeg
  • 2011年03月30日 16:57
  • 6835

Android OpenGL ES 画球体

Android OpenGL ES 画球体
  • yarkey09
  • yarkey09
  • 2014年07月03日 12:49
  • 5657
您举报文章:OpenGL ES Tutorial for Android – Part III – Transformations