如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出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图形的各个三角面由哪些顶点组成,

使用OpenGL ES绘制3D图形的更多相关文章

  1. 【Qt for Android】OpenGL ES 绘制彩色立方体

    Qt 内置对OpenGL ES的支持.选用Qt进行OpenGL ES的开发是很方便的,很多辅助类都已经具备.从Qt 5.0開始添加了一个QWindow类,该类既能够使用OpenGL绘制3D图形,也能够 ...

  2. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  3. [OpenGL ES 03]3D变换:模型,视图,投影与Viewport

    [OpenGL ES 03]3D变换:模型,视图,投影与Viewport 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商业用途-保持一致”创作公用协议 系列 ...

  4. Python 使用 matplotlib绘制3D图形

    3D图形在数据分析.数据建模.图形和图像处理等领域中都有着广泛的应用,下面将给大家介绍一下如何在Python中使用 matplotlib进行3D图形的绘制,包括3D散点.3D表面.3D轮廓.3D直线( ...

  5. Python绘制3D图形

    来自:https://www.jb51.net/article/139349.htm 3D图形在数据分析.数据建模.图形和图像处理等领域中都有着广泛的应用,下面将给大家介绍一下如何使用python进行 ...

  6. Python plot_surface(Axes3D)方法:绘制3D图形

    3D 图形需要的数据与等高线图基本相同:X.Y 数据决定坐标点,Z 轴数据决定 X.Y 坐标点对应的高度.与等高线图使用等高线来代表高度不同,3D 图形将会以更直观的形式来表示高度. 为了绘制 3D ...

  7. 2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

    在之前成功绘制变色的几何图形之后,今天利用Openg ES的可编程管线绘制出第一张纹理. 学校时候不知道OpenGL的重要性,怕晦涩的语法.没有跟老师学习OpenGL的环境配置,现在仅仅能利用coco ...

  8. Android OpenGL ES 开发(四): OpenGL ES 绘制形状

    在上文中,我们使用OpenGL定义了能够被绘制出来的形状了,现在我们想绘制出来它们.使用OpenGLES 2.0来绘制形状会比你想象的需要更多的代码.因为OpenGL的API提供了大量的对渲染管线的控 ...

  9. Qt OpenGL:学习现代3D图形编程之四,透视投影浅析

    一.非真实的世界 与之前几篇文章不同的是,这里要画12个三角形,这个12个三角形构造一个方形棱柱(这里为长方体).棱柱的每个四边形表面由两个三角形组成.这两个三角形其中的一条边重合,而且它们的六个顶点 ...

随机推荐

  1. iOS - AVPlayer 音视频播放

    前言 NS_CLASS_AVAILABLE(10_7, 4_0) @interface AVPlayer : NSObject @available(iOS 4.0, *) public class ...

  2. Linux基础知识之—— nohup命令使程序在后台运行的方法

    在linux操作系统中从后台一直运行某个程序的方法,就是使用nohup命令了. 参照网址:http://www.jb51.net/LINUXjishu/189964.html

  3. [转载] [Mark]分布式存储必读论文

    原文: http://50vip.com/423.html 分布式存储泛指存储存储和管理数据的系统, 与无状态的应用服务器不同, 如何处理各种故障以保证数据一致,数据不丢, 数据持续可用, 是分布式存 ...

  4. bootstrap 图片轮播效果

    <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http: ...

  5. 我想有个梦想(I want have a dream)

    成东青说过:梦想是什么,梦想就是你坚持就觉得是幸福东西. 多好啊,有梦想,想想就觉得幸福的.也许你会觉得有点做作,但我真觉得是这样.没有梦想就像一个没有了灵魂的躯壳,整天浑浑噩噩,整天麻木的上班下班, ...

  6. mysql Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

    错误原因:/var/lib/mysql目录中socket文件不存在.连接mysql服务器有两种方式:tcp连接,通过socket文件连接.通过socket文件,启动mysql服务,mysql服务会自动 ...

  7. odoo关联表查询方法

    testinfo=self.env['product.attribute.value'].search([('product_ids.product_tmpl_id','=',2047)]) for ...

  8. (三)uboot源码分析

    一.九鼎官方uboot和三星原版uboot对比(1)以九鼎官方的uboot为蓝本来学习的,以三星官方的这份为对照.(2)不同版本的uboot或者同一版本不同人移植的uboot,可能目录结构和文件内容都 ...

  9. golang chan 超时

    golang chan 超时 Posted on 2013-12-24 13:03 oathleo 阅读(4227) 评论(0)  编辑  收藏 package main import (    &q ...

  10. 工作流学习——重要概念扫盲篇一步曲 (zhuan)

    http://blog.csdn.net/zwk626542417/article/details/46592471 ***************************************** ...