Share

CAT Controllers

Rig Controller Setup

In general, we have followed a design pattern in CAT where functional groups have been separated out into unit pieces. The functional units are :

  • Hub (pelvis/ribcage/head)
  • Limb (arm/leg)
  • Bone
  • Digit
  • Tail
  • Spine (spine/neck)

The controllers in a unit are inter-dependent and cannot be constructed or used in isolation. Apart from a Hub (which is a single bone), there is a central class that holds data common to the unit and provides management functions, called a Data or a Manager class. There is one data class created to manage each unit. These data classes are LimbData, BoneData, DigitData, SpineData, and TailData. Each one of these data classes is responsible for the creation and maintenance of its associated node controllers.

Note from the rig layout diagram – BoneData is somewhat of a special case. BoneData is the class that provides the transform for an individual limb bone. It is managed by LimbData, but it is also a manager itself. It manages an array of 1-to-N BoneSegTrans classes. This is because although the limb is a functional unit made up of many limb bones, each limb bone can also be broken down into segments to provide twisting. The BoneSegTrans class looks to BoneData to manage it, and BoneData looks to LimbData to manage it.

Base CAT classes

CATControl

This class is at the root of the rig control structure in CAT. Its job is to provide the common functionality required by all the classes that make up CAT's rig structure, and a method of iterating all the controls that make up a given CAT rig.

Some major functionality provided:

  • GetCATParentTrans – provides access to the common data pool Rig iteration - The CATControls in a rig are linked in a tree structure, where every CATControl has a pointer back to the CATControl that 'owns' it. Access is provided via GetParentCATControl and GetChildCATControl
  • Bone ID : Each CATControl has an identifier to distinguish it from its siblings. The identifier is unique to siblings of the same class only. In other words, an Id on a LimbData is unique among sibling LimbData's. The Bone ID is usually also the index in the bone in its array, so if a hug has a single tail and a single limb, the Id of both the TailData and the LimbData will be 0.
  • CATMessage: The CATParent triggers events on the rig via a message passing system internal to CAT. Because there is no reference between the rig elements and the CATParentTrans, when something on the CATParent changes (eg CATUnits), we need to manually update the rig. The message system can also trigger changes on the bones, eg, baking animation, changing length axis, or adding/removing a layer.
  • Save/Load rig/pose/clip: CATControl provides the base functionality, although derived classes still need to specialize it.

CATNodeControl : CATControl

The CATNodeControl class specializes the CATControl class for the Matrix3 controllers applied to INodes. This class is the primary workhorse of the CATSystem. It provides all the functions for managing the rig elements data, and returning values to Max. In general, if 3ds Max calls a function on a CAT element, CATNodeControl will be the class that implements the function.

Primary tasks:

  • Implement GetValue/SetValue - The primary role of any transform controller is to provide a transform (Matrix3) value to Max. CATNodeControl provides a framework for evaluating CAT data to generate a Matrix3.
  • As part of the Get/Set value, the CATNodeControl also provides the functionality for inheritance, rig stretching, locking, limits, etc. The structure of the GetValue/SetValue function should also be examined.
  • Add functionality for generating ArbBones - ArbBones is essentially an implementation of CATNodeControl without any element-specific functionality. All ArbBone management happens on CATNodeControl
  • Add functionality for Extra Rig Nodes/Extra rig controllers.
  • Destruction: When a CATNodeControl is deleted, it is its own responsibility to re-parent any CATNodeControl children it may have to its parent. This is to allow (for example) removing spine links, and have the hub at the end of the spine re-parented to whatever link is now at the end of the spine. The same concept applies to all CAT nodes, when it is deleted, any children will be reparented to maintain the hierarchy structure.
  • Pass-through to the Layer Controllers : An implementation of CATNodeControl contains no animation data. Therefore, all they keyframing methods (defined by Animatable) need to passed through to the Layer controller which handles the animation data.

CATClipValue

This class is the base of the layer system. A layer is essentially a list controller – it contains an array of generic Max controllers, and it merges their values according to the rules of the layer. The rules are specified by the type of layer, this data is stored on the CATClipRoot LayerDesc classes. Originally, we had an implementation of CATClipValue for every value type in Max – float, position, rotation, point3 etc. However, over time we have removed almost all these layer types, and now simply provide implementations of float (CATClipFloat) for scalar values, and Matrix3 (CATClipMatrix3) for transform values. The basic list behavior functionality is implemented in CATClipValue. Here you can find the code for adding/removing layers, cloning, maintaining weights etc. The implementation's main job is to calculate the value of the appropriate type. CATClipFloat is fairly simple, but CATClipMatrix3 contains a lot of calculation to generate its values and handle things like inheritance correctly.

Was this information helpful?