分类: C/C++
2015-03-16 15:02:31
今天,我们要在之前的基础上,在屏幕上同时显示三角形和矩形。为了做到这点,我们需要移动它们。移动物体这个动作我们称之为转化。(坐标转换)
在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 // 所有的物体的 x 坐标向左移动 1.5个像素
ytrans = 0.0
ztrans = -6.0 // 所有的物体的 z 坐标向前移动 6 个像素
下面,我们将重新调用我们绘制三角形和矩形的函数,记住,它们应该在屏幕的中心位置。如果我们按以前的教程来绘制它们,它们可能会点对点的绘制到一起。
因此,为了解决这个问题,我按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”你会在你的屏幕上看到这样的图片:
glLoadIdentity(); glTranslatef(-1.5, 0.0, -6.0); glRotatef(45.0, 0.0, 0.0, 1.0); // Add this line // 以 Z 轴位旋转轴,旋转 45度。 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); |