Loading a Tank Hierarchy


That seems pretty simple, doesn't it? Unfortunately, nothing is ever as simple as it seems because outside of storing the device variable and setting a property, you haven't covered any of the other methods before. The animation root frame object is completely new. In the Direct3D API, the mesh hierarchies are commonly used to facilitate animation (and technically, that's what you're doing as well). The primary function of the mesh hierarchy is skeletal animation, but your tank doesn't have any bones. The only thing you care about is the frame hierarchy, which maintains the child/sibling relationship for the data in the frame. After that frame is loaded, you can use a method on the frame class to get the bounding sphere of the tank.

Construction Cue

You might be asking yourself, why do I care about the bounding sphere of the tank? What could it possibly mean? Well, right now, you don't need it, but soon when you want to see whether a player has been shot, or whether the tank is trying to leave a level, it will be important. It's easy to calculate whether an object is within a sphere, so when you are testing to see if any objects collide with your tank, you will use this value to do so.


Loading the hierarchy from a file takes many of the same parameters that loading a mesh normally takes, but an entire new class is instantiated during the process, and you haven't even defined that class yet. You want to do that now, so add a new code file into your project. You can call it hierarchy.cs because that's what its job will be. You will find the implementation for this class in Listing 13.3.

Listing 13.3. The Allocate Hierarchy Class
 public class TankAllocHierarchy : AllocateHierarchy {     /// <summary>     /// Create a new hierarchy frame     /// </summary>     public override Frame CreateFrame(string name)     {         // Create the new derived tank frame         TankFrame frame = new TankFrame();         // Store the variables         frame.Name = name;         frame.TransformationMatrix = Matrix.Identity;         frame.CombinedTransformationMatrix = Matrix.Identity;         return frame;     }     /// <summary>     /// Create a new mesh container for the tank hierarchy     /// </summary>     public override MeshContainer CreateMeshContainer(string name,         MeshData meshData, ExtendedMaterial[] materials,         EffectInstance[] effectInstances,         GraphicsStream adjacency, SkinInformation skinInfo)     {         TankMeshContainer mesh = new TankMeshContainer();         // Store the variables we care about         mesh.Name = name;         mesh.MeshData = meshData;         return mesh;     } } 

As you see here, the TankAllocHierarchy class derives from the AllocateHierarchy abstract class, which requires you to implement a CreateFrame and CreateMeshContainer method. The frames hold the actual hierarchy data, but the mesh containers hold the vertex and adjacency data for each section of the hierarchy. In each of these methods, the objects are simply created, the name is set, and then they are returned. The name corresponds to the string constants you declared earlier this chapter (although you didn't cover all the names the tank files have). You might also notice in the frame creation sets some matrices as well.

The matrices are needed because of the relationship between the full object (for example, the whole tank) and the partial object (for example, the gun barrel). The stored transformation matrix is the matrix that will transform a particular frame into the correct position and orientation relative to its parent. The combined transformation matrix is simply the combination of the frame matrix with those of its parents. It might benefit you to see the implementations of these two classes, which appear in Listing 13.4.

Listing 13.4. The Frame and Mesh Container Classes
 public class TankFrame : Frame {     // Store the combined transformation matrix     private Matrix combined = Matrix.Identity;     public Matrix CombinedTransformationMatrix     {         get { return combined; } set { combined = value; }     } } public class TankMeshContainer : MeshContainer {     // We need no extra data here } 

You'll notice that you don't define the normal transformation matrix in the frame because that is stored in the base class. The mesh container class doesn't need any extra data, but because the mesh container base class is marked abstract, you must take the time to derive a new class from it. That's it for loading a frame hierarchy. Are you surprised how simple it was?

Back in the tank's object constructor, when the LoadHierarchyFromFile method is called, the CreateMeshContainer and CreateFrame methods are called quite a few times while each submesh is loaded into the hierarchy. Next, you simply store the root frame, and you're now off and ready to start rendering a tank. You can see the draw method in Listing 13.5.

Listing 13.5. Drawing a Tank
 public void Draw(GameEngine engine) {     // Set the device's texture that will be used for rendering     // the tank in either scenario     engine.RenderingDevice.SetTexture(0, tankTexture);     // Draw the mesh hierarchy     DrawFrame(engine, engine.RenderingDevice, rootFrame); } 



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