Pose a figure by angles, not by positions

A field figure is a set of primitives with endpoints, and the fastest way to animate it is to write down where each endpoint sits in pose A, where it sits in pose B, and blend. It hits both poses perfectly. Everything between them is wrong.

The same two-bone arm swinging through 90 degrees. Left: joint positions interpolated. Right: forward kinematics. The amber circle is the upper arm's true reach, and the elbow marker should never leave it.

Watch the elbow marker against the amber circle, which is drawn at the upper arm's actual length. On the right it rides the circle the whole way, because the bone is a constant and only its angle changes. On the left it cuts inside, the arm visibly shortens through the middle of the swing, and it snaps back to correct at each end.

Why it shortens

Interpolating between two points travels the straight line between them, and the straight line between two points on a circle is a chord. The bone is the radius. Halfway through a swing of angle A, the chord's midpoint sits at L·cos(A/2) from the joint, so the bone reads as shorter by 1 − cos(A/2).

Note what is NOT in that formula: the bone's length. The error is a pure fraction of it, so the table below is the same for a four-head mascot and a realistic adult, and changing the figure cannot invalidate it. That is worth checking rather than assuming, because most of the constants around a demo like this one are figure-dependent.

The formula is the whole guide to when this matters:

Which explains the usual discovery path. Small motions look fine, the method gets adopted, and then the first big swing exposes it in a build that is already animating forty things the same wrong way.

What forward kinematics actually is

Nothing more than: a joint's transform is its parent's transform followed by its own rotation. Positions come out of the chain; they are never inputs.

elbow = shoulder + rotate(vec2(upperLen, 0), aShoulder);
hand  = elbow    + rotate(vec2(lowerLen, 0), aShoulder + aElbow);

The angles add as you go down the chain, which is the part worth saying out loud: a child's stored angle is relative to its parent. That is what makes a wrist stay put when the shoulder moves, and it is why animation data is angles.

The consequences that are not the shrink

The one place positions are correct

Inverse kinematics is the opposite ask: you know where the hand must be, and you solve for the angles that put it there. That is still angles at the end. A two-bone IK solution is closed form and short, so reach-for-a-thing does not need a library. The rule stands either way: the figure is stored as angles and the positions are derived, never the reverse.

Rules of thumb

  1. Store poses as angles. Derive positions from the chain every frame.
  2. A child's angle is relative to its parent, and the angles accumulate down the chain.
  3. Bone lengths are constants. If a length changes during an animation, something is wrong.
  4. Estimate the error as 1 − cos(A/2) before deciding a shortcut is safe.
  5. Debug by drawing a circle of the bone's length around its parent. The joint must stay on it.

All 61 notes How to use them Credits