Android沿用了J2ME的OPENGL ES API.

相比C版本的OpenGL,Opengl ES 没有glu和glut库,而且只能画三角形(多边形需要三角化)。

没有直接的drawXXX 方法,只有通过 glVertiexPointer传入顶点画图。

另外参数上,没有指针和C风格的数组,Java需要用Buffer类来代替这个。

先看android的glVertexPointer :

GL10.glVertexPointer(int size, int type, int stride, Buffer pointer):

这个方法为 后面openGL绘图准备顶点数据。

size : 代表每个顶点包含几个坐标参数 ,如pointer的buffer中只含有 x,y坐标, 则传2, OpenGL会默认使用0作为z坐标。如果包含 x,y,z 坐标,则传3。其他值在这里都不适用。 type : 是一个枚举值,可以为 GL_FLOAT和 GL_FIXED,浮点数可对应java 的 float,要求pointer为 FloatBuffer. GL_FIXED意为定点数,长度4字节,高16位表示整数部分,低16位表示小数部分。传入int值前需要先左移16位(即需扩大 0x10000倍)。要求pointer为IntBuffer. stride :指每个元素之间,间隔多少个值。加入buffer中坐标点数值间紧密相连,那么stride就是0,如果点1,点2间还有不用到的值,则stride就是这种值的个数。 pointer:这是最需要注意的一个参数,也是Java版OpenGL特有的。Buffer类型是一个基类,具体的类型是 FloatBuffer还是IntBuffer要根据前面type参数来决定。 Java中的 Buffer分两种,一种direct,一种非direct.这里只支持 DirectBuffer,也就是通过ByteBuffer.allocateDirect(int cap) 分配而来的buffer. 通过allocateDirect 得到的是一个 ByteBuffer,实际使用时,如果要作为FloatBuffer,可以通过 ByteBuffer.asFloatBuffer来得到,IntBuffer也同样。 做到这些当然还不够,ByteOrder也对这个参数有影响。当的ByteBuffer作为FloatBuffer,则float的4字节默认是按照小端排列在directBuffer中,在 某些大端的设备中这个buffer的格式就不正确,需要根据设备设置ByteOrder. 所以以FloatBuffer为例,创建方法如下: FloatBuffer buffer = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asFloatBuffer(); 有了FloatBuffer,我们还需要将实际顶点坐标传入这个buffer。这只需要调用 FloatBuffer.put(float)的方法即可。 注意放顶点坐标是x,y...的格式,还是x,y,z...的格式要和前面第一个参数 size是2还是3统一。 所有的值放完以后,需要调用 buffer.rewind()或者 buffer.position(0),将buffer内游标置回0,否则OpenGL会从最后一次put的下一个位置开始读取。 关于三角化的算法: Android的OpenGL API 画多边形目前只支持 triangle_fan,triangles, triangle_strip 三种。如果只有简单无洞的凸多边形,只需要将所有点当作triangle_fan的顶点就可以画出。 如果存在凹多边形,就需要进行三角化(当然凸多边形也可以三角化,保持逻辑上的统一)。 有个最简单的三角化算法叫做 ear clipping三角化。几何上非常容易理解: 一个多边形的一个顶点,和它相邻两个顶点可以组成一个三角形,如果这个三角形内部不存在这个多边形的其他顶点,就可以把这个顶点和相邻点组成的三角形当作一个ear. 这个ear可以被切下来(沿两个相邻顶点切)。每切一次,得到一个三角形和一个少了一个顶点的多边形,然后再对这个多边形做同样操作,直到剩下的这个多边形也只剩下3个顶点。 如此一来,这个多边形被完全分解为3角形。 要把把几何上的操作变成代码,只要解决这几个问题: #如何判断多边形的一串顶点是逆时针还是顺时针排列的? - 从某个顶点指向它下一个顶点,可以得到一个向量,多边形有几条边就得到几个向量,如果所有相邻两个向量的叉积(前一个向量和后一个向量的叉积)之和大于0,则排列是逆时针的,反之是顺时针的 (根据右手坐标系判断,一系列逆时针向量围成的面积是指向z轴正向的),为0有两种情况,这串点是直线,或者多边形某两条边交叉,这种多变形不符合这个三角化算法的条件。 #根据顶点顺逆情况,调整顶点排列,保证逆时针排序,则可以得到如下结论: - 如果相邻两个向量,前一个向量和后一个向量叉积,值为正,则两个向量连接点这个顶点是凸点,值为负则为凹点。 - 如果有相邻3个顶点 p1,p2,p3 组成三角形,有另外一个顶点 P,如何判断P是否在三角形内? 分别做如下几个叉积p2P X p1p2, p3P X p2p3 , p1P X p3p1 ,如果这3个叉积同为正或同为负,则这个顶点在三角形内部。 关于 glEnableClientState, glDisableClientState, glEnableClientState(int cap); cap : GL_COLOR_ARRAY GL_EDGE_FLAG_ARRAY GL_FOG_COORD_ARRAY GL_INDEX_ARRAY GL_NORMAL_ARRAY GL_SECONDARY_COLOR_ARRAY GL_TEXTURE_COORD_ARRAY GL_VERTEX_ARRAY 是用来启用或者关闭和这些数组功能。 如同前面的glVertexPointer ,还有别的诸如 glColorPointer, glEdgeFlagPointer等等接口, glVertexPointer描述顶点位置,其他的描述顶点或者平面的属性。 这些数组默认都是disable状态,如果用这两个接口enable了某个数组,那么当glDrawArrays 调用之前必须把相应的数组准备好。否则draw不能成功。 所以如果不准备传入某个数组,draw之前要先 disable这个数组(如果前面enable过)。 反之如果要使用某个数组,也要事先enable。

还有Java中缺少的API,比如没有glPerspective的时候如何用glFrustm实现glPerspective,以及没有gluLookAt的时候如何用modelView来得到同样效果。将在之后文章里面解说。

更多相关文章

  1. Android填充多边形
  2. Android OpenGL入门示例:绘制三角形和正方形 (附完整源码)
  3. Android 3D 旋转的三角形(一)
  4. Android drawable 三角形
  5. Android下使用OpenGL绘制三角形
  6. Android svg 绘制三角形
  7. Android 3D 旋转的三角形(二)
  8. Android 3D 旋转的三角形(四)
  9. Android 3D 旋转的三角形(三)

随机推荐

  1. Vite+React+TypeScript手撸TodoList的项
  2. 通过C#编写一个简易的Windows截屏增强工
  3. C语言超细致讲解函数递归
  4. usbmanger android 底下USB的工作模式
  5. Android(安卓)在init.rc启动一个c++程序
  6. Android平台上的11个感应器你都知道吗
  7. Android多文件断点续传(二)——实现数据库
  8. Android(安卓)ActionBar的源代码分析(二)
  9. FileProvider无法获取外置SD卡问题解决方
  10. Android5.1系统通过包名给应用开放系统权