The Bind Pose and Skinning

A character mesh is just a bag of vertices — a few hundred thousand points floating in space. A skeleton is a tree of joints, each carrying a transform that says where its bone sits and how it is oriented right now. On their own these two things know nothing about each other. Skinning is the glue: it makes the skin follow the bones, so that when the elbow joint rotates, the vertices of the forearm swing with it and the arm bends. This page pins down the single most important idea that makes that glue work — the bind pose and the inverse bind matrix — and shows the exact transform a rigidly-attached vertex obeys.

The bind pose: where skin and skeleton were introduced

When a rigger first attaches a mesh to a skeleton, the character is standing in one specific pose — arms out, legs slightly apart, the classic T-pose or A-pose. This is the bind pose (also called the rest pose or reference pose): the pose in which the mesh was modelled and in which it was bound to the skeleton. It is the one moment where we know, for certain, exactly where every vertex sits relative to every joint. Every later pose is measured as a departure from this one.

The skinning transform: undo the bind, then re-apply the pose

Take a vertex v that is rigidly attached to a single joint j — imagine a freckle painted on the forearm, glued to the elbow. In the bind pose it sits at some position in mesh space. Now the animator poses the skeleton, and joint j's current world transform is M_j. Where does the freckle go? Two steps:

First we ask: where did this vertex sit relative to the joint, back at bind time? That is exactly what B_j^{-1} computes — it carries v into the joint's local frame. That local position is frozen; it never changes, because the freckle is glued to the bone. Then we re-plant that local position using the joint's current world transform M_j. Composing the two:

v' \;=\; M_j \, B_j^{-1} \, v.

The pairing M_j \, B_j^{-1} is often precomputed once per joint per frame and called the joint's skinning matrix; every vertex bound to that joint is then a single matrix-times-vector away.

The bind pose is the identity — that is the whole point

Here is the check that makes the formula click. In the bind pose, nothing has moved yet, so every joint's current transform equals its bind transform: M_j = B_j. Substitute:

v' \;=\; M_j \, B_j^{-1} \, v \;=\; B_j \, B_j^{-1} \, v \;=\; I \, v \;=\; v.

The vertex is left exactly where it was. This is precisely what we want: in the bind pose the mesh should be undeformed, sitting where the modeller put it. The B_j^{-1} is the piece that makes the bind pose collapse to the identity — it cancels the bind transform so that deformation only ever measures the difference between the current pose and the bind pose.

Seeing it move

Below, a bone runs from the elbow joint outward, with a handful of vertices bound to it (their frozen local positions relative to the bone). Press play — or step the timeline — to rotate the joint. Each vertex keeps its local relationship to the bone exactly (the freckle stays a freckle) while its world position swings around: that is v' = M_j \, B_j^{-1} \, v in action, with only M_j changing between the two panels.

Worked example: a freckle on the forearm

Work in 2-D for clarity. Suppose the elbow joint, at bind time, sits at the origin with no rotation, so its bind matrix is the identity's cousin — a pure placement. Say B_{\text{elbow}} places the joint at (2,0) with no rotation, so

B_{\text{elbow}} = \begin{bmatrix} 1 & 0 & 2 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}, \qquad B_{\text{elbow}}^{-1} = \begin{bmatrix} 1 & 0 & -2 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}.

A freckle sits on the forearm at mesh position v = (5, 0) — that is, 3 units out along the bone from the joint. First undo the bind:

B_{\text{elbow}}^{-1} \, v = (5 - 2,\; 0) = (3, 0),

which is the freckle's local position: three units down the bone, as expected. Now the animator rotates the elbow by 90^\circ (keeping the joint at (2,0)), so the current transform M_{\text{elbow}} rotates about that pivot. Applying it to the local point (3,0) swings it up:

v' = M_{\text{elbow}} \, B_{\text{elbow}}^{-1} \, v = (2,\, 0) + \big(3\cos 90^\circ,\; 3\sin 90^\circ\big) = (2, \, 3).

The freckle has swung from (5,0) to (2,3) — straight up above the joint, exactly as a forearm point should when the elbow bends a quarter turn. And in the bind pose (M_{\text{elbow}} = B_{\text{elbow}}) the same formula returns (2,0) + (3,0) = (5,0) = v: unmoved.

Weights: one vertex, several bones

A vertex glued to a single joint is fine deep inside a limb, but a vertex near a joint — at the elbow crease, or where the shoulder meets the torso — needs to be pulled by more than one bone at once, or it creases like folded cardboard. So each vertex carries a small list of skin weights: a set of joints j with weights w_j \ge 0 saying how much each one influences it, and the weights sum to one:

\sum_j w_j = 1.

The natural thing to do is blend the single-joint answers, weighted: v' = \sum_j w_j \, M_j \, B_j^{-1} \, v. That weighted average of skinning matrices is linear-blend skinning — the workhorse of real-time character deformation, and the subject of the next lesson. For now, the key idea is just that the rigid formula M_j \, B_j^{-1} \, v is the atom, and weights are how we mix several atoms together.

Setting those weights is a craft called painting weights: the rigger literally paints influence onto the mesh with a brush, one joint at a time, watching a heat-map of "how much this bone owns this patch of skin". Auto-binding gives a first guess; the hand-painting cleans up the elbows, armpits, and other creases where a smooth blend matters most. A well-painted arm bends without collapsing; a badly-painted one pinches or balloons.

You could, in principle, bake each vertex's local position into the joint's frame once and store that. But meshes are authored, exported, and edited in mesh/world space — that is the space the modeller and every tool speaks in. The inverse bind matrix lets the engine keep the mesh in its natural coordinates and convert on demand: B_j^{-1} is computed once, at bind time, from the skeleton the artist set up, and shipped alongside the mesh. It is the clean bridge between "the space the artist modelled in" and "the space the joint animates in", and it means the same mesh can be re-bound to a different skeleton just by recomputing the B_j^{-1}s. One matrix per joint, computed once — a small price for keeping everything else in friendly coordinates.

The single most common skinning bug is applying the joint's current transform straight to the vertex — v' = M_j \, v — and dropping the B_j^{-1}. It looks harmless, but it double-applies the bind transform: the vertex already sits at its bind-pose world position, and M_j shoves it through the joint's full placement again. In the bind pose you would get v' = B_j \, v \ne v — the mesh is offset and warped before a single frame of animation plays; rotate the joints and it flies apart into the notorious exploding-character mess. The fix is the whole lesson: B_j^{-1} is exactly the piece that cancels the bind, forcing the bind pose to be the identity M_j B_j^{-1} = I so that deformation measures only the departure from bind. If your rig blows up on load, the missing inverse bind matrix is the first suspect.