Rendering Your 3D Model with Your User Interface


You've already loaded 3D meshes in your games up to this point, and in Blockers, you actually did something similar to what you'll do here, but there you had the mesh a part of the user interface screen itself, rather than its own separate object. Add a new code file called tank.cs to your project, and add the code from Listing 12.13 to that file.

Listing 12.13. The Tank Selection Model
 using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using Microsoft.Samples.DirectX.UtilityToolkit; namespace Tankers {     /// <summary>     /// Will hold the possible tank colors     /// </summary>     public enum TankColors : byte     {         Gray,         Black,         Green,         Sand,         FirstColor = Gray,         LastColor = Sand,     }     /// <summary>     /// Will hold the model information for selecting the tank     /// </summary>     public class TankSelectionModel : IDisposable     {         private Mesh tankMesh = null;         private Texture tankTexture = null;         private int numberSubsets = 0;         // Stored rendering device         private Device device = null;         // Current Tank Color         private TankColors currentColor = TankColors.Sand;         /// <summary>         /// Create a new tank object         /// </summary>         public TankSelectionModel(Device renderingDevice)         {             // Store the device             device = renderingDevice;             // First create our 'flat' hierarchy mesh             ExtendedMaterial[] mtrl = null;             tankMesh = Mesh.FromFile(GameEngine.MediaPath + Tank.TankMeshFile,                 MeshFlags.Managed, renderingDevice, out mtrl);             // Store the number of subsets             if ((mtrl != null) && (mtrl.Length > 0) )             {                 numberSubsets = mtrl.Length;             }             tankTexture = GetTankTexture(device, currentColor);         }         public void Dispose()         {             if (tankMesh != null)             {                 tankMesh.Dispose();             }         }     } } 

Check out the enumeration used to define the tank colors. There are a few things to notice about the enumeration. First, realize that it derives from byte. The major reason is for network traffic. If you want to send over the color of the tank, using a single byte is more efficient than any other single piece of data you could pass. Besides, do you really need more than 255 differently colored tanks? The other things to notice are the first and last color members. They are used to indicate when you've gone beyond the scope of the tank colors, which you'll see in a moment.

The creation of the mesh itself is standard, but notice that there is a change from how you did things before. You're not storing the materials or textures that came from the mesh. You record the number of subsets and then call the GetTankTexture method (see Listing 12.14) to retrieve the texture. You can do this because the texture uses only a single texture, and each material is simply pure white anyway (which you defined in the game engine). There is no good reason to store multiple versions of the same data, so you don't.

Listing 12.14. Getting the Tank Texture
 public static Texture GetTankTexture(Device device, TankColors color) {     switch(color)     {         case TankColors.Black:             return TexturePool.CreateTexture(device, "LowResBlack.png");         case TankColors.Gray:             return TexturePool.CreateTexture(device, "LowResGray.png");         case TankColors.Green:             return TexturePool.CreateTexture(device, "LowResGreen.png");         case TankColors.Sand:             return TexturePool.CreateTexture(device, "LowResSand.png");         default:             throw new ArgumentException("Not a valid color.", "color");     } } 

This method simply returns a texture from the pool based on which color you've passed in. For each of the tank colors defined, there is a corresponding texture. This method is marked public because more than one class will be using it later. You'll notice in Figure 12.5 that there are left and right buttons to select the next and previous tanks, which update the color of the tank (and thus its texture). This part is where those two "extra" enumeration values come into play. See Listing 12.15 for more information.

Listing 12.15. Selecting a New Tank Color
 public void SelectNextColor() {     // Update the color     currentColor++;     if (currentColor > TankColors.LastColor)     {         currentColor = TankColors.FirstColor;     }     // Update the textures     tankTexture = GetTankTexture(device, currentColor); } public void SelectPreviousColor() {     // Update the color     currentColor--;     if ((byte)currentColor == 0xff)     {         currentColor = TankColors.LastColor;     }     // Update the textures     tankTexture = GetTankTexture(device, currentColor); } 

When you select the next color, you increment the current color counter, and if it's gone past the last color, you simply set it back to the first color. This move allows the colors to wrap as you go through them. Selecting the previous color does the same thing, with one minor caveat. If you're on the first color (the value is 0), and you move back one (via the decrement operator), you go back to 0xff in your byte. So you simply catch that and move to the last color. Drawing the tank is similar to what you've done before, but do you remember the count of vertices and faces rendered in the main game engine? Here is the first time you get to see it happen. See Listing 12.16 for the code that updates these member variables and renders the tank.

Listing 12.16. Rendering the Selected 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); #if (DEBUG)     engine.numberFaces += tankMesh.NumberFaces;     engine.numberVerts += tankMesh.NumberVertices; #endif     for (int i = 0; i < numberSubsets; i++)     {         tankMesh.DrawSubset(i);     } } 



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