MIRPAMO/CLAUDE.md
jing a148b4a543 MIRPAMO v0: local Mixamo — autorig + retarget via headless Blender
- autorig: landmark detection from vertex cloud (markers JSON override),
  mixamorig 22-bone skeleton fit, bone-heat weights + nearest-bone rescue
- retarget: world-space quaternion delta transfer, hip-height scale
  compensation, fuzzy/explicit bone mapping (CMU map bundled)
- smoke: procedural test humanoid + synthetic BVH -> rig -> retarget -> verify
- deploy: push to gitea, pull + smoke on m3ultra and m1ultra

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 01:26:13 +10:00

1.6 KiB

MIRPAMO — notes for Claude

Local Mixamo replacement: auto-rig + retarget via headless Blender. The CLI (bin/mirpamo) is plain python3 stdlib; ALL bpy code lives in bpy/ and runs as blender -b --python bpy/<stage>.py -- <args>. Never pip install anything — the pipeline must run on a bare Mac with only Blender.app present.

Verify

make smoke is the ground truth (procedural mesh → rig → retarget → verify). Run it after touching anything in bpy/. It must pass on Blender 5.0 and 5.1 (m1ultra is one minor version behind).

Conventions

  • Skeleton naming is mixamorig: — do not rename bones; the whole point is 1:1 compatibility with the existing Mixamo clip bank (~/Documents/mixamo-fetch/out/ on machines that have it).
  • Blender units: meters, Z-up, character on the floor facing -Y.
  • Outputs land in out/ (gitignored). Assets never get committed to this repo — meshes live in ~/Documents/character_kit/ and ~/Documents/3D=models/ per the asset-pipeline skill.
  • Deploy = make deploy (push to Gitea → pull on m3ultra + m1ultra → remote smoke). Hosts are listed in scripts/deploy.sh.

Gotchas

  • Bone-heat weighting (ARMATURE_AUTO) can fail on non-manifold meshes; autorig dies loudly when a mesh ends up without an armature modifier.
  • The retargeter computes pose-bone matrix_basis by hand (see formula in bpy/retarget.py) instead of setting pose_bone.matrix, to avoid a depsgraph update per bone per frame.
  • glTF export uses export_animation_mode='ACTIONS' when available so each retargeted clip becomes its own named animation.