A runnable example that rigs a mech arm — flanged bolted pedestal and
shoulder fairing, a panel-seamed upper arm ending in clevis cheeks, the
elbow hinge pin and knuckle barrel capped with hex bolts through a ribbed
flex cuff, a long seam-grooved forearm, wrist cuff and collar, and a
three-finger gripper — with deliberately rich five-bone weight bumps in
the cuffs, then enforces the game-engine
maximum of four bone influences per vertex through the data API, following
mesh-editing-and-bmesh and
building on the linear-blend-skinning precedent of
armature-bend.
Pipeline arc: modeling/LOD in lod-decimate-chain,
weighting here, export in gltf-export-roundtrip.
What it witnesses: the skinning constraint every game engine enforces and AI-generated rigging code most often violates silently.
- The limit is a data-API operation, not a context operator. Instead of
bpy.ops.object.vertex_group_limit_total, the example reads each vertex's groups, keeps the top four by weight,VertexGroup.removes the rest, and renormalizes the survivors. Dropping without renormalizing leaves sums at 0.984 — a mesh that shrinks toward the origin under load (the check's measured failure, 1.616e-02 off unit sum). - The armature modifier is still exactly linear blend skinning after the
limit: every depsgraph-evaluated vertex equals
Σ wᵢ · (pose.matrix @ bone.matrix_local.inverted()) @ rest, with the weights read back from the mesh's own deform layer (v.groups) — the weights on the mesh are the contract, not the weights you meant to write. Measuredlbs_err = 2.7e-07. - Pruning must not damage the pose. Evaluated positions before and after the limit are held within 0.05 (measured 2.8e-03), the pedestal mount stays exactly pinned (Root is unposed), and the pre-limit authoring really carries five influences in the cuffs — otherwise the witness would be vacuous.
The vertex-group API (v.groups, VertexGroup.add/remove) is stable between
Blender 4.5 LTS and 5.1 — the example runs identically on both, which is itself
the version witness (measured values match to the digit).
The render shows the pruned arm mid-pose: the flex cuffs carry the teal accent — the five-influence zones the limit prunes glow at the elbow hinge and wrist, sealed by the bright hoop on the elbow cuff — proof that the limited weights still deform as authored.
# Cheap correctness check (no render) — the CI check:
blender --background --python vertex_weight_limit.py --
# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts):
blender --background --python vertex_weight_limit.py -- --output arm.png
blender --background --python vertex_weight_limit.py -- --output arm.png --engine cyclesIt exits non-zero on failure (vacuous authoring, a vertex over the cap, broken
weight sums, pose damaged by pruning, LBS drift, or a moved Root mount). The
blender-smoke workflow runs the check on Blender 4.5 LTS and 5.1.
The --output render path additionally measures framing against the Layer 1 band via examples/gallery_framing.py (exit 10 on violation) before writing the still.