zoukankan      html  css  js  c++  java
  • 使用OpenGL ES绘制3D图形

    如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了。

    使用OpenGL  ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的顶点数据,而且3D图形需要绘制更多的三角形。

    使用glDrawArrays(int  mode , int  first  ,  int  count)方法绘制3D,还需要使用glDrawElements(int  mode  , int  count  , int  type , Buffer  indices)方法来组织三维空间上的多个顶点,根据indices指定的索引点来绘制三角形。该方法的第一个参数指定绘制的图形的类型,可设为GL10.GL_TRIANGLES或GL10.GL_TRIANGLE_STRIP;第二个参数指定一共包含多少个参数最重要,它包装了一个长度为3N的数组,比如让该参数包装{0,2,3,1,4,5}数组,这意味着告诉OpenGL  ES要绘制两个三角形,第一个三角形的三个顶点为0、2、3个顶点,第二个三角形的三个顶点为1、4、5个顶点。

    由此可见,如果希望在程序中使用glDrawElements(int  mode  , int  count  , int  type , Buffer   indices)方法来绘制3D图形,不仅需要指定每个3D的顶点位置信息,也需要指定3D图形的每个面由哪三个顶点组成。

    下面的程序使用glDrawElements(int  mode  , int  count  , int  type , Buffer   indices)方法绘制了两个简单的3D图形:三棱锥和立方体,该程序的Renderer实现类的代码:

    import java.nio.ByteBuffer;
    import java.nio.FloatBuffer;
    import java.nio.IntBuffer;

    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;

    import android.opengl.GLSurfaceView.Renderer;

    public class MyRenderer3 implements Renderer{
      //定义三棱锥的4个顶点
      float[] taperVertices = new float[]{
        0.0f,0.5f,0.0f,
        -0.5f,-0.5f,-0.2f,
        0.5f,-0.5f,-0.2f,
        0.0f,-0.2f,0.2f
      };
      //定义三棱锥的4个顶点的颜色
      int[] taperColors = new int[]{
        65535,0,0,0,//红色
        0,65535,0,0,//绿色
        0,0,65535,0,//蓝色
        65535,65535,0,0//黄色
      };
      //定义三棱锥的4个三角面
      private byte[] taperFacets = new byte[]{
        0,1,2,//0、1、2三个顶点组成一个面
        0,1,3,//0、1、3三个顶点组成一个面
        1,2,3,//1、2、3三个顶点组成一个面
        0,2,3//0、2、3三个顶点组成一个面
      };
      //定义立方体的8个顶点
      float[] cubeVertices = new float[]{
        //屏幕之外的正方形的四个顶点
        0.5f,0.5f,0.5f,
        0.5f,-0.5f,0.5f,
        -0.5f,-0.5f,0.5f,
        -0.5f,0.5f,0.5f,
        //屏幕之内的正方形的四个顶点
        0.5f,0.5f,-0.5f,
        0.5f,-0.5f,-0.5f,
        -0.5f,-0.5f,-0.5f,
        -0.5f,0.5f,-0.5f
      };
      //定义立方体所需要的6个面(一共是12个三角形所需的顶点)
      private byte[] cubeFacets = new byte[]{
        0,1,2,
        0,2,3,
        2,3,7,
        2,6,7,
        0,3,7,
        0,4,7,
        4,5,6,
        4,6,7,
        0,1,4,
        1,4,5,
        1,2,6,
        1,5,6
      };
      FloatBuffer taperVerticesBuffer;
      IntBuffer taperColorsBuffer;
      ByteBuffer taperFacetsBuffer;
      FloatBuffer cubeVerticesBuffer;
      ByteBuffer cubeFacetsBuffer;
      //控制旋转的角度
      private float rotate;
      public MyRenderer3(){
        //将三棱锥的顶点位置数据数组包装成FloatBuffer
        taperVerticesBuffer = FloatBuffer.wrap(taperVertices);
        //将三棱锥的四个面的数组包装成ByteBuffer
        taperFacetsBuffer = ByteBuffer.wrap(taperFacets);
        //将三棱锥的四个顶点的颜色数组包装成IntBuffer
        taperColorsBuffer = IntBuffer.wrap(taperColors);
        //将立方体的顶点位置数据数组包装成FloatBuffer
        cubeVerticesBuffer = FloatBuffer.wrap(cubeVertices);
        //将立方体的6个面(12个三角形)的数组包装成ByteBuffer
        cubeFacetsBuffer = ByteBuffer.wrap(cubeFacets);
      }

      @Override
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 关闭抗抖动
        gl.glDisable(GL10.GL_DITHER);
        //设置系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        gl.glClearColor(0, 0, 0, 0);
        //设置阴影平滑模式
        gl.glShadeModel(GL10.GL_SMOOTH);
        //启用深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        //设置深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);
      }

      @Override
      public void onSurfaceChanged(GL10 gl, int width, int height) {
        // 设置3D视窗的大小及位置
        gl.glViewport(0, 0, width, height);
        //将当前矩阵模式视为投影矩阵
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //初始化单位矩阵
        gl.glLoadIdentity();
        //计算透视视窗的宽度、高度比
        float ratio = (float)width/height;
        //调用此方法设置透视视窗的空间大小
        gl.glFrustumf(-ratio,ratio, -1, 1, 1, 10);
      }

      @Override
      public void onDrawFrame(GL10 gl) {
        // 清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
        //启用顶点坐标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //启用顶点颜色数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        //设置当前矩阵模式为模型视图
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        //----------绘制第一个图形---------
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(-0.6f, 0.0f, -1.5f);
        //沿着Y轴旋转
        gl.glRotatef(rotate, 0.0f, 0.2f, 0f);
        //设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, taperVerticesBuffer);
        //设置顶点的颜色数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, taperColorsBuffer);
        //按taperFacetsBuffer指定的面绘制三角形
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,
        taperFacetsBuffer.remaining(), GL10.GL_UNSIGNED_BYTE,
        taperFacetsBuffer);

        //----------绘制第二个图形---------
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(0.7f, 0.0f, -2.2f);
        //沿着Y轴旋转
        gl.glRotatef(rotate, 0f, 0.2f, 0f);
        //沿着X轴旋转
        gl.glRotatef(rotate, 1f, 0f, 0f);
        //设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeVerticesBuffer);
        //不设置顶点的颜色数据,还用以前的颜色数据
        //按cubeFacetsBuffer指定的面绘制三角形
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,
        cubeFacetsBuffer.remaining(), GL10.GL_UNSIGNED_BYTE,
        cubeFacetsBuffer);
        //绘制结束
        gl.glFinish();
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        //旋转角度增加1
        rotate += 1;
      }

    }

    从上面的程序不难看出,绘制3D图形的步骤与绘制2D图形的步骤基本相似,区别只是绘制3D图形不仅需要定义各顶点位置的坐标,还需要定义3D图形的各个三角面由哪些顶点组成,

  • 相关阅读:
    微信支付 h5
    微信支付 h5
    Android stadio butternife工具
    Android stadio butternife工具
    Android stadio 自定义debug release keystore
    Android stadio 自定义debug release keystore
    Android 微信支付步骤
    Android 微信支付步骤
    t
    t
  • 原文地址:https://www.cnblogs.com/jiww/p/5627226.html
Copyright © 2011-2022 走看看