And an update for this yearly work:
This course allowed me to learn a bunch of new stuff and polish my knowledge in regards to rigging, having great mentors: Josh Carey, Brad Clark, Daniel McCrummen.
My tasks were to rig a human character and a non organic one, a kite. I’ve intensively used PyMel scripting to automate tasks, which will be parts of a new PyMel version of my MEL automated rigging script ( like implementing scaling for ik chains, no mattter the solever, fully fingers rigging, legs and arms rigging)
For the kid, i was responsible only for it’s body rigging.
- ik/fk arms and legs
- independet scale and volume per limb
- automatic breathing with adjustable frequency and volume
- ribbon limbs with auto volume on/off
- stretchy spine
- non flip knee
- elbow/knee locking
- space switching for ik hands / head/ neck
The kite features:
- fully dynamic ropes, stripes, strings
- fk multipliers to ease the animation of the stripes/strings, but with the ability of still controlling in FK mode if wanted
- the main string has an fk/ ik /dynamic implementation, allowing to have the kite in an anchored mode, with a knot that can be placed around something.
Scripting: PyMel , PyQt
UI: QtDesigner ( for the static part of the interface)
What it does:
- Imports controllers and resolves the namespaces
- Dynamically generated UI for controllers
- Easy to add controllers, just a matter of drag and drop in the ‘controllers’ folder
- Color based controllers
- Mirror behavior / orientation
- Proper shape mirroring in case of mirroring with orientation
- Supports multi-shapes controllers
- Supports hierarchy controllers ( fingers for example)
While these days there are a lot of modular rigging tools that bring the animation controllers along, as a TD you still have to rig various things that require ( supposedly) some curves for the animator to grab and move stuff around. And this scripts just does that.
Basically on the same path with the script you need a folder where to drop your favorite controllers as MA files, with the files named so you have an idea whats inside. Why ? The script will look into that folder and use the file names to set the labels for the buttons.
Here’s a link to a demo of it :
Two approaches for facial rigging:
- first is joint based, using corrective shapes.
- second is blendshapes based.
First model was bought from turbosquid.com, second model was created by Touchwood Animation Studio.
Back to Rigging Dojo , this time to work as character rigger for a non-profit short film -> http://labs.anomalia.eu/wildlife-crossing.
Great chance to meet new people and new mentors.
what it does:
- helps creating a fully rigged skeleton without facial rigging
Yet Another Rigging Tool …
While i was developing it, from some reason i wanted to create all the animation controllers on the fly .. which i did. Basically they are all box type, with the size of them based on the length of the joint they are driving . Maybe not the best idea in the world, but hey, it seem like a great idea at that point.
Currently I am working on a Python-ic version of it, more modular and with the help of PyQT / QtDesigner for the interface.
I will be adding actual code under this category … be warned, even though i will try to invent a new wheel, it will take some time probably . You can grab the script at the end of the post.
This type of script exist for like forever, the only different thing is that ive used vectors to do it, mainly subtraction and scaling of vectors:
#get the joints positions and convert to MVectors strJntRaw = cmds.xform(startJnt,ws=True,q=True,t=True) strJntPos = om.MVector(strJntRaw, strJntRaw, strJntRaw)
endJntRaw = cmds.xform(jntChild,ws=True,q=True,t=True) endJntPos = om.MVector(endJntRaw, endJntRaw, endJntRaw)
#subtracting vectors in order to get to the segments position subJnt = endJntPos - strJntPos
for i in range(1,int(numSegments)): newJntPos = subJnt * i * (1/numSegments) + strJntPos
Also, Ive tried to check for the proper orient rotation ( aka the child joint was not moved with Insert and has translation in only one axis) using vectors, specifically getting the norm vector of the child and checking to see if it has 1 on one of the axis. This is done in local space ( it would not work in world).
endJntRaw = cmds.xform(endJoint,q=True,t=True) endJntPos = om.MVector(endJntRaw, endJntRaw, endJntRaw) downAxis = '' endJntNorm = endJntPos.normal() for i in range(0,3):
if endJntNorm[i] == 1: if i==0: downAxis = 'x' print 'its x' elif i==1: downAxis = 'y' print 'its y' elif i==2: downAxis = 'z' print 'its z' return downAxis
Maya, QT Designer
what it does:
- renames multiple objects using an index based convention
how it does:
- the user needs to select at least one object
- a mask is required for the renaming, with a choice of prefix and suffix too.
- by default the index is 2 digits based ( as in starts counting from 00 to 99). Should the selected object be over 100, automatically 3 digits are used. I assume nobody wants to rename 1000+ objects
- UI is built using QT Designer, but all the events are added in Maya
- the function used to retrieve the widgets paths was written by Chris G.
what it does:
- copies mocap data ( imported as fbx file) on rigged characters
how it does:
- opens the fbx file
- cleans up the names
- imports the rigged characters and tries to automatically match up the height of the character
- copies the animation from mocap onto the animation controllers
- removes all the mocap data
- animation now can be tweaked/cleaned/enhanced by the animators
- prepares the file for export
- mocap files were pretty messy, naming wise and structure wise
- a mocap file could have between 1 and 11 players with multiple footballs, the script is handling all the cases
- occasionally the user had to get his/her hands dirty ( like properly naming/duplicating the footballs)