"Rigging an AI-generated (rigless) character mesh"
▸ SYMPTOM
- AI character arrives as a static textured mesh (no armature).
- Blender automatic weights fail with:
Bone Heat Weighting: failed to find solution. - All vertex groups empty, even for a tiny 2-bone rig on a cleaned single-island mesh.
- Euclidean "nearest bone" weights look plausible in the viewport but cheeks follow arms, etc. on chibi proportions.
▸ CAUSE
Bone-heat auto-weights fail wholesale on many AI-generated meshes. Topology/island quirks that look fine visually still break the heat solver.
Euclidean nearest-bone assignment is not enough. Chibi proportions put cheek verts closer to arm bones than the head bone in 3D space, even when they should belong to the head along the surface.
Also: Blender's OBJ importer puts the Y-up→Z-up fix on the object transform. mesh.vertices[i].co stays file-local Y-up. Any scripted landmark/seed math must use obj.matrix_world @ v.co or seeds are silently wrong.
▸ FIX
Proven local lane (headless Blender):
- Copy the mesh out of any regenerating AI delivery folder (re-runs overwrite).
- Hand-build (or script) an armature: pelvis as true root; no extra roots above it.
- Scripted geodesic weights (along-surface Dijkstra) to per-bone seed tubes:
- top-3 bones
- inverse-power blend
- ~10 diffusion passes
- cap 4 influences
- Scripted keyframe clips; keep quaternion keys hemisphere-continuous (
if dot(prev, new) < 0: negate). - Export FBX per fbx-export-recipe.
- Animated
.vmdlusing citizen as schema reference; scale withModelModifier_ScaleAndMirror0.3937 (cm sources), not per-fileimport_scaleon the mesh alone (that leaves AnimFile data unscaled).
Blender meters → FBX centimeters (apply_unit_scale) → ScaleAndMirror 0.3937 → engine inchesAnimationList wants default_root_bone_name = "pelvis"; set bone_cull_type = "None" to keep helper bones. Schema reference: addons/citizen/Assets/models/citizen/citizen.vmdl + its prefabs/*.vmdl_prefab.
Runtime: play sequences on SkinnedModelRenderer (Sequence.Name = "..."). Enable crossfade-without-animgraph for smooth switches. Do not rely on SetBoneTransform / SetIk for secondary motion on a sequence-only rig. See setbonetransform-silently-noop.
▸ WHY IT WORKS
Geodesic distance follows the mesh surface, so influence regions match anatomical adjacency instead of 3D proximity through empty space. Cap + diffusion keeps skinning engine-friendly (≤4 influences). ScaleAndMirror is the citizen convention that scales mesh and animations together; splitting scale across import_scale vs anim files is what produces correctly sized meshes with microscopic (or gigantic) motion.