This section discusses the capping of shapes using a mesh. The SDK provides tools for easily creating these mesh caps for shapes.
Typically for an extruded object, the capping on the front of the object is exactly the same as the capping on the back of the object. For example, if you extrude the letter 'M'. It's redundant to have to cap this separately for the front and back (as they are the same). When dealing with complex shapes, having to go back and do the second cap is very time consuming. So the capping system tries to cache information to speed up the process.
Sample code for capping can be found in the extrude and lathe modifiers. These plugins are in \MAXSDK\SAMPLES\MODIFIERS\SURFREV.CPP and\MAXSDK\SAMPLES\MODIFIERS\EXTRUDE.CPP.
The following code fragments are taken fromEXTRUDE.CPP. This demonstrates the basic process for capping a shape. This code is part of the method ExtrudeMod::BuildMeshFromShape().
For this example, we are starting of with a ShapeObject shape that we want capped with a mesh. The first thing to do is convert the shape to a PolyShape. This greatly simplifies the mesh conversion. The code below shows how this is done.
// Make the shape convert itself to a PolyShape. // This makes our mesh conversion MUCH easier! PolyShape pShape; shape->MakePolyShape(t, pShape);
Next, we organize the curves into a hierarchy. This automatically figures out the shape nesting and directions for proper capping.
ShapeHierarchy hier = pShape.OrganizeCurves(t);
Next we need to reverse the shapes whose directions are incorrect for the hierarchy. The hierarchy calculated above contains a BitArray that describes which shapes need to be reversed. This is passed into the Reverse() method of the PolyShape to tell it which shapes to reverse.
// Need to flip the reversed curves in the shape! pShape.Reverse(hier.reverse);
At this point the PolyShape is all set up with the proper clockwise/counter-clockwise ordering on all the polygons so all that needs to be done is to generate the faces. You may refer to the full source of EXTRUDE.CPP to see how this is done.
The next thing is just to create the caps. This begins by instantiating a MeshCapInfo class and asking the PolyShape to make a cap. This fills up the MeshCapInfo class with all the information it needs to create a cap. The type can be morph or grid capping. Morph capping only uses the existing vertices in the PolyShape to generate the cap. The capping code does the best job it can given this constraint, however it is possible to wind up with long sliver-like faces on the cap. This is referred to as a morph cap because if you cap a shape using this method it does not generate any new vertices and you can then morph between shapes with the same number of vertices. A Grid cap generates new vertices in the interior of the shape in a grid pattern. This helps to break up the shape and helps reduce slivering. Grid capping will generate different number of vertices based on the shape and thus the shapes are not morphable.
MeshCapInfo capInfo; pShape.MakeCap(t, capInfo, capType);
After this is done, the MeshCapInfo is cached within the shape. Therefore if this is needed again, no work needs to be done.
Next, a MeshCapper object is created. This is done by passing the PolyShape as an argument to the constructor. This gets the MeshCapper ready for the topology of the shape. Developers don't need to understand the inner workings of the MeshCapper, it's just a tool used to aide in capping.
// Build information for capping MeshCapper capper(pShape);
Below is the code where the start of the extrusion is capped. Inside the capper is a MeshCapPoly. There is one for each polygon in the shape. The MeshCapPoly needs to know the corresponding mesh vertex for each vertex in the PolyLine. This is done by calling SetVert() on the MeshCapPoly. For example, this might associate vertex 0 in the PolyLine with vertex 200 in the mesh, vertex 1 with mesh vertex 220, etc.
if(capStart) { vert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; for(int v = 0; v < lverts; ++v) // Gives this vert's location in the mesh! capline.SetVert(v, vert++); vert += lverts * levels; }
The next thing that is done is used only for grid capping. A grid cap generates new vertices inside the shape that make up the grid. In the case of a SurfRev for example, the end cap might be rotated, or scaled in some manner. A matrix is required so the capper knows how to orient the vertices into the correct location. This matrix is ignored for non-grid capping.
// Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset1);
The final step is to cap the mesh. This is done using a method of the capper named CapMesh(). This method is passed the output mesh, the MeshCapInfo, a flag that indicates if the cap should be flipped, the smoothing group number for all the faces in the cap, and a pointer to the orientation matrix.
capper.CapMesh(mesh, capInfo, TRUE, 16, &gridMat);
Once this is done the shape has been capped with a mesh.