Simplifying Meshes

We spent a good amount of time understanding the basic Mesh class that is included in the extensions library; however, there are actually three other mesh types we haven't looked at yet. During the course of this chapter we will explore these remaining objects.

You've already looked at creating a simplified mesh by using the Simplify method on the mesh class. Since the common case for using a simplified mesh is to show a less-detailed version of a model, in any given scene, it's probably not a great idea to store multiple versions of a mesh, particularly if you're not even going to be using some of them.

The SimplificationMesh object can be used to encapsulate the process of simplifying a mesh. However, you can't actually use the object to do the rendering; you must first get an actual mesh from the simplification mesh. If you remember the simplified example before, there were two "modes" for the example. One mode was an up-close mode that displayed the model before it was simplified. There was also a "far away" mode that displayed the same model in the distance with many fewer faces and vertices. You will do something similar now, except allowing the model to gradually go into the distance.

Rather than starting with the simplify mesh sample we did in Chapter 7, "Using Advanced Mesh Features," it will be easier if we simply start with the example we did in Chapter 5, "Rendering with Meshes," for loading a mesh from a file. We will simply add our code to this example instead. The first thing we will need is a declaration for our SimplificationMesh object, as well as a variable to control our camera's position. Add the following variables:

 private SimplificationMesh simplifiedMesh = null; private float cameraPos = 580.0f; 

Storing the camera's depth position as a variable will allow us to easily change where the camera is located. You will also need to update the view transform to actually use the correct position as well. In the SetupCamera method, update the view transform as follows:

 device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, cameraPos),     new Vector3(), new Vector3(0,1,0)); 

Obviously since the SetupCamera method is called every frame, any update we make to this variable will update the camera as well, which is what we want. This simplification mesh variable is obviously where we store the data to simplify our mesh. If you notice, we don't have any extra mesh objects. Anytime we simplify our mesh, we will simply replace it with the "new" one.

We will need to modify the LoadMesh method in order to make sure our mesh is cleaned and our simplification mesh object is created correctly. We will need to replace this method with the one in Listing 9.1:

Listing 9.1 Creating a Simplification Mesh
 private void LoadMesh(string file) {     ExtendedMaterial[] mtrl;     GraphicsStream adj;     // Load our mesh     mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out adj, out mtrl);     // If we have any materials, store them     if ((mtrl != null) && (mtrl.Length > 0))     {         meshMaterials = new Material[mtrl.Length];         meshTextures = new Texture[mtrl.Length];         // Store each material and texture         for (int i = 0; i < mtrl.Length; i++)         {             meshMaterials[i] = mtrl[i].Material3D;             if ((mtrl[i].TextureFilename != null) &&                 (mtrl[i].TextureFilename != string.Empty))             {                 // We have a texture, try to load it                 meshTextures[i] = TextureLoader.FromFile(device, @"..\..\" +                     mtrl[i].TextureFilename);             }         }     }     // Clean our main mesh     Mesh tempMesh = Mesh.Clean(mesh, adj, adj);     // Replace our existing mesh with this one     mesh.Dispose();     mesh = tempMesh;     // Create our simplification mesh     simplifiedMesh = new SimplificationMesh(mesh, adj); } 

As you see, we will need to maintain the adjacency information for both the cleaning and our simplification mesh. Once our mesh has been loaded and our textures created (if any existed), we will clean our mesh preparing it for simplification. We then create our simplification mesh object from the newly cleaned mesh.

Actually, we don't really need to do anything else, since the mesh will draw just fine now. However, we want to add some code that will allow us to move our mesh farther from the camera, and lower the detail of the mesh as we do so. We will allow the keyboard to control this "movement," so we will add the override in Listing 9.2:

Listing 9.2 KeyPress Event Handler
 protected override void OnKeyPress(KeyPressEventArgs e) {     if (e.KeyChar == '+')     {         cameraPos += (MoveAmount * 2);         simplifiedMesh.ReduceFaces(mesh.NumberFaces - MoveAmount);         simplifiedMesh.ReduceVertices(mesh.NumberVertices - MoveAmount);         mesh.Dispose();         mesh = simplifiedMesh.Clone(simplifiedMesh.Options.Value,             simplifiedMesh.VertexFormat, device);     }     if (e.KeyChar == 'w')         device.RenderState.FillMode = FillMode.WireFrame;     if (e.KeyChar == 's')         device.RenderState.FillMode = FillMode.Solid; } 

You'll notice that we are using an undefined constant here to control the amount of movement each keypress will activate. You can define the constant as you see fit; the value I used was

 private const int MoveAmount = 100; 

In this method, if the "w" key is pressed, we switch to wire-frame mode, which allows an easier viewing of the actual triangles being drawn. Pressing "s" will switch back to the solid fill. If the "+" key is pressed, we will move our camera away from our model somewhat (based on our constant) to simulate "moving away" from the model. With the model farther away now, we then reduce the number of faces and vertices by our specified constant amount. We then dispose of the original mesh. We will want to use the clone of our simplified mesh to do the drawing in the rendering method, so we replace our original mesh with this clone.

Running the application now, you can press the "+" key a few times and switch between wire-frame and solid mode, and probably not be able to tell the difference as the model gets farther away (which is entirely the point). However, to show that something is actually being done, let's add some text to our rendered scene to show the number of faces and vertices for the mesh being rendered. Add the following variable to control our font:

 private Microsoft.DirectX.Direct3D.Font font = null; 

We will also need to initialize our font object before we can actually use it to draw any text. After the call to LoadMesh in the IntializeGraphics method, add this initialization code:

 // Create our font font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font     ("Arial", 14.0f, FontStyle.Bold | FontStyle.Italic)); 

Feel free to change the options here and create a different type of font, or a different size or style. Finally, all we need to do is draw some text. Immediately after the call to the DrawMesh method, you can add this code:

 font.DrawText(null, string.Format("Number vertices in mesh: {0}",     mesh.NumberVertices), new Rectangle(10, 10, 0, 0),     DrawTextFormat.NoClip, Color.BlanchedAlmond); font.DrawText(null, string.Format("Number faces in mesh: {0}",     mesh.NumberFaces), new Rectangle(10, 30, 0, 0),     DrawTextFormat.NoClip, Color.BlanchedAlmond); 

Now it's easy to see as you move your model farther away that the number of vertices and faces being drawn is being reduced. You should see something similar to Figure 9.1 after hitting the "+" key a few times.

Figure 9.1. A simplified mesh.

graphics/09fig01.gif

One of the first problems you may notice with this application is that we can't seem to regain any of the lost vertices. Sure, we can simplify the mesh just fine, but what if we wanted to bring the model closer to us once more? There is no RaiseVertices method, and using the ReduceVertices method and passing in a larger number of vertices has no effect. The SimplificationMesh objects are designed to simplify meshes, and that is all; there is no going back. Progressive meshes were designed to handle this case.



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