前一篇里使用了glDrawArrays,这次要绘制3D的图形,需要用到glDrawElements,比较一下两者的使用

glDrawArrays(mode, first, count) 
        这是在OpenGL下绘制一个三角形的方法, 第一个模式如GL10.GL_FLOAT等, 第二个是当前三角形点的索引(标号),第三个参数是点数目, ,  该函数会从数组中找到第first个点, 向后找到count个, 用这些点来点点依次相连绘制成一个个三角形。在opengl es中是不支持直接绘制除三角形外的多边形的。
glDrawElements(mode, count, type, indices)
        第一个参数是类型(如GL_TRIANGLES),第二个点数目,第三个指的是第四个参数的类型,第四个参数是三角形的索引数据。
        第一个参数好理解;第二个参数就是你用glTexCoordPointer传入点的个数;第三个参数是只最后一个参数的类型,要注意,opengl es是不支持GL_UNSIGNED_INT的,现在只支持GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT这两个参数。第四个参数要注意,稍有不慎就会把图片贴得缺胳膊少腿的。下面举个例子:

          我们用基本的四变形来举例子,我们有个四边形(v1,v2,v3,v4),那我们怎么去把这个四边形分割为2个三角形呢,就是根据这个索引。如(0,1,2,3)就告诉系统,前3个组成一个三角形,后3个点组成三角形,  0123代表着对应坐标数组的下标。如果说这个索引有问题的话,有可能导致2个三角形不能组成一个四边形,这样纹理贴图就会缺少一块。    

下面绘制一个旋转的三角锥和一个正方体

android如何显示3d模型 android绘制3d图形_数组

重点是renderer类,Activity部分和上一篇一样

public class MyRenderer 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 MyRenderer()
	{
		// 将三棱椎的顶点位置数据数组包装成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, 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;
	}
}