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.