Android OpenGL ES(十一)绘制一个20面体 .

前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形。其它所有复杂的2D或3D图形都是由这些基本图形构成。

本例介绍如何使用三角形构造一个正20面体。一个正20面体,有12个顶点,20个面,30条边构成:

创建一个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
 
};

 

将顶点,面,颜色存放到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面体,如何旋转模型将在后面的坐标系统和坐标变换中介绍.

完整代码:

MainActiviy.java

package com.example.gltest;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;



public class MainActivity extends Activity
       implements IOpenGLDemo{
    private FloatBuffer vertexBuffer;
     
    private FloatBuffer colorBuffer;
     
    private ShortBuffer indexBuffer;
    
    private GLSurfaceView mGLSurfaceView;
     

    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 };
    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
             
            };
    

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            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);
            
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow()
             .setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
     
            mGLSurfaceView = new GLSurfaceView(this);
            mGLSurfaceView.setRenderer(new OpenGLRenderer(this));
            setContentView(mGLSurfaceView);
        }
     
//        public void DrawScene(GL10 gl) {
//            gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
//            // Clears the screen and depth buffer.
//            gl.glClear(GL10.GL_COLOR_BUFFER_BIT
//              | GL10.GL_DEPTH_BUFFER_BIT);
//     
//        }
        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);
             
            float angle=0;
            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++;
             
            }
        @Override
        protected void onResume() {
            // Ideally a game should implement
            // onResume() and onPause()
            // to take appropriate action when the
            //activity looses focus
            super.onResume();
            mGLSurfaceView.onResume();
        }
     
        @Override
        protected void onPause() {
            // Ideally a game should implement onResume()
            //and onPause()
            // to take appropriate action when the
            //activity looses focus
            super.onPause();
            mGLSurfaceView.onPause();
        }
     
        
     
    }

其他类似。

 

 

 

 

posted @ 2015-04-24 10:02  Anita-ff  阅读(770)  评论(0编辑  收藏  举报