CS185c
Chris Pollett
Nov. 3, 2010
package org.pollett;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.ArcShape;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
public class AnimationTest3 extends Activity {
protected static final int GUIUPDATEID = 0x1FF;
AnimRunnable animRunnable;
GraphicsTestView myGraphicsView;
Handler myGUIUpdateHandler = new Handler() {
public void handleMessage(Message msg)
{
switch(msg.what)
{
case AnimationTest3.GUIUPDATEID:
myGraphicsView.invalidate();
break;
}
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
myGraphicsView = new GraphicsTestView(this);
setContentView(myGraphicsView);
new Thread(new AnimRunnable(this)).start();
}
private static class AnimRunnable implements Runnable
{
AnimationTest3 myAnimation;
public AnimRunnable(AnimationTest3 myAnim)
{
myAnimation = myAnim;
}
public void run()
{
while(!Thread.currentThread().isInterrupted())
{
Message message = new Message();
message.what = AnimationTest3.GUIUPDATEID;
myAnimation.myGUIUpdateHandler.sendMessage(message);
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
}
private static class GraphicsTestView extends View
{
private ShapeDrawable myDrawable;
int ovalX;
int ovalY;
int direction;
public GraphicsTestView (Context context)
{
super(context);
setFocusable(true);
OvalShape oval = new OvalShape();
myDrawable = new ShapeDrawable(oval);
myDrawable.getPaint().setColor(0xFFFF0000);
ovalX = 10;
ovalY = 10;
direction = 5;
}
@Override
protected void onDraw(Canvas canvas)
// the onDraw method is where a view draws itself
{
int width = 50;
int height = 20;
myDrawable.setBounds(ovalX, ovalY, ovalX+ width, ovalY + height);
myDrawable.draw(canvas);
if(ovalX < 10 || ovalX > 250)
{
direction = -direction;
}
ovalX +=direction;
}
}
}
package org.pollett;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class OpenGLTest extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GLView(this));
}
}
class GLView extends SurfaceView implements SurfaceHolder.Callback
{
GLView(Context context)
{
super(context);
getHolder().addCallback(this); // we will be called if surface
// created or destroyed
// set up hardware acceleration if possible
getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
public void surfaceCreated(SurfaceHolder holder)
{
}
public void surfaceDestroyed(SurfaceHolder holder)
{
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
// should implement to handle window resizing
}
private GLThread glThread;
public void surfaceCreated(SurfaceHolder holder)
{
glThread = new GLThread(this);
glThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
glThread.requestExitAndWait();
glThread = null;
}
class GLThread extends Thread
{
private final GLView view;
private boolean done = false;
GLThread(GLView view)
{
this.view = view;
}
@Override
public void run()
{
while(!done)
{
//draw a frame
}
}
public void requestExitAndWait()
{
//called when surface is destroyed
//Tell the thread to quit
done = true;
try
{
join();
}
catch(InterruptedException ex)
{
}
}
}
@Override
public void run()
{
// Init OpenGL
EGL10 egl = (EGL10)EGLContext.getEGL();
// create and initialize a display handle
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
egl.eglInitialize(display, version);
//set up that we want 16 bits of color and how they are split into rgb
EGLConfig[] configs = new EGLConfig[1];
int[] configSpec = { EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6, EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE};
int[] numConfig = new int[1];
egl.eglChooseConfig(display, configSpec, configs, 1, numConfig);
EGLConfig config = configs[0];
//using the config stuff we create a context and a surface
EGLContext glc = egl.eglCreateContext(display,
config, EGL10.EGL_NO_CONTEXT, null);
EGLSurface surface = egl.eglCreateWindowSurface(display, config, view.getHolder(), null);
egl.eglMakeCurrent(display, surface, surface, glc);
//create an interface into openGL
GL10 gl = (GL10)(glc.getGL());
init(gl); //will describe in a bit
//loop until asked to quit
while(!done)
{
//draw a frame (describe in a minute)
drawFrame(gl);
egl.eglSwapBuffers(display, surface);
//Error Handling
if(egl.eglGetError() == EGL11.EGL_CONTEXT_LOST)
{
Context c = view.getContext();
if(c instanceof Activity)
{
((Activity) c).finish();
}
}
}
//Free OpenGL resources
egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(display, surface);
egl.eglDestroyContext(display, glc);
egl.eglTerminate(display);
}
private void init(GL10 gl)
{
//define the view frustrum
gl.glViewport(0, 0, view.getWidth(), view.getHeight());
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float ratio = (float) view.getWidth() / view.getHeight();
//set viewing angle of view frustrum. ratio of its width to
// height, near and far clipping planes
GLU.gluPerspective(gl, 45.0f, ratio, 1, 100);
//pixels farther than those already drawn ignored
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}
private void drawFrame(GL10 gl)
{
//clear screen to black
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//Position model so can see
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -3.0f);
}
class GLCube
{
private final IntBuffer mVertexBuffer;
GLCube()
{
int one = 65536;
int half = one/2;
int vertices[] =
{
//Front
-half, -half, half, half, -half, half,
-half, half, half, half, half, half,
//Back
-half, -half, -half, -half, half, -half,
half, -half, -half, half, half, -half,
//Left
-half, -half, half, -half, half, half,
-half, -half, -half, -half, half, -half,
//Right
half, -half, -half, half, half, -half,
half, -half, half, half, half, half,
//Top
-half, half, half, half, half, half,
-half, half, -half, half, half, -half,
//Bottom
-half, -half, half, -half, -half, -half,
half, -half, half, half, -half, -half
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asIntBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
}
void draw(GL10 gl)
{
gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
gl.glColor4f(1, 1, 1, 1);
gl.glNormal3f(0, 0, 1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glNormal3f(0, 0, -1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
gl.glColor4f(1, 1, 1, 1);
gl.glNormal3f(-1, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
gl.glNormal3f(1, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
gl.glColor4f(1, 1, 1, 1);
gl.glNormal3f(0, 1, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
gl.glNormal3f(0, -1, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
}
}
private final GLCube cube = new GLCube();to our GLThread class.
private void drawFrame(GL10 gl)
{
//clear screen to black
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//Position model so can see
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -3.0f);
cube.draw(gl);
}