Since I spent quite a few hours trying to get my first OpenGL ES triangle on the Android phone’s screen I thought I should share the code with everyone to ease a bit the pain. Hopefully this will help someone get going on Android.
MainActivity.java
package com.ruibm;
import android.app.Activity;
import android.graphics.PointF;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
public class MainActivity extends Activity {
private PointF touchStart;
private GLSurfaceView glSurfaceView;
private TriangleRenderer renderer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
touchStart = new PointF();
glSurfaceView = new GLSurfaceView(this);
renderer = new TriangleRenderer();
glSurfaceView.setRenderer(renderer);
setContentView(glSurfaceView);
}
@Override
protected void onResume() {
super.onResume();
glSurfaceView.onResume();
}
@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
renderer.move(event.getX() - touchStart.x, touchStart.y - event.getY());
touchStart.set(event.getX(), event.getY());
glSurfaceView.requestRender();
return true;
case MotionEvent.ACTION_DOWN:
touchStart.set(event.getX(), event.getY());
return true;
default:
return super.onTouchEvent(event);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
renderer.move(0, 1);
glSurfaceView.requestRender();
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
renderer.move(0, -1);
glSurfaceView.requestRender();
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
renderer.move(-1, 0);
glSurfaceView.requestRender();
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
renderer.move(1, 0);
glSurfaceView.requestRender();
return true;
default:
return super.onKeyDown(keyCode, event);
}
}
}
TriangleRenderer.java
package com.ruibm;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.graphics.PointF;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;
public class TriangleRenderer implements Renderer {
private PointF surfaceSize;
private PointF offset;
private ShortBuffer triangleBuffer;
public TriangleRenderer() {
surfaceSize = new PointF();
offset = new PointF();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
surfaceSize.set(width, height);
// Create our triangle.
final int div = 1;
short[] triangles = {
0, 0, 0,
0, (short) (surfaceSize.y / div), 0,
(short) (surfaceSize.x / div), (short) (surfaceSize.y / div), 0,
};
triangleBuffer = ShortBuffer.wrap(triangles);
// Disable a few things we are not going to use.
gl.glDisable(GL10.GL_LIGHTING);
gl.glDisable(GL10.GL_CULL_FACE);
gl.glDisable(GL10.GL_DEPTH_BUFFER_BIT);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glClearColor(.5f, .5f, .8f, 1.f);
gl.glShadeModel(GL10.GL_SMOOTH);
float ratio = surfaceSize.x / surfaceSize.y;
gl.glViewport(0, 0, (int) surfaceSize.x, (int) surfaceSize.y);
// Set our field of view.
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(
-surfaceSize.x / 2, surfaceSize.x / 2,
-surfaceSize.y / 2, surfaceSize.y / 2,
1, 3);
// Position the camera at (0, 0, -2) looking down the -z axis.
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// Points rendered to z=0 will be exactly at the frustum's
// (farZ - nearZ) / 2 so the actual dimension of the triangle should be
// half
gl.glTranslatef(0, 0, -2);
}
public void onDrawFrame(GL10 gl) {
gl.glPushMatrix();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glTranslatef(offset.x, offset.y, 0);
gl.glColor4f(1.0f, 0.3f, 0.0f, .5f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_SHORT, 0, triangleBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPopMatrix();
}
public void move(float xDelta, float yDelta) {
offset.x += xDelta;
offset.y += yDelta;
Log.d("TriangleRenderer", "offset=[" + offset.x + " ," + offset.y + "]");
}
}