Simplifying a Mesh


Now, imagine that the racing game you're creating has a model which sits to the side of the track. This model is quite detailed and has plenty of vertices in it; however, you don't want to waste time drawing the highly detailed model if you can't see it all. You could ask your artist to give you a second, less detailed model and swap out the models you're using, depending on the situation, but that implies that the artist has a lot of free time to make these low-resolution models.

It is easier to simply take the meshes you already have (the high detailed ones) and use the built-in Simplify method on the mesh object. Simplifying a mesh is the act of taking an existing mesh and using a set of provided weights to remove as many faces or vertices to achieve a lower detail mesh. However, before a mesh can be simplified, it must first be cleaned.

You clean a mesh by adding another vertex where two fans of triangles share the same vertex. Let's look at the overload you use for the Clean method:

 public static Microsoft.DirectX.Direct3D.Mesh Clean (    Microsoft.DirectX.Direct3D.CleanType cleanType ,    Microsoft.DirectX.Direct3D.Mesh mesh ,    Microsoft.DirectX.GraphicsStream adjacency ,    Microsoft.DirectX.GraphicsStream adjacencyOut ,    System.String errorsAndWarnings ) 

The first parameter of this method tells the runtime what type of operations should be performed to clean the mesh. See Table 21.1 for the possible values for this parameter.

Table 21.1. Possible Clean Type Flags

CleanType.BackFacing

This option merges triangles that share the same vertex indices but have face normals pointing in opposite directions (commonly called back-facing triangles).

CleanType.BowTies

This option splits a shared vertex if it is at the apex of two triangle fans and mesh operations affect one of the fans.

CleanType.Skinning

This option uses the BackFacing flag to prevent infinite loops during skinning operations.

CleanType.Optimization

This option uses the BackFacing flag to prevent infinite loops during optimization operations.

CleanType.Simplification

This option uses both the BackFacing and BowTies flags to prevent infinite loops during simplification operations.


It's pretty obvious the Simplification flag is the one that is required for the call to Simplify. The other parameters are the mesh that should be cleaned, the adjacency information, and an out parameter that gives you any errors or warnings that occurred during the cleaning operations.

Construction Cue

Remember, if you are using the overload with the out parameter for errors and warnings, ensure that no exception is thrown if an error occurs. You need to manually check the string to see if any error occurred in this case.


Now you should update your rendering code to clean your mesh, so find the OnNewGame method where you load the mesh and replace it with the one in Listing 21.1.

Listing 21.1. Loading and Cleaning Mesh
 private void OnNewGame(object sender, EventArgs e) {     ExtendedMaterial[] materials = null;     GraphicsStream adj = null;     // Create the kart mesh and textures     using (Mesh tempMesh = Mesh.FromFile(MediaPath + "kart.x", MeshFlags.Managed,                 sampleFramework.Device, out adj, out materials))     {         if ( (materials != null) && (materials.Length > 0) )         {             // Create the textures             kartTextures = new Texture[materials.Length];             for(int i = 0; i < materials.Length; i++)             {                 kartTextures[i] =                 ResourceCache.GetGlobalInstance().CreateTextureFromFile(                 sampleFramework.Device,  MediaPath +                 gameUI.GetComboBox(PickKartControl).GetSelectedData() as string);             }         }         string errors = null;         kartMesh = Mesh.Clean(CleanType.Simplification | CleanType.Optimization,             tempMesh, adj, adj, out errors);         if ( (errors != null) && (errors.Length > 0) )             throw new InvalidOperationException("Error cleaning mesh: " + errors);         // Now optimize the mesh in place         kartMesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache, adj);     }     currentState = GameState.Gameplay; } 

You'll notice a few changes to the underlying code here. First, you add the adj parameter to store adjacency information about the mesh. It is returned to you from the FromFile method on the mesh class. Notice also that you change and add that method into a using statement. Instead of getting the kartMesh directly from that method, you create a temporary mesh. The cleaning operation returns a new mesh, and that's the mesh that you want to use as the kart's mesh.

After the textures are loaded (same as in the last chapter), the mesh is then cleaned. The flags passed in are for both simplification and optimization because the mesh is optimized directly after this part. Notice that the method will throw an exception if any data in the errors parameter notifies you that the operation failed.

Now, your mesh is ready to be simplified. Look at the overload for the Simplify method:

 public static Microsoft.DirectX.Direct3D.Mesh Simplify (     Microsoft.DirectX.Direct3D.Mesh mesh ,     Microsoft.DirectX.GraphicsStream adjacency ,     Microsoft.DirectX.Direct3D.AttributeWeights vertexAttributeWeights,     Microsoft.DirectX.GraphicsStream vertexWeights ,     System.Int32 minValue ,     Microsoft.DirectX.Direct3D.MeshFlags options ) 

The structure of this method should seem similar. The mesh you want to simplify is the first parameter, followed by the adjacency, which you can specify as either an integer array or a graphics stream. Because you're using a graphics stream for your adjacency currently, it just makes sense to use this overload.

The AttributeWeights structure for the next parameter sets the weights for the various values used when simplifying the mesh. Most applications should use the overloads that do not take this member because the default structure only considers geometric and normal adjustment. Only in special cases would other members need to be modified. The default values for this structure, if you do not pass it in, would be the following:

 AttributeWeights weights = new AttributeWeights(); weights.Position = 1.0f; weights.Boundary = 1.0f; weights.Normal = 1.0f; weights.Diffuse = 0.0f; weights.Specular = 0.0f; weights.Binormal = 0.0f; weights.Tangent = 0.0f; weights.TextureCoordinate = new float[] {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; 

The next member is a list of weights for each vertex. If you pass in null for this member, it is assumed that each weight is 1.0f.

The minValue member is the minimum number of faces or vertices (depending on the flags you pass in) that you want to simplify the mesh to. The lower this value, the lower the details of the resulting mesh.

Construction Cue

You should be aware that just because this call succeeds, it does not mean that your mesh has this exact number of vertices or faces. This member is intended to be a desired minimum, not an absolute minimum. It might not be possible to simplify your mesh to the desired level.


The final parameter to this function can be only one of two flags in the MeshFlags enumeration. If you want to simplify the number of vertices, you should pass in MeshFlags.SimplifyVertex; otherwise, you simplify the number of indices and use MeshFlags.SimplifyFace.

Although you don't need to simplify the go-kart mesh in this example, if you wanted to create a simplified version of the mesh, you could do so like this:

 Console.WriteLine("Number of faces: {0} - Vertices {1}",     kartMesh.NumberFaces, kartMesh.NumberVertices); Mesh temp = Mesh.Simplify(kartMesh, adj, null, 1, MeshFlags.SimplifyVertex); kartMesh.Dispose(); kartMesh = temp; Console.WriteLine("Number of faces: {0} - Vertices {1}",     kartMesh.NumberFaces, kartMesh.NumberVertices); 

Construction Cue

Make sure you clean the mesh again after optimization to ensure that it is ready for simplification.




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