业精于勤,荒于嬉
全部博文(763)
分类: C/C++
2010-01-30 10:21:15
起初,我想下一章介绍光照的,但是我又想到别的。我们依然有很多基本对象及转换没有完成,特别是我们在不同的坐标系中对不同的物体进行转换。
记得我们如何在整个屏幕内使用 glTranslatef() 和 glRotatef ()?如果我想作一些不同的事情,我就会使用一个很方便的函数: glLoadIdentity().但是 glLoadIdentity()是“代价昂贵”在屏幕渲染技术中,所以现在,我会采用更有效的方法。
要作到这点,我将介绍一个新的对象。我们将增加一个金字塔,并且使用 glTranslatef()来移动它,使用 glRotatef()来旋转它。和立方体独立开,并且不使用 glLoadIdentity() 来重置矩阵。
在我们的世界里增加一个金字塔
这不是仅仅增加一个三角形,让我们坚持使用3d物体,我们会增加一个金字塔(想像一下Giza平原上的大石头)
有件事,我在以前的教程中避免去说明的,就是我们创建的立方体事一个复杂对象,即物体是由一个以上的原点组成的。从技术上来说,我们的矩形也是一个复杂物体,但我们只使用了单一的OpenGL的函数去绘制它,我们可以将其看为一个简单物体,我避免说明复杂物体是因为我不想让我们的工作看起来是一个“艰苦的工作”
现在你已经完成了一个复杂物体了。恭喜你!并且,现在是时候建立第二个了。
金字塔不是难事。它是由一个矩形以及会聚到这个矩形上面的中心点的4个三角形组成的。一旦你将物体可以分解为你所认知的简单图元,任何复杂的物体都不是问题。唯一的变化是你物体中图元的数目而已。
好,开启Xcode并且开启上个教程的工程。这次不要删除任何东西,我们增加代码来构成一个平行线。
为了帮助你组成金字塔,我们需要分解它的各个组成部分,让我们开始:
const GLfloat pyramidVertices[] = {
// Our pyramid consists of 4 triangles and a square base.
// We'll start with the square base
-1.0, -1.0, 1.0, // front left of base
1.0, -1.0, 1.0, // front right of base
1.0, -1.0, -1.0, // rear left of base
-1.0, -1.0, -1.0, // rear right of base
因此,我们创建了一个新的物体,和我们作的一样。这个矩形是底座,所有的y坐标都是-1.0。
现在,我们可以创建金字塔的正面,这次我们创建的三角形而不是矩形。
// Front face
-1.0, -1.0, 1.0, // bottom left of triangle
1.0, -1.0, 1.0, // bottom right
0.0, 1.0, 0.0, // top centre -- all triangle vertices
// will meet here
这是我们创建的唯一的真实三角形,这个三角形的角在矩形的前边,然后向后倾斜,上面的点在矩形的中心上面(在x轴线上)
我们继续创建其他的三个三角形,使用相同的方法,下面是完整的顶点数组。
// Our new object definition code goes here const GLfloat pyramidVertices[] = { // Our pyramid consists of 4 triangles and a square base. // We'll start with the square base -1.0, -1.0, 1.0, // front left of base 1.0, -1.0, 1.0, // front right of base 1.0, -1.0, -1.0, // rear left of base -1.0, -1.0, -1.0, // rear right of base // Front face -1.0, -1.0, 1.0, // bottom left of triangle 1.0, -1.0, 1.0, // bottom right 0.0, 1.0, 0.0, // top centre -- all triangle vertices // will meet here // Rear face 1.0, -1.0, -1.0, // bottom right (when viewed through front face) -1.0, -1.0, -1.0, // bottom left 0.0, 1.0, 0.0, // top centre // left face -1.0, -1.0, -1.0, // bottom rear -1.0, -1.0, 1.0, // bottom front 0.0, 1.0, 0.0, // top centre // right face 1.0, -1.0, 1.0, // bottom front 1.0, -1.0, -1.0, // bottom rear 0.0, 1.0, 0.0 // top centre }; |
glPushMatrix(); { glTranslatef(2.0, 0.0, -8.0); glRotatef(rota, 1.0, 1.0, 1.0); glVertexPointer(3, GL_FLOAT, 0, cubeVertices); glEnableClientState(GL_VERTEX_ARRAY); // Draw the front face in Red glColor4f(1.0, 0.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Draw the top face in green glColor4f(0.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 4, 4); // Draw the rear face in Blue glColor4f(0.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 8, 4); // Draw the bottom face glColor4f(1.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 12, 4); // Draw the left face glColor4f(0.0, 1.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 16, 4); // Draw the right face glColor4f(1.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 20, 4); } glPopMatrix(); |
- (void)drawView { // Our new object definition code goes here const GLfloat pyramidVertices[] = { // Our pyramid consists of 4 triangles and a square base. // We'll start with the square base -1.0, -1.0, 1.0, // front left of base 1.0, -1.0, 1.0, // front right of base 1.0, -1.0, -1.0, // rear left of base -1.0, -1.0, -1.0, // rear right of base // Front face -1.0, -1.0, 1.0, // bottom left of triangle 1.0, -1.0, 1.0, // bottom right 0.0, 1.0, 0.0, // top centre -- all triangle vertices // will meet here // Rear face 1.0, -1.0, -1.0, // bottom right (when viewed through front face) -1.0, -1.0, -1.0, // bottom left 0.0, 1.0, 0.0, // top centre // left face -1.0, -1.0, -1.0, // bottom rear -1.0, -1.0, 1.0, // bottom front 0.0, 1.0, 0.0, // top centre // right face 1.0, -1.0, 1.0, // bottom front 1.0, -1.0, -1.0, // bottom rear 0.0, 1.0, 0.0 // top centre }; const GLfloat cubeVertices[] = { // Define the front face -1.0, 1.0, 1.0, // top left -1.0, -1.0, 1.0, // bottom left 1.0, -1.0, 1.0, // bottom right 1.0, 1.0, 1.0, // top right // Top face -1.0, 1.0, -1.0, // top left (at rear) -1.0, 1.0, 1.0, // bottom left (at front) 1.0, 1.0, 1.0, // bottom right (at front) 1.0, 1.0, -1.0, // top right (at rear) // Rear face 1.0, 1.0, -1.0, // top right (when viewed from front) 1.0, -1.0, -1.0, // bottom right -1.0, -1.0, -1.0, // bottom left -1.0, 1.0, -1.0, // top left // bottom face -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, // left face -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, // right face 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0 }; const GLshort squareTextureCoords[] = { // Front face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right // Top face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right // Rear face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right // Bottom face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right // Left face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right // Right face 0, 1, // top left 0, 0, // bottom left 1, 0, // bottom right 1, 1, // top right }; [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glViewport(0, 0, backingWidth, backingHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glTexCoordPointer(2, GL_SHORT, 0, squareTextureCoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Our new drawing code goes here rota += 0.5; glPushMatrix(); { glTranslatef(-2.0, 0.0, -8.0); glRotatef(rota, 1.0, 0.0, 0.0); glVertexPointer(3, GL_FLOAT, 0, pyramidVertices); glEnableClientState(GL_VERTEX_ARRAY); // Draw the pyramid // Draw the base -- it's a square remember glColor4f(1.0, 0.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Front Face glColor4f(0.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLES, 4, 3); // Rear Face glColor4f(0.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLES, 7, 3); // Right Face glColor4f(1.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLES, 10, 3); // Left Face glColor4f(1.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLES, 13, 3); } glPopMatrix(); glPushMatrix(); { glTranslatef(2.0, 0.0, -8.0); glRotatef(rota, 1.0, 1.0, 1.0); glVertexPointer(3, GL_FLOAT, 0, cubeVertices); glEnableClientState(GL_VERTEX_ARRAY); // Draw the front face in Red glColor4f(1.0, 0.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Draw the top face in green glColor4f(0.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 4, 4); // Draw the rear face in Blue glColor4f(0.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 8, 4); // Draw the bottom face glColor4f(1.0, 1.0, 0.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 12, 4); // Draw the left face glColor4f(0.0, 1.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 16, 4); // Draw the right face glColor4f(1.0, 0.0, 1.0, 1.0); glDrawArrays(GL_TRIANGLE_FAN, 20, 4); } glPopMatrix(); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; [self checkGLError:NO]; } |