Understanding a Mesh Hierarchy


The problem (if you want to call it one) with the standard mesh class is that it treats the object it is going to render as a single solid object. In the real world, though, that's almost always not the case. Take your body, for example: sure it is a single "solid" object, but the various parts of your body can move independently. How about an example?

Take your arm and hold it straight out in front of you. Now move your arm up and down. Do you notice how only your arm is moving? If you were being rendered as a single mesh, your entire body would be moving up and down, which is definitely not what you want to do (even if levitating sounds exciting).

Now, you can break it down even further. With your arm still sticking straight out in front of you, bend it at the elbow. Notice that you can move only the small section after your elbow without moving any other part of your body. One last visual to get before you're done: with your arm straight out in front of you once more, stand up and then rotate your upper body by turning at your waist. Notice how your arm moves with you and rotates when you do? The arm can be considered a "child" of the upper body. Look at Figure 13.1.

Figure 13.1. A tank hierarchy.


Here you can see the tank, and you can tell that the tank shouldn't be a single solid object. The gun turret should be able to rotate, the gun barrel should be able to move up and down, and the wheels should be able to spin. During your work in this chapter, that's what you will be implementing.

Luckily, a mechanism built in to the API makes this work relatively simple. When a mesh is created by an artist, that mesh can have a hierarchy, meaning that the entire mesh can consist of numerous other child meshes. Using the analogy with your body, your single body mesh actually contains a few different parts. You have your torso, your legs, your feet, your arms, your head, and so on. In a hierarchy, these various parts can be children to another part (such as your hands are children of your arms), and other parts would be siblings (such as your two legs would be siblings of each other).

Meshes are the same way. In the tank, you have a central parent section, which is basically the hull of the tank. The wheels are children of the hull but siblings to each other. The gun turret is also a child of the hull, and it too has a child in the gun barrel. Allowing these pieces to move individually will give you a realistic-looking tank.

Now I'm sure that you're anxious to start writing some code. (Aren't you always?) As they say, there's no time like the present, so let's get going! You should add a new class to your tank.cs code file. (Feel free to add it to a new file if you want, but I just prefer to keep the tank-related stuff together.) See Listing 13.1 for the base framework of this class.

Listing 13.1. The Basic Tank Class
 public class Tank : IDisposable {     public const string TankMeshFile = "LowResTank.X";     private const string GunBarrelFrame = "GunBarrel";     private const string GunCasingFrame = "GunCasing";     private const string GunTurretFrame = "GunTurret";     private static readonly string[] WheelFrames = new string[] { "LeftWheel15",         "LeftWheel13", "LeftWheel16" ,"RightWheels04", "RightWheels03",         "LeftWheel17", "RightWheels02", "RightWheels01", "RightWheels",         "RightWheels05", "RightWheels07", "RightWheels08", "RightWheels09",         "RightWheels10" };     private const float MaxTurretAngle = 1;     private const float MinTurretAngle = -1;     private const float MaxBarrelAngle = 0;     private const float MinBarrelAngle = -0.5f;     public const float GunBarrelLength = 280.0f;     private Texture tankTexture = null;     // Used for the full hierarchy mesh     private TankFrame rootFrame = null;     // Stored rendering device     private Device device = null;     // Stored direction     private Vector3 facingDirection;     // Stored rotation matrix     private Matrix rotationMatrix;     // Gun Barrel information     private Vector3 gunDirection;     private Vector3 gunPosition;     // State values     private float wheelAngle = 0.0f; // The current rotation angle of the wheels     private float barrelAngle = 0.0f; // The current angle of the gun barrel     private float turretAngle = 0.0f; // The current angle of the gun turret     private float rotationAngle = 0.0f; // The current rotation angle                                         // of the tank itself     private Vector3 tankPosition; // The current position of the tank     private float tankRadius = 0.0f; // The radius of the bounding sphere                                      // the tank encompasses     private Vector3 tankCenter; // The center of the tank     // Current Tank Color     private TankColors currentColor = TankColors.Sand; } 

All you've really done is define the constants and variables that will be used for rendering the tank in the game. The string constants at the top of the file are actually the names of some of the objects within the mesh hierarchy. You use them later when you're learning how to manipulate each section individually. The other constants are bounds for the tank's gun turret and barrel. Although I'm sure it would have been awesome to make a turret pitch 360° and shoot itself, the real world just doesn't work that way. We want the tank to behave somewhat realistically.

Construction Cue

If you look at the code on the included CD, you'll notice that you can use a compiler directive called USE_HIGH_RES. The game will by default use a lower-resolution mesh for playing, but it ships with a high-resolution model to be used during the game as well. The code is remarkably similar regardless of which model you use, so if you want to use the high-resolution model in the game, simply include USE_HIGH_RES define. See the code for more information on the differences.


For the instance variables, the tank has a texture (which you'll just get from the texture pool) that is picked by the user before the game starts. The rest of the variables are used for controlling the tank itself, but you can learn about them once you get to the methods they manipulate. Let's look at the constructor for this object, which you'll find in Listing 13.2.

Listing 13.2. Creating the Tank Object
 public Tank(Device renderingDevice) {     // Store the device     device = renderingDevice;     // Set up the matrices     TankRotation = 0.0f;     // Now create our allocate hierarchy object     AnimationRootFrame ar = Mesh.LoadHierarchyFromFile(GameEngine.MediaPath +         TankMeshFile, MeshFlags.Managed, renderingDevice         , new TankAllocHierarchy(), null);     rootFrame = ar.FrameHierarchy as TankFrame;     tankRadius = Frame.CalculateBoundingSphere(rootFrame, out tankCenter); } 



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