注册 登录
主题 : 西蒙iphone-OpenGL ES 教程-03
级别: 侠客

UID: 1030
精华: 1
发帖: 52
可可豆: 1420 CB
威望: 1420 点
在线时间: 476(时)
注册时间: 2008-10-14
最后登录: 2016-07-21
0 楼:  发表于: 2009-07-02 10:26    发自: Web Page
来源于 3D图形 分类

西蒙iphone-OpenGL ES 教程-03   

OpenGL ES 03 – 转化

今天,我们要在之前的基础上,在屏幕上同时显示三角形和矩形。为了做到这点,我们需要移动它们。移动物体这个动作我们称之为转化。(坐标转换)

在OpenGL ES中,对模型/物体进行转换有三种不同的类型。它们是:

1.Translate – 在3d空间里移动物体。
2.Rotate – 在x,y,z坐标轴上进行旋转。
3.Scale – 改变物体的尺寸。主要应用于在3d空间中的2d投影体。当然,也可以应用于特殊效果。

为了展示这些不同的方法,我们使用translate函数在屏幕上同时生成三角形和矩形,以后在着手做其他2个(方法)。

Translate
为了显示移动的效果,OpenGL ES给了我们一个单一的方法供我们使用,这个方法叫: glTranslatef()。注意到函数的结尾是‘f’了吗?这意味着,我们要提供给OpenGL一个浮点数。OpenGL ES 也提供了使用16进制的方法,方法叫: glTranslatex()。16进制的写法应用于那些没有浮点运算的硬件,幸运的是iPhone本身就有浮点运算,所以我们不需要使用16进制的算法,直接用浮点运算就可以了。

我觉得需要指出的是,如果你在XCode里面用16进制的算法完成你的工程,你是不会发现有什么不同的(与浮点运算比较)

ok,让我们开始删除一些代码。开启XCode,打开你的工程。我希望你昨天只是屏蔽了三角形数据和它的渲染而不是删除了它们,否则的话,你只能重新再写一遍了。
首先,让我们来看看2个顶点数组。我们对这些顶点的z轴做一些改变,把z轴改为0,就象如下所示:


const GLfloat triangleVertices[] = {
        0.0, 1.0, 0.0,                // Triangle top centre
        -1.0, -1.0, 0.0,              // bottom left
        1.0, -1.0, 0.0                // bottom right
    };

const GLfloat squareVertices[] = {
        -1.0, 1.0, 0.0,               // Top left
        -1.0, -1.0, 0.0,              // Bottom left
        1.0, -1.0, 0.0,               // Bottom right
        1.0, 1.0, 0.0                 // Top right
    };


你想起来我们之前为什么要把z设置为-6了吗?这示因为我们要把物体放置再屏幕的里面,因为我们的照相机是在(0.0,0.0,0.0)的位置上。现在我们将使用 glTranslatef()  函数来将物体后退6点,而不是象之前那样在顶点中修改。

首先,我们将告诉OpenGL 我们将使用移动: 无论是投影(世界观)或对象(模型内的世界) 。在这样的情况下,我们要告诉OpenGL来生成一个三角形和一个矩形。在drawView函数中呼出glClear()函数。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      glMatrixMode(GL_MODELVIEW);


函数 glMatrixMode 告诉OpenGL,我们工作在顶点模式下,而不是投影。 在我们setupView方法,我们使用同样的函数,但使用GL_PROJECTION枚举作为参数。OpenGL是一个引擎,它会保持在一个状态,除非你告诉它要进行改变。所以,矩阵模型将维持在 GL_PROJECTION 状态,直到我们说到模型视窗里面调用 glMatrixMode(GL_MODELVIEW)。现在我们将保持OpenGL的状态为 GL_MODELVIEW ,直到我们告诉它改变。

实际上,如果我们希望达到最佳效果,我们应该在我们第一个教程中的setupView函数调用之后使用它。另外,我们是在教程中,而不是现实做项目,所以,此刻我们就在drawView函数中使用它就行了。

我知道我还没有真正的涉及OpenGL中的投影,所以,你如果没有完全理解的话,不要紧张。我们要做的就是在屏幕中放上一些物体,让你一边玩弄这些物品一边学习OpenGL ES.

现在,去掉绘制三角形代码的屏蔽,象下面一样:


glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_TRIANGLES, 0, 3);

在这三行代码之前,再增加两行:


glLoadIdentity();
glTranslatef(-1.5, 0.0, -6.0);
glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
      glEnableClientState(GL_VERTEX_ARRAY);
      glDrawArrays(GL_TRIANGLES, 0, 3);

glLoadIdentity() 只是一个覆盖(重置)函数,它只是基本重置所有的条件(重置所有状态)。所以如果我们不调用这个功能的话, glTranslatef() 函数将会移动物体不断的向左和里面,直到物体消失。实际上,我可以使用另外一种更好的函数来达到这点(下一个教程),但是现在我们只需要重置目标数据,所以它就足够了。

下个函数的调用使这里发生变化。

glTranslatef() 函数有3个参数:

glTranslatef(GLfloat xtrans, GLfloat ytrans, GLfloat Ztrans);

在继续之前,在看下我画的这个3d空间。



记住,照相机在(0.0,0.0,0.0)的位置。我们呼叫 glTranslatef() 使用以上的三个函数。
    xtrans = -1.5
    ytrans =  0.0
    ztrans = -6.0

下面,我们将重新调用我们绘制三角形和矩形的函数,记住,它们应该在屏幕的中心位置。如果我们按以前的教程来绘制它们,它们可能会点对点的绘制到一起。

因此,为了解决这个问题,我按x坐标向左移动1.5个点。看下上面的3维坐标空间,你会发现,x的左边是负的。所以,-1.5

z转换为-6,替换我们在顶点数组里的-6

移动矩形
绘制矩形的代码几乎和三角形一样,如下:


glLoadIdentity();
    glTranslatef(1.5, 0.0, -6.0);
    glVertexPointer(3, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);



这次,你通过 glTranslatef()函数里的xtrans的值将矩形移动到右侧。

点击”Build and Go”你会在你的屏幕上看到这样的图片:


请注意,y轴一直在屏幕的中心,所以2个图元并排着。

在我们移动前
尝试修改 glTranslatef 函数里的那3个参数,看看哪些地方改变了。 我花了许多小时只是改变参数来看会发生什么事情。您甚至可以屏蔽掉了glLoadIdentity ( ) ,并看看会发生什么。

旋转
在结束你的试验以后,把你的代码修改为原始的模式,让我们来快速的看下旋转是怎么回事。我们旋转的模式是2d的,因为我们的物体是2d的(尽管它在3d空间里)。之后,我们将创建一个全3d的物体,并且在全3d的空间里去旋转它(并且,我们可以做它的纹理映射)

旋转是很简单的:
glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);


这个方法的时候是很简单的。首先,第一个参数设定了你需要旋转多少度,然后,我们指定轴来进行旋转。

下面,我将师范2种不同的旋转方式。首先,是一个静态的旋转,然后我们将动态的不停的旋转。旋转的目标就是这个三角形和矩形。

首先,让我们做一个简单的旋转,回到drawView函数里,对三角形和矩形的绘制函数修改如下:


glLoadIdentity();
    glTranslatef(-1.5, 0.0, -6.0);
    glRotatef(45.0, 0.0, 0.0, 1.0);         // Add this line
    glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    glLoadIdentity();
    glTranslatef(1.5, 0.0, -6.0);
    glRotatef(45.0, 0.0, 0.0, 1.0);         // Add this line
    glVertexPointer(3, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);



我们要做的是,让三角形和矩形沿着z轴进行旋转。看到z轴那个1.0的参数了没?这就告诉OpenGL,沿着z轴,旋转45度。

看下生成的图像,如下:



就象你开车的时候,轮胎旋转一样,物体沿z轴进行旋转。注意了,z轴是深入屏幕的一条线,所以是沿这条线旋转的。

X轴旋转的,就如同看着一个旋转的汽车轮胎的赛车走向你(即您在汽车的前面) 。Y轴旋转的是,轮胎的外观作为司机轮流方向盘,以避免您(希望! ) 。(就是从上往下看一个旋转的轮胎)。如果你没搞清楚,也别紧张,在下列的师范里,你就会知道,到底发生了什么。
旋转我们的物体
为了旋转我们的三角形和矩形,你需要在每次绘制的时候都增加旋转的角度。到EAGLView.h文件,增加一个参数:
GLfloat rota;

然后回到EAGLView.mm里的initWithCoder函数里,增加下面这行。
rota = 0.0;

我们做的就是当前旋转角度的变量。
现在,回到drawView,然后增加下面这行,在 glLoadIdentity() 方法之前。

rota += 0.5;

我们要做的就是,每次绘制的时候,都增加旋转角度0.5度。修改glRotatef()函数如下:
        glRotatef(rota, 0.0, 0.0, 1.0);

现在,我们完成了自我增加旋转角度的实现。第一次绘制,将旋转0.5度,第二次绘制,将旋转1.0度。

编译程序,看看轮胎旋转吧。

你自己的实验
在离开本教程之前,我希望你自己做一些实验,比如如下的:

1.改变旋转轴。把z轴改为0,将x,y改为1。看看沿着其他轴旋转是怎么一回事。

2.将当前的旋转值1.0改为-1.0,注意下,现在它们的旋转和之前的相反了。

3.把当前正的旋转值修改为负的。看看会发生些什么。

我希望你能从中获得些什么。


原文位置:
http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/31_OpenGL_ES_03_-_Transformations.html



清空我的评分动态本帖最近评分记录: 共威望条评分记录
gagaga 贡献值 +5 2008-09-19
隐藏评分记录
级别: 圣骑士

UID: 1168
精华: 0
发帖: 45
可可豆: 5710 CB
威望: 5710 点
在线时间: 5230(时)
注册时间: 2008-10-30
最后登录: 2016-10-18
1 楼:  发表于: 2009-07-02 11:12    发自: Web Page
感谢,支持。
这个教学应该在wiki也放一份吧?
级别: 侠客
UID: 634
精华: 0
发帖: 34
可可豆: 1743 CB
威望: 1743 点
在线时间: 317(时)
注册时间: 2008-09-06
最后登录: 2017-08-03
2 楼:  发表于: 2009-07-02 11:15    发自: Web Page
好东西支持下!
级别: 侠客
UID: 5488
精华: 0
发帖: 16
可可豆: 2000 CB
威望: 2000 点
在线时间: 235(时)
注册时间: 2009-05-06
最后登录: 2016-03-27
3 楼:  发表于: 2009-07-02 15:19    发自: Web Page
好东西  谢了 lz  学习了      
做一个徘徊在牛A 和 牛C 之间滴人.........
级别: 管理员

状态: 连续签到 - [3天]
UID: 2
精华: 9
发帖: 7688
可可豆: 73313 CB
威望: 73439 点
在线时间: 5514(时)
注册时间: 2008-03-29
最后登录: 2016-08-05
4 楼:  发表于: 2009-07-02 23:34    发自: Web Page
我也觉得应该在wiki放一个。准备把Wiki加入代码高亮整合
In all thy ways acknowledge Him, and He shall direct thy paths.
级别: 新手上路
UID: 4073
精华: 0
发帖: 2
可可豆: 350 CB
威望: 350 点
在线时间: 71(时)
注册时间: 2009-04-03
最后登录: 2015-03-19
5 楼:  发表于: 2009-07-14 12:49    发自: Web Page
能不能把工程发一下。。我想要一个绘制rgb数组绑定纹理的,然后绘制纹理的例子
级别: 圣骑士
状态: 连续签到 - [171天]
UID: 7132
精华: 0
发帖: 100
可可豆: 8521 CB
威望: 8150 点
在线时间: 942(时)
注册时间: 2009-07-19
最后登录: 2017-05-30
6 楼:  发表于: 2009-08-08 10:40    发自: Web Page
学习中,强烈支持3
有人说人生最大的幸福是:睡觉睡到自然醒,数钱数到手抽筋。其实我认为最大的幸福是:无论几点睡觉最后一眼看到的是心爱的人,无论几点醒来第一眼看到的是心爱的人。无论赚多少钱,都是和心爱的人一起赚,如论花多少钱,都是和心爱的人一起花。
级别: 圣骑士
UID: 13184
精华: 0
发帖: 577
可可豆: 2034 CB
威望: 2034 点
在线时间: 428(时)
注册时间: 2010-01-20
最后登录: 2014-08-03
7 楼:  发表于: 2010-04-15 20:42    发自: Web Page
太好的文章了,忍不住给贴子加法!
Never drop yourself in darkness.
级别: 新手上路
UID: 27957
精华: 0
发帖: 35
可可豆: 166 CB
威望: 296 点
在线时间: 269(时)
注册时间: 2010-08-18
最后登录: 2016-02-23
8 楼:  发表于: 2010-08-18 16:05    发自: Web Page
学习加收藏?
级别: 骑士
UID: 60761
精华: 0
发帖: 252
可可豆: 1860 CB
威望: 1840 点
在线时间: 308(时)
注册时间: 2011-03-31
最后登录: 2015-07-13
9 楼:  发表于: 2011-05-03 11:00    发自: Web Page
我正看的津津有味。
描述
快速回复

关注本帖(如果有新回复会站内信通知您)

发帖、回帖都会得到可观的积分奖励。查看论坛积分规则

按"Ctrl+Enter"直接提交
    顶部