Countdown, the Short Animated Film: #14, What’s in a rig?
From Journal Entry: Monday, October 27, 2008
The following was written originally as a journal of the process for my master’s degree thesis film project titled, Countdown.
Arrrggg… rigging!
It is likely my inexperience, but sometimes there is some really bizarre stuff going on behind Maya when rigging. Creating joints is not all that complicated. Having a simple hinge for one section to another section is easy. Creating a full character with an entire working, controllable skeleton, without any strange behavior, can be a challenge. Okay, so, lay out the bones, set up an IK, and what’s going to be at the end of that? A foot? A hand? A head? Create clusters? Is it a simple or rotate plane? How can this be simplified? And what should this do for the character? Should he stretch? Really the story and what the character is doing in the story dictates. With this, some experimentation is in order with different setups.
I looked at several rigs available to understand what they did and how they functioned. This helped to understand what I might want and some of the limits for a rig. One of the first obvious choices was to look at the Hogan rig which was introduced to me in the initial animation classes, as well as Hogan's successor, Norman which was also introduced in a later animation class. While there are other rigs I looked at, I also felt that these had the features needed, and I've used them for animation.
While I wanted to just copy the controls and modify them from an existing rig, I realized how easy it is to create and edit controls, and how having really fancy controls is not really necessary. Nice, but not necessary. Having the ability to zero out the controls to get the rig back to the default t-pose is a great advantage. The Norman controls have a lot of capabilities and features but there may be more than I really need or want.
Stretchy IK on the Spine
When drawing, or even modeling to a certain extent, there is a bit of instant gratification. That is a problem with rigging. There are no real instantaneous results. There are sometimes problems when setting things up initially, so it's got to be laid out well from the start. From the initial laying out of joints, to actually getting the character to move, the process is long and steps to be done in the proper order. Adding a spine that stretches is the next level of difficulty though.
Stuck on Modeling
It’s hard to put all the modeling away. To call the Kid model complete is difficult. There are a few things here and there that seem to need more attention. Currently, the few things of concern are the size and shape of the feet. This mostly applies when rigging, where an interesting thought occurred to me. Initially, the kid’s feet were modeled in the "duck" foot pose, with the feet sticking out at an angle, not straight ahead. It would seem that a rig is more challenging to set up this way. There are a few solutions to solve this problem, like setting up an influence object or attempting to align the joints properly to handle the off-angle. Or an even easier task, just model the character with the feet straight out in front, rig, and then just turn the feet out with the controls. This will keep rigging easier and still achieve the result I want. This is the route I chose since changing the model would be easier than rigging with his feet in this duck foot position.
IK Elbow Pole Vector
Laying out bones is all easy work, select the joint tool, click here, click there, and wham, there are two joints with a bone in between them. Keep doing that at very specific places, and eventually, you have a skeleton. Leave it all at that and you can move the bones around, and get all sorts of motion.
However, to start adding controls and Inverse Kinematic controls, some very odd stuff might occur. I learned my first lesson, if there are more than two bones between and there needs to be an IK handle when the joint doesn't act like a simple ball joint, then there needs to be a pole vector. A pole vector keeps the joint hinge going in the direction of the pole vector.
To set this up, the IK handle needs to be a Rotate Plane solver and to be able to do this right, the joints really need to be on the same plane as the pole vector. When the IK is created at the base of the IK, the first joint clicked will display a rotation disk with a white pointer called the Reference Plane Indicator. The direction of this pointer is the direction that the IK will orient itself to when it is attached to the pole vector shape. In other words, if this is pointing in any other direction other than the pole vector shape, the joints will twist when the Pole Vector Constraint is added.
Arm IK, with Pole Vector and Wrist Twist
Recommended by LinkedIn
Create an IK from the shoulder to the wrist. Select Pole Vector shape, shift select IK handle, go to Constraint menu, and choose Pole Vector. Now as long as the joints are in line, and the center pivot is also in line with the joints, the shape will control the pole vector and the joints along the chain won’t move. Set up a control curve around the wrist. Parent this to the ik handle. Set up a wrist twist attribute on the curve.
Foot Controls
Following a few tutorials, and with some deviation, I managed to work out a good set-up for the foot. I had to make a lot of notes, and if I messed something up (usually several steps back) I adjusted my notes, went back and started over. While this took a bit of time, each iteration was better and faster to create. Once done, I was able to follow the same steps on the other foot and was able to create it in a matter of minutes.
Adding Foot Banking Controls
Hip joint to Ankle joint (Rotate Plane - ikRpSolver)
Ankle joint to Ball joint (Single Chain - ikScSolver)
Ball joint to Toe joint (Single Chain - ikScSolver)
Interesting Lessons in Joint Orientation
As anyone who has any experience with breaking joints while rigging will tell you, joint orientation is crucial. A bit of advice, do not rotate joints while creating them. One reason that riggers seem to always switch to the appropriate orthographic view while setting up joints, is to make sure that the joints will orient themselves in that view. Manually resetting joint orientation is maddening. If the rotation of the joint changes, it could just mess up many joints below the chain. However, if this is the last joint in the chain, it’s not so important.
Notes on the Kid Foot Rig
The kid’s feet were rigged with reverse lock foot joints. While the actual foot joints are above the reverse lock joints, the idea behind the positioning of the reverse lock joints was to have a joint at the very end of the heel, the heel pivot point, and the end of the toe, the toe pivot point likewise the ball is at the base of the shoe too. Then the actual toe joint is inside the shoe, where the toe would be, the ball inside the shoe, and the ankle, well at the ankle. The idea here is to have the positioning of these as accurate as possible. This may be a little too precise, but due to the size of the shoes, when binding the geometry to the bones, hopefully, the joints will deform the right stuff to make it look good. And if it doesn’t, well this will be the place to go back to and correct. The joints may need to be moved like the toe and the reverse lock toe might need to be moved closer to each other (possibly vert snapped), and the same with the ball.
A Few Thoughts on MEL
Knowing Mel (the Maya-Embedded Language) is almost essential to working with Maya. Sometimes I think this is why people either love or hate Maya. And even the lovers may even hate it sometimes. Creating something very simple in Mel can either be just that, simple or then sometimes, quite complex. Take for example some of the screenshots, or playblasts that were taken for the image examples in this journal. I developed a relatively simple Mel script and saved as a shelf button to create a single-frame playblast of the current view. It might be simple enough to run the Playblast with specific settings, but it is nice to be able to have all the settings automated in a single click on a shelf. It can be easy to have, but slightly complicated to set up. The code to do this rather automatically had some interesting requirements.
Something very peculiar, originally the script I wrote performed a command to populate the projPath, and that was to query a variable called browserLocationimageimages which was supposed to be populated with the current project’s image directory, pretty much this is the rendered image files location. Well, this worked while Maya was open at the time the script was written. The next time it was opened, and the project set, the script returned an error with that variable. After querying the entire list of variables, this variable no longer existed. Interesting, why would this no longer be available? After shutting down Maya, restarting, setting the project again (without opening a file) and querying the list, the variable was still not there. Who knows why, it was there once, and disappeared.
It is possible that the path is not needed; because the playblast command already recognizes what directory the images should be saved.
// playblast the current frame as a JPG image
// current path to the project images
string $projPath = `optionVar -q "browserLocationimageimages"`;
// get the base file name
string $path = `file -q -shn -sn`;
string $basename = basename( $path, ".ma" );
// add a time identification
string $timeStamp = `date -format "_hhmm"`;
// set up a path separator, just in case this script goes public and needs to work on windows macines - right now only mac and Maya internal functions will work
string $pathSep = "/";
// find the current render image format, save this and change it to JPG, then set the image format back to the original
string $curRendSet = `getAttr "defaultRenderGlobals.imageFormat"`;
if ($curRendSet != 8) {
// not jpg
setAttr "defaultRenderGlobals.imageFormat" 8;
}
playblast -frame `currentTime -q` -percent 100 -format image -orn 1 -viewer 0 -cc 1 -completeFilename ($projPath+$pathSep+$basename+$timeStamp+".jpg");
// return the render settings
if ($curRendSet != 8) {
// not jpg
setAttr "defaultRenderGlobals.imageFormat" $curRendSet;
}