# Skinning

The process of attaching the vertices of a 3D mesh to a posed skeleton is known as "Skinning".

Each vertex can be *bound* to one or more joints.

The vertex's positions is a *weighted average* of the positions it would have assumed if it had been bound to each joint independently.

At each vertex, you ned to have the following information:

- The index or indices of the
`Joint`

s to which it is bound, - The weighting factor describing how much influence that joint should have on the final vertex position.

`#![allow(unused)] fn main() { struct SkinnedVertex { position: Vector3, normal: Vector3, texture_coordinates: Vector2, joint_indices: [u8; 4], // max of 4 joints joint_weight: [u8; 3], // you don't need 4 weights since the last can be calculated on the fly. } }`

### Tracking mesh vertices to joints

A `skinning matrix`

is a matrix that can transform the vertices of a mesh **from bind pose** into new positions that correspond to the current pose of the skeleton.

The position of a skinned vertex is specified in model space, like all mesh vertices.

**Unlike other matrix transforms, a skinning matrix is NOT a change of basis transform**: it goes from model space (bind pose) to model space (actual pose)

Given the bind pose of the joint \(j\) in model space, \(B_{j \rightarrow M}\), this matrix transforms a point whose coordinates expressed in \(j\)'s space into an equivalent set of model-space coordinates.

Then, given a vertex whose coordinates are expressed in model-space, if you want to express it in joint-space, you can do so with the *inverse* of the above bind pose matrix.

\[ \vec{v_j} = \vec{v_M^B} B_{M \rightarrow j} = \vec{v_M^B} \left( B_{j \rightarrow M} \right)^{-1} \]

Given a joint's *current pose*, similar to the bind pose matrix, it defines vertices in joint space in model space, i.e., \(C_{j \rightarrow M}\).

\[ \begin{align} \vec{v_M^C} &= v_j C_{j \rightarrow M} \\ &= \vec{v_M^B} \left( B_{j \rightarrow M} > \right)^{-1} C_{j \rightarrow M} \\ &= \vec{v_M^B} K_j \end{align} \]

Where

- \(K_j = \vec{v_M^B} \left( B_{j \rightarrow M} > \right)^{-1} C_{j \rightarrow M} \)
- This \(K_j\) is known as the
skinning matrix.

When you have multiple joints, it can be useful to create an array of skinning matrices \(K_j\) for every joint.

\(B_{j \rightarrow M}\) matrices never change so can be calculated once per vertex. The current poses \(C_{j \rightarrow M}\) change on each frame and will therefore need to be calculated on the fly.

Don't forget that a single matrix from joint space to model space represents a *global pose*, meaning for a given joint, you have to walk up its local pose matrices to the root joint to create either \(B_{j \rightarrow M}\) or \(C_{j \rightarrow M}\).

### When multiple joints per vertex are involved

Calculate a new vector for each joint individually, then average all the vectors together.

\[ \vec{v_M^C} = \sum_{i=0}^{N-1} w_i \vec{v_M^B} K_{ji} \]

Where

- \(N\) is the number of joints associated with vertex \(\vec{v}\).
- \(w_i\) is the weighting factor of joint \(i\).
- \(K_{ji}\) is the skinning matrix for joint \(j_i\).