Skip to content

Half Dozen Hello Worlds Part 5 – Android and OpenGL

HelloRender.java should look like this by default.

package com.learnandroid.helloworld;
 
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
 
import android.opengl.GLSurfaceView.Renderer;
 
public class HelloRenderer implements Renderer {
 
	@Override
	public void onDrawFrame(GL10 arg0) {
		// TODO Auto-generated method stub
 
	}
 
	@Override
	public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) {
		// TODO Auto-generated method stub
 
	}
 
	@Override
	public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
		// TODO Auto-generated method stub
 
	}
 
}

The Renderer Interface provides three methods: onDrawFrame, onSurfaceChanged, and onSurfaceCreated. One thing to note is the Renderer in Android will continually draw frames. It will call onDrawFrame repeatedly, allowing you to perform any animations through the logic in this method. In our example program we will be drawing the same thing over and over again, so it will look like a static image, but it is important to realize that frames are constantly being drawn.

onSurfaceCreated provides a place to do any initialization that doesn’t depend on the screen size or orientation. We won’t be using this method in our example.

onSurfaceChanged is called every time there is a new orientation or screen size (including the first time). We are going to put the following code in this method.

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		GLU.gluPerspective(gl, 60.0f, (float)width / (float)height, 0.1f, 100.0f);
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

glViewPort describes the actual flat representation of the 3D objects. If we were using a camera we would call this the photograph. The first two parameters are the x and y position of the bottom left of the viewport. The last two parameters are the width and height of the viewport. We could have a viewport displayed in a window, which would have values other than (0,0) for the position of its bottom left corner and window height and window width instead of screen height and screen width. In our case, however, we are just going to use the screen values.

glMatrixMode tells OpenGL whether your commands are affecting the projection or the models. Using the camera analogy, we need to be able to specify if we are moving the camera or an object in front of the camera.

gl.glMatrixMode(GL10.GL_PROJECTION)

will allow us to issue commands to our camera.
OpenGL provides ways to reuse transformations. Our next command:

gl.glLoadIdentity();

simply resets the projection matrix so we know that no previous commands sent to OpenGL will be compounded with our commands.

Finally, we get to the actual command we are trying to issue to our projection matrix (camera).

GLU.gluPerspective(gl, 60.0f, (float)width / (float)height, 0.1f, 100.0f);

The values that are passed to gluPerspective are our GL10 object, the angle of view, the aspect ratio, and the distance to the near and far planes.  I’ve provided links to information about angle of view and aspect ratio.  The near plane how close an object can be (beyond the near plane) before it is included in the picture.  The far plane is the greatest distance an object can be from the camera before it is no longer included.  You can think of this is setting your range of vision.  The values I picked here are largely arbitrary for everything except aspect ratio.  Feel free to play around with these numbers and note the affect on the rendered image.

Finally we call these lines of code to put us back into ModelView (so our commands will affect the objects instead of the camera) and reset the Model matrix.

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();

You will frequently see this pattern in OpenGL where you setup your camera and then leave it fixed while manipulating the objects.

{ 11 } Comments