Implementing forward kinematics for linear blend skinning

I’ve implemented linear blend skinning and forward kinematics many times now. Each time I start out I have to scratch my head a little about what gets stored where and how best to construct the final bone transformations. Here’s a little explanation that will hopefully help in the future.

First let’s recall the linear blend skinning formula:

v' = ∑ wi(v) Ti * v

where v' is the new position of some point v on our shape, and wi(v) is bone i’s weight function evaluated at v and Ti is bone i’s transformation.

We’re specifically dealing with rigid bones, in fact we’ll consider our skeleton a rigid kinematic chain. Then the formula becomes:

v' = ∑ wi(v) (Qi * v + ti)

where Qi is the absolute bone (or joint) rotation (e.g. stored as a quaternion) of bone i. These absolute rotations are just a concatenation down from the root to bone i of the relative rotations we’re storing for each bone. These relative rotations are what we’re changing during an animation. The translation part for each bone ti is what gets a tad confusing. It is a function of the static (rest) skeleton (specifically the rigid bone lengths and relative positions in space) and the center of each bone rotation (i.e. joints positions).

Let’s go through a small example. Suppose we have two bones and we’re storing relative rotations q₀ and q₁.

forward kinematics

First we’ll figure out Q₀ and t₀. We want our rotation q₀ to be centered about the bone’s “joint” or upper endpoint. To do this we first translate so that endpoint is at the origin,

forward kinematics

then rotate by q₀,

forward kinematics

and then translate back,

forward kinematics

This affectively computes Q₀ and t₀. Imagine we apply these operations to some arbitrary point x. First translate so that the endpoint is at the origin: x-x₀, then rotate q₀(x-x₀), then translate back q₀(x-x₀)+x₀. Now separate the rotation and translation and you have q₀x-q₀x₀+x₀, revealing that Q₀ = q₀ and t₀ = -q₀x₀+x₀.

Now, a bit more tricky let’s consider then next bone. Again we want to rotate about the bone’s parent joint, so translate such that it’s at the origin,

forward kinematics

then rotate, but remember we need to rotate not just for this bone but also its parent (and in general all its ancestors),

forward kinematics

then finally translate back, but now we want the center to end up connected with its parent bone, so translate to the transformed parent joint location,

forward kinematics

Again, this computes Q₁ and t₁. Let’s go through it again for some arbitrary point x. First translate so that the parent joint is at the origin x-x₁, then rotate by the parent’s rotation and this bone’s q₁q₀(x-x₁), then translate to meet the parent’s transformation of the joint q₁q₀(x-x₁) + (q₀x₁-q₀x₀+x₀). Separating the rotation from the translation we have q₁q₀x - q₁q₀x₁ + q₀x₁-q₀x₀+x₀, revealing that Q₁ = q₁q₀ and t₁ = - q₁q₀x₁ + q₀x₁-q₀x₀+x₀.

Finally, putting both bones together we see the fully transformed skeleton.

forward kinematics

In general, we can write the absolute rotations and translations determined by forward kinematics as a recursive function of the relative rotations and rest joint locations:

Qi = qi Qp 
ti = - Qi xi + Qp xi - Qp xp + xp

where bone p is the parent of bone i.

Note: If you’re storing your skeleton as a tree where each bone i knows its parent p then one affective and efficient way to compute the result of this recursive formula is using dynamic programming. Alternatively, if each bone p knows each of its children i then one can just use breadth or depth first traversal.

Note: This is just for determining the absolute rigid transformations corresponding to each bone. It does not depend on the fact that we’re using linear blend skinning. The same construction applies if fancier skinning formulae are used like dual quaternion skinning.

Tags: , , , , , , ,

Leave a Reply