Rendering a Mesh Hierarchy


You're probably thinking to yourself right now, "Wow! That was pretty easy!" You wouldn't be wrong, but it is a little more complicated than the two lines shown here make it out to be. After setting the texture (all the mesh subsets in the hierarchy use the same texture), you draw the root frame. Sounds simple enough, but drawing the root frame takes a few different steps. You can see its implementation in Listing 13.6.

Listing 13.6. Drawing a Frame
 private void DrawFrame(GameEngine engine, Device renderDevice, TankFrame frame) {     TankMeshContainer mesh = frame.MeshContainer as TankMeshContainer;     while(mesh != null)     {         DrawMeshContainer(engine, renderDevice, mesh, frame);         mesh = mesh.NextContainer as TankMeshContainer;     }     if (frame.FrameSibling != null)     {         DrawFrame(engine, renderDevice, frame.FrameSibling as TankFrame);     }     if (frame.FrameFirstChild != null)     {         DrawFrame(engine, renderDevice, frame.FrameFirstChild as TankFrame);     } } 

The structure of this method is used in a few places because this is how you "walk the hierarchy." Starting at the root (the initial call), you want to see whether this frame has any meshes that could be rendered. If it does, you call the DrawMeshContainer method to do the actual mesh rendering. (You see that method in Listing 13.7 in just a moment.) It continues looking for more meshes to render in the current frame until there are no more left, and then it calls back into itself recursively for any siblings or children of the current frame. It's important to realize that any one frame can have a maximum of one sibling and one child. In the case of the wheels in Figure 13.1 earlier, the first wheel has one sibling, and the second wheel, in turn, has one sibling (the third wheel). Children are the same way. You'll see this structure in a method again soon.

Listing 13.7. Drawing a Mesh Container
 private void DrawMeshContainer(GameEngine engine, Device renderDevice,      TankMeshContainer mesh, TankFrame frame) { #if (DEBUG)     engine.numberFaces += mesh.MeshData.Mesh.NumberFaces;     engine.numberVerts += mesh.MeshData.Mesh.NumberVertices; #endif     // Each mesh in the hierarchy will have a single subset     engine.SetWorldTransform(frame.CombinedTransformationMatrix);     mesh.MeshData.Mesh.DrawSubset(0); } 

This code should look familiar because it is similar to how you always render a mesh. One of the new items here is the SetWorldTransform method from the game engine, which you haven't implemented yet. Back in your game engine code class, add this method so you can call it:

 public void SetWorldTransform(Matrix worldTransform) {     device.Transform.World = worldTransform * sceneCamera.ViewMatrix; } 

Construction Cue

The camera class hasn't been defined yet, but that happens in the near future. In the meantime, you should understand why the world transform is being set this way. In Direct3D when you set the View transform (as you did for the Blockers game), you must store or recalculate a multitude of internal states, which can cause slowdowns if done many times per frame. However, this isn't the case with the world matrix (because it is designed to be set plenty of times). Because everything in the "world" will be transformed by the coordinates, you can get by without ever setting the view transformation by simply combining the world matrix with the current view matrix. This can be a significant performance boost, which is why it's done here.




Beginning 3D Game Programming
Beginning 3D Game Programming
ISBN: 0672326612
EAN: 2147483647
Year: 2003
Pages: 191
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net