• Aucun résultat trouvé

Initializing the New Matrices

Dans le document OpenGL ES 2 for Android (Page 170-176)

The next step is to update onSurfaceChanged() and initialize the view matrix.

Update onSurfaceChanged() to match the following contents:

AirHockeyWithImprovedMallets/src/com/airhockey/android/AirHockeyRenderer.java

@Override

public void onSurfaceChanged(GL10 glUnused, int width, int height) { // Set the OpenGL viewport to fill the entire surface.

glViewport(0, 0, width, height);

MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width / (float) height, 1f, 10f);

setLookAtM(viewMatrix, 0, 0f, 1.2f, 2.2f, 0f, 0f, 0f, 0f, 1f, 0f);

}

Chapter 8. Building Simple Objects

158

The first part of the method is pretty standard: we set the viewport, and we set up a projection matrix. The next part is new: we call setLookAtM() to create a special type of view matrix:

setLookAtM(float[] rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

This is the destination array. This array’s length should be at least sixteen elements so that it can store the view matrix.

float[] rm

setLookAtM() will begin writing the result at this offset into rm.

int rmOffset

This is where the eye will be. Everything in the scene will appear as if we’re viewing it from this point.

float eyeX, eyeY, eyeZ

This is where the eye is looking; this position will appear in the center of the scene.

float centerX, centerY, centerZ

If we were talking about your eyes, then this is where your head would be pointing. An upY of 1 means your head would be pointing straight up.

float upX, upY, upZ

Table 6—setLookAtM() parameters

We call setLookAtM() with an eye of (0, 1.2, 2.2), meaning your eye will be 1.2 units above the x-z plane and 2.2 units back. In other words, everything in the scene will appear 1.2 units below you and 2.2 units in front of you. A center of (0, 0, 0) means you’ll be looking down toward the origin in front of you, and an up of (0, 1, 0) means that your head will be pointing straight up and the scene won’t be rotated to either side.

Updating onDrawFrame

A couple of last changes remain before we can run our program and see the new changes. Add the following code to onDrawFrame() just after the call to glClear():

AirHockeyWithImprovedMallets/src/com/airhockey/android/AirHockeyRenderer.java

multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

This will cache the results of multiplying the projection and view matrices together into viewProjectionMatrix. Replace the rest of onDrawFrame() as follows:

Integrating Our Changes

159

AirHockeyWithImprovedMallets/src/com/airhockey/android/AirHockeyRenderer.java

positionObjectInScene(0f, mallet.height / 2f, -0.4f);

colorProgram.useProgram();

colorProgram.setUniforms(modelViewProjectionMatrix, 1f, 0f, 0f);

mallet.bindData(colorProgram);

mallet.draw();

positionObjectInScene(0f, mallet.height / 2f, 0.4f);

colorProgram.setUniforms(modelViewProjectionMatrix, 0f, 0f, 1f);

// Note that we don't have to define the object data twice -- we just // draw the same mallet again but in a different position and with a // different color.

mallet.draw();

// Draw the puck.

positionObjectInScene(0f, puck.height / 2f, 0f);

colorProgram.setUniforms(modelViewProjectionMatrix, 0.8f, 0.8f, 1f);

puck.bindData(colorProgram);

puck.draw();

This code is mostly the same as it was in the last project, but there are a few key differences. The first difference is that we call positionTableInScene() and posi-tionObjectInScene() before we draw those objects. We’ve also updated setUniforms() before drawing the mallets, and we’ve added code to draw the puck.

Did you also notice that we’re drawing two mallets with the same mallet data?

We could use the same set of vertices to draw hundreds of objects if we wanted to: all we have to do is update the model matrix before drawing each object.

Let’s add the definition for positionTableInScene():

AirHockeyWithImprovedMallets/src/com/airhockey/android/AirHockeyRenderer.java private void positionTableInScene() {

// The table is defined in terms of X & Y coordinates, so we rotate it // 90 degrees to lie flat on the XZ plane.

setIdentityM(modelMatrix, 0);

rotateM(modelMatrix, 0, -90f, 1f, 0f, 0f);

multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);

}

Chapter 8. Building Simple Objects

160

The table is originally defined in terms of x and y coordinates, so to get it to lie flat on the ground, we rotate it 90 degrees back around the x-axis. Note that unlike previous lessons, we don’t also translate the table into the distance because we want to keep the table at (0, 0, 0) in world coordinates, and the view matrix is already taking care of making the table visible for us.

The last step is to combine all the matrices together by multiplying viewProjec-tionMatrix and modelMatrix and storing the result in modelViewProjectionMatrix, which will then get passed into the shader program.

Let’s also add the definition for positionObjectInScene():

AirHockeyWithImprovedMallets/src/com/airhockey/android/AirHockeyRenderer.java private void positionObjectInScene(float x, float y, float z) {

setIdentityM(modelMatrix, 0);

translateM(modelMatrix, 0, x, y, z);

multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);

}

The mallets and puck are already defined to lie flat on the x-z plane, so there’s no need for rotation. We translate them based on the parameters passed in so that they’re placed at the proper position above the table.

Go ahead and run the program. If everything went according to plan, then it should look just like Figure 45, Air hockey with improved mallets, on page 162.

The new mallets and puck should appear, with the view centered on the table.

The mallets may appear a little too solid; we’ll learn how to improve this in Chapter 13, Lighting Up the World, on page 253.

8.7 A Review

Congratulations on making it through another intense chapter! We learned all about generating triangle strips and triangle fans and how to put them together into objects. We also learned how to encapsulate the drawing calls when building these objects so that we can easily tie them together into a single command.

We also introduced the idea of a matrix hierarchy: one matrix for the projec-tion, one for the camera, and one to move objects around in the world. Splitting things up in this way makes it easier to manipulate the scene and move stuff around.

8.8 Exercises

As your first exercise, rotate your viewpoint slowly around the table by adding one single method call to onDrawFrame().

A Review

161

Figure 45—Air hockey with improved mallets

For a more challenging exercise, take a look at the following figure:

Chapter 8. Building Simple Objects

162

How would you update the mallet generator to more closely approximate this type of mallet? You can still build the mallet out of simple geometric shapes.

Here’s one way you might want to approach it:

• Two regular cylinder sides: one for the handle, one for the outside of the base

• Two rings: one for the top of the base and one for the inside of the base

• One sloped cylinder side for the inside of the base to connect the two rings

• A half-sphere to cap the top of the mallet

Of course, your imagination is the limit, and you can be as creative as you want to be. When you’re ready, we’ll learn how to move the mallets around with our fingers in the next chapter!

Exercises

163

CHAPTER 9

Dans le document OpenGL ES 2 for Android (Page 170-176)