Math Behind Two-Bone Inverse Kinematics in 3D Games

Two-bone inverse kinematics (IK) is a foundational technique in 3D character animation used to realistically position limbs, such as arms and legs, toward a specific target. This article explores the mathematical principles governing this system, covering distance constraints, the Law of Cosines for interior joint angles, vector projection for base rotation, and pole vectors for controlling the limb's bending plane.

The Geometric Setup

A two-bone IK chain consists of three joints and two rigid segments:

  • Root joint (\(J_1\)): The shoulder or hip, located at position \(\vec{P}_1\).
  • Mid joint (\(J_2\)): The elbow or knee, located at position \(\vec{P}_2\).
  • End effector (\(J_3\)): The wrist or ankle, which aims to reach the target position \(\vec{T}\).

The lengths of the two bones are fixed scalars: \(L_1\) (length between \(J_1\) and \(J_2\)) and \(L_2\) (length between \(J_2\) and \(J_3\)).

1. Reachability and Clamping

The vector from the root to the target is defined as: \[\vec{D} = \vec{T} - \vec{P}_1\] The distance between the root and target is the magnitude \(d = \|\vec{D}\|\).

Before solving the joint angles, the system must evaluate whether the target is physically reachable. According to the triangle inequality, a valid triangle can only be formed if: \[|L_1 - L_2| \le d \le L_1 + L_2\]

  • Target beyond maximum reach (\(d \ge L_1 + L_2\)): The limb is fully extended. The distance \(d\) is clamped to slightly less than \(L_1 + L_2\) to avoid computational singularities, and the bones align straight toward \(\vec{T}\).
  • Target closer than minimum reach (\(d \le |L_1 - L_2|\)): The limb fully folds. The distance \(d\) is clamped to \(|L_1 - L_2|\).

2. Solving Interior Angles via the Law of Cosines

When \(d\) is within valid bounds, the three joints form a triangle with side lengths \(L_1\), \(L_2\), and \(d\). The interior angles are determined using the Law of Cosines: \[c^2 = a^2 + b^2 - 2ab \cos(C)\]

Mid Joint Angle (\(\alpha_2\))

To find the interior angle at the knee or elbow (\(\theta_{mid}\)), solve for the angle opposite to side \(d\): \[\cos(\theta_{mid}) = \frac{L_1^2 + L_2^2 - d^2}{2 L_1 L_2}\] \[\theta_{mid} = \arccos\left(\text{clamp}\left(\frac{L_1^2 + L_2^2 - d^2}{2 L_1 L_2}, -1, 1\right)\right)\]

In skeletal animation, the mid joint's relative flexion angle (\(\alpha_2\)) is typically measured as the deviation from a straight line (\(180^\circ\) or \(\pi\) radians): \[\alpha_2 = \pi - \theta_{mid}\]

Root Joint Offset Angle (\(\alpha_1\))

To determine how much the upper bone deviates from the line connecting \(J_1\) to \(\vec{T}\), solve for the angle opposite to side \(L_2\): \[\cos(\alpha_1) = \frac{L_1^2 + d^2 - L_2^2}{2 L_1 d}\] \[\alpha_1 = \arccos\left(\text{clamp}\left(\frac{L_1^2 + d^2 - L_2^2}{2 L_1 d}, -1, 1\right)\right)\]

3. Defining the Bending Plane with a Pole Vector

A triangle in 3D space requires a plane of orientation. Without a constraint, the mid joint can rotate infinitely around the axis \(\vec{D}\).

A Pole Vector (\(\vec{P}_{pole}\)) is introduced as an external point in space that defines the direction the joint should bend (e.g., forward for a knee, outward or backward for an elbow).

  1. Construct the target direction unit vector: \[\hat{u}_D = \frac{\vec{D}}{\|\vec{D}\|}\]
  2. Vector from the root to the pole target: \[\vec{V}_{pole} = \vec{P}_{pole} - \vec{P}_1\]
  3. Project \(\vec{V}_{pole}\) onto the plane perpendicular to \(\hat{u}_D\) using Gram-Schmidt orthogonalization to define the upward bending direction: \[\vec{Y} = \vec{V}_{pole} - (\vec{V}_{pole} \cdot \hat{u}_D)\hat{u}_D\] \[\hat{u}_Y = \frac{\vec{Y}}{\|\vec{Y}\|}\]
  4. Compute the normal vector of the triangle plane: \[\hat{u}_N = \hat{u}_D \times \hat{u}_Y\]

4. Constructing the Final Joint Rotations

With the plane and interior angles established:

  1. Root Bone Direction: The upper bone begins pointing along \(\hat{u}_D\) and is rotated by angle \(\alpha_1\) around the normal axis \(\hat{u}_N\) toward \(\hat{u}_Y\). This sets the global direction vector of the first bone (\(\vec{B}_1\)): \[\vec{B}_1 = \cos(\alpha_1)\hat{u}_D + \sin(\alpha_1)\hat{u}_Y\] The position of the mid joint is then: \[\vec{P}_2 = \vec{P}_1 + L_1 \vec{B}_1\]

  2. Mid Bone Direction: The lower bone vector points from \(\vec{P}_2\) to the final target: \[\vec{B}_2 = \frac{\vec{T} - \vec{P}_2}{L_2}\]

These directional vectors (\(\vec{B}_1\) and \(\vec{B}_2\)), combined with the surface normal \(\hat{u}_N\), are converted into rotation matrices or quaternions. These transforms are applied to the character's local joint hierarchy to yield the final, stable limb pose.