
Hi,
in an effort to expand my rigging knowledge (and solving another problem) I thought of setting up a skinCluster manually in the node editor. Such a trivial thing to do through the UI, but not that obvious when you want to do it yourself. Not much info out there on this topic, so i’l thought i might put it up here, maybe it can be useful to someone. i think it’s a nice thing to know as a rigger and it sheds some light on the architecture of Maya.
Given: 1 joint, 1 mesh, 1 empty skincluster node
1 set up the joint:
Connect joint.worldMatrix[0] to skinCluster.matrix[0],
2 Set the bind pre matrix
Set the bind pre matrix of the joint on the skincluster in order to set the starting point for the driving joint (identity matrix). you can do this via a setAttr command or just use another joint’s world inverse matrix through a connection.
[quote=]matrix = cmds.getAttr (‘your_joint.worldInverseMatrix[0]’)
cmds.setAttr (‘your_skinCluster.bindPreMatrix[0]’, matrix, type = ‘matrix’)[/quote]
you should do the same for the mesh matrix
[quote=]matrix = cmds.getAttr (‘your_mesh.worldInverseMatrix[0]’)
cmds.setAttr (‘your_skinCluster.geomMatrix’, matrix, type = ‘matrix’)
[/quote]
3 create the skinCluster deformation set.
Maya uses these to keep track over which components are needed for deformation (very useful for optimization of your rigs)
These sets don’t display in your default outliner since the outliner has a filter applied which hides them,
you can see them in the relation editor and node editor or create your own outliner as done here:
[quote=]
import maya.cmds as cmds
def create_deformer_outliner ():
cmds.window()
cmds.frameLayout( labelVisible=False )
panel = cmds.outlinerPanel()
outliner = cmds.outlinerPanel(panel, query=True,outlinerEditor=True)
cmds.outlinerEditor( outliner, edit=True,
mainListConnection=‘worldList’,
selectionConnection=‘modelList’,
showShapes=False,
showReferenceNodes=False,
showReferenceMembers=False,
showAttributes=False,
showConnected=False,
showAnimCurvesOnly=False,
autoExpand=False,
showDagOnly=True,
ignoreDagHierarchy=False,
expandConnections=False,
showNamespace=True,
showCompounds=True,
showNumericAttrsOnly=False,
highlightActive=True,
autoSelectNewObjects=False,
doNotSelectNewObjects=False,
transmitFilters=False,
showSetMembers=True,
#setFilter=‘defaultSetFilter’, < filter disabled
ignoreHiddenAttribute=False,
ignoreOutlinerColor=False )
cmds.showWindow() }
create_deformer_outliner () [/quote]
I simply created a Set through the UI with a vert selection of the final mesh:
connect deformationSet.usedBy[0] to skinCluster.message
I think this connection tells maya what verts are needed for i.e. skin painting,
You can always add verts manually by selecting them and running this code.
4 The Bind Pose
[quote=] This node is used to store information about a hierarchical pose.
This node performs no computation. It is typically used in conjunction with the dagPose command in order to save and restore poses.
Poses are also created when skin is bound to a skeleton. These poses are called bindPoses, and are unique in that each joint/transform is only allowed to be placed in a single bindPose.[/quote]
This node is not important, more of a Maya way of storing the initial position of the binding (which breaks a lot of times when doing stuff like adding influences) .
But lets create it for completeness. Create a ‘dagPose’ node,
connect joint.message to bindPose.members[0] ,
bindPose.world to bindPose.parents[0],
joint.bindPose to bindPose.worldMatrix[0]
bindPose.message to skinCluster.bindPose.
5 Create an Orig Shape:
Create an Orig shape by duplicating the mesh without history. This is a hard copy of your mesh before deformation, deforming this will flow downstream. The orig shapes is typically not visible in the outliner. To mimic this default maya behaviour, parent the shape node of the Orig Mesh underneath the mesh transform node and set the ‘intermediate’ attr in the display options to True if you like. This will hide it from you in the outliner.
[quote=]cmds.parent (‘your_Orig_Shape’, ‘mesh_transform_Node’, shape = True, relative = True)
cmds.setAttr (‘your_Orig_Shape.intermediateObject’, 1)[/quote]
6 The group id.
Now we enter a new dimension of Maya, auxiliary nodes !
These nodes don’t display by default, so go to outliner > show > show auxiliary nodes. (also put disable the ’ show dag nodes only’ if you didn’t do that already)
Maya needs a ‘group parts’ node and a unique ‘groupId’ number to tell the skinCluster what components (verts) to use of the Orig Shape,
Maya generates this id by it self and we actually already created the id node through the UI when creating the deformation set.
So create the groupParts node and :
connect origShape.WorldMesh[0] to groupParts.inputGeometry
connect groupId.groupId to groupParts.groupId.
connect groupId.groupId to skinCluster.input[0].groupId
7 The tricky peace of the puzzle
ok, we are almost there, one piece of the puzzle is still missing and hard to spot without knowing it, we need to specify what components to use in the ‘groupParts’ node. We need to set
a wildcard: vtx[li] meaning deform all verts in the mesh.
[/li]
[quote=]cmds.setAttr(‘your_groupParts_node.inputComponents’,1, “vtx[li]”, type = ‘componentList’)
[/li][/quote]
8 Connect the skinCluster output to the mesh:
connect skinCuster.outputGeometry[0] to mesh.inMesh
notice the mesh disappears, this is what we want… we haven’t set the deformation weights yet!
9 Setting the weights.
To enable the lock weights functionality for skin painting you need to add an attr and connect it ( some mystery here since the attr is visible in the the attr editor,
but throws an error if you tick it.)
connect your_joint_name.lockInfluenceWeights to skinCluster.lockInfluenceWeights[0]
Now that’s in place we need to set the weights, you can paint if if you like.
if maya doesn’t display or update the weights on the skinClusterNode, you can do it your self, but it might be a symptom that something is not right:
[quote=]for index, i in enumerate (cmds.ls(‘your_mesh_name.vtx[li]’,flatten = True)):
[/li] cmds.setAttr (‘your_skinCluster_node.weightList[’+str(index)+’].weights[0]’,1)[/quote]
That wraps it up! your mesh should deform !
Greetings Tristan M.