::skeleton builder 101: part3::

December 7th, 2010 by hamish download the zooToolBox

This is the third post in a series of posts on the Skeleton Builder tool – it’ll be focusing on the class the defines how to rig a skeleton part.

The base class for defining a rig part is called – inventively – the RigPart class.  So any given rig part can be associated with any number of skeleton parts.  Each RigPart class has a class variable called SKELETON_PRIM_ASSOC that defines which skeleton parts it “knows” how to rig.  This variable is just a tuple containing the actual skeleton part classes the rig knows how to work with – You may notice that the existing parts use an unusual piece of functionality to get these classes (ie SkeletonPart.GetNamedSubclass) – I’ll talk more about that below.

For example, one of the rig parts is a simple control chain.  Now if you wanted, you could have this rig part associated with every single skeleton part.  Its not – but there’s no reason it couldn’t be.  After all, the rigging code simply takes a bunch of joints and their children, creates a control for each joint, and then parent’s it to the control that controls its parent joint if one exists.  Ie the rigging code will work on any hierarchy of nodes – and will thus work on any type of skeleton part.  By default however, the control chain is only setup to work on the Arbitrary Chain part.

So anyway, writing rigging code for skeleton builder is super easy – its little more than writing the rigging code in whatever fashion you want (you can even write it in mel – although you’ll need to hook up a tiny bit of glue code in python to make skeleton buidler aware of it).  Once your rig code is written skeleton builder will automatically put all nodes created by the rig into a “container”.  I don’t actually use container (coz they suck*) nodes, I instead use set nodes.  But these containers contain all the nodes used to define that piece of the rig.  So once a rig part is built, you can always go back and see exactly what nodes are involved in that part, delete them if you want, or whatever else.

You can also query existing rig parts in the scene, just like skeleton parts.  A rig part knows about all the nodes that make it work – but it also knows which ones of those nodes are controls, and a few other useful things like “placer” nodes – which I’ll talk about in a bit.  So for example, if you’re writing some code to rig up an arm and you want to know what rig part is above the arm in the hierarchy, just ask the arm skeleton part for its parent part, and then ask that part for the rig part that controls it.  Obviously rig parts don’t really have a strict hierarchy in general, so asking a rig part for its parent doesn’t make sense – but joints in the skeleton obviously have hierarchy, and you can make queries of the skeleton from within your rig code should you need to.

So placer nodes.  Placer nodes are just locators nodes that can be used as “markup”.  So for example the legs can create them for users to define where the foot roll pivots are, heel pivots, toe pivots etc…  They can also be used to help define alignment on end joints for chains like fingers or arbitrary chains.

Rig parts can also be nested.  For example just say you wanted to build a bunch of functionality on top of a simple FK spine.  You could create a new rig part that creates a basic FK spine and then adds stuff on top of it.  Skeleton Builder will then organize the parts so they’re nested into containers properly – so inside the new spine container you’ll see another container for the basic FK spine.

Now skeleton part rigs don’t need to be animator puppet rigs – they can be anything.  In fact one of the most useful things to do with skeleton builder is define “helper” parts – like for example you could define your own “pectoral deformation helper” part which rigs itself up so that it drives proper pectoral area deformation in your character.  This sort of part need not be even seen by animators – although again, if you wanted to expose a control to the animator for whatever reason, you could.

So whats with the use of GetNamedSubclass?  So this is basically a dependency issue.  The skeleton builder modules should be independent where possible.  The SKELETON_PRIM_ASSOC is a tuple of class objects, so to keep the modules independent you need some way of getting the class object without actually importing the skeleton part you want to add an association to.

When you import skeletonBuilder, all the modules get imported based on their script names.  The SkeletonPart’s metaclass then tracks any subclasses that get defined and implements the GetNamedSubclass on the SkeletonPart class so you can get a part class by name, or iterate over all available part classes.  The RigPart does the same thing.  The GetNamedSubclass returns None if it cannot find the named class.  This way you can even delete a skeleton part script and the rig parts work fine because there isn’t a hard dependency between the skeleton part script and the rig part script.

Anyway thats the overview of the rigging class – next post I might see if I can go into some actual code – maybe walk through defining a new skeleton part and a rig part (hint: its really easy).

*Container nodes almost don’t suck – they’re actually a cool concept, but they’re implemented in this kinda shit way.  For a start, any node in a container doesn’t quite act the same way in the channel box, which pisses off animators or anyone else who has to work with attributes.  They also don’t quite work with the outliner and a bunch of other UI.  So great idea in theory, but lots of little implementation failures.  Autodesk don’t really do details.


This post is public domain

This entry was posted on Tuesday, December 7th, 2010 at 21:57 and is filed under main. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.