Topology Modifiers

Topology modifiers alter the face or polygon structures of the objects they are applied to. Smoothing groups and materials are also part of the topology channel. Edge visibility is also part of this channels since it is an attribute of the face structure. The face normals are also part of the topology channel. The example below is from the Normals modifier which allows the user to unify and flip the face normals of a mesh. The full source code is available in \MAXSDK\SAMPLES\MODIFIERS\SURFMOD.CPP.

Below are the implementations of Modifier::InputType(), Modifier::ChannelsUsed(), and Modifier::ChannelsChanged() from the Normals modifier.

Class_ID InputType() {
  return triObjectClassID;
}
 
ChannelMask ChannelsUsed() {
  return OBJ_CHANNELS;
}
 
ChannelMask ChannelsChanged() {
  return GEOM_CHANNEL|TOPO_CHANNEL;
}

Note that this modifier only operates on triangle mesh objects, or those objects that are able to convert themselves to triangle meshes. Also note that this modifier specifies the object channels for those that it needs up to date to perform its modification. Since this modifier changes the vertex and face structure of the mesh to alter the normals it specifies it modifies the geometry channel and the topology channel in Modifier::ChannelsChanged().

Below is the implementation of Modifier::ModifyObject(). Note that when the modifier is done it updates the validity of the object flowing down the pipeline by calling Object::UpdateValidity() and passing the topology channel number.

void NormalMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{
   Interval valid = FOREVER;
   int flip, unify;
   pblock->GetValue(PB_FLIP,t,flip,valid); 
   pblock->GetValue(PB_UNIFY,t,unify,valid); 
   assert(os->obj->IsSubClassOf(triObjectClassID));
   TriObject *triOb = ( TriObject *)os->obj;
   BOOL useSel = triOb->mesh.selLevel==MESH_FACE;
   if (unify) {
     triOb->mesh.UnifyNormals(useSel); 
   }
   if (flip)
   {
     for (int i=0; i<triOb->mesh.getNumFaces(); i++)
     {
      if (!useSel || triOb->mesh.faceSel[i])
       {
         FlipMeshNormal(&triOb->mesh,(DWORD)i);
       }
     }
   }
 
   triOb->UpdateValidity(TOPO_CHAN_NUM,valid); 
   ...
}