`
melord
  • 浏览: 145459 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

OpenGL ES教程III之移动变换(原文对照)

阅读更多

OpenGL ES Tutorial for Android – Part III – Transformations

January 1st, 2010 by Per-Erik BergmanAndroid, Embedded

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.

在这里,我不打算讲一些算法以使你感到厌倦,但我相信知道OpenGL在展现网格时矩阵相乘原理是很重要的。所有的移动变换都是通过不同方式的矩阵相乘得到。你可以这样认为,矩阵是一张纸,在开始绘画之前,你没有移动笔,笔的位置固定在纸中心。做矩阵变换相当于移动纸(和中心点)旋转可以看做是纸绕着中心点旋转。缩放的话,理解更难一点,可以看做是更改网格纸的网格大小。

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.

OpenGL 使用一种称之为右手坐标系,坐标轴末端相对于原点为正方向,逆时针方向视为正向旋转。

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.

当启动OpenGL视图,并未应用任何移动变换的话,那么各轴方向为:X轴是从左到右,Y轴从下到上,Z轴从背面到前面。如右图所示

 

Translate

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

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

移动是矩阵的相加,看起来像是网格在移动一样,移动按当前状态分别在三个轴的方向相加。移动导致多边形上的所有顶点在相同轴上相加一个相等的偏移量。因移动方向有正有负,所以也可以认为移动是在当前值进行加或减操作。右图显示的是一个2D的移动。

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:

在上个教程中,将方块指向屏幕内部方向移动4单位,相当于对当前位置做了一个{x:0, y:0, z:-4}的移动。

// 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

对于记住坐标轴的对齐位置非常棘手,(我不认为这是一件困难的事,包括关于矩阵的相加与相乘的原理在高中时期就已经全面的学过了。)这里作者提供了一种快速记忆的方式,按如下图,伸出你的左手,掌心向着身体,食指方向为X轴,拇指方向为Y轴,中指方向为Z轴,在作者刚开始学3D编程时,常常将XYZ写在手指上的。

 

Rotate

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.

旋转可以看作是对网格的转动,如何未做移动的话,那么认为按原点进行旋转。X,y,z值定义了旋转的中心点,旋转的单位是角度(不是弧度)。

 

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.

许多计算机上的框架和数学函数旋转值使用的是弧度,但是OpenGL不一样,它使用的角度。

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).

如果你想要还原的话,可以再转相同的负角底,或是按各轴的相反值进行旋转。如做了glRotatef(angle, x, y, z),想要还原的话,可以使用glRotatef(-angle, x, y, z)glRotatef(angle, -x, -y, -z)

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

参考下图,各旋转之后的色子如下(绿色的箭头是X轴方向,蓝色的是Y轴方向,红色的为Z轴方向)

gl.glRotatef(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.

 

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

gl.glRotatef(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.

 

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

gl.glRotatef(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.

 

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.

如下图,先平移再旋转

 


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

下图为先旋转,后平移的结果

 

Scale

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.

缩放可以认为在每个轴方向进行单独的缩放。下图展示的是进行缩放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.

同时进行移动与缩放,他们的先后顺序也是很重要的。请看下面的图,是先执行平移,再缩放的结果

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

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

 


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.5,再平移2,最终平移相当于1,如下图

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

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

 

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.

在进行平移,旋转,缩放时,如果你不想应用一些预处理来恢复到变换前的状态,可以重新当前矩阵达到同样的效果。

glLoadIdentity

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:

glLoadIdentity的作用是将单位矩阵替换当前矩阵,等同于使用以下矩阵:

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.

如果你不想重围模型矩阵的话,只是想简单的回到刚才变换前的矩阵,可以使用以下函数:

glPushMatrix

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.

作用是生成当前矩阵的拷贝,并将其压入栈中,这意味着在此之后,你对矩阵的任何操作,实际上相当于对复本的操作,不影响到原来的矩阵。

glPopMatrix

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.

恢复到使用glPushMatrix之前的矩阵。推荐的做法是在帧开始时使用glLoadIdentity,然后后面使用glPushMatrixglPopMatrix

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.

在这里,我们使用三个方块ABC来模拟太阳,地球和月亮。其中BA绽放50%的结果,CB缩放50%的结果。A逆时针自转。BA顺时针转。CB顺时针转,并且高速逆时针自转

public void onDrawFrame(GL10 gl) {

        // Clears the screen and depth buffer.

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        // Replace the current matrix with the identity matrix

        gl.glLoadIdentity();

        // Translates 10 units into the screen.

        gl.glTranslatef(0, 0, -10); 

 

        // SQUARE A

        // Save the current matrix.

        gl.glPushMatrix();

        // Rotate square A counter-clockwise.

        gl.glRotatef(angle, 0, 0, 1);

        // Draw square A.

        square.draw(gl);

        // Restore the last matrix.

        gl.glPopMatrix();

 

        // SQUARE B

        // Save the current matrix

        gl.glPushMatrix();

        // 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.

        square.draw(gl);                      

 

        // SQUARE C

        // Save the current matrix

        gl.glPushMatrix();

        // 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.

        square.draw(gl);

 

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

        gl.glPopMatrix();

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

        gl.glPopMatrix();

 

        // Increse the angle.

        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.

        ...

References

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

You can download the source for this tutorial here: Tutorial_Part_III
You can also checkout the code from: code.google.com

Previous tutorial: OpenGL ES Tutorial for Android – Part II – Building a polygon
Next tutorial: OpenGL ES Tutorial for Android – Part IV – Adding colors

Per-Erik Bergman
Consultant at
Jayway

 

分享到:
评论

相关推荐

    Android开发之OpenGL ES教程

    Android平台上的OpenGL ES教程主要帮助开发者了解如何在Android应用程序中集成和使用这个库来创建交互式的图形界面。 在Android上设置OpenGL ES视图是开发过程中的第一步,而`GLSurfaceView`是实现这一目标的关键...

    OpenGL ES 3D 坐标变换

    3D坐标变换是OpenGL ES编程中的核心概念,它涉及到物体在三维空间中的位置、旋转和缩放。 在3D图形编程中,坐标变换是构建复杂场景的基础。OpenGL ES使用右手坐标系统,其中X轴正方向通常向右,Y轴正方向向上,Z轴...

    OpenGL教程 OpenGL教程 OpenGL教程 OpenGL教程 OpenGL教程

    OpenGL教程 OpenGL教程 OpenGL教程 OpenGL教程 OpenGL教程

    OpenGLES经典教程大全

    教程名称:OpenGL ES经典教程大全课程目录:【】Android应用OpenGLES制作3D图像【技术文档】【】OpenGL ES 2.0 官方手册【】OpenGL ES 2.0 编程指南【】OpenGL ES 2.0【】OpenGL ES【】OpenGL ES教程以及COCOS 2D...

    Android OpenGL ES 简明开发教程

    ### Android OpenGL ES 开发教程详解 #### 概述与历史沿革 OpenGL ES(OpenGL for Embedded Systems)作为OpenGL API的子集,专为移动设备、PDA和游戏主机等嵌入式系统设计,旨在简化3D图形应用的开发流程。自2003...

    OpenGLES demo - 9. 矩阵变换

    本教程将深入探讨OpenGLES中的矩阵变换,并通过一个实际的示例代码来演示其工作原理。OpenGLES是一个用于在iOS设备上进行2D和3D图形渲染的API,而矩阵变换则是它实现复杂图形操作的基础。 矩阵变换主要包括平移、...

    opengles 教程

    opengles 教程

    OpenGL es 2.0教程 part1

    OpenGL es 2.0教程 OpenGL es 2.0教程 附带源码和库 part2: http://download.csdn.net/source/3152396

    OPENGL ES 3.0编程指南

    它通常与OpenGL ES不直接交互,但在构建例如3D地理信息系统或可视化应用时,可能会利用Elasticsearch来检索和组织数据,然后通过OpenGL ES进行呈现。 总的来说,OpenGL ES 3.0编程指南涵盖了移动和嵌入式设备图形...

    Android OpenGL ES 简明开发教程四:3D 坐标变换

    在OpenGL ES的环境中,3D坐标变换是构建和操作3D场景的核心概念之一。本文将深入探讨3D坐标变换中的平移、旋转和缩放,以及这些变换如何在OpenGL ES中具体应用。 #### 1. 坐标系:右手规则 OpenGL ES采用右手坐标...

    OpenGL ES相关的矩阵和变换(附实例代码)

    OpenGL ES 是一种针对嵌入式系统的图形库,用于在移动设备和嵌入式系统上创建和渲染2D、3D图形。在这个主题中,我们将深入探讨矩阵和变换在OpenGL ES中的应用,以及如何通过Java代码实现这些操作。 首先,了解3D...

    OpenGL ES教程以及COCOS 2D教程大全(文档)

    OpenGL ES和Cocos2D是移动平台上开发2D和3D图形应用的两个核心工具,尤其在iOS设备上,它们是构建游戏和其他视觉效果的重要技术。这篇教程集合旨在为开发者提供一个全面的学习资源,帮助他们掌握这两项技术。 ...

    西蒙iphone-OpenGL ES 中文教程

    西蒙iphone-OpenGL ES 中文教程涉及到的知识点主要包括了iOS平台下的OpenGL ES技术,这是一套用于嵌入式系统中开发二维和三维图形应用程序的跨语言、跨平台的API。OpenGL ES是由OpenGL三维图形API简化而来的,专为...

    OpenGL ES 1.0 教程

    OpenGL ES 1.0 教程是一份专为学习移动设备和嵌入式系统图形编程设计的资源。OpenGL ES(Embedded Systems)是OpenGL标准的精简版本,特别针对低功耗设备,如智能手机、平板电脑和掌上电脑,如Windows CE平台。这个...

    [OpenGL ES] OpenGL ES 入门教程 (英文版)

    [Apress] OpenGL ES 入门教程 (英文版) [Apress] Learn OpenGL ES (E-Book) ☆ 出版信息:☆ [作者信息] Prateek Mehta [出版机构] Apress [出版日期] 2013年08月30日 [图书页数] 220页 [图书语言] 英语 ...

    opengles 2.0教程

    - 实例代码:`opengles_sample`可能包含了一些实际的示例代码,通过分析和运行这些代码,可以加深对OpenGL ES 2.0的理解。 - 在线教程:网上有许多教程和指南,如LearnOpenGLES.com、OpenGL-Tutorial.org等,它们...

    Android OpenGL ES 2.0学习书籍.rar

    最后,了解如何与硬件加速的OpenGLES API交互,以及熟悉GLSL语言(OpenGL Shading Language),是成为OpenGL ES 2.0专家的必经之路。通过编写高效、可读性强的着色器代码,可以创造出各种复杂的视觉效果,实现令人...

    opengl es 1.1教程(很好)

    opengl es 1.1 很好的教程,2.0 可以看看,有反射,透明等效果实现。

Global site tag (gtag.js) - Google Analytics