Making Lots of Little Meshes Out of One Big One

Rather than just removing vertices from your mesh, what if you actually wanted to split your one large mesh into many different pieces? Let's once again take our MeshFile example and modify it slightly to split the one large mesh into smaller, more manageable meshes.

When you split a mesh up, you will take the existing single mesh and turn it into an array of meshes that can be used to do the rendering. For this example, you will maintain both the original mesh as well as the split mesh so that you can see them both rendered and compare them.

First, you will need to declare an array of meshes to hold the split mesh. You will also need some Boolean variables to control how and which meshes are being rendered. Add the following variables to your declaration section:

 // Split information private Mesh[] meshes = null; private bool drawSplit = false; private bool drawAllSplit = false; private int index = 0; private int lastIndexTick = System.Environment.TickCount; 

These variables will hold the entire list of newly created meshes after the split, as well as the flag on whether or not you are drawing the original or split mesh (you should default to the original). If you are drawing the split mesh, there is a second flag to see whether you are drawing all of the split meshes in the array, or a single one at a time; again, you should default to a single one at a time. You will need to maintain the current index of the mesh you are drawing (in case you are drawing one at a time), plus a "mini-timer" to determine when to switch to the next mesh (if you are drawing one at a time).

With the variable declarations out of the way, we can create our array of meshes. Directly after the LoadMesh call in InitializeGraphics, add the following section of code:

 meshes = Mesh.Split(mesh, null, 1000, mesh.Options.Value); 

We should take a look at the various parameters the split function takes. There are two overloads, so we will look at the most complete one:

 public static Microsoft.DirectX.Direct3D.Mesh[] Split (Mesh mesh , int[] adjacencyIn ,     System.Int32 maxSize , MeshFlags options ,     out GraphicsStream adjacencyArrayOut ,     out GraphicsStream faceRemapArrayOut ,     out GraphicsStream vertRemapArrayOut ) 

As you can see, the call takes in the mesh we want to split as the first parameter. The adjacency is the next parameter (you can pass null as we've done above if you don't care about this member). The third parameter is the maximum number of vertices you want each of the newly created meshes to have. In our previous example, we want a maximum of 1,000 vertices per new mesh. The options parameter is used to specify the flags for each of the newly created meshes. The final three out parameters all return the information about each of the new meshes in a stream. We will use the overloads without this information.

With our newly created array of meshes, we now need a way to specify which meshes we will be drawing: the original or the array. Before we can do that, though, we need a way to toggle between them. We will use the same keys we used earlier: the space bar and "m". Replace the OnKeyPress method with the following code:

 protected override void OnKeyPress(KeyPressEventArgs e) {     if (e.KeyChar == ' ')     {         drawSplit = !drawSplit;     }     else if (e.KeyChar == 'm')     {         drawAllSplit = !drawAllSplit;     } } 

Here we toggle whether to draw the original mesh or the split mesh, as well as toggling whether to draw individual members of the split mesh, or the whole thing. Now, we should update the DrawMesh method to actually use these variables. Replace the contents of this method with the code in Listing 7.2.

Listing 7.2 Rendering Your Split Meshes
 if ((System.Environment.TickCount - lastIndexTick) > 500) {     index++;     if (index >= meshes.Length)         index = 0;     lastIndexTick = System.Environment.TickCount; } device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, roll) *     Matrix.Translation(x, y, z); for (int i = 0; i < meshMaterials.Length; i++) {     device.Material = meshMaterials[i];     device.SetTexture(0, meshTextures[i]);     if (drawSplit)     {         if (drawAllSplit)         {             foreach(Mesh m in meshes)                 m.DrawSubset(i);         }         else         {             meshes[index].DrawSubset(i);         }     }     else     {         mesh.DrawSubset(i);     } } 

In this updated function, we now increment our index over half of a second, and ensure that we wrap if it happens to go over the length of our split array. Then, if we are drawing the split mesh, we check if we are drawing the entire thing, or a single member, and behave accordingly. Otherwise, we draw the original mesh.

Running this example now will start it rendering the original un-split mesh. Hit the space bar, though, and it starts rendering each of the split meshes individually. If you hit the "m" key while in this mode, it will render all of the split meshes simultaneously. Can you tell the difference between rendering the original mesh, and rendering the entire array of split meshes?



Managed DirectX 9 Graphics and Game Programming, Kick Start
Managed DirectX 9 Kick Start: Graphics and Game Programming
ISBN: B003D7JUW6
EAN: N/A
Year: 2002
Pages: 180
Authors: Tom Miller

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