Android OpenGL ES 开发教程(12):绘制一个20面体

jerry OpenGL ES 2015年11月25日 收藏

前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形。其它所有复杂的2D或3D图形都是由这些基本图形构成。

介绍如何使用三角形构造一个正20面体。一个正20面体,有12个顶点,20个面,30条边构成:

创建一个DrawIcosahedron Activity, 定义20面体的12个顶点,和20个面如下:

  1. static final float X=.525731112119133606f;
  2. static final float Z=.850650808352039932f;
  3.  
  4. static float vertices[] = new float[]{
  5. -X, 0.0f, Z, X, 0.0f, Z, -X, 0.0f, -Z, X, 0.0f, -Z,
  6. 0.0f, Z, X, 0.0f, Z, -X, 0.0f, -Z, X, 0.0f, -Z, -X,
  7. Z, X, 0.0f, -Z, X, 0.0f, Z, -X, 0.0f, -Z, -X, 0.0f
  8. };
  9.  
  10. static short indices[] = new short[]{
  11. 0,4,1, 0,9,4, 9,5,4, 4,5,8, 4,8,1,
  12. 8,10,1, 8,3,10, 5,3,8, 5,2,3, 2,7,3,
  13. 7,10,3, 7,6,10, 7,11,6, 11,0,6, 0,1,6,
  14. 6,1,10, 9,0,11, 9,11,2, 9,2,5, 7,2,11 };

OpenGL ES缺省使用同一种颜色来绘制图形,为了能够更好的显示3D效果,我们为每个顶点随机定义一些颜色如下:

  1. float[] colors = {
  2. 0f, 0f, 0f, 1f,
  3. 0f, 0f, 1f, 1f,
  4. 0f, 1f, 0f, 1f,
  5. 0f, 1f, 1f, 1f,
  6. 1f, 0f, 0f, 1f,
  7. 1f, 0f, 1f, 1f,
  8. 1f, 1f, 0f, 1f,
  9. 1f, 1f, 1f, 1f,
  10. 1f, 0f, 0f, 1f,
  11. 0f, 1f, 0f, 1f,
  12. 0f, 0f, 1f, 1f,
  13. 1f, 0f, 1f, 1f
  14.  
  15. };

添加颜色可以参见Android OpenGL ES 简明开发教程五:添加颜色 以后也会有详细说明。

将顶点,面,颜色存放到Buffer中以提高性能:

  1. private FloatBuffer vertexBuffer;
  2.  
  3. private FloatBuffer colorBuffer;
  4.  
  5. private ShortBuffer indexBuffer;
  6.  
  7. ByteBuffer vbb
  8. = ByteBuffer.allocateDirect(vertices.length * 4);
  9. vbb.order(ByteOrder.nativeOrder());
  10. vertexBuffer = vbb.asFloatBuffer();
  11. vertexBuffer.put(vertices);
  12. vertexBuffer.position(0);
  13.  
  14. ByteBuffer cbb
  15. = ByteBuffer.allocateDirect(colors.length * 4);
  16. cbb.order(ByteOrder.nativeOrder());
  17. colorBuffer = cbb.asFloatBuffer();
  18. colorBuffer.put(colors);
  19. colorBuffer.position(0);
  20.  
  21. ByteBuffer ibb
  22. = ByteBuffer.allocateDirect(indices.length * 2);
  23. ibb.order(ByteOrder.nativeOrder());
  24. indexBuffer = ibb.asShortBuffer();
  25. indexBuffer.put(indices);
  26. indexBuffer.position(0);

看一看DrawScene代码:

  1. public void DrawScene(GL10 gl) {
  2. super.DrawScene(gl);
  3.  
  4. gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
  5. gl.glLoadIdentity();
  6. gl.glTranslatef(0, 0, -4);
  7. gl.glRotatef(angle, 0, 1, 0);
  8.  
  9. gl.glFrontFace(GL10.GL_CCW);
  10.  
  11. gl.glEnable(GL10.GL_CULL_FACE);
  12.  
  13. gl.glCullFace(GL10.GL_BACK);
  14.  
  15. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  16.  
  17. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
  18.  
  19. gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
  20.  
  21. gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
  22.  
  23. gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
  24. GL10.GL_UNSIGNED_SHORT, indexBuffer);
  25.  
  26. gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
  27.  
  28. gl.glDisable(GL10.GL_CULL_FACE);
  29. angle++;
  30.  
  31. }

用来绘制20面体使用了gl.glDrawElements:

public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定义顶点的顺序,顶点的顺序由indices Buffer 指定。

会显示一个绕Y轴不断旋转的20面体,如何旋转模型将在后面的坐标系统和坐标变换中介绍.

DrawLine, DrawTriangle,及下载