OpenGL ES系列(5--3D立体图形)

转自:http://www.guidebee.info/wordpress/archives/1554

前面的例子尽管使用了OpenGL ES 3D图形库,但绘制的还是二维图形(平面上的正方形)。Mesh(网格,三角面)是构成空间形体的基本元素,前面的正方形也是有两个Mesh构成的。本篇将介绍使用Mesh构成四面体,椎体等基本空间形体。

Design设计

在使用OpenGL 框架时一个好的设计原则是使用“Composite Pattern”,本篇采用如下设计:

Mesh

首先定义一个基类 Mesh,所有空间形体最基本的构成元素为Mesh(三角形网格) ,其基本定义如下:

1 public class Mesh {
2  // Our vertex buffer.
3  private FloatBuffer verticesBuffer = null;
4  
5  // Our index buffer.
6  private ShortBuffer indicesBuffer = null;
7  
8  // The number of indices.
9  private int numOfIndices = -1;
10  
11  // Flat Color
12  private float[] rgba
13  new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
14  
15  // Smooth Colors
16  private FloatBuffer colorBuffer = null;
17  
18  // Translate params.
19  public float x = 0;
20  
21  public float y = 0;
22  
23  public float z = 0;
24  
25  // Rotate params.
26  public float rx = 0;
27  
28  public float ry = 0;
29  
30  public float rz = 0;
31  
32  public void draw(GL10 gl) {
33  // Counter-clockwise winding.
34  gl.glFrontFace(GL10.GL_CCW);
35  // Enable face culling.
36  gl.glEnable(GL10.GL_CULL_FACE);
37  // What faces to remove with the face culling.
38  gl.glCullFace(GL10.GL_BACK);
39  // Enabled the vertices buffer for writing and
40  //to be used during
41  // rendering.
42  gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
43  // Specifies the location and data format
44  //of an array of vertex
45  // coordinates to use when rendering.
46  gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
47  // Set flat color
48  gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
49  // Smooth color
50  if (colorBuffer != null) {
51  // Enable the color array buffer to be
52  //used during rendering.
53  gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
54  gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
55  }
56  
57  gl.glTranslatef(x, y, z);
58  gl.glRotatef(rx, 100);
59  gl.glRotatef(ry, 010);
60  gl.glRotatef(rz, 001);
61  
62  // Point out the where the color buffer is.
63  gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices,
64  GL10.GL_UNSIGNED_SHORT, indicesBuffer);
65  // Disable the vertices buffer.
66  gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
67  // Disable face culling.
68  gl.glDisable(GL10.GL_CULL_FACE);
69  }
70  
71  protected void setVertices(float[] vertices) {
72  // a float is 4 bytes, therefore
73  //we multiply the number if
74  // vertices with 4.
75  ByteBuffer vbb
76  = ByteBuffer.allocateDirect(vertices.length * 4);
77  vbb.order(ByteOrder.nativeOrder());
78  verticesBuffer = vbb.asFloatBuffer();
79  verticesBuffer.put(vertices);
80  verticesBuffer.position(0);
81  }
82  
83  protected void setIndices(short[] indices) {
84  // short is 2 bytes, therefore we multiply
85  //the number if
86  // vertices with 2.
87  ByteBuffer ibb
88  = ByteBuffer.allocateDirect(indices.length * 2);
89  ibb.order(ByteOrder.nativeOrder());
90  indicesBuffer = ibb.asShortBuffer();
91  indicesBuffer.put(indices);
92  indicesBuffer.position(0);
93  numOfIndices = indices.length;
94  }
95  
96  protected void setColor(float red, float green,
97  float blue, float alpha) {
98  // Setting the flat color.
99  rgba[0] = red;
100  rgba[1] = green;
101  rgba[2] = blue;
102  rgba[3] = alpha;
103  }
104  
105  protected void setColors(float[] colors) {
106  // float has 4 bytes.
107  ByteBuffer cbb
108  = ByteBuffer.allocateDirect(colors.length * 4);
109  cbb.order(ByteOrder.nativeOrder());
110  colorBuffer = cbb.asFloatBuffer();
111  colorBuffer.put(colors);
112  colorBuffer.position(0);
113  }
114 }
  • setVertices 允许子类重新定义顶点坐标。
  • setIndices 允许子类重新定义顶点的顺序。
  • setColor /setColors允许子类重新定义颜色。
  • x,y,z 定义了平移变换的参数。
  • rx,ry,rz 定义旋转变换的参数。

Plane

有了Mesh定义之后,再来构造Plane,plane可以有宽度,高度和深度,宽度定义为沿X轴方向的长度,深度定义为沿Z轴方向长度,高度为Y轴方向。

Segments为形体宽度,高度,深度可以分成的份数。 Segments在构造一个非均匀分布的Surface特别有用,比如在一个游戏场景中,构造地貌,使的Z轴的值随机分布在-0.1到0.1之间,然后给它渲染好看的材质就可以造成地图凹凸不平的效果。

上面图形中Segments为一正方形,但在OpenGL中我们需要使用三角形,所有需要将Segments分成两个三角形。为Plane 定义两个构造函数:

// Let you decide the size of the plane but still only one segment.
public Plane(float width, float height)

// For alla your settings.
public Plane(float width, float height, int widthSegments, int heightSegments)

比如构造一个1 unit 宽和 1 unit高,并分成4个Segments,使用图形表示如下:

左边的图显示了segments ,右边的图为需要创建的Face(三角形)。

Plane类的定义如下:

1 public class Plane extends Mesh {
2  public Plane() {
3  this(1111);
4  }
5  
6  public Plane(float width, float height) {
7  this(width, height, 11);
8  }
9  
10  public Plane(float width, float height, int widthSegments,
11  int heightSegments) {
12  float[] vertices
13  new float[(widthSegments + 1)
14  * (heightSegments + 1) * 3];
15  short[] indices
16  new short[(widthSegments + 1)
17  * (heightSegments + 1)* 6];
18  
19  float xOffset = width / -2;
20  float yOffset = height / -2;
21  float xWidth = width / (widthSegments);
22  float yHeight = height / (heightSegments);
23  int currentVertex = 0;
24  int currentIndex = 0;
25  short w = (short) (widthSegments + 1);
26  for (int y = 0; y < heightSegments + 1; y++) {
27  for (int x = 0; x < widthSegments + 1; x++) {
28  vertices[currentVertex] = xOffset + x * xWidth;
29  vertices[currentVertex + 1] = yOffset + y * yHeight;
30  vertices[currentVertex + 2] = 0;
31  currentVertex += 3;
32  
33  int n = y * (widthSegments + 1) + x;
34  
35  if (y < heightSegments && x < widthSegments) {
36  // Face one
37  indices[currentIndex] = (short) n;
38  indices[currentIndex + 1] = (short) (n + 1);
39  indices[currentIndex + 2] = (short) (n + w);
40  // Face two
41  indices[currentIndex + 3] = (short) (n + 1);
42  indices[currentIndex + 4] = (short) (n + 1 + w);
43  indices[currentIndex + 5] = (short) (n + 1 + w - 1);
44  
45  currentIndex += 6;
46  }
47  }
48  }
49  
50  setIndices(indices);
51  setVertices(vertices);
52  }
53 }

Cube

下面来定义一个正方体(Cube),为简单起见,这个四面体只可以设置宽度,高度,和深度,没有和Plane一样提供Segments支持。

1 public class Cube extends Mesh {
2  public Cube(float width, float height, float depth) {
3  width  /= 2;
4  height /= 2;
5  depth  /= 2;
6  
7  float vertices[] = { -width, -height, -depth, // 0
8  width, -height, -depth, // 1
9  width,  height, -depth, // 2
10  -width,  height, -depth, // 3
11  -width, -height,  depth, // 4
12  width, -height,  depth, // 5
13  width,  height,  depth, // 6
14  -width,  height,  depth, // 7
15  };
16  
17  short indices[] = { 045,
18  051,
19  156,
20  162,
21  267,
22  273,
23  374,
24  340,
25  476,
26  465,
27  301,
28  312, };
29  
30  setIndices(indices);
31  setVertices(vertices);
32  }
33 }

Group

Group可以用来管理多个空间几何形体,如果把Mesh比作Android的View ,Group可以看作Android的ViewGroup,Android的View的设计也是采用的“Composite Pattern”。

Group的主要功能是把针对Group的操作(如draw)分发到Group中的每个成员对应的操作(如draw)。

Group定义如下:

1 public class Group extends Mesh {
2  private Vector<Mesh> children = new Vector<Mesh>();
3  
4  @Override
5  public void draw(GL10 gl) {
6  int size = children.size();
7  forint i = 0; i < size; i++)
8  children.get(i).draw(gl);
9  }
10  
11  /**
12  * @param location
13  * @param object
14  * @see java.util.Vector#add(int, java.lang.Object)
15  */
16  public void add(int location, Mesh object) {
17  children.add(location, object);
18  }
19  
20  /**
21  * @param object
22  * @return
23  * @see java.util.Vector#add(java.lang.Object)
24  */
25  public boolean add(Mesh object) {
26  return children.add(object);
27  }
28  
29  /**
30  *
31  * @see java.util.Vector#clear()
32  */
33  public void clear() {
34  children.clear();
35  }
36  
37  /**
38  * @param location
39  * @return
40  * @see java.util.Vector#get(int)
41  */
42  public Mesh get(int location) {
43  return children.get(location);
44  }
45  
46  /**
47  * @param location
48  * @return
49  * @see java.util.Vector#remove(int)
50  */
51  public Mesh remove(int location) {
52  return children.remove(location);
53  }
54  
55  /**
56  * @param object
57  * @return
58  * @see java.util.Vector#remove(java.lang.Object)
59  */
60  public boolean remove(Object object) {
61  return children.remove(object);
62  }
63  
64  /**
65  * @return
66  * @see java.util.Vector#size()
67  */
68  public int size() {
69  return children.size();
70  }
71  
72 }

其它建议

上面我们定义里Mesh, Plane, Cube等基本空间几何形体,对于构造复杂图形(如人物),可以预先创建一些通用的几何形体,如果在组合成较复杂的形体。除了上面的基本形体外,可以创建如Cone,Pryamid, Cylinder等基本形体以备后用。

本例示例代码下载,显示结果如下:

Android开发 之 OpenGL ES系列(5--3D立体图形)相关推荐

  1. Android 开发使用OpenGL ES绘制三棱锥并进行纹理贴图

    效果图: 直接上代码 MainActivity.java的代码 package com.zzu.shiyan3;import androidx.appcompat.app.AppCompatActiv ...

  2. 在Android中使用OpenGL ES开发第(五)节:GLSL基础语法

    一.前期基础储备 笔者之前的四篇文综述了Android中使用OpenGL ES绘制基本图形和实现了简单的相机预览,初次接触OpenGL ES开发的读者可能对其中新的概念比较迷惑,尤其是其中的顶点着色器 ...

  3. android平台下OpenGL ES 3.0从零开始

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  4. android平台下OpenGL ES 3.0绘制圆点、直线和三角形

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  5. android平台下OpenGL ES 3.0绘制纯色背景

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  6. android平台下OpenGL ES 3.0使用GLSurfaceView对相机Camera预览实时处理

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  7. android平台下OpenGL ES 3.0实例详解顶点属性、顶点数组

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  8. android平台下OpenGL ES 3.0绘制立方体的几种方式

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  9. Android Camera使用OpenGL ES 2.0和TextureView对预览进行实时二次处理(黑白滤镜)

    本系列教程会有三篇文章讲解Android平台滤镜的实现方式,希望在阅读本文之前先阅读下述第一篇文档,因为第一篇讲过的知识,本文并不会细讲了. 第一篇 Android Camera使用OpenGL ES ...

最新文章

  1. skiller v3 beta2_S10全球总决赛:赛前叫嚣却遭打脸!V3被LGD踢出S10,日本撸友彻底炸锅:真是悲哀...
  2. show status 优化mysql_mysql优化--show status
  3. jsch设置代理_Java使用JSch组件实现SSH协议代理服务
  4. 谷歌大佬花了半年整理的Leetcode刷题笔记
  5. 鲁尼禁赛萨哈一射一传领风骚 曼联客场3-0查尔顿
  6. s5pv210开发板、原理图、刷机和数据手册
  7. Linux CentOS 7 安装 Redis
  8. [计算机系统] - 链接
  9. 小小的 Python 编程故事
  10. 统计学习(二):统计推断
  11. 如何检索综述类文献?
  12. DTU是什么,什么是工业4G DTU?
  13. thinkpadt410接口介绍_联想t410配置参数详解
  14. 邮件群发工具使用说明​
  15. PAT初级1031(C++)查验身份证
  16. php拼车网源码,PHP拼车网源码 微信拼车源码 手机拼车源码 PC+微信双终端
  17. 阿里云ECS服务器被DDoS无解攻击,我改怎么办
  18. 计算机空格键作用,电脑空格键有哪些作用?你知道几个?
  19. 亚马逊云(AWS)、微软云(Azure)、阿里云性能对比之哪家好?
  20. 解决Xubuntu任务栏(Panel)消失的问题

热门文章

  1. 微信前台WEUI前台实例+EXCEL导出,SSM框架完整流程
  2. 一台计算机两个硬盘怎么设置密码,怎样给硬盘加密码? 两招解决硬盘加密难题...
  3. CorelDraw论坛cdr2022V24.0.0301简体中文包
  4. 微信开放平台开源_开源需要开放徽章的3个原因
  5. 【数字IC】深入浅出理解I2C协议
  6. linux centos数据备份,centOS系统的备份与还原
  7. 移动最快apn服务器,中国移动修改APN为CMTDS提高4G网速
  8. GB28181系列笔记-语音对讲功能
  9. c++判断某一天是这一年的第几天
  10. Oracle数据库-函数总结