Capping a Shape with a Patch

This section discusses the capping of shapes with patches. This is very similar to the mesh capping discussed above.

Again, the following code fragments are taken fromEXTRUDE.CPP. This demonstrates the basic process for capping a shape with a patch.

Here we try to use a BezierShape to create the cap. First a BezierShape object is created. Then the shape to be capped is asked if it can make a transformation from itself to a BezierShape. If it can, we just ask it to make a BezierShape. If it cannot, we are forced to use a PolyShape. For patch capping this is much less desirable, but if we can't make a BezierShape, then this is used. The shape is asked to convert to a PolyShape, and then the PolyShape is converted to a BezierShape. This is a very poor conversion, as all it does is make a linear spline out of the PolyShape.

// If the shape can convert itself to a BezierShape, have it do so!
BezierShape bShape;
 
if (shape->CanMakeBezier())
   shape->MakeBezier(t, bShape);
else
{
   PolyShape pShape;
   shape->MakePolyShape(t, pShape);
   bShape = pShape; // UGH -- Convert it from a PolyShape -- not good!
}

Next, the curves are organized into a hierarchy. This automatically figures out the shape nesting and directions for proper capping.

ShapeHierarchy hier;
bShape.OrganizeCurves(t, &hier);

Next we need to reverse the shapes whose direction is 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 BezierShape to tell it which shapes to reverse.

// Need to flip the reversed polys...
bShape.Reverse(hier.reverse);

At this point the BezierShape is all set up with the proper clockwise/counter-clockwise ordering on all the polygons. Next the extrude modifier generates the patches. You may refer to the full source of EXTRUDE.CPP to see how this is done.

The next step is to create the caps. This begins by instantiaing a PatchCapInfo class and asking the BezierShape to make a cap. This fills up the PatchCapInfo class with all the information it needs to create a cap.

PatchCapInfo capInfo;
bShape.MakeCap(t, capInfo);

After this is done, the PatchCapInfo is cached within the shape. Therefore if this is needed again, no work needs to be done.

Next, a PatchCapper object is created. This is done by passing the BezierShape as an argument to the constructor. This gets the PatchCapper ready for the topology of the shape. Developers don't need to understand the inner workings of the PatchCapper, it's just a tool used to aide in capping.

// Build information for capping
PatchCapper capper(bShape);

Below is the code where the start of the extrusion is capped. Inside the capper is a PatchCapPoly. There is one for each polygon in the shape. The PatchCapPoly needs to know the vertex number in the patch mesh that corresponds to the given knot in the bezier spline. This is done by calling SetVert() on the PatchCapPoly. After this is done, the same thing happens for each of the vectors when SetVec() is called.

if(capStart)
{
   vert = 0;
   intbaseVec = 0;
   for(poly = 0; poly < polys; ++poly)
   {
     Spline3D *spline = bShape.splines[poly];
     PatchCapPoly &capline = capper[poly];
     int lverts = spline->KnotCount();
     for(int v = 0; v < lverts; ++v)
     {
      // Gives this vert's location in the mesh!
      capline.SetVert(v, vert++);
     }
     vert += lverts * levels;
     vec = baseVec;
     int lvecs = spline->Segments() * 2;
     for(v = 0; v < lvecs; ++v)
     {
      // Gives this vec's location in the mesh!
      capline.SetVec(v, vec++);
     }
     baseVec += lvecs * (levels + 1) + spline->KnotCount() * levels * 2;
   }
}

There are vectors generated inside the patch cap. 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 vectors into the correct location.

 // Create a work matrix for capping
 Matrix3 mat = TransMatrix(offset1);

The final step is to cap the patch mesh. This is done using a method of the capper named CapPatchMesh(). This method is passed the output patch mesh, the PatchCapInfo, a flag that indicates if the cap should be flipped, the smoothing group number for all the patches in the cap, and a pointer to the orientation matrix.

 capper.CapPatchMesh(pmesh, capInfo, TRUE, 16, &mat);

Once this is done the shape has been capped with a patch.