VortexActivity.java
package com.vortex_android; import android.app.Activity; import android.os.Bundle; public class VortexActivity extends Activity{ private static final String LOG_TAG=VortexActivity.class.getSimpleName(); private VortexView vortexView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); vortexView=new VortexView(this); setContentView(vortexView); } }
VortexView
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.vortex_android; import android.content.Context; import android.opengl.GLSurfaceView; import android.view.MotionEvent; /** * * @author Administrator */ public class VortexView extends GLSurfaceView{ private static final String LOG_TAG=VortexView.class.getSimpleName(); private VortexRenderer renderer; private MotionEvent eventMediator; private float x=0; private float y=0; public VortexView(Context context){ super(context); renderer=new VortexRenderer(); this.setRenderer(renderer); } //GLSurfaceView equals to GLJPanel, also a view container; @Override public boolean onTouchEvent(final MotionEvent event){ //2 method both will be OK . onDrawFrame(GL10 gl) will run //automatic when the GLSurfaceView.setRenderer; it is the same as //opengl2. //not need to get the runnable thread and control it //but it also works; // eventMediator=event; //// this.queueEvent(glRunnable); // renderer.setColor(eventMediator.getX()/getWidth(), eventMediator.getY()/getHeight(), 1); // renderer.setAngleY(event.getX()); if(event.getAction()==MotionEvent.ACTION_DOWN){ x=event.getX(); y=event.getY(); } if(event.getAction()==MotionEvent.ACTION_MOVE){ final float xdiff=(event.getX()-x); final float ydiff=(event.getY()-y); renderer.setAngleX(renderer.getAngleX()+ydiff); renderer.setAngleY(renderer.getAngleY()+xdiff); x=event.getX(); y=event.getY(); } return true; } private Runnable glRunnable=new Runnable(){ public void run() { renderer.setColor(eventMediator.getX()/getWidth(), eventMediator.getY()/getHeight(), 1); } }; }
VortexRenderer
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.vortex_android; import android.opengl.GLSurfaceView; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; /** * * @author Administrator */ public class VortexRenderer implements GLSurfaceView.Renderer{ private static final String LOG_TAG=VortexRenderer.class.getSimpleName(); private float red=0.9f; private float green=0.2f; private float blue=0.2f; private ShortBuffer indexBuffer; private ShortBuffer indexBufferStatic; private FloatBuffer vertexBuffer; private FloatBuffer vertexBufferStatic; // private short[] indexArray; // private int numVertices=3; private FloatBuffer colorBuffer; private float angleX; private float angleY; private float width=320; private float height=480; //renderer equals to GLEventListener; //GLJPanle gljpanel.addGLEventListener(glListener); public VortexRenderer() { } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //equlas to init(GLAutoDrawable drawable){}; gl.glMatrixMode(GL10.GL_PROJECTION); //ortho // float ratio=width/height; // gl.glOrthof(-1, 1, -1/ratio, 1/ratio, -100, 100); // gl.glViewport(0,0,(int)width,(int)height); //frustum // float size=.01f * (float) Math.tan(Math.toRadians(45.0) / 2); float size=0.002f; float ratio=width/height; gl.glFrustumf(-size, size, -size/ratio, size/ratio, 0.01f, 100); gl.glViewport(0, 0, (int)width, (int)height); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glEnable(GL10.GL_CULL_FACE); gl.glCullFace(GL10.GL_BACK); gl.glEnable(GL10.GL_CCW); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_FRONT_AND_BACK); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); initTriangle(); // initStaticTriangle(); } public void onSurfaceChanged(GL10 gl, int w, int h) { //equals to reshape(GLAutoDrawbale drawable,int x,int y,int width,int height); width=w; height=h; gl.glViewport(0, 0, w, h); } public void onDrawFrame(GL10 gl) { //equals to display(GLAutoDrawable drawable){}; gl.glClearColor(red, green, blue, 1); gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); //draw one pyramid gl.glLoadIdentity(); gl.glPushMatrix(); gl.glTranslatef(0, 0, -5); gl.glRotatef(angleX,1,0,0); gl.glRotatef(angleY,0,1,0); gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer); gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer); // GL10 glDrawElement is different from GL2. GL10 can draw a whole quene of TRIANGLES // in GL2 must use glDrawRangeElement gl.glDrawElements(GL10.GL_TRIANGLES, vertexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer); gl.glPopMatrix(); //draw multi pyramid // gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); // gl.glColorPointer(4,GL10.GL_FLOAT,0,colorBuffer); // // for(int i=0;i<11;i++){ // gl.glLoadIdentity(); // gl.glTranslatef(0, -1, -1-1.5f*i); // gl.glRotatef(angleX, 1, 0, 0); // gl.glRotatef(angleY, 0, 1, 0); // gl.glDrawElements(GL10.GL_TRIANGLES, vertexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer); // // } } private void initTriangle(){ float[] coords=new float[]{ -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, 0 }; float[] colors=new float[]{ 1,0,0,1, 0,1,0,1, 0,0,1,1, 1,1,1,1 }; short[] indices=new short[]{ 0,2,1, 0,1,3, 0,3,2, 1,2,3 }; vertexBuffer=FloatBuffer.allocate(coords.length); indexBuffer=ShortBuffer.allocate(indices.length); colorBuffer=FloatBuffer.allocate(colors.length); vertexBuffer.put(coords); indexBuffer.put(indices); colorBuffer.put(colors); vertexBuffer.rewind(); indexBuffer.rewind(); colorBuffer.rewind(); } // private void initStaticTriangle(){ // vertexBufferStatic=FloatBuffer.allocate(numVertices*3); // indexBufferStatic=ShortBuffer.allocate(indexArray.length); // // float[] coords=new float[]{ // -0.4f, -0.4f, 0, // 0.4f, -0.4f, 0, // 0, 0.4f, 0, // }; // // vertexBufferStatic.put(coords); // indexBufferStatic.put(indexArray); // // vertexBuffer.rewind(); // indexBuffer.rewind(); // // } public void setAngleX(float ang){ angleX=ang; } public float getAngleX(){ return angleX; } public void setAngleY(float ang){ angleY=ang; } public float getAngleY(){ return angleY; } public void setColor(float r, float g, float b){ red=r; green=g; blue=b; } }
Activity must set a GLSurfaceView or its children class
GLSurfaceView must set a renderer which extends GLSurfaceView.Renderer;
must implement 3 functions :
1. onSurfaceCreate(GL10 gl, EGLConfig config) refer to init(Gl2 gl)
2. onDrawFrame(GL10 gl) refer to display(GL2 gl)
3. onSurfaceChanged(Gl10 gl, int w,int h) refer to reshape(GL2 gl , int x, int y, int width, int height)
the renderer nearly equals to the GLEventListener , the GLSurfaceView nearly equals to the GLJPanel
some points of warnings:
1. the VBO is disable in GL10 ES , so just can use normal Buffer .
2. must use unsigned-short instead of int for most android CPU.
So the drawing process would be:
1. enable all params necessery in the onSurfaceCreate function;
2. make the buffers . vertexBuffer, colorBuffer, normalBuffer , indexBuffer .
remenber to rewind() after put data.
3. indicate the pointer to each buffer .
4. drawElements
note that draw elements without VBO is a little different from the situation that with VBO.
VBO draw element must follow the buffer pointer .
So you must set the buffer pointer each time for the indexBuffer.
However, without VBO , you can draw the whole vertexBuffer with the whole index buffer.