## An Example

We want to create a cube mesh, as shown in the preceding snippets, with the crate texture applied. Since we model the cube in model space around the origin, we have to use glTranslatef() to move it into world space, much like we did with Bob's model in the BobTest example. We also want our cube to spin around the y-axis, which we can achieve by using glRotatef(), again like in the BobTest example. Listing 10-6 shows the complete code of the CubeScreen class contained in a CubeTest class.

Listing 10-6. Excerpt from CubeTest.java: Rendering a Texture Cube class CubeScreen extends GLScreen { Vertices3 cube; Texture texture; float angle = 0;

public CubeScreen(Game game) { super(game); cube = createCube();

texture = new Texture(glGame, "crate.png");

private Vertices3 createCube() {

public CubeScreen(Game game) { super(game); cube = createCube();

texture = new Texture(glGame, "crate.png");

private Vertices3 createCube() {

 float[] vertices = { -0.5f, -0.5f, 0.5f, 0, 1, 0.5f, -0.5f, 0.5f, 1, 1, 0.5f, 0.5f, 0.5f, 1, 0, -0.5f, 0.5f, 0.5f, 0, 0, 0.5f, -0.5f, 0.5f, 0, 1, 0.5f, -0.5f, -0.5f, 1, 1, 0.5f, 0.5f, -0.5f, 1, 0, 0.5f, 0.5f, 0.5f, 0, 0, 0.5f, -0.5f, -0.5f, 0, 1, -0.5f, -0.5f, -0.5f, 1, 1, -0.5f, 0.5f, -0.5f, 1, 0, 0.5f, 0.5f, -0.5f, 0, 0,
 -0.5f, -0.5f, -0.5f, 0, 1, -0.5f, -0.5f, 0.5f, 1, 1, -0.5f, 0.5f, 0.5f, 1, 0, -0.5f, 0.5f, -0.5f, 0, 0, -0.5f, 0.5f, 0.5f, 0, 1, 0.5f, 0.5f, 0.5f, 1, 1, 0.5f, 0.5f, -0.5f, 1, 0, -0.5f, 0.5f, -0.5f, 0, 0, -0.5f, -0.5f, 0.5f, 0, 1, 0.5f, -0.5f, 0.5f, 1, 1, 0.5f, -0.5f, -0.5f, 1, 0, -0.5f, -0.5f, -0.5f, 0, 0

short[] indices = { 0, 1, 3, 1, 2, 3, 4, 5, 7, 5, 6, 7, 8, 9, 11, 9, 10, 11, 12, 13, 15, 13, 14, 15, 16, 17, 19, 17, 18, 19, 20, 21, 23, 21, 22, 23,

Vertices3 cube = new Vertices3(glGraphics, 24, 36, false, true); cube.setVertices(vertices, 0, vertices.length); cube.setIndices(indices, 0, indices.length); return cube;

^Override public void resume() { texture.reload();

^Override public void update(float deltaTime) { angle += 45 * deltaTime;

^Override public void present(float deltaTime) { GL10 gl = glGraphics.getGL();

gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glMatrixMode(GL10.GL_PROJECTION);

GLU.gluPerspective(gl, 67, glGraphics.getWidth() / (float) glGraphics.getHeight(), 0.1f, 10.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity();

gl.glEnable(GL10. GL_DEPTH_TEST); gl.glEnable(GL10. GL_TEXTURE_2D); texture.bind(); cube.bind();

gl.glTranslatef(0,0,-3); gl.glRotatef(angle, 0, 1, 0); cube.draw(GL10.GL_TRIANGLES, 0, 36); cube.unbind();

gl.glDisable(GL10. GL_TEXTURE_2D); gl.glDisable(GL10. GL_DEPTH_TEST);

^Override public void dispose() { }

We have a field to store the cube's mesh, a Texture instance, and a float to store the current rotation angle in. In the constructor we create the cube mesh and load the texture from an asset file called crate.png, a 128x128-pixel image of one side of a crate.

The cube creation code is located in the createCube() method. It just sets up the vertices and indices, and creates a Vertices3 instance from them. Each vertex has a 3D position and texture coordinates.

The resume() method just tells the texture to reload it. Remember, textures must be reloaded after an OpenGL ES context loss.

The update() method just increases the rotation angle by which we'll rotate the cube around the y-axis.

The present() method first sets the viewport and clears the framebuffer and depthbuffer. Next we set up a perspective projection and load an identity matrix to the model-view matrix of OpenGL ES. We enable depth testing and texturing, and bind the texture, as well as the cube mesh. Then we use glTranslatef() to move the cube to the position (0,0,-3) in world space. With glRotatef() we rotate the cube in model space around the y-axis. Remember that the order in which these transformations get applied to the mesh is reversed. The cube will first be rotated (in model space), and then the rotated version will be positioned in world space. Finally we draw the cube, unbind the mesh, and disable depth-testing and texturing. We don't need to disable those states; I just put that in in case we are going to render 2D elements on top of the 3D scene. Figure 10-12 shows the output of our first real 3D program.

Figure 10-12. A spinning texture cube in 3D