Andriod OpenGL 教程 05 - 3D空间

来源:互联网 发布:c语言1到n求和 编辑:程序博客网 时间:2024/04/27 03:37

关键字: android OpenGL 移动开发 教程

在上节课的基础上,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D世界中的2D对象。我们给三角形增加一个左侧面,一个右侧面,一个后侧面来生成一个金字塔(四棱锥)。给正方形增加左、右、上、下及背面生成一个立方体。我们混合金字塔上的颜色,创建一个平滑着色的对象。给立方体的每一面则来个不同的颜色。这样在我们的工程中MyTriangle类变成了MyPyramid , MySquare变成了MyCube

MyPyramid.java

package wintop.gllesson05;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;  public class MyPyramid {   private FloatBuffer vertexBuffer;  // 顶点数组缓冲区   private FloatBuffer colorBuffer;   // 顶点颜色缓冲区   private ByteBuffer indexBuffer;    // 索引数组缓冲区       private float[] vertices = { // 在(x,y,z)坐标系中金字塔的五个顶点坐标      -1.0f, -1.0f, -1.0f,  // 0. 左-底-后       1.0f, -1.0f, -1.0f,  // 1. 右-底-后       1.0f, -1.0f,  1.0f,  // 2. 右-底-前      -1.0f, -1.0f,  1.0f,  // 3. 左-底-前       0.0f,  1.0f,  0.0f   // 4. 顶   };             private float[] colors = {  // 五个顶点的颜色(RGBA模式)      0.0f, 0.0f, 1.0f, 1.0f,  // 0. 蓝      0.0f, 1.0f, 0.0f, 1.0f,  // 1. 绿      0.0f, 0.0f, 1.0f, 1.0f,  // 2. 蓝      0.0f, 1.0f, 0.0f, 1.0f,  // 3. 绿      1.0f, 0.0f, 0.0f, 1.0f   // 4. 红   };     private byte[] indices = { // 四个三角形的顶点索引      2, 4, 3,   // 前面 (CCW)      1, 4, 2,   // 右面      0, 4, 1,   // 后面      4, 0, 3    // 左面   };     // 构造函数 - 设置缓冲区   public MyPyramid() {  // 设置顶点数组,顶点数据为浮点数据类型。一个浮点类型的数据长度为四个字节      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);      vbb.order(ByteOrder.nativeOrder()); // 使用原生字节顺序      vertexBuffer = vbb.asFloatBuffer(); // 将字节类型缓冲区转换成浮点类型      vertexBuffer.put(vertices);         // 将数据复制进缓冲区      vertexBuffer.position(0);           // 定位到初始位置        // 设置颜色缓冲区. 颜色数据为浮点数据类型。一个浮点类型的数据长度为四个字节      ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);      cbb.order(ByteOrder.nativeOrder());      colorBuffer = cbb.asFloatBuffer();      colorBuffer.put(colors);      colorBuffer.position(0);        // 设置索引缓冲区. 索引数据为字节数据类型.      indexBuffer = ByteBuffer.allocateDirect(indices.length);      indexBuffer.put(indices);      indexBuffer.position(0);   }     // 绘图   public void draw(GL10 gl) {      gl.glFrontFace(GL10.GL_CCW);  // 设置正前面为逆时针方面        // 数组使能并定义它们各自的缓冲区      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);      gl.glEnableClientState(GL10.GL_COLOR_ARRAY);      gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);            gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE,indexBuffer);            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);      gl.glDisableClientState(GL10.GL_COLOR_ARRAY);   }}


 

MyCube.java

package wintop.gllesson05;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;  public class MyCube {   private FloatBuffer vertexBuffer;  // 顶点数组缓冲区   private int numFaces = 6;      private float[][] colors = {  // 六个面的颜色      {1.0f, 0.5f, 0.0f, 1.0f},  // 0. 橙色      {1.0f, 0.0f, 1.0f, 1.0f},  // 1. 紫色      {0.0f, 1.0f, 0.0f, 1.0f},  // 2. 绿色      {0.0f, 0.0f, 1.0f, 1.0f},  // 3. 蓝色      {1.0f, 0.0f, 0.0f, 1.0f},  // 4. 红色      {1.0f, 1.0f, 0.0f, 1.0f}   // 5. 黄色   };     private float[] vertices = {  // 六个面的顶点坐标      // 前      -1.0f, -1.0f,  1.0f,  // 0. 左-底-前       1.0f, -1.0f,  1.0f,  // 1. 右-底-前      -1.0f,  1.0f,  1.0f,  // 2. 左-顶-前       1.0f,  1.0f,  1.0f,  // 3. 右-顶-前      // 后       1.0f, -1.0f, -1.0f,  // 6. 右-底-后      -1.0f, -1.0f, -1.0f,  // 4. 左-底-后       1.0f,  1.0f, -1.0f,  // 7. 右-顶-后      -1.0f,  1.0f, -1.0f,  // 5. 左-顶-后      // 左      -1.0f, -1.0f, -1.0f,  // 4. 左-底-后      -1.0f, -1.0f,  1.0f,  // 0. 左-底-前       -1.0f,  1.0f, -1.0f,  // 5. 左-顶-后      -1.0f,  1.0f,  1.0f,  // 2. 左-顶-前      // 右       1.0f, -1.0f,  1.0f,  // 1. 右-底-前       1.0f, -1.0f, -1.0f,  // 6. 右-底-后       1.0f,  1.0f,  1.0f,  // 3. 右-顶-前       1.0f,  1.0f, -1.0f,  // 7. 有-顶-后      // 上      -1.0f,  1.0f,  1.0f,  // 2. 左-顶-前       1.0f,  1.0f,  1.0f,  // 3. 右-顶-前      -1.0f,  1.0f, -1.0f,  // 5. 左-顶-后       1.0f,  1.0f, -1.0f,  // 7. 右-顶-后      // 下      -1.0f, -1.0f, -1.0f,  // 4. 左-底-后       1.0f, -1.0f, -1.0f,  // 6. 右-底-后      -1.0f, -1.0f,  1.0f,  // 0. 左-底-前       1.0f, -1.0f,  1.0f   // 1. 右-底-后   };           // 构造函数 - 设置缓冲区   public MyCube() {   // 设置顶点数组,顶点数据为浮点数据类型。一个浮点类型的数据长度为四个字节      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);      vbb.order(ByteOrder.nativeOrder()); // 使用原生字节顺序      vertexBuffer = vbb.asFloatBuffer(); // 将字节类型缓冲区转换成浮点类型      vertexBuffer.put(vertices);         // 将数据复制进缓冲区      vertexBuffer.position(0);           // 定位到初始位置   }     // 绘图   public void draw(GL10 gl) {     gl.glFrontFace(GL10.GL_CCW);    // 正前面为逆时针方向      gl.glEnable(GL10.GL_CULL_FACE); // 使能剔除面      gl.glCullFace(GL10.GL_BACK);    // 剔除背面(不显示)        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);      // 渲染所有的面      for (int face = 0; face < numFaces; face++) {         // 设置每个面的颜色         gl.glColor4f(colors[face][0], colors[face][1], colors[face][2], colors[face][3]);         // 根据顶点数据直接绘制图元         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, face*4, 4);      }      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);      gl.glDisable(GL10.GL_CULL_FACE);   }}

     立方体所有面相对应法向法向都是按逆时针方向排列。这样使我们可以进行背面剔除操作,背面剔除操作的代码如下:

     gl.glFrontFace(GL10.GL_CCW);   //正前面为逆时针方向

     gl.glEnable(GL10.GL_CULL_FACE);//使能剔除面

     gl.glCullFace(GL10.GL_BACK);   //剔除背面(不显示)

立方体的面顶点排列方式


最终运行结果如下图所示:

 

源代码下载地址:http://download.csdn.net/detail/seniorwizard/4460814

原创粉丝点击