Modern 2D Skeletal Runtimes: Mesh Deformation, Draw Order, and Constraints
Modern 2D Skeletal Runtimes: Mesh Deformation, Draw Order, and Constraints
Search
Ask the AI

Modern 2D Skeletal Runtimes: Mesh Deformation, Draw Order, and Constraints

Once a character is rigged and the weights are painted, a set of effects appears that bones simply cannot produce: the flutter at the hem of a skirt, the subtle bulge of a cheek under compression, an arm swinging from behind the body to in front of it during a turn. These are not badly painted weights. They are things linear blend skinning cannot express as a model. Modern 2D skeletal runtimes — Spine, DragonBones, Live2D and their relatives — are far more complex than “bones plus skinning” precisely because they stack several independent deformation and ordering mechanisms on top of it.

What bones can and cannot express

Recall the central equation from linear blend skinning: the final position of a mesh vertex v is a weighted sum of the transforms of the bones it is bound to.

v' = Σ_i w_i · M_i · B_i⁻¹ · v        Σ_i w_i = 1

Here B_i⁻¹ is the inverse bind matrix and M_i the bone’s current world matrix. The expressive power of this equation is tightly bounded: a vertex position can only ever be a linear combination of bone transforms. There are finitely many bones, each offering only translation, rotation and scale, so any deformation outside the linear span of that set is unreachable by skinning.

Three categories fall outside it. Local non-rigid detail such as bulges and folds. Changes in appearance that alter no bone pose at all, such as swapping a mouth shape. And something that is not deformation in the first place: draw order.

Mesh deformation animates the vertex offsets themselves

The first addition is mesh deformation — called Deform in Spine, and historically FFD, free-form deformation. The mechanism is direct: before skinning runs, add an animatable offset Δv to the vertex in its bind pose.

v' = Σ_i w_i · M_i · B_i⁻¹ · (v + Δv(t))

Δv(t) is a displacement stored per vertex per keyframe, entirely independent of the bones. Under one and the same bone pose you can therefore sculpt cloth folds, cheek compression, or a bending weapon.

Note that the offset is applied in bind space, not world space: offset first, then skin. That ordering is what makes a sculpted fold rotate along with the bone instead of staying pinned to a screen direction. Get the order backwards in an implementation or an exporter and the symptom is unmistakable — the character turns, and the folds keep pointing the old way.

The cost is data volume. Δv is one vector per vertex per keyframe, so denser meshes and more deform keys grow the file quickly. In practice meshes are refined only on parts that need detail deformation — faces, cloth — while rigid parts such as weapons and armour stay low-poly or skip meshes entirely.

Draw order is its own animation track

When a character turns, an arm has to move from behind the body to in front of it. Bones can move the arm across, but what decides which is drawn on top is render order, and that lives in no matrix.

Modern runtimes model draw order as a keyable track: each keyframe stores a permutation of the slots, and playback renders in the order given by the current frame. It is inherently discrete — two keyframes cannot be interpolated, because “between third and fifth in the ordering” is meaningless.

One practical rule follows. Schedule a draw-order change on the frame where it is most occluded or the motion is fastest. The change is necessarily a jump, and viewers only notice an arm popping in front when the image is otherwise stable. That is exactly why turn-around actions usually include a transitional frame in which the arm fully covers the torso, or the body is at its narrowest.

Constraints are a second evaluation pass after the hierarchy

Constraints run after the bone hierarchy has been evaluated, rewriting the final transforms of selected bones. Three kinds are common, each solving a different problem.

An IK constraint aligns the tip of a bone chain to a target — the problem solved in two-bone inverse kinematics. Runtime versions typically add two parameters: mix, blending the IK result against the original FK pose so animation can cross smoothly between them, and softness, which eases off as the chain approaches full extension so a knee or elbow does not snap rigid at the limit.

A transform constraint makes one bone partially copy another’s transform:

b.rotation = lerp(b.rotation, source.rotation + offset, mix)

This is the standard way to build follow-through and lag. Set mix to 0.3, add a few frames of delay, and hair or a cape trails the body automatically — far cheaper than keying every hair bone by hand, and rhythmically consistent by construction.

A path constraint binds a run of bones to a spline, distributed by arc length. Tank treads, chains and objects travelling along a rail use it. The implementation must reparameterise the spline by arc length first, or bones bunch up wherever curvature is high — the same problem you hit treating a Bezier curve as a constant-speed motion path.

Live2D takes a different route: parameters driving deformers

Tools in the Spine family are organised around bones. Live2D is organised around parameters and deformers, and the difference in thinking is substantial.

A model declares parameters, for instance ParamAngleX for turning the head left and right, ranging from −30 to 30. The artist sculpts keyforms at selected values of that parameter: the mesh vertex positions at −30, at 0, at 30. At runtime, given a parameter value p, the two neighbouring keyforms are interpolated:

for p in [p_0, p_1]
u = (p - p_0) / (p_1 - p_0)
vertex = (1 - u) · vertex@p_0 + u · vertex@p_1

This is what “pseudo-3D” head rotation actually is. There is no three-dimensional geometry anywhere; the artist drew several angles and the runtime interpolates between them. It reads as dimensional because the keyforms already contain the perspective, the occlusion relationships and the shifted facial feature positions — that information was drawn, not computed.

Deformers come in two kinds: rotation deformers, which rotate children about a pivot and behave much like bones, and warp deformers, a deformable control lattice that bends every child mesh with it. Deformers nest, and their transforms accumulate down the hierarchy — the same matrix concatenation seen in symbol hierarchies and bone hierarchies.

When several parameters act at once, keyforms are blended multilinearly across the parameter dimensions. That also explains why Live2D modelling effort grows so steeply with parameter count: two parameters with three values each require nine keyforms for full coverage.

Physics is a parameter wired to a spring

Secondary motion in hair and accessories is usually not keyed by hand. A physics system takes an input parameter — typically body or head angle — drives a damped spring or pendulum, and writes the output back into another parameter such as hair sway angle.

a = (k · (target - x) - c · v) / m
v += a · dt
x += v · dt

The critical detail is that dt must be real elapsed time, never “one frame”. This matches the frame-rate-independent conclusion from keyframe interpolation: once frames are dropped, a spring integrated by frame count produces a completely different amplitude. Dropped frames also require clamping dt and integrating in substeps, because a large dt makes explicit integration diverge — visible as hair exploding right after a stutter.

Common failures, in the order worth checking

  • Mesh tearing at a seam. Weights disagree on the shared seam vertices. Check that co-located vertices bind to the same bones and that every weight set normalises to 1.
  • Deformation swallowed by the bones. The mesh offset was applied in world space, or after skinning. Confirm the order is add Δv, then skin.
  • Layers popping during a turn. The draw-order keyframe landed on a visually stable frame. Move the switch to the most-occluded frame.
  • Joints locking at full extension. No softness on the IK, or the target is beyond the chain’s total length. Clamp the target distance first, then tune softness.
  • Hair flying apart at low frame rates. Physics integrated by frame count rather than real time, or dt left unclamped.

Which layer to add first

None of this has to arrive at once. Ranked by return: get the bone hierarchy and weights clean first, since everything else builds on them; add the draw-order track next, because turns are close to mandatory; then use transform constraints to solve follow-through and lag in bulk, which is the best effort-to-result ratio available; and leave mesh deformation for last, applied only to the parts a viewer actually studies — it carries the highest cost in both data and authoring time.

For the underlying bone and skinning mathematics, work through the 2D Animation Principles series in order.

Leave a Reply

Scroll down