Browse the wiki

05. Rigging the hand

In this section we are going to create the joints and controls for the hands.

Introduction

If body language can speak louder than words, it’s imperative that an animator is given a hand rig that offers a great deal of flexibility as well as efficiency. For this reason, we’ll be adding a control which allows the animator to pose the whole hand, while also creating individual controls for each phalanx. Additionally, with regard to the fingers, we are going to add the metacarpal bones to enable a credible fist to be formed.

 Before we start, we’ll clean up the arm rig…

001. Cleaning up the arm rig

 

Before we dive in to the hand, I just want to do a little housework and add the ability to twist the IK arm from the l_arm_IK control. At the moment we can twist the arm using l_elbow_ctrl, but this twist will just give the animator another option.

Start by selecting l_arm_ik_ctrl and go Modify > Add Attribute. Give it a Long name of elbowTwist, set the Data Type as Float, and then leave the Minimum and Maximum fields empty and the Default at 0. Now go Window > General Editors > Connection Editor (CE). The CE allows you to make one-to-one connections, which is precisely what we’d like to do in this instance. Select l_arm_ik_ctrl and on the CE window, hit Reload Left. This will be the driver object. Now select l_arm_ik, and hit Reload Right on the CE window. This will be the driven object.

In the left-hand side of the CE window, you will see the Outputs for l_arm_ik_ctrl. Navigate to and select elbowTwist from the list. On the right-hand side of the CE window, you’ll see the inputs of the l_arm_ik. This time, navigate to and select twist. You should now be able to twist the IK arm either using the elbowTwist attribute or through the l_elbow_ctrl.

Let’s turn to the house-keeping now. First, I’d like to attach the clavicle joint to the spine. To do this, we’ll add an additional joint that acts as a bridge between the upper limb and the torso. We can also use this joint for skinning purposes later on. In the Front view, use the Joint tool to create a single joint, then point snap it to spine12_ik_jnt and translate it slightly to the (screen) right of the spine. Rename this joint l_shoulder_jnt and increase the Radius of the joint in the Channel Box to make it more easily selectable.

Then take l_clavicle_jnt and parent it under l_shoulder_jnt, and then parent l_shoulder_jnt under spine12_ik_jnt. Now take l_clavicle_ctrl_offset and parent it under spine_chest_ik_ctrl.

Select l_elbow_ctrl and rename it l_elbow_ik_ctrl to fit our naming convention. Do the same for the auto and offset node for that control. Then select l_arm_ik_ctrl_offset, l_elbow_ik_ctrl_offset, and hit Ctrl + G. Rename this new group l_arm_ik_ctrl_grp. You’ll now have an empty group in the Outliner called l_arm_jnt_grp, so select and delete it.

Now select neck1_jnt, hit Ctrl + G, and rename that group head_jnt_grp. Take both torso_jnt_grp and head_jnt_grp, hit Ctrl + G, and rename this group rig_jnt_grp. Take eyes_ctrl_offset, group it to itself and rename that group to eyes_ctrl_grp.

Now take torso_ctrl_grp, eyes_ctrl_grp, and l_arm_ik_ctrl_grp, and group them together. Call this new group rig_ctrl_grp. Lastly, take torso_doNotTouch_grp and world_follow_loc_grp, and group them together. Rename this group rig_doNotTouch_grp.

After all the renaming and grouping madness, test that the rig still works correctly by rotating and translating the controls.

002. Creating the finger joints

 

We’ll start by creating the main joint that will drive the hand. For this joint, select l_arm_end_jnt and hit Ctrl + D to duplicate it. Hit Shift + P to un-parent the joint, then rename it l_carpals_jnt. Duplicate l_carpals_jnt and rename the new joint l_carpals_end_jnt. Then parent l_carpals_end_jnt under l_carpals_jnt. With l_carpals_end_jnt still selected, use the Translate Y attribute to move it down the palm. To make the l_carpals_jnt more easily selectable, increase the Radius in the Channel Box.

We’ll go to the finger joints now and start with the little finger. Jump to the top view and use the Joint tool to create a three-joint chain. Pop the first joint at the base of where the metacarpal joint would lie, the second joint at root of the proximal phalanx (first knuckle), and then the third joint at the end of the finger. We’ll be adding the additional joints in a while using the jointSplitter tool. Switch to the Perspective view now and translate the root joint up so that it sits within the body of the finger.

Using the Orient Joint tool, set the orientation so that positive X rotation equals flexion. I used the following settings: Primary Axis: Y, Secondary Axis: Z, and Secondary Axis World Orientation: Z (-). Duplicate the root joint three times to create the additional finger joints, then position and rotate them to sit within the fingers.

Remember, you can translate the root joint on any axis, but for any children joints you should only use the Translate Y attribute (the length). You can rotate the joints, but do remember to freeze the transformations to send the rotation values to the Joint Orient.

As we’ll be using the jointSplitter tool to create the additional joints, we need to make sure that the names of the joints do not clash, which they currently do. For now, go in and quickly add a ‘p’ on the end of all the pinky finger joints, an ‘r’ to the end of all the ring finger joints, an ‘m’ for the middle finger joints and an ‘i’ on the end of all the index finger joints. Now load the jointSplitter tool, select the pinky joint that needs splitting and set that as the Start Joint. Set the Jnt Qty to 2 and hit Split Joints. Do the same for the rest of the fingers and then reposition the new joints and rotate them into place. Again, freeze the transformations when you are happy with the placement of the joints.

Back in the Top view, create a 4 joint chain for the thumb (we won’t be using the jointSplitter tool here). Select the root joint and open up the Orient Joint tool. Set the Primary Axis to Y, the Secondary Axis to Z and the Secondary Axis World Orientation to Z (-). Positive X rotation should now curl the thumb in towards the pinky finger. Then select the root joint of the chain and translate and rotate it into the geometry of the thumb. Continue to rotate the rest of the finger joints so that when you rotate the joints they curl under the palm, rather than into it. Once again, with the risk of sounding like a broken record, do remember to freeze the transformations for all the joints.

Now take all the root joints for each finger and the thumb and parent them under l_carpals_jnt.

003. Rename the joints

Time for some wholesome renaming. To speed things up, we’ll again be using the cometRename tool. Load the tool and select all the joints of the pinky finger from root to tip. In cometRename’s Rename field, type l_pinky and hit Rename and Number. Then type _jnt into the Suffix field and hit Add Suffix. Then select the end joint for the pinky (l_pinky5_jnt) and change the _fk to _end_fk. Repeat the same process for the rest of the fingers, giving them the name of ring, middle, index and thumb.

004. Create the controls

To create the controls for the fingers and palm, we’ll be using the createControls.py script. Load the script into the Script Editor and update the following lines to read like so:

16 ctrl = cmds.circle( nr=(0, 1, 0), r=1.5, n=ctrlName)[0]
21cmds.orientConstraint(ctrl, s, mo=0)

This will reduce the radius of the controls (feel free to experiment with the value) and will then orient constraint the joints to the controls. Now select all the finger joints (minus the end joints), the l_carpals_jnt, and execute the script. You should now have all the controls created, each with its own auto and offset group node. Switch to component mode and edit the position of the controls for ease of selection.

The next thing to tackle is the hierarchy for our hand controls so they mimic the FK setup of the joints. Starting with the pinky, select l_pinky4_ctrl_offset and parent it under l_pinky3_ctrl. Take l_pinky3_ctrl_offset and parent it under l_pinky2_ctrl. Parent l_pinky2_ctrl_offset under l_pinky1_ctrl. Parent l_pinky1_ctrl_offset under l_carpals_ctrl. This is the same process to follow for all the fingers, so I’ll let you take care of them now.

With the hierarchy in place, the controls now orient the joints correctly. Unfortunately, if we translate the l_carpals_ctrl, the joints do not follow. To fix this, simply select l_carpals_ctrl, shift-select l_carpals_jnt and go Constrain > Point.

With the joints and the controls in place, we can chop up the geometry and parent the slices to each joint. Rather than use the Cut Faces Tool here, I decided to grab a selection of faces and simply extract them, working my way from the tip of the finger towards the root.

005. Create the low-res geometry

006. Create the main finger controls

 

We are now going to create a control that will allow the animator to quickly pose the hand. In the Top view, go Create > CV Curve Tool (Options) and set the Curve degree to 1 Linear. Then, using that tool, draw a curve that goes around the body of the hand (excluding the fingers). Snap the last CV to the first CV to close the curve. To do this, hold down the C key to activate Snap to curve. Then using the CV Curve tool again, draw a curve for each finger and for the thumb. Once you have created all the curves, you should have 6 curves in total and together, they should mimic a very simplified hand.

Now rename the first curve (the body of the hand) l_fingers_ctrl and rename the remaining five curves l_pinky_ctrl, l_ring_ctrl, l_middle_ctrl, l_index_ctrl and l _thumb_ctrl. With all the curves renamed, select all the new finger curves and parent them under l_fingers_ctrl. With all the curves selected, go Modify > Center Pivot. Position l_fingers_ctrl close to the hand and scale it so that it’s easily selectable. I’ve rotated the control by around 45˚ so it’s easier to grab in the front or side view. For the control to follow our existing hand rig, parent l_fingers_ctrl under l_carpals_ctrl, then select all our new curves and go Modify > Freeze Transformations.

Next we’ll be adding some custom attributes to drive the hand, and have no need for the transform attributes that each curve currently has. Select all our new finger curves and highlight all the Translate, Rotate, and Scale attributes in the Channel Box. Hold down the RMB and Lock and Hide Selected.

007. Add the finger attributes

 

It’s now time to add some custom attributes to our new controls. Select all the new control curves, go Modify > Add Attribute and add the following:

Long NameData TypeMin, Max, Default
Curl Float-10, 10, 0
ScrunchFloat-10, 10, 0
SpreadFloat-10, 10, 0

Now select just the l_fingers_ctrl and add the following attribute:

Long NameData TypeMin, Max, Default
RelaxFloat-10, 10, 0

Select the all the fingers controls and add the following attributes:

Long NameData TypeMin, Max, Default
metacarpalFloat-10, 10, 0
ProximalFloat-10, 10, 0
MedialFloat-10, 10, 0
DistalFloat-10, 10, 0

Lastly, select the thumb control and add the following attributes:

Long NameData TypeMin, Max, Default
metacarpalFloat-10, 10, 0
ProximalFloat-10, 10, 0
DistalFloat-10, 10, 0

008. Finger curl with SDKs

 

We’ll now drive the curling of the fingers using our custom control through Set Driven Keys (SDKs). As we do this, it’s very important that we apply the SDKs to the _auto node of all our controls. This will allow us to be able to animate on top of the SDKs using the control curves around the fingers.

Open up the SDK window by going Animate > Set Driven Key > Set. Select the l_fingers_ctrl and click on the Load Driver button on the SDK window. Then select all the _auto nodes for the finger controls and click Load Driven. Rather than finding and selecting the _auto nodes in the Outliner, select all the finger controls in the viewport and hit the up arrow on the keyboard. This should select all the _auto nodes by “pickwalking” up the hierarchy.

With all the objects in the SDK window, let’s set up the finger curl. First we need to key the default pose. In the SDK window, highlight l_fingers_ctrl from the top-left box, Curl from the top-right box, all the _auto nodes from the bottom-left box, and Rotate X from the bottom-right box.

With everything at 0, hit Key on the SDK window. Then up the Curl attribute to 10 on the l_fingers_ctrl. Using the _auto nodes, create a fist with the hand. Remember to only use the Rotate X attribute. I also add some rotation to the metacarpal controls, especially the pinky control, to create a nice arc from the knuckles. Once you’re happy with the pose, hit Key on the SDK window.

If you go from 0 to 10 with the Curl attributes on the l_finger_ctrl, you should be able to create a fist. Set the Curl attribute to -10 and then hyperextend the fingers as illustrated in Fig.07c. In this instance, I do not add any rotation to the metacarpal joints. Again, make sure to only use the Rotate X attribute. When ready, hit Key on the SDK window. Do make sure to test out the results before moving on.

009. Finger scrunch, spread and relax

 

Let’s create the scrunch pose next. If you are wondering what the scrunch pose should look like, imagine how you would pose your hand to scrape your fingernails against a blackboard. Back in the SDK window, make sure that l_fingers_ctrl is still set as the Driver. Bring in all the _auto nodes for the finger controls, but leave out the metacarpal controls. Make sure everything is at 0, highlight Scrunch in the top-right box, Rotate X in the bottom-right box, and hit Key to set the default pose. Then up the value of Scrunch to 10 and create a scrunch pose as illustrated in Fig.08a.

When you are happy with the pose, hit Key on the SDK window once more. Then take the Scrunch attribute down to -10 and create a pose like that in Fig.08b. Clearly, this is not a very natural pose, but for very fast movements it can help to add fluidity. One you are happy with the pose, hit Key once more on the SDK window.

Using the same technique, do the same for the Spread and Relax attributes. For the Spread, the driven attribute should be set to Rotate Z. I only use the auto nodes for the metacarpal controls and the proximal controls to create these poses. Increasing the Spread attribute to 10 would bring the fingers together, and decreasing the value to 10 would spread the fingers apart.

For the Relax, all the _auto nodes for the fingers were used (excluding the thumb), and Rotate X was again used as the Driven attribute. In this case, upping the Relax attribute to 10 would relax the fingers, with the pinky being the most relaxed and the index the least, and then -10 would make the index finger the most relaxed and the pinky the least.

010. Copy SDKs

 

So far, we can pose the hand as a whole. I’d now like to extrapolate the SDKs for the entire hand and pop them onto each individual finger. We could simply do this manually, like for the current SDKs, which would be a little slow and tiresome, or we could grab a script from online to speed up the process. Another way to handle this is to copy the animation curves from one attribute to another. This will be the route we take now. Using the SDK window in conjunction with the Graph Editor, we will first create an SDK for our new Driver object. Following that, we’ll copy the animation curve data from one control (l_fingers_ctrl) and paste it onto another control.

First I’ll give you a working example which you can use for the rest of the controls. In this example, we’ll copy the SDKs from the Curl attribute of l_fingers_ctrl and paste them to the Curl attribute of l_index_ctrl. Open up the SDK window and set l_index_ctrl as the Driver object. Then select l_index1_ctrl_auto, l_index2_ctrl_auto, l_index3_ctrl_auto, and l_index4_ctrl_auto, and load them in as the Driven objects. Highlight Curl in the top-right box, highlight all four _auto nodes in the bottom-left box, Rotate X in the bottom-right window, and hit Key to set the initial pose.

Now with l_index1_ctrl_auto, l_indexB2ctrl_auto, l_index3_ctrl_auto, l_index4_ctrl_auto selected, pop into the Graph Editor (Windows > Animation Editors). Here you should see all the animation data for the SDKs you created in the previous steps. On the left-hand side are the attributes driving the motion. Take a look under l_index1_ctrl_auto and you’ll see three different attributes are driving the Rotate X: l_fingers_ctrl.Curl, l_fingers_ctrl.Relax, and the attribute we just added, l_index_ctrl.Curl.

What we want to do now is copy the animation data from l_fingers_ctrl.Curl to l_index_ctrl.Curl. Before we do that, we need to edit a few settings. So in the Graph Editor window, go Edit > Paste (Options). Set the Time range to Clipboard, the Paste method to Replace, the Replace region to Entire curve, and then disable Connect.

Now, highlight l_fingers_ctrl.Curl and select the animation curve. Hit Ctrl + C on the keyboard to copy it. Then highlight l_index_ctrl.Curl and hit Ctrl + V to paste the animation curve on to this attribute. If you use the Curl attribute now on the l_index_ctrl, you should see that it is also creating the same motion as l_fingers_ctrl.Curl. Next, all we need to do is copy and paste the animation for the rest of the controls. It may seem like a long-winded process, but you should be able to get through it quickly once you’ve done it a few times.

By copying the animation data, we ensure that regardless of whether the animator uses l_fingers_ctrl or each individual finger, he’ll always hit the same final pose when it’s maxed out. This indicates that we’ve been successful in adding consistency to the rig.

Once complete, you should now have three levels of controls. You can use the l_fingers_ctrl to drive all the fingers at once; the individual finger controls allow you to make broad changes to each finger; lastly, the control curves around each phalange allow you to add minute changes to the fingers.

011. Connect the hand to the arm

 

With the main strokes of our hand rig in place, it’s time to attach it to the arm. Unfortunately, we can’t simply parent the l_carpals_jnt and constrain the l_carpals_ctrl to l_arm_end_jnt. Doing this would yield good results when in FK mode, but in IK mode the orientation of the hand wouldn’t stay in a locked-off position as you’d want. This would result in the animator having to counter-animate, which is never a good thing. To get this working correctly, we’ll need some locators and some constraints.

Create a locator and call it l_carpals_fk_con. With the locator selected, hit Ctrl + G and call that new group l_carpals_fk_con_offset. Take the _offset node now and duplicate it (Ctrl + D) and change the name to l_carpals_ik_con_offset. Also change the name of the locator living under that group node to l_carpals_ik_con. Select both _offset nodes and parent them under l_carpals_ctrl. Zero out the translation and rotation values so they pop into place, and then un-parent them. To make the locators more easily selectable, select them and increase the Local Scales X, Y, and Z in the Channel Box (you’ll find this setting under SHAPES).

In this order, select l_carpals_fk_con, l_carpals_ik_con, and l_carpals_ctrl_offset, and go Constrain > Parent. Then select l_arm_end__fk_jnt and l_carpals_fk_con_offset, in that order, go Constrain > Point and then Constrain > Orient.

Let’s go on to the IK side of things now. In this order, select l_arm_end_ik_jnt and l_carpals_ik_con_offset, and go Constrain > Point. The hand should now follow both the FK and the IK arm. We now want to use a Set Driven Key to control which arm chain it should follow.

Open up the SDK window by going Animate > Set Driven Key > Set, and with the fkIk_ctrl selected, hit Load Driver. Then select the parentConstraint node that lives under l_carpals_ctrl_offset and hit Load Driven. Set the L Arm attribute to 0 (FK mode) on the fkIk_ctrl, and on the parentConstraint node, set the L Carpals Fk Con W0 to 1 and the L Carpals Ik Con W1 to 0. Hit Key on the SDK window. Now set the fkIk_ctrl to 1 (IK mode), and on the parentConstraint node, set the L Carpals Fk Con W0 to 0 and the L Carpals Ik Con W1 to 1. Hit Key on the SDK window once more. The palm should now follow the arm correctly in both FK and IK modes.

012. Adding the forearm twist

 

We are now going to drive the forearm twist through the l_carpals_ctrl and by using an expression. To do this, open up the Expression Editor (Windows > Animation Editor), and type the following into the Expression box:

l_radUlnaTwist1_jnt.rotateY = l_carpals_ctrl.rotateY *.25;

l_radUlnaTwist2_jnt.rotateY = l_carpals_ctrl.rotateY *.5;

l_radUlnaTwist3_jnt.rotateY = l_carpals1_ctrl.rotateY *.75;

Rename the expression to l_radiusUlna_twist_expr. If you are going through the video, you’ll notice that I initially set this to be driven by l_carpals_jnt. I later found that this caused twisting issues and updated the script so that it was driven by the control instead.

013. Tidying up the rig so far

 

Now that the majority of the hand rig is set up, let’s round off by tidying up the rig in the Outliner. Start by selecting and deleting l_hand_geo_grp. Then select both l_carpals_fk_con_offset and l_carpals_ik_con_offset, group them together, and call that new group l_carpals_con_grp. Select l_carpals_con_grp and l_carpals_ctrl_offset, group them together and call that group l_hand_ctrl_grp. Select l_carpals_jnt, group it to itself and call that group l_hand_jnt_grp. Select l_hand_ctrl and parent it under rig_ctrl_grp. Lastly, parent l_hand_jnt_grp under rig_jnt_grp.

With the parenting madness out of the way, let’s now hide a couple of things to make them un-selectable. Select both l_carpals_fk_con and l_carpals_ik_con and hit Ctrl + H to hide them. Later on, we’ll also lock the visibility so they can’t be revealed by Display > Show All. This will help to keep the rig safe from being accidentally tampered with.

The next thing to do is to add a little color to the controls so we can differentiate between the left-hand side controls and the torso controls. And once we have the right-hand side controls, we will want to color them also. Using the Drawing Overrides in the Attribute Editor, I make the left-arm controls green, the FK torso controls orange, the IK torso controls blue, and the COG control yellow. I also like to color the right-hand controls red (right > red) so that during the animation process, it’s easy for the animator to know which side of the character they’re working with.

I then color-code the geometry to clearly differentiate between the right and left sides. I select the sliced parts of the right-arm geometry (including the clavicle and scapula pieces), then hold down the RMB and go Assign Favorite Material > Lambert. When the shader pops up in the Attribute Editor, give it a pale green colour and rename it green_lambert. For the torso, I color the geometry pale blue; the neck and head are assigned a deeper blue lambert shader. Remember to rename all the shaders as you go.

014. Mirror the joints

 

Mirroring the Joints over is a simple process. To do this, select l_shoulder_jnt and go Skeleton > Mirror Joint (Options). Set the Mirror across to YZ and the Mirror function to Behavior. In the Search for field, type l_, and in the Replace with field, type r_, and hit Mirror. In the Outliner, find the mirrored joints (it will also mirror over the FK and the IK arm chains) and delete all the constraint nodes it will have duplicated. The geometry for the arm will have also been duplicated and may be randomly placed in your scene, so delete that too. Repeat the step for the joints of the hand.

Now select the geometry of the left arm, duplicate it by hitting Ctrl + D, and then un-parent it from the hierarchy using Shift + P. Rename the slices by going Modify > Search and Replace Names. Search for l_ and replace with r_ and hit Replace. Then get rid of the number 1 that exists on any of the ends of the geometry slices.

With all slices selected, hit Ctrl + G to group them together and then pop a -1 into the Scale X attribute of that group. This will flip the geometry over into the correct position. Select all the geometry for the right arm and hit Shift + P to bring them out of the group, then go Modify > Freeze Transformations to invert the normal, and set the Scale X back to 1.

The controls on the other hand are not something you can simply mirror over cleanly in Maya (without the aid of some scripts). For that reason, I tend to rebuild the controls of the right-hand side manually. However, I do copy and mirror the existing controls, drop them into a layer, and then set that layer mode to Reference. This gives me a guide for where to create the new controls..

I’ll leave you to rebuild the right arm, and next we will tackle the legs.

Tip 001. Update SDKs in the Graph Editor

We’ve been creating Set Driven Keys quite a bit now, and using the SDK UI can be a little confusing when you want to make changes to existing Keys. If I need to do this, however, I find it a lot easier to handle in the Graph Editor. Here you’re able to edit everything: from the values that drive the attribute, to how you transition from one position to another.

Tip 002. Use Quick Select Sets

When making large selections, knowing that you’ll need to go back and re-select the same objects, I tend to use Quick Select Sets (QSS). The QSS will then be available in the Outliner and/or on your Shelf, allowing you to re-select a set of objects. This can be particularly useful when doing things like setting up the SDKs for the fingers, as you’ll have a tendency to want to re-select the same controls. You can create QSS by having a selection of objects selected and then going Create > Sets > Quick Select Set.

 

Leave a Comment