前面介紹了 OpenGL ES 所有能夠繪制的基本圖形,點,線段和三角形。其它所有復雜的 2D 或 3D 圖形都是由這些基本圖形構成。
本例介紹如何使用三角形構造一個正20面體。一個正 20 面體,有 12 個頂點,20 個面,30 條邊構成:
http://wiki.jikexueyuan.com/project/opengl-es-guide/images/60.png" alt="" />
創建一個 DrawIcosahedron Activity,定義 20 面體的 12 個頂點,和 20 個面如下:
static final float X=.525731112119133606f;
static final float Z=.850650808352039932f;
static float vertices[] = new float[]{
-X, 0.0f, Z, X, 0.0f, Z, -X, 0.0f, -Z, X, 0.0f, -Z,
0.0f, Z, X, 0.0f, Z, -X, 0.0f, -Z, X, 0.0f, -Z, -X,
Z, X, 0.0f, -Z, X, 0.0f, Z, -X, 0.0f, -Z, -X, 0.0f
};
static short indices[] = new short[]{
0,4,1, 0,9,4, 9,5,4, 4,5,8, 4,8,1,
8,10,1, 8,3,10, 5,3,8, 5,2,3, 2,7,3,
7,10,3, 7,6,10, 7,11,6, 11,0,6, 0,1,6,
6,1,10, 9,0,11, 9,11,2, 9,2,5, 7,2,11 };
OpenGL ES 缺省使用同一種顏色來繪制圖形,為了能夠更好的顯示3D效果,我們為每個頂點隨機定義一些顏色如下:
float[] colors = {
0f, 0f, 0f, 1f,
0f, 0f, 1f, 1f,
0f, 1f, 0f, 1f,
0f, 1f, 1f, 1f,
1f, 0f, 0f, 1f,
1f, 0f, 1f, 1f,
1f, 1f, 0f, 1f,
1f, 1f, 1f, 1f,
1f, 0f, 0f, 1f,
0f, 1f, 0f, 1f,
0f, 0f, 1f, 1f,
1f, 0f, 1f, 1f
};
添加顏色可以參見 Android OpenGL ES 簡明開發教程五:添加顏色 以后也會有詳細說明。
將頂點,面,顏色存放到 Buffer 中以提高性能:
private FloatBuffer vertexBuffer;
private FloatBuffer colorBuffer;
private ShortBuffer indexBuffer;
ByteBuffer vbb
= ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer cbb
= ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
colorBuffer = cbb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
ByteBuffer ibb
= ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
看一看 DrawScene 代碼:
public void DrawScene(GL10 gl) {
super.DrawScene(gl);
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -4);
gl.glRotatef(angle, 0, 1, 0);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
angle++;
}
用來繪制 20 面體使用了 gl.glDrawElements:
public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定義頂點的順序,頂點的順序由 indices Buffer 指定。
本例會顯示一個繞 Y 軸不斷旋轉的 20 面體,如何旋轉模型將在后面的坐標系統和坐標變換中介紹。
http://wiki.jikexueyuan.com/project/opengl-es-guide/images/59.png" alt="" />
DrawLine,DrawTriangle,及本例下載。