The 3 arm setup usually consists of 3 sets of joints which gives the animator fine control over IK/FK blending. The IK hierarchy would be used to animate with IK while the FK hierarchy would be used to animate in traditional FK. The last hierarchy would be the result of the two after blending the IK and FK animation, and is also used for skinning.
Create 3 joints in the top view
The joint at the shoulder should not be placed too inside of the body, nor too far out. Imagine the mesh deforming later, where would be a good center of rotation?
For this exercise, it would be easier to keep the joints perfectly straight in BOTH the top and front view (hold down shift while creating the joints).
One issue with perfectly straight joints is that maya would not know how to bend the joint when solving the IK. To prevent your arm from bending in the wrong direction, set the preferred angle.
- Do a small rotation of the elbow in the Y axis
- Hold down the right mouse button and choose ‘Set Preferred Angle’.
- Undo the earlier rotation.
Name the joints as j_UpArm_L, j_ForeArm_L, j_Hand_L and j_HandEnd_L.
Duplicate with transform (Shift+d) the joints twice to get a total of 3 hierarchies. Name them as such:
Hide the j and FK set, we’ll be working on the IK set first.
Create 2 IKs, IK_UpArm_L to IK_Hand_L and IK _Hand_L to IK_HandEnd_L. Name them IK _Arm_L and IK_Hand_L respectively.
Create a controller for IK_Arm_L. Create it at the origin, group it and snap the group to the joint at the wrist. Name the control ctrl_Arm_L and the group grp_Arm_L .
Parent the 2 IK’s below the controller ctrl_Arm_L.
Test the controller.
Create a locator for the arm. Snap it to the elbow joint and translate in Z.
Create a controller of your choice at the locator. (Remember to freeze and delete history). Here I used an OmniCurvy from smControllerCreator. Name the controller ctrl_Elbow_L.
Create a Pole Vector constraint for IK_Arm_L.
- Select master before the slave. i.e. select controller before the IK (IK_Arm_L).
- Constrain -> Pole Vector
Parent the locator to the controller. Test the setup.
Now we’re going to apply stretching to the arm.
Create a distance tool from shoulder to wrist.
- Create -> Measure Tools -> Distance Tool
- Click on the shoulder joint (IK_UpArm_L)
- Click on the wrist joint (IK_Hand_L)
- Name the locators loc_Shoulder and loc_Hand respectively
Create an attribute on the arm control
- Select the arm control (ctrl_Arm_L)
Modify -> Add Attribute
- Enter ArmLength as the long name and leave data type as Float
Connect this attribute to the value from the Distance Tool
- Open the Connection Editor (Window -> General Editors -> Connection Editor)
- Load the shape node of the Distance Tool in the left panel
- Load ctrl_Arm_L in the right panel
- Select Distance on the left and ArmLength on the right.
Test the rig. Does ArmLength change when you move the arm controller?
Create an expression to control the length of the upper arm and fore arm joints (IK_UpArm_L & IK_UpArm_L).
- Open expression editor (Window -> Animation Editors -> Expression Editor)
- Enter exp_Arm_Stretch_L in the name.
Use the following expression:
IK_UpArm_L.scaleX = IK_ForeArm_L.scaleX = (ctrl_Arm_L.ArmLength > 6.634013) ? ctrl_Arm_L.ArmLength/6.634013 : 1;
We will be creating an attribute to control whether the arm follows the body.
Duplicate with transform (Shift+d) the arm controller group twice. Name them grp_Arm_L_0, grp_Arm_L_1 respectively.
Parent constraint the arm controller to both of them.
- Select grp_Arm_L_0 and grp_Arm_L_1
- Select arm controller
- Constrain -> Parent Constraint
Create a Follow attribute to the arm controller
Connect this attribute to the Grp Arm L 1W1 attribute of grp_Arm_L’s parent constraint.
- Steps using Connection Editor:
- Load ctrl_Arm_L to the left panel of the Connection Editor.
- Load grp_Arm_L’s parent constraint to the right. (Select the parent constraint node from the channel box and click ‘Reload Right’
- Click on Follow on the left and Grp Arm L 1W1 on the right.
Use a reverse node to connect the reverse value of ctrl_Arm_L.Follow to Grp Arm L 0W0 of _Arm_L’s parent constraint.
- Steps using Hypershade:
- Open Hypershade (Window -> Rendering Editors -> Hypershade)
Create a Reverse node.
Connect ctrl_Arm_L.Follow to inputX of the Reverse node.
- Connect OutputX of the Reverse node to Grp Arm L 0W0 of _Arm_L’s parent constraint.
We’ll be working on FK now. Hide the IK hierarchy and controllers and show the FK hierarchy.
Create a controller for the shoulder joint. Freeze transform and delete history.
Group the controller and snap the group to the shoulder joint.
Suggestion: Use a controller which indicates the rotation of the joint clearly. In this case I’ve used a simple nurbs circle perpendicular to the joint.
Name the controller and group ctrl_FK_UpArm and grp_FK_UpArm respectively.
Duplicate with transform the FK controller for the elbow joint and wrist joint and name accordingly.
Connect the rotation values of the controller to the shoulder joint (FK_UpArm_L)
- Open Connection Editor (Window -> General Editors -> Connection Editor)
- Load the FK controller in the left and the joint in the right.
- Select rotate (not rotateX) on the left and rotate on the right.
- Do the same for the other 2 FK controllers.
Test your controllers.
Result Joint Setup
Cleanup the Scene (hide unnecessary stuff )
Orient Constraint the result hierarchy to both the IK and FK hierarchy.
- Select in order, IK_UpArm, FK_UpArm, j_UpArm
- Constrain -> Orient (maintain offset optional since they should be at exactly the same location)
- Repeat for j_ForeArm and j_Hand
Create a controller to control the weight of the orient constraint. (Freeze transformation and delete history). Name it ctrl_IKFK_L.
Group it once, name the group grp_IKFK.
Snap the group to j_Hand.
Create an attribute IKFK of type float for the controller.
Connect this attribute to the orient constraints. (Like in the head and hand set up previously).
- Open the connection editor. Load the arm controller on the left and j_UpArm’s orientConstraint on the right.
- Connect IKFK to FK_UpArm_LW0.
- Load j_ForeArm’s orientConstraint on the right.
- Connect IKFK to FK_ForeArm_LW0.
- Load j_Hand’s orientConstraint on the right.
- Connect IKFK to FK_Hand_LW0.
- Load j_HandEnd’s orientConstraint on the right.
- Connect IKFK to FK_HandEnd_LW0.