- 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>
36 lines
1.6 KiB
Markdown
36 lines
1.6 KiB
Markdown
# MIRPAMO — notes for Claude
|
|
|
|
Local Mixamo replacement: auto-rig + retarget via **headless Blender**.
|
|
The CLI ([bin/mirpamo](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](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](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.
|