Building a Model

Depending on the complexity of the objects you want to draw, you will typically create them using a graphical design tool and import them into your program. For the purposes of this example, we'll just define a simple model in code: a cube.

Download OpenGL/src/org/example/opengl/GLCube.java Line 1 package org.example.opengl;

- import java.nio.ByteBuffer;

- import java.nio.ByteOrder; 5 import java.nio.IntBuffer;

- import javax.microedition.khronos.opengles.GL10;

- import android.content.Context; 10 import android.graphics.Bitmap;

- import android.graphics.BitmapFactory;

- import android.opengl.GLUtils;

15 private final IntBuffer mVertexBuffer;

- -half, -half, -half, -half, half, -half, 25 half, -half, -half, half, half, -half,

- -half, -half, -half, -half, half, -half, // RIGHT

- -half, half, -half, half, half, -half, 35 // BOTTOM

// Buffers to be passed to gl*Pointer() functions must be 40 // direct, i.e., they must be placed on the native heap

- // where the garbage collector cannot move them.

// Buffers with multi-byte data types (e.g., short, int,

- // float) must have their byte order set to native order

45 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);

- vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asIntBuffer(); mVertexBuffer.put(vertices);

- mVertexBuffer.position(O);

public void draw(GL10 gl) {

gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);

- g1.g1Norma13f(0, 0,1); g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

- g1.g1Norma13f(0, 0, -1); g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

- g1.g1Norma13f(-1, 0,0); g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); g1.g1Norma13f(1, 0,0);

65 g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

- g1.g1Norma13f(0, 1,0); g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);

g1.g1DrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);

The vertices array on line 19 defines the corners of the cube in fixed-point model coordinates (see the "Fixed vs. Floating Point" sidebar). Each face of a cube is a square, which consists of two triangles. We use a common OpenGL drawing mode called triangle strips. In this mode, we specify two starting points, and then after that every subsequent point defines a triangle with the previous two points. It's a quick way to get a lot of geometry pumped out to the graphics hardware in a hurry.

Note that each point has three coordinates (x, y, and z). The x- and y-axes point to the right and up, respectively, and the z-axis points out of the screen toward the eye point.

In the draw method (line 52), we use the vertex buffer created in the constructor and draw six different runs of triangles (for the six sides of the cube). In a real program, you would want to combine the calls into one or two strips, because the fewer number of OpenGL calls you make, the faster your program will go.

Now let's use our new class in GLRenderer:

Download OpenGL/src/org/example/opengl/GLRenderer.java

private final GLCube cube = new GLCube(); public void onDrawFrame(GL10 gl) { // ...

OpenGL ES provides fixed-point (integer) and floating-point interfaces for all its methods. The fixed-point methods end with the letter x, and the floating-point ones end with the letter f. For example, you can use either glColor4x() and glColor4f() to set the four components of a color.

A fixed-point number is scaled by 2A16, or 65,536. So, 32,768 in fixed point is equivalent to 0.5f. Put another way, the integral part uses the most significant two bytes of a four-byte int, while the fractional part uses the least significant two bytes. This is quite different from the way the native Android 2D library uses integers, so be careful.

In a simple example like this one, it doesn't matter whether you use fixed-point or floating-point arithmetic, so I use them interchangeably as convenient. Keep in mind, though, that some Android devices will not have floating-point hardware, so fixed point might be faster. On the other hand, some developers report it's actually slower than emulated floating point for them. Your mileage may vary.

My advice is to code it first using floating point, because it's easier to program. Then optimize the slow parts using fixed point later if necessary.

Now if you run the program, you'll see the exciting image in Figure 10.3, on the following page. Well, it's more exciting than black.

0 0

Post a comment