Switching between FK and IK
We now need a control to allow us to switch between FK and IK. In the front view, turn on Grid Snapping (or hold down the X key) and go Create > CV Curve Tool (Options). Set the Curve Degree to 1 Linear and then draw out the letters FKIK. I did this as 4 individual curves. You can draw out any shape you like but I figure a control made from the letters FKIK will be pretty easy for the animator to work out. Then select all the curves and go Modify > Center Pivot. I now want to combine these curve shapes together. To do this, in the Outliner, hold down the right-mouse button and turn on Show Shapes. Now select curveShape2, curveShape3, curveShape4 and then Ctrl+select curve1. Now in the Command Line (make sure it is set to MEL), type and execute the following command:
parent ?r ?s;
Combining multiple curves together for the fkIkSwitch_ctrl
This will pop all the curve shapes under the one node. You can now turn off Shaw Shapes and then delete the empty curve nodes. Selecting any one of the letters now will select the one object. Rename the control fkIkSwitch_ctrl and move it to sit slightly behind the torso of the character. With the control selected, go Modify > Freeze Transforms and Edit > Delete By Type > History. Now parent the control under COG_ctrl and then lock and hide all the translate, rotate and scale channels for fkIkSwitch_ctrl.
Let's add some attributes now to allow the animator to switch between FK and IK. Select the fkIkSwitch_ctrl and go Modify > Add Attribute. Then add the following 4 attributes: l_arm, r_arm. l_leg, r_leg. For all 4 attributes, set the Data Type set to Float, Minimum set to 0, Maximum set to 1 and the Default set to 0.
Adding the attributes that will allow the animator to switch between FK and IK
Now let's use Set Driven Keys (SDK) to get everything working. To open up the SDK window, go Animate > Set Driven Key > Set. Select the fkIkSwitch_ctrl and hit Load Driver on the SDK window. Then select the 3 orient constraint nodes (you'll find these living under l_upperArm_jnt, l_lowerArm_jnt and l_armEnd_jnt) and hit Load Driven on the SDK window. Set the l_arm attribute to 0 on the fkIkSwitch_ctrl (this will be FK) and then, one-by-one, set the IK Jnt W1 to 0 on each constraint. Make sure to leave FK Jnt W0 at 1. Then, in the top right portion of the SDK window, highlight L Arm and in the bottom left window, highlight the first orient constraint node. Then highlight the 2 constraint weights in the bottom-right window and hit Key. Do this for the remainder of the orient Constraints. That should be the FK covered; let's take care of the IK next. To do this, set the L Arm attribute to 1 (IK mode) on the fkIkSwitch_ctrl. Then reverse the weights on each constraint so FK Jnt W0 is set to 0 and IK Jnt W1 is set to 1 and hit Key with the relevant attributes highlighted in the SDK window.
Using Set Driven Keys to control which joint chain (the FK or the IK) should drive the main arm chain
Creating the FK controls
To create the controls for the FK arm chain, we will use the createControls.py script (found in the scripts directory in the 3dt_rigging folder supplied with this tutorial
). Select both l_upperArm_FK_jnt, l_lowerArm_FK_jnt and execute the script to create the controls. They may be pretty small to begin with so select the newly created controls from the Outliner and hit F8 to go into component mode and resize and reposition the controls so they are easily selectable. Remember not to edit the control shapes in object mode. Next parent l_lowerArm_FK_ctrl_offset under l_upperArm_FK_ctrl to create a control hierarchy that mimics the FK arm chain and behaves correctly.
Link to assets
Now for the shoulder control: select l_shoulder_jnt and once again, run the createControls.py script. Using component mode (F8), reshape and reposition the new control. Now parent l_upperArm_FK_ctrl_offset under l_shoulder_ctrl and the entire FK arm structure should follow the shoulder control.
Using the createControls.py script to add the FK arm and shoulder controls
Setting up the clavicle
Select l_clavicle_jnt and execute the createControls.py script to create the control. Once again, reshape and reposition the control so it is easily selectable in component mode. Parent l_clavicle_Ctrl_offset under l_shoulder_ctrl to have the clavicle follow the main driving control. To have the clavicle create some subtle movement as the arm is raised and lowered, we will use an expression.
First let's add an attribute so the animator can decide if he/she would like the expression to be active. Select l_clavicle_ctrl and go Modify > Add Attribute. Give it a Long name of autoClavicle, make it a Float with a Minimum of 0 and a Maximum of 1. Now open up the Expression Editor and create the following expression:
l_clavicle_ctrl_auto.rotateX = l_upperArm_jnt.rotateX * l_clavicle_ctrl.autoClavicle;
l_clavicle_ctrl_auto.rotateY = l_upperArm_jnt.rotateY * l_clavicle_ctrl.autoClavicle;
l_clavicle_ctrl_auto.rotateZ = l_upperArm_jnt.rotateZ * l_clavicle_ctrl.autoClavicle;
Using an expression to allow the clavicle to be driven by the arm
Now set a value of 0.05 (I think this value worked best) for the autoClavicle attribute on l_clavicle_ctrl and you should see some subtle movement to the clavicle if you rotate the l_upperArm_FK_ctrl. The animator can now control how much or how little the clavicle should follow the arm and as we have applied the expression to the auto node on the clavicle hierarchy, the animator can still animate on top using the l_clavicle_ctrl.
Let's now create the scapula control. Select l_scapula_jnt and execute the createControls.py script. Again, reshape and reposition the control in component mode and then parent l_scapula_ctrl_offset under l_shoulder_ctrl.
The scapula control in place and parented under the shoulder control
Setting up the scapula
Again, we will use an expression to drive the scapula as we have the clavicle. First select the scapula and go Modify > Add Attribute. Give it a Long name of autoScapula, make it a Float with a Minimum of 0 and a Maximum of 1. Now open up the Expression Editor and create the following expression:
l_scapula_ctrl_auto.rotateX = -1 * l_shoulder_jnt.rotateZ * l_scapula_ctrl.autoScapula;
Set the value of autoScapula to 0.5, rotate the shoulder control in the Z-axis and you should see some movement to the scapula. Again, how much movement you want here can be altered by playing with the autoScapula attribute. Plus, as we have applied this to the auto node of our scapula control hierarchy, the animator can still work on top using the l_scapula_ctrl.
The scapula being driven by the rotation of the shoulder
Setting up the IK arm
Switch to IK mode by setting the L Arm attribute to 1 on the fkIkSwitch_ctrl and then hide the FK joint chain and l_upperArm_FK_ctrl. Now select l_upperArm_IK_jnt and hit Ctrl+D to duplicate it. Rename the new chain from root to tip: l_upperArmDrive_IK_jnt, l_lowerArmDrive_IK_jnt and l_armEndDrive_IK_jnt. We will now drive the original IK set of joints by this new chain, only we will not constrain the rotate Y axis of the l_lowerArm_IK_jnt. This way, we can apply an IK Rotate-Plane Solver to drive the arm and still be able to twist the forearm from the elbow region.
Duplicating the IK joint chain to create a driver set
So now, go Skeleton > IK Handle Tool (Options) and make sure the Current Solver is set to Rotate-Plane Solver. In the Outliner, click on l_upperArmDrive_IK_jnt, hold down the Ctrl key and then click on l_armEndDrive_IK_jnt. Rename the ikHandle1 to l_arm_IK. Create a control for l_arm_IK using the createControls.py script. Make sure that you edit the final line to read cmds.pointConstraint(ctrl, s, mo=0) rather than cmds.orientConstraint(ctrl, s, mo=0). Go in and also rename the controls correctly as the script will not do so for anything that does not have a suffix of _jnt. Once the control is created, go into component mode (F8) and reshape and reposition the control so it is easily selectable.
Now we want to drive the original set of IK joints with the driver set of joints. In the Outliner, select l_upperArmDrive_IK_jnt, ctrl-select l_upperArm_IK_jnt and go Constrain > Orient (Options). Make sure the Constrain axes parameter is set to All and hit Apply. Then select l_lowerArm_Drive_IK_jnt, ctrl-select l_lowerArm_IK_jnt and go Costrain > Orient (Options). This time set the Constraint axes to X and Y only and hit Apply.
Make sure not to constrain the Y-axis when orient constraining the lower arm joint
Next, we need to drive the elbow twist. Select l_arm_IK_ctrl and go Modify > Add Attribute. Give it a Long name of elbowTwist, make it a Float and leave all the other parameters blank. Go Window > General Editors > Connection Editor and with the l_arm_IK_ctrl selected hit Reload Left. Select l_lowerArm_IK_jnt and hit Reload Right in the Connection Editor window. On the left-hand side, highlight elbowTwist and on the right-hand side, highlight rotateY (you will find this under Rotate). You can now drive the twist of the elbow using the new attribute.
Let's add the ability to twist the entire arm now. Select l_arm_IK_ctrl and go Modify > Add Attribute. Give it a Long name of armTwist, make it a Float and leave all the other parameters blank. Go Window > General Editors > Connection Editor and with the l_arm_IK_ctrl selected, hit Reload Left. Select l_arm_IK and hit Reload Right in the Connection Editor window. On the left-hand side, highlight armTwist and on the right-hand side, highlight twist. The new attribute will now twist the entire arm.
A slight problem that we have now is that if we position the arm in certain poses, the elbow twist creates some funky behavior. To fix this, select l_lowerArm_IK_jnt, open up the Attribute Editor (Ctrl+A) and set the Rotate Order to YZX. Set the Rotate Order to YZX for l_lowerArm_jnt, l_lowerArm_FK_jnt, l_lowerArmDrive_IK_jnt and l_lowerArm_FK_ctrl.
Using the Connection Editor allow the animator to twist the elbow region from the main IK control