Advanced Animation Controls
In this section, you add some more complicated controls to your character rig. This process involves using math functions to create automatic torso motions, setting driven keys to create a rolling foot control, creating an advanced backbone with spline IK and clusters, and creating color indicators that warn when a control has been moved too far. Although these controls require more time to set up, they make it easier and faster for you to animate your character.
Some of the expressions used in this section use expression functions. An expression function is a predefined command that can be used in an expression instead of explicitly writing the complicated math associated with the command. Some common expression functions used in Maya are abs, trunc, cos, rand, and time. You can view a list of functions in the Expression Editor under the Insert Functions menu (see Figure 3.55). To view a complete list with detailed explanations of each function, look in the Expressions section in the online documentation of the Help menu.
Figure 3.55 You can find a list of the advanced expression functions on the menu bar in the Expression Editor.
Constraining the Torso to the Feet
One thing that can be useful for easily moving your character around in a scene is to connect the torso to the feet with an average expression. This always keeps the UpperBody icon between the two leg boxes whenever they move in X and Z. In addition, you create an expression to make the torso automatically dip in Y each time a foot takes a step. The amount of the dip is based on the size of the step (see Figure 3.56).
Figure 3.56 Add expressions to make your character's torso automatically move when each foot takes a step.
Keep in mind that although these expressions make certain actions easier to animate, they may not be appropriate for all scenes. Sometimes you will want to disable these expressions and animate these motions manually. This is especially true if your character is going to rotate extensively from the Rig node, such as to perform a 360-degree flip. This is because the Rig and Feet nodes, which are parents of the nodes involved in the expressions, cannot be affected by the upper body and leg boxes. The reason for this is that having a child node affect a parent node causes a cycle, which generates an error message from Maya. Because this is undesirable, using the expressions causes the Rig and Feet nodes to get left behind as soon as you begin moving your character around using the average expressions. In turn, this causes the pivot points to be off for any kind of body rotation using these nodes.
Exercise 3.12: Creating Torso Averages and Dip
The first step in constraining the torso to automatically move when the legs move is to create a couple of group nodes that are sitting directly on top of, and are the parents of, the UpperBody icon. If you constrain the channels of the UpperBody icon directly with these expressions, you will no longer be able to manually animate the upper body of your character. Instead, you constrain the channels on some parent group nodes that propagate the movement to the upper body through the parent child relationship. You can then manually add keyframes to the UpperBody icon in addition to the automatic movements. The term often used for keeping the channels of a child node open for setting manual keyframes is a freedom node.
After you have some channels to constrain on the UpBodAuto nodes, you can begin writing the expressions for averaging the torso between the leg box positions. One important thing to check before writing the expressions is that the Feet node is directly between the leg boxes. Keep in mind that the information in the channels of the leg boxes is based on the parent node's position. You want, therefore, to make sure that the Feet node is directly between the leg boxes in X, and lined up with the center of the boxes in Z. In addition, before writing the expressions, check the channels of the objects involved for any irregularities in the rotation or scaling channels. They should not, for instance, have Scaling values other than 1, or Rotation values other than 0. The first expression you write should constrain the X translation of the UpBodAuto1 node with an average. Adding a number of values, and dividing the result by the same number of values, creates an average. Use the following syntax:
One thing you may notice when you test your average constraints is the leg boxes tend to pull the feet out of their sockets when a foot steps. The reason this happens is because the torso doesn't dip when your character steps in X or Z. In a real body, when you take a step, your torso dips. The bigger you step, the more your torso dips. If your torso didn't dip, your feet would come out of your sockets too!
In the hypergraph view, select the UpperBody icon, and press Ctrl+G twice. Name the top group node UpBodAuto1, and the lower group node UpBodAuto2 (see Figure 3.57). If your UpperBody icon was originally placed right on top of the Rig node, your two group nodes should be sitting right on top of the UpperBody icon. If not, go into insert mode and move accordingly. Because you are going to write expressions, you want the channels of your group nodes to have 0 values in translation and rotation, and 1 in scaling. If they are sitting right on top of the Rig and UpperBody nodes, this should be the case. Keep in mind that in versions of Maya before 4.5, you should not freeze the transforms of nodes that are parented in your skeleton hierarchy. Doing so changes the orientations of your skeleton centers and dislocates any IK handles that are child to these nodes. This problem seems to be fixed in the latest version of Maya, however.
Figure 3.57 Making two group nodes as parents of the UpperBody icon creates extra channels that can be constrained in your expressions.
(A + B) / 2
Replace the letters A and B in the preceding expression with each leg box's X translation to average the X translation of the UpBodAuto1 node. Do this on your rig by opening the Expression Editor, and type the following expression:
UpBodAuto1.tx = (LtLeg.tx + RtLeg.tx) / 2;
Name the expression Averages, and click Create. Test the control by translating one of the leg boxes in X. Your character's torso should remain directly in between both leg boxes. To constrain the Z translation in the same way, edit the expression by copying the first expression, and paste it on the next line, changing each X-axis to Z. The second line in your expression should look like this:
UpBodAuto1.tz = (LtLeg.tz + RtLeg.tz) / 2;
One other average constraint that you may want to use on your character is placed on the Y rotation channel. It is written like this:
UpBodAuto1.ry = (LtLeg.ry + RtLeg.ry) / 2;
So to make your character's torso automatically dip when your character takes a step, you can just create another expression. In the Expression Editor, click the New Expression button, and type in the following:
UpBodAuto1.ty = 0 ((abs(LtLeg.tx - RtLeg.tx) + abs(LtLeg.tz - RtLeg.tz)) / 6);
This expression finds how far the distance is between the feet by subtracting one foot from the other in X and Z. The absolute function removes negative signs from the expression, because there is no such thing as a negative distance. Dividing is needed because you don't want your character to dip as far as it steps. Name the expression Dip, click the Create button, and move your leg boxes to test the dip.
You probably need to divide the effect by more than 6 to produce less of a dip. In addition, your character has probably moved out of its default position in Y (see Figure 3.58). This is because the expression is activated when the feet move apart, and the feet are already apart in their default pose. You can type in a number greater than 0 as the start number to adjust the character back up in Y. Another way you can make adjustments to your character's default position is by just translating your freedom nodes. The only channel that will be constrained on UpBodAuto2 is the X translation channel. So you can make any needed adjustments to the Z or Y translation of your character on this node. Also notice that although the expressions force the torso to move with the feet automatically, you can animate the UpperBody icon to compensate or add to the movement as needed. This enables you to animate basic movement of your character quickly, while adding subtle variations to the movement by manually animating the freedom node.
Figure 3.58 Check to see whether the expressions constraining the torso caused your character to move out of its default position.
Writing Conditional Expressions
Another kind of advanced expression is a conditional expression, which uses the if and else commands. These commands enable you to set up a condition of some kind, and do one of two expressions depending on whether the condition evaluates as true or false. This is a good way, therefore, to have your character controls switch between two opposing actions. The automatic controls you create with conditional expressions on your character simulate the torso shifting weight when a foot is raised, and cause the hips to rotate in Y when a foot steps forward and backward. The general syntax for a conditional expression in Maya is as follows:
if (condition) Expression evaluated if the condition is true; else Expression evaluated if the condition is false;
The condition used can be any mathematical statement that evaluates as true or false; for the examples in this book, however, you use greater than (>) or less than (<) statements. If the condition evaluates as true, the If expression runs. If it evaluates as false, on the other hand, the Else expression runs. Keep in mind that you can use the If command without the Else command, but the Else command always requires the If command be used before it. If you don't use an Else command, the expression does nothing if the condition evaluates as false.
Exercise 3.13: Using Conditional Expressions on Your Rig
To make the torso automatically shift from side to side when a foot is raised, the translation in X of the UpBodAuto2 node must be constrained with a conditional expression. You must place this expression on the UpBodAuto2 node because the X translation channel on the UpBodAuto1 node is already being used by the average expression. This expression also uses the absolute function, because it involves calculating the distance each foot is raised to set the shifting amount. This amount is then divided at the end of the expression to make the movement subtler. In the Expression Editor, create the conditional expression in the following way:
A similar conditional expression can be done to make the Hips box rotate in Y when a foot steps in Z. To do this, and still be able to manually animate the Hips box, you must make a group node parent to the Hips box. Do this by selecting the Hips box, press Ctrl+G, and name the new node HipsAuto. In insert mode, move the pivot of HipsAuto to sit on top of the Hips center. It doesn't matter whether the HipsAuto node has any numbers in its translation channels, but make sure the number in the rotation channels is 0. When finished, copy the previous conditional expression, and paste a second conditional expression in the same window. Then change the second expression to look like the following:
if (LtLeg.ty > RtLeg.ty) UpBodAuto2.tx = 0 (abs (LtLeg.ty - RtLeg.ty) / 2); else UpBodAuto2.tx = 0 + (abs (LtLeg.ty - RtLeg.ty) / 2);
It's okay to separate the expressions onto different lines by pressing the regular Enter key, if this makes them easier to read. Maya still sees only one expression command until it reaches a semicolon. The above expression can be read, "If the left leg rises above the right leg, shift the torso to one side; otherwise, shift it to the other side." Name the expression Conditionals, and click Create. If you then raise one of the leg boxes, you should see the torso translate over the opposite leg as if its weight shifted to keep the character balanced (see Figure 3.59). Notice that the only difference between the If and Else expression is the plus and minus signs. If you find your character shifting in the wrong direction, reverse the signs.
Figure 3.59 Use a conditional expression to make your character shift its torso over the opposite foot when a leg is raised.
if (LtLeg.tz > RtLeg.tz) HipsAuto.ry = 0 (abs (LtLeg.tz - RtLeg.tz) * 3); else HipsAuto.ry = 0 + (abs (LtLeg.tz - RtLeg.tz) * 3);
When finished, click Edit to update the Conditionals expression. If you then move a leg box in Z, you should see the hips rotating in the same direction. Adjust the plus and minus signs if necessary to get the correct rotation. The reason the division should be changed to multiplication in the second expression is because the translation of the legs is affecting the rotation of the hips. For instance, 5 units of translation on the leg boxes makes the hips rotate only 5 degrees, which is not very noticeable. Multiplying the expression makes the hips rotate a noticeable amount.
Other Advanced Math Functions
A couple of other interesting expressions you can use on your character involve creating a breathing control, an eye-jitter control, and a tail-whip control. The breathing expression involves using a cosine function and a time function that references the timeline. The eye-jitter control involves using a randomize function and custom channels. Finally, the whipping tail expression also involves referencing the timeline, and introduces the use of MEL commands in an expression to create a delay effect.
Exercise 3.14: Using Functions to Create Additional Controls
To create some breathing controls, in the top view draw a two-joint FK skeleton in the left chest area of your character. The skeleton should start inside the chest and end at the surface of the chest (see Figure 3.60). Translate and rotate the root joint as needed to place the skeleton correctly in the chest area. Name the joints LtBreathRoot and LtBreathEnd. Mirror the skeleton to the right side, and name the right skeleton appropriately. Select both root joints and group twice, naming the group nodes BreathPad1 and BreathPad2. For now, make BreathPad1 child to Back3, so the breath joints move with your character's backbone. You use an expression to control the X scaling of the skeletons. This causes the front of the chest to move forward and backward.
To create an eye-jitter control, you must first parent two group nodes in between the EyesLook circle and the locators constraining each eye. Select the LtEyeLook locator, and press Ctrl+G twice. Name the top group node EyeJitterPad, and bottom group node EyeJitter. Then make the RtEyeLook locator child to EyeJitter. The translation channels on the EyeJitter node should all be at 0, and they should be sitting directly on top of the center of the EyeControl circle. Freeze the nodes if necessary to set the translation channels to 0.
The next expression creates a delay on the rotations of the joints in a tail to create a whipping effect (see Figure 3.61). Because Maya doesn't have a delay function, you have to use some MEL scripting to make the expression work.
Name the expression TailWhip, and click Create. This expression uses MEL scripting to create a delay effect on the tail joints. Because this expression references the timeline, it is necessary to set keyframes on the Y rotation channel of the Hips box to see the whipping effect. Rotate the Hips box in Y, and right-click the Y channel in the channels box to set keys at several frames. If you then scrub or play the timeline, you should see a whipping effect on the tail.
Figure 3.60 Draw two skeletons in the chest area of your character to use as breathing controls.
On the UpperBody icon, create two custom channels named breathSpeed and breathSize. Set the minimum and maximum limits of both channels to .1 and 10, with a default of 1. In the previous expressions shown in this chapter, you divided and multiplied your expressions by specific numeric values to control the amount of movement produced. Doing this sets a static amount of control that cannot change during your animation. In this expression, you divide by a channel that can be animated to change over time. This enables you to vary the movement produced by the expression over the course of your animation. Type the following lines in the Expression Editor to create the breathing effect:
LtBreathRoot.sx = 1 + (cos (time / UpperBody.breathSpeed) / UpperBody.breathSize); RtBreathRoot.sx = 1 + (cos (time / UpperBody.breathSpeed) / UpperBody.breathSize);
Name the expression Breathing, and click Create. This expression uses the cosine function in conjunction with the time function. A cosine function creates a wave, which is useful for making the X scaling of the breath joints go up and down. Using the time function makes the scaling happen automatically whenever the timeline is played. Scrub or play the timeline to see the breath joints scaling continuously. Change the breath speed and size channels to change the rate and scale of the breathing. Try setting the UpperBody.breathSpeed channel to .5, for instance, and the UpperBody.breathSize channel to 8.
You may want to create an additional breath skeleton in the stomach cavity, to simulate deep breathing. This skeleton should be drawn from the middle of the abdomen to the belly button, and named LowBreathRoot. Use the same kind of expression as used on the chest skeletons to create the breathing effect. Bear in mind that these skeletons will later be bound to the skin of the torso to make it deform in a subtle manner as the joints scale continuously in X.
After you have created the two new nodes, make three custom channels that will control the jitter. On the EyeJitter node, create a jitterMin and jitterMax channel. The jitterMin channel should go from 10 to 0, with a default setting of 0. The jitterMax channel should go from 0 to 10, with a default setting of 0. Then on the EyesLook icon, create a jitterControl channel that goes from 0 to 10, with a default setting of 0. After you have made all the channels, type the following expression into the Expression Editor:
EyeJitter.jitterMax = 0 + EyesLook.jitterControl; EyeJitter.jitterMin = 0 - EyesLook.jitterControl; EyeJitter.tx = 0 + rand (EyeJitter.jitterMin,EyeJitter.jitterMax) / 8; EyeJitter.ty = 0 + rand (EyeJitter.jitterMin,EyeJitter.jitterMax) / 8;
Name the expression JitteryEyes, and click the Create button. The way this expression works is that the jitterControl channel controls both the jitterMin and jitterMax channels. When the jitterControl channel is set to 5, for instance, the jitterMin channel is set to 5, and the jitterMax channel is set to 5. These two channels are then used to define the minimum and maximum amounts that the randomize function requires, which is then used to control the translation channels of the EyeJitter node. Try increasing the jitterControl channel and notice that the eyes start to shake. The shaking continues as long as the timeline is played.
Draw an FK skeleton for a tail in the top view, starting in the middle of the hips and going straight back behind your character. For this example, the tail has five joints. Name the joints TailRoot, Tail2, Tail3, Tail4, and TailEnd. Point-constrain the root joint of the tail skeleton to the Hips box. When the tail skeleton is placed so that it starts in the Hips box and goes straight back behind the character, type the following lines in the Expression Editor:
int $time = 'currentTime -query'; int $delay10 = 'getAttr -time ($time - 10) Hips.ry'; int $delay20 = 'getAttr -time ($time - 20) Hips.ry'; int $delay30 = 'getAttr -time ($time - 30) Hips.ry'; int $delay40 = 'getAttr -time ($time - 40) Hips.ry'; TailRoot.rotateZ = 0 + Hips.rotateY; Tail2.rotateZ = 0 + $delay10; Tail3.rotateZ = 0 + $delay20; Tail4.rotateZ = 0 + $delay30; TailEnd.rotateZ = 0 + $delay40;
Figure 3.61 Use an expression that creates a delay on the rotation of joints to make a whipping effect on a tail.
This expression uses two MEL commands: The currentTime command finds out what frame the timeline is on; the getAttr command enables you to get the value for the hips' rotation in Y at a particular frame. Both of the results for these commands are being placed in the variables $time, $delay10, $delay20, and so on. These variables are then used in the expressions to constrain each tail joint to rotate with an increasing delay. This creates the whipping effect on the tail. Don't worry if you don't entirely understand the MEL scripting used in this expression. You learn more detail about creating variables and using MEL commands in Chapter 6, "Scripting MEL Character Controls."
Creating a Rolling Foot
Next you create a more complicated foot hierarchy and set driven keys to drive a rolling foot control. The new foot setup involves creating group nodes that are used as pivot points for your current foot skeletons. A custom roll channel is created on each leg box to drive the pivot points so that each foot can roll forward and backward. When a foot rolls backward, it should pivot back on the heel. When it rolls forward, it should pivot up on the ball of the foot and then up onto the toe.
Exercise 3.15: Adding Foot Controls
Open a hypergraph view, and zoom in on the feet section of your character rig hierarchy. Hide the visibility of the RtLeg box, so the right foot isn't in the way when you are working on the left foot. Disconnect the left-leg IK handle and polygon reference bones from your hierarchy by selecting them and pressing Shift+P. Be careful not to disconnect or change the parenting on the LtLeg box, or your torso may be affected through the expression connections. Then make sure your left-foot root joint is child to the ankle box. To create the new pivot points, select the foot root joint, and group three times. In the hypergraph, this creates three group nodes in the hierarchy that are between the left-leg box and the left-foot root joint.
To create a single control that drives all three of the foot pivots, create a custom channel on the left-leg box named roll. (Channel names are normally not capitalized.) Make the minimum and maximum limits on the channel go from 5 to 10, with a default setting of 0. Then load the LtLeg box into the Set Driven Key options box, and choose the roll channel as the driver. Load the X rotation of the LtHeel node as the driven channel. Set a driven key with the roll channel at 0, and the heel node in its default position. Then change the roll channel to 5, rotate the heel node backward about 25 degrees in X, and set another key. This should create the backward rotation on the heel part of the foot roll.
When all the driven keys are set, test the roll channel. You should see your character's foot rolling backward when the roll channel goes in a negative direction and roll forward when the roll channel goes in a positive direction. One thing you should add to this setup is a node for manually animating the toes' rotation. Do this by selecting the toe IK, and press Ctrl+G. Name the group node LtToeRot, and move its pivot point to the ball of the foot. Then create a custom toeRotate channel on the left-leg box, and connect it with driven keys to the X rotation of the LtToeRot node. Keep in mind that you can still manually rotate your whole foot by just rotating the leg box.
Name the three new group nodes from top to bottom as LtHeel, LtToe, and LtFoot. Press the Insert key, and move each group node's pivot to the appropriate place on the foot. The heel pivot should be where the heel touches the ground, the toe pivot should be where the toe touches the ground, and the foot pivot should be at the ball of the foot (see Figure 3.62). Then constrain the foot joints with IK twice. Using the IK handle tool, create IK from LtFootRoot to LtFootBall, and then create another IK from LtFootBall to LtFootEnd. Name the two new IK handles LtFootIK and LtToeIK. If your joints moved a little when you added the IK handles, translate the handles to put them back in place.
Figure 3.62 Create three new group nodes for each foot to use as the pivot points in a foot roll.
To finish the left-foot setup, parent the IK handles. Make the LtLegIK handle child to LtFoot, and make both the LtFootIK and LtToeIK child to LtToe. Then reparent the polygon foot bones under the foot root joint, and the polygon toe bones under the LtFootBall joint (see Figure 3.63). When everything is parented, test the three new pivot points by rotating them in X.
Figure 3.63 Make all the foot skeletons and IK handles child to the new group nodes.
Set the roll channel to 0 again, and load in the X rotation of the LtFoot node as the driven channel. Key them both in their default positions. Then change the roll channel to 5, rotate the LtFoot node forward in X about 30 degrees, and set a driven key. This should make the foot roll up on the ball of the foot (see Figure 3.64). Finally, set the roll channel to 5, load in the X translation of the LtToe node, and set a driven key for its default position. It is important to do this at 5 on the roll channel, so the foot doesn't start at 0 to roll forward onto the toe. Then change the roll channel to 10, and rotate the toe node forward about 30 degrees in X, and set another key. Also at 10, load the LtFoot node in again, and rotate it backward about 20 degrees, and set a final key. This causes the foot to uncompress at the ball of the foot when it rolls up on the toe.
Figure 3.64 Set driven keys on the group nodes to make the foot roll from the heel up onto the ball of the foot, and then onto the toe.
Building a Flexible Backbone
Although the current FK backbone skeleton in your rig can bend in all directions, it has some limitations. It lacks fine controls for posing the backbone in more arched positions. It is also not easy to shift areas of the backfor instance, to stick your chest outwithout causing problems to the joint centers. To upgrade your character's backbone controls to be more flexible, you create a new backbone skeleton that contains spline IK. This new backbone structure is added to your original backbone skeleton, so that you have two levels of backbone controls. In addition to this, you create a stretching quality to the backbone that can be used for both subtle or cartoon effects.
Exercise 3.16: Creating a Spline IK-Based Backbone
Begin by creating two new box icons named MidBack and UpperBack. Move and scale the MidBack box so it is right above the Hips box and covers the abdomen area of your character. Move and scale the UpperBack box so that it surrounds the upper chest and shoulders area of your character (see Figure 3.65). You can also go into component mode and scale vertices to create a better shape. When in place, freeze the transforms on both boxes.
To create a more flexible backbone, you must draw a new backbone skeleton, with joints that follow the curve of the back. This doesn't mean, however, that you have to create as many joints as exist in a real backbone. You can create half the number of joints in a real backbone and still get enough flexibility. The fewer joints you have, the easier it is for you to add controls for each joint. Before drawing any joints, however, hide the BackPad1 node and the thorax polygon bone. This should give you a clear view of your polygon backbones in the side view. Also, make sure that IK is turned off in the Joint Tool options box before drawing joints.
Spline IK uses the shape of a curve to control the orientation of joints in a skeleton. Assign the spline IK to your character's new backbone by choosing Skeleton, IK Spline Handle Tool q. Set the spline IK options to the following:
To make controlling the points on the backbone curve easier, create cluster handles for each point. Select the lowest point on the curve, and choose Deform, Create Cluster q. Make sure the options are at their default settings, with Relative turned off, and click Create (see Figure 3.67). Repeat the process for each point, and then name the clusters from lowest to highest Bc1 through Bc4.
Repeat the same process for the hips of your character. Starting around the L1 vertebrae, in the side view draw a four-joint skeleton to the bottom of the pelvis. Because there are not many hipbones, you can draw a joint for each bone. When drawing, make sure you do not connect your hips skeleton to your backbone skeleton. To ensure this doesn't happen, click out to the side of the character, and drag the root joint of the hips over the backbone root joint. Name the hips joints from top to bottom H1 through H4. Once created, assign spline IK from the root to the end of the hips skeleton. Use the same settings as used previously. This action results in a curve with four points, and an IK handle, which you should name HipsCurve and HipsIK respectively. Create four cluster handles on the hips curve, and name them from top to bottom Hc1 through Hc4. Parent the polygon lower vertebrae and pelvis bone to the appropriate Maya joints.
Yet again, repeat the same process for the neck. Start your new neck skeleton where the backbone skeleton ends, but don't attach it. Create joints for each neck vertebrae, from around C7 to C1. Name the joints N1 through N7. Then assign spline IK to the neck skeleton from the root joint to the end joint, with the same settings as used previously. Name the new curve and IK handle NeckCurve and NeckIK. Finally, create clusters on the points of the neck curve from bottom to top, and name them Nc1 through Nc4.
To integrate the new backbone into your current rig hierarchy, you must make the clusters children of the control boxes, and the control boxes children of the original backbones. Do this by making Bc1 and Bc2 child to the MidBack box, and make Bc3 and Bc4 child to the UpperBack box. Create two group node parents for each back box, naming the group nodes from top to bottom MidBackPad1, MidBackPad2, UpBackPad1, and UpBackPad2. This keeps the rotation channels on the boxes at 0 when you parent them to the original backbone joints. Then make Back2 the parent of MidBackPad1, and Back3 the parent of UpBackPad1 (see Figure 3.68).
After you parent all the boxes and clusters, you should have three levels of controls for your character's back and neck, and two levels of controls for your character's hips. The first level of controls on the back and neck are the original FK skeletons. On the backbone, for instance, rotating the BackBend circle creates a basic side-to-side bend on the backbone. The next level of controls, namely the boxes, enables you to adjust the bend on three main sections of the backbone (see Figure 3.70). The finest level of controls is reached by translating individual clusters. You can animate the clusters manually, or set driven keys to control them with custom or transform channels on the boxes. This level of detail may not always be necessary, but is available when needed. On the hips, you do not have the FK level of control, but instead just the box and cluster levels.
When testing your back controls, you may have noticed a problem. The controls that bend the character to the side, forward, and backward should all work fine, but the controls that twist the back in Y are no longer working right (see Figure 3.71). The character doesn't actually twist, but just wobbles slightly. The reason this is the case is that the spline IK is constraining the twist of the backbone, neck, and hip skeletons. After you put spline IK on a skeleton, you must control the twisting of the skeleton through the twist channel on the spline IK handle.
One other channel on the spline IK that you must set controls for is the roll channel. If you try rotating the UpperBody node in Y, you will see a problem similar to the previous twisting problem. The difference between the twist and roll channels is the twist channel has a falloff when rotating the joints, whereas the roll channel rotates all the joints evenly. To fix this, set driven keys on the roll channels of the spline IK for the back, hips, and neck.
Your character's backbone should be working correctly at this point. There are still, however, several stray nodes that are not parented into your rig hierarchy. Select the root joints for the new backbone, neck, and hips, and press Ctrl+G. Name the parent group node NewUpBody. Also select all the spline IK curves and IK handles, create a group node parent named SplineIK, and make it child to the NewUpBody node. Finally, create a group node parent of the Rig node named DoNotMove, and make NewUpBody and SplineIK child to it (see Figure 3.72). The spline IK curves and handles should never be transformed or animated. Because they are being controlled by constraints, if you move them directly they force a double transform on the skeletons. Because this will cause the pieces of your rig to separate, avoid it! There are times, however, when you will need to parent spline IK-controlled skeletons under a control object. This sometimes is required when using spline IK on appendages like ears or a tail. If your character has spline IK on some large rabbit ears, for example, you might see the skeletons twist when the Head box is rotated. This occurs independently of the roll and twist values in the spline IK handle. Parenting the spline IK constrained skeletons under the Head box will fix this problem.
To make the backbone be able to stretch, you must get information on the length of the back curve. Do this by selecting the back curve, and type in the following MEL command on the command line or in the Script Editor:
Figure 3.65 Place a couple of new curve boxes to control the middle and upper areas of the new backbone skeletons.
Draw the new backbone skeleton starting where the waist bends up to where the neck starts to bend. On real skeleton vertebrae, this is from between L2 and L3 to between T1 and C7. Use your polygon reference bones as a guide, drawing straight up the middle of the bones, placing each joint between every second vertebrae. In addition, do not draw a joint for every backbone, but instead draw one for every other backbone. This should create about eight backbone joints. When finished, name the joints B1 through B8.
It is important for all the joint centers to be oriented correctly on your backbone skeleton. Show the centers on your joints, and check to see whether any are flipped 180 degrees in X (see Figure 3.66). This happens when you change directions when drawing a skeleton. If this is the case, use the same method described earlier in this chapter to rotate the joints to the correct orientation. This involves using the question mark (?) symbol in component mode to select the center and clicking the shelf button you created for rotating the center 180 degrees in X (the shelf button should execute the MEL code rotate r os 180 0 0.)
Figure 3.66 Check to see whether any of the centers on your new backbone joints are flipped around 180 degrees in X.
When your joint centers are all oriented in the same way, finish your new backbone skeleton by parenting all the appropriate polygon vertebrae to the new Maya joints. Each backbone joint should be parent to two polygon vertebrae. The polygon thorax bone should be made child to B5 or B6. You can adjust this later.
Root on Curve: On
Number of Spans: 1
Auto Parent Curve: Off
Root Twist Mode: Off
Auto Create Curve: On
Twist Type: Linear
Auto Simplify Curve: On
Using these options creates a simple curve that follows the shape of the backbone skeleton. It also creates an IK handle that contains a twist channel used to rotate the joints in X with a linear falloff, so the top twists more than the bottom. Close the options box, and click your backbone skeleton's root joint, and then click its end joint. In the hypergraph view, notice that a new curve and IK handle are created. Spline IK differs from regular IK in that you do not animate the transforms of the IK handle. Instead, select the new curve and switch to component mode. The curve should have four points, and moving the points causes the backbone skeleton to flex. Name the new curve and IK handle BackCurve and BackIK.
Figure 3.67 Create cluster handles on each point in your backbone curve.
Figure 3.68 Parent the MidBack and UpperBack boxes under the original backbone joints.
To make sure everything on the limbs and head moves with the new backbone, make BackPad1 child to the last joint in your new backbone. Depending on how many new backbone joints you made, this will probably be B8. If there are any other children of the original backbones, such as the breathing skeletons, be sure to parent them under the appropriate new backbone joints. In addition, parent the neck clusters under the Head and UpperBack boxes. Make Nc1 and Nc2 child of the UpperBack box, and make Nc3 and Nc4 child of the Head box. Rotating the original neck joint moves the Head box, whereas rotating the box flexes the neck as the head and jaw rotate.
After parenting the neck clusters, make the hip clusters child to the MidBack box and Hips box. Hc1 should be child to the MidBack box, and Hc2, Hc3, and Hc4 should be child to the Hips box. Also make LtLegRoot, RtLegRoot, LtHipRoot, and RtHipRoot child to H3 so that they will move with the new hip joints. When finished, check the parenting of the new backbone controls (see Figure 3.69).
Figure 3.69 Check the hierarchy of your new backbone controls to make sure all the boxes and clusters are parented.
Before testing your new backbone, make sure the pivot points of the boxes are in the correct places. The pivot point for the UpperBack box should sit on the top back curve cluster handle named Bc4. The MidBack box pivot should be in the middle of the stomach, and the Hips box pivot should be directly on top of Bc1 and Hc1. Move the pivot points in insert mode as needed.
Figure 3.70 Rotate your circle controls to create a basic bend in the backbone, and then adjust the boxes to create more specific poses, such as an arched back.
Figure 3.71 When using spline IK, your character will no longer twist in Y by just rotating the controls, as seen here. Instead, you must use a separate twist channel.
You can use an expression or set driven keys to control the twist channel on the spline IK handles. To make the rotation in Y of the UpperBack box control the BackIK.twist channel with an expression, for example, type the following line in the Expression Editor:
BackIK.twist = 0 + UpperBack.ry;
Name the expression Twists, and click Create. After creating the expression, try rotating the UpperBack box in Y. If the back is rotating in the wrong direction, change the plus sign to a minus sign. Although you could have made the green BackTwist circle constrain the twist channel, it makes more sense to do it on the level of the boxes that affect the spline IK. Because the BackTwist circle is no longer needed, just delete it. In addition, the Y rotation of the Hips box should control the HipsIK.twist channel, and the Y rotation of the Head box should control the NeckIK.twist channel. These expressions will look something like this:
HipsIK.twist = 0 - Hips.ry; NeckIK.twist = 0 + Head.ry;
The reason you should use driven keys is because you may want to create more than one driver. Load the Y rotation channel of the UpperBody icon as the driver, and use the Shift key to load all the spline IK handles as driven. Again, use the Shift key to select all the spline IK handles in the Set Driven Key options box, and choose the roll channel as the driven channel. Rotate the UpperBody icon in Y, adjust the roll channels as needed to make the skeletons line up with the boxes, and set driven keys. If you are using the Y rotation average expression on the UpBodAuto1 node, load that node as a second driver, and set driven keys in a similar manner.
Figure 3.72 Finish your rig hierarchy by parenting all stray nodes. Make sure you parent the spline IK nodes and curves under a node that will never be animated.
arclen ch 1;
Press the Enter key on the numeric keyboard to run the MEL code. Then, with the back curve still selected, graph the node in the hypergraph by clicking the icon for Input and Output Connections. You should see a node called curveInfo1. Right-click this node to open the Attribute Editor, and make a note of the value in the arcLength attribute (see Figure 3.73). This number is the default length of the back curve and is based on the size of your character.
Figure 3.73 Make a note of the arcLength value of the curveInfo1 node in the Attribute Editor.
To make the backbone stretch, you will use expressions to make the joints translate in their local X-axis according to the length of the back curve. Translating all the joints except the root joint according to their local X-axis causes the skeleton to get larger or smaller. In the following expressions, you divide the current curveInfo1.arcLength channel value by the original length, as noted previously in the Attribute Editor. When the expression is evaluated, if the lengths are the same, the result is 1, which causes no stretching. If the curve is longer or shorter, however, a result other than 1 is generated to make the backbone stretch. In the expression, the results generated by the curve length are multiplied by each joint's start value. It is important that this number reflect the default X Translation value of each joint. You must, therefore, select each joint to find out which numbers to use in your expression. Based on your character's backbone, your expressions should look something like this:
B2.tx = .954 * (curveInfo1.arcLength / 7.714); B3.tx = .923 * (curveInfo1.arcLength / 7.714); B4.tx = .9 * (curveInfo1.arcLength / 7.714); B5.tx = .87 * (curveInfo1.arcLength / 7.714); B6.tx = .854 * (curveInfo1.arcLength / 7.714); B7.tx = .8 * (curveInfo1.arcLength / 7.714); B8.tx = .792 * (curveInfo1.arcLength / 7.714);
Name this expression Backstretch and click Create. Because this is meant to have the effect of stretching the backbone joints, it is not necessary to write a line for the root joint. Make sure you use the default X Translation value for each joint as its start number. Look in the channels to get the correct value. After creating the expression, try translating the UpperBack box in Y to see the stretch effect on the backbone skeleton (see Figure 3.74).
Figure 3.74 Create an expression that makes the backbone stretch when the backbone boxes are moved.
Creating Warning Signs
Many controls in your character rig have defined limits. These have been done through setting actual transform limits in the Attribute Editor, or by how you set the minimum and maximum settings on the custom channels of your control icons. Sometimes, however, it is better not to limit the controls, but instead make some kind of warning that tells animators that they have moved a control past its normal settings. Then the animator has the choice of how far to manipulate a control. Occasionally, the animator may want to go beyond the normal limits of a control to create dramatic effects. Such a warning can be done in a variety of ways, from making some text or symbol appear, to making your polygon reference bones change color. In the next exercise, you place some of these warning signs on your character when the backbone is stretched too far, or when an arm or leg is hyperextended.
Exercise 3.17: Making Text and Color Warnings
A warning can be any kind of indication to the animator that a control has been moved too far. For instance, you could create a text message that is revealed whenever the backbone is stretched or compressed too far. Choose Create, Text q to create something to use as a warning message, such as "Whoa buddy, you're going a bit too far!" Make sure you use curves, and scale or translate the text as needed. Place it beside your character where it will be easy to see. In the hypergraph, name the top group node for the text WarningText1. Make the WarningText1 node child to the UpperBack box. The following expression sets the visibility of the warning text based on the length of the back curve. The expression contains an Or symbol, known as a double pipe (||), which can be found on the Backslash key. Your expression will look similar to the following:
Another warning you can create is for when an arm or leg box is translated too far. To do this effectively, you need to calculate the distance between the shoulder and the hand. Keep in mind that the shoulder is the main pivot for the arm, while the hand moves around it in an arc. You want to have Maya calculate when the hand reaches the limit of that arc. To do this, you use the Distance tool by choosing Create, Measure Tools, Distance Tool. Then in the front view, click once above your character's left shoulder, and once above your character's left-arm box. This creates two locators that have a distance connection. Name the shoulder locator Loc1, and the wrist locator Loc2.
if (curveInfo1.arcLength > 8 || curveInfo1.arcLength < 7) WarningText1.visibility = 1; else WarningText1.visibility = 0;
Name the expression Warnings, and click Create. The expression reads: "If the back curve gets stretched beyond 8 or gets compressed smaller than 7, reveal the warning text by setting its visibility to 1. Otherwise, hide the warning text by setting its visibility to 0." The values used in the expression should be based on the length of your character's back curve, and may differ from the example. When finished, test the warning by translating the UpperBack box in Y (see Figure 3.75). You should see the text warning appear whenever the back is stretched beyond the lengths specified.
Figure 3.75 Create a control that shows a text warning whenever the backbone is stretched too far.
You can use the same kind of expression to make your polygon reference bones change color when the back curve is stretched too far. Just constrain the incandescence channels on the Bonecolor material node rather than the text visibility. Open a hypershade view to select the Bonecolor material, and notice three incandescence channels are not being used. To have your bones turn red when the back is stretched, create a similar expression to the following:
if (curveInfo1.arcLength > 8 || curveInfo1.arcLength < 7) Bonecolor.incandescenceR = 1; else Bonecolor.incandescenceR = 0;
To calculate the distance on the left arm, you need to point-constrain the locators to the arm root and arm box. Select Loc1 and Loc2 and group them, naming the parent node LimbDistances. When created, point-constrain Loc1 to the LtArmRoot joint, and point-constrain Loc2 to the LtArm box.
Also notice that a distanceDimension node has been created in the hypergraph. Right-click the node to open it in the Attribute Editor, and note the distance listed under the Shape tab. This distance can be used to create a warning for when the left arm is translated too far. You can write such a warning by creating an expression similar to the following:
if (distanceDimensionShape1.distance > 9.2) Bonecolor.incandescenceG = 1; else Bonecolor.incandescenceG = 0;
This expression makes the Bonecolor turn green whenever the left arm is translated too far (see Figure 3.76). The best way to create warning colors on your character is to create multiple copies of the Bonecolor material and place them on specific areas of your polygon reference bones. This process enables you to specify a material that affects only a single limb, or just the backbone, in your warning expressions. Also keep in mind that you can do all these warnings by setting driven keys, instead of using expressions. This can produce a gradual changing of color on the polygon bones, instead of the color being full on or off.
Figure 3.76 You also can use a distanceDimension node to create a warning color for when a limb is translated too far.