Skinning

 
 
 

Skinning is the process of deforming a shape according to the transformation of joints or other influence objects. There are two types of skinning: smooth and rigid. Smooth skinning produces a skin that is smooth around joints as soon as it is bound and you can modify the weights to achieve more customized affects. Rigid skinning produces a skin that initially behaves as if it is parented to the attached joint. Either flexors can be added to produce smoothing around joints, or weights on the rigid jointCluster node can be modified for customized effects. The following table lists the differences between smooth skinning and rigid skinning.

Detail Smooth Skinning Rigid Skinning
Node Type skinCluster jointCluster
API Type MFn::kSkinCluster MFn::kJointCluster
API function set MFnSkinCluster MFnWeightGeometryFilter
Influence objects Any type of transform Joints
Number of deformers One per skin One per joint
Number of weights Up to one per influence/per CV One per CV
MEL command to edit weights skinPercent Percent

The most significant difference is that rigid skinning produces a single jointCluster per joint. The jointCluster is then shared by all skins that are rigidly bound to the joint. Unlike rigid skinning, smooth skinning produces one skinCluster per skin, and all of the influences that affect that skin are connected to the skinCluster.

Smooth skinning in general is easier and its algorithm is quicker to compute depending on the number of influences that are given weights.

Node Configuration in Smooth Skinning

In smooth skinning, there is one skinCluster per skin. Unlike other deformers, you cannot modify the set membership of a skinCluster to add more skins. Each skin must have its own skinCluster. You can modify the set membership of a skinCluster by removing vertices, for example, if you want to skin only half of an object.

In a skinCluster there can be any number of influence objects. The worldMatrix output of the influence objects are connected to the skinCluster's matrix attribute. The attribute logicalIndex of this connection is used by the skinCluster to correlate influences with their weights. The API method MFnSkinCluster::indexForInfluenceObject enables you to query the skinCluster for determining the index of the associated influence object.

The weights for the skinCluster are stored in the multi-multi attribute called weightList[].weights[]. The first index of the multi is the index of the vertex. The second is the index of the influence object. The weights are in general stored sparsely, so if you weigh a vertex by two of the 50 influence objects, only two elements exist in the weights array for that vertex. The exception is that if data exists in the data block and is later set to zero by some operation, the zero-valued data remains in the data block until the file is saved. When the file is saved, the file save code determines that the value zero is the default data, which does not need to be saved. The next time the file is read, only the non-zero valued elements will exist in the skinCluster.

The transformation of the joints at the time of the bind is called the bindPose. The skinning algorithm uses this information to perform the deformation. The bindPose is stored in a node called the dagPose node. It is stored in detail by the skinning algorithm because the extra details are needed to help in restoring the bindPose.

The dagPose node stores the worldMatrix for all of the influences at the time of the bind. It also stores the local matrix as a full transformation matrix (MTransformationMatrix), and stores the parenting information. Only the worldMatrix is used by the skinning algorithm and is contained in the skinCluster node of the bindPreMatrix attribute. The bindPreMatrix is a multi-attribute that correlates its multi-index to the related influence object.

For joints only, the bindMatrix is also stored in the bindPose attribute. The joint has some other bind-related attributes, but they are obsolete in Maya 4.0 and remain only for backward compatibility.

Algorithm

Each point P is assigned a set of weights {w1,w2,...,wn}. One weight for each of the n influence objects affecting the skin with the default weight value of zero. Typically, the following equation holds:

w1 + w2 + ... + wn = 1.0

If Ti is the current world transformation matrix of influence i and Bi is the world transformation matrix of the same influence at the time of the bind. If W(p) is the world position of P at the time of the bind, then Li(p) can be computed as the position of point P in the local coordinate system of influence i as shown in the following equation:

Li(p) = Bi - 1 x W(p)

You can then compute what the world position of the point will be if it is parented under transform i as shown in the following equation:

Ni(p) = Ti x Li(p)

You can multiply this world position by the corresponding weight for influence i and get Mi(p) as shown in the following equation:

Mi(p) = wi x Ni(p)

Now, add all the Mi(p) to get the deformed position of the point in world space as shown in the following equation:

NewWorldPos(p) = M1(p) + M2(p) + ... + Mn(p)

All the rotations happen at the joint/transform pivots and a linear interpolation is done using the weight to compute the final point positions.