In the Expressions Lab we examined a couple of inverse kinematics (IK) expressions developed by Brian Maffitt. Those expressions are a lot of fun, but they have some pretty rigorous setup requirements. For example, you have to edit the code if your arm/leg pieces are oriented vertically instead of horizontally. Also, you have to edit the code to get the IK chain to bend counter clockwise instead of clockwise. The layer names are embedded in the code and you have to find them and make the correct substitutions for your project. Things don't always work as expected if you scale or rotate your pieces before you link them together and apply the expressions. Also, since the hands/feet are not parented to the rest of the chain, they can become detached if you move them too far from the body.

I'd say it's time to take another look at these expressions and see if we can't make them a little more robust and user-friendly.

First of all, we'll put anything that may need to be modified right up front, in a block of variables. This will include the layer names of the arm/leg pieces, an indicator of whether to bend the pieces clockwise or counter clockwise, and another indicator to identify whether the expression is for an upper limb piece or a lower limb piece.

Since the expressions for the upper and lower limb pieces have a lot of identical code, it makes sense to combine the two expressions into one and use our upper/lower indicator to choose which code to execute. That way, there's only one expression to worry about.

In the original IK expressions, the extremity layer (usually a hand or foot) is dragged around to position the IK chain. A null layer is used as a stand-in for the extremity in the angle calculations. A side effect of this is that you can easily detach an extremity from the lower limb by moving it too far away. To fix that, we're going to parent the extremity to the lower limb piece, and use an "effector" layer to do the positioning. Also, if we make the effector a guide layer, we can set it up so that the effectors are visible in the comp, but don't render.

The key to getting this all to work smoothly is the initial setup of the pieces. After you have all your body parts loaded into your comp, you want to move each piece's anchor point to the location of the joint for that piece. For example, for an upper arm, you would move the anchor point to the location of the shoulder joint.


Once you have the anchor points set up, position the pieces and create the parenting relationships. You want to make the torso the parent of the upper limb piece, the upper limb piece the parent of the lower limb piece, and the lower limb piece the parent of the extremity. Then you need to add the effector layers. I used 10x10 solids (don't forget to make these guide layers - Layer > Guide Layer). Position the effector layers so that they are at the same location as the anchor points of the extremities. Leave the effectors without parents for now (we'll get back to this shortly). Here's a screen shot showing the parenting relationships of the pieces for my character:


Here's a screen shot of the fully-assembled character with the effector layers added:


All that's left to do is add the expression to the rotation property of each upper and lower limb piece. Once you have pasted in the expression, be sure to edit the six variables at the top to reflect the layer names of your pieces for this limb, whether the limb rotates in a clockwise direction, and whether the expression is for the upper piece. If you've done everything correctly, you should be able to move the effectors around to position the limbs. A side effect of setting things up this way is that if you move the torso, the effectors don't move (because they aren't parented to anything). This means that the wrists and ankles will try and maintain their current positions as you move the torso around (try it - it's fun!). This can be handy (especially for the feet), but if you want the character to keep its pose as you move the torso, you can simply parent the effectors to the torso. This screen shot shows the effect of moving the torso, first with no parents for the effectors and then with the hand effectors parented to the torso:


There's one other piece of business we need to cover before we dive into the IK code. In this incarnation of the IK expressions, the feet are parented to the lower legs. In the previous version (from the Expressions Lab), the feet had no parents. This means that now, as the lower leg rotates, the foot will rotate with it. This may normally be OK, but it can possibly make your character's toes dip below the "floor". Applying a counter-rotation expression to the foot doesn't work for mysterious reasons - apparently having to do with creating a chain of expressions that loops back upon itself. In any case, if you need to keep the feet level, you can do it by applying a Transform effect to each foot. You should then apply this simple expression to the Anchor Point and Position properties of the Transform effect:

anchorPoint

Then apply this expression to the Rotation property of the Transform effect:


v = toWorldVec([1,0,0]);
-radiansToDegrees(Math.atan2(v[1],v[0]))

This illustration shows the "before and after" of applying the leveling expression to the feet.

Now we're ready to take a look at the main IK code for the upper left arm piece of the character. The code for the other limb pieces is identical, except for the variables defined in the first six lines of code.



cw = false;
upper = true;
upperLimb = "l upper arm";
lowerLimb = "l lower arm";
extremity = "l hand";
effector = "l hand effector";

function getWorldPos(theLayerName){
  L = thisComp.layer(theLayerName);
  return L.toWorld(L.anchorPoint);
}

A = getWorldPos(upperLimb);
B = getWorldPos(lowerLimb);
C = getWorldPos(extremity);
E = getWorldPos(effector);

a = length(B,C);
b = length(E,A);
c = length(A,B);

x = (b*b + c*c - a*a )/(2*b);
alpha = Math.acos(clamp(x/c,-1,1));
if (upper){
  D = E - A;
  delta = Math.atan2(D[1],D[0]);
  result = radiansToDegrees(delta - (cw ? 1 : -1)*alpha);
  V = B - A;
  adj1 = radiansToDegrees(Math.atan2(V[1],V[0]));
  result - adj1 + value;
}else{
  y = b - x;
  gamma = Math.acos(clamp(y/a,-1,1));
  result = (cw ? 1 : -1)*radiansToDegrees(gamma + alpha);
  V1 = B - A;
  adj1 = radiansToDegrees(Math.atan2(V1[1],V1[0]));
  V2 = C - B;
  adj2 = radiansToDegrees(Math.atan2(V2[1],V2[0]));
  result +  adj1 - adj2 + value;
}

An example of a "cut out" character rigged with inverse kinematics expressions.

Note that I named the body parts of my character with reference to my left and right, not the character's. This explains why the code defines the left arm as bending counter clockwise (in case you were wondering). I find this notation easier to work with, but you can do it the other way if it works better for you.

Once you get the character fully rigged, you'll probably want to lock the limb and extremity layers. That way you won't accidentally select them when you attempt to move an effector layer.