31ba2911df
Skills (.claude/skills/): animation-creation, iclone-video-mocap, pose-estimation (MediaPipe models via LFS), retarget-animations (deprecated). Tools: cc/mixamo/kevin/mocap retargeters + composite baker. Plans: animation-gen-pipeline + skills-adoption. exchange/: incoming-fbx, converted-glb, reference-video (LFS for fbx/glb/mp4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Skill: Animation Retargeting (Kevin → BoZo) — DEPRECATED
DEPRECATED May 19, 2026. BoZo and Kevin characters retired. Quaternius character system replaces them — no retargeting needed. This skill is kept for engine reference (Godot fork rest fixer fix).
# 1. Clean import (creates default .import files)
rm -f assets/animations/kevin/*.import assets/models/characters/Body/Body_BasicBody.fbx.import
rm -f .godot/imported/Archer*.scn .godot/imported/Body_BasicBody*.scn .godot/imported/Villager*.scn .godot/imported/Throwing*.scn
godot --headless --path . --import
# 2. Patch .import files with BoneMap + retarget config
godot --headless --path . -s setup_retarget.gd
# 3. Delete cache + reimport with retarget config
rm -f .godot/imported/Archer*.scn .godot/imported/Body_BasicBody*.scn .godot/imported/Villager*.scn .godot/imported/Throwing*.scn
godot --headless --path . --import
IMPORTANT: Must delete .godot/imported/*.scn cache between steps 2→3, otherwise Godot skips reimport.
What the pipeline does
- Bone renamer: Renames Kevin bones (
B-hips→Hips) and BoZo bones (pelvis→Hips) to Humanoid standard - Overwrite Axis (method 1): Changes skeleton rest poses to match SkeletonProfileHumanoid reference
- Animation conversion: Transforms keyframe values from old rest coordinate system to new rest coordinate system using formula from
post_import_plugin_skeleton_rest_fixer.cpp:777:new_q = new_pg_q.inv * old_pg_q * qt * old_rest_q.inv * old_pg_q.inv * new_pg_q * new_rest_q
Known Bug (patched in tinqs/godot fork)
Commit: 4e16c3f5bd on main
The %GeneralSkeleton unique node resolution via get_node() fails in headless import mode. Original code at line 733:
Node *node = (ap->get_node(ap->get_root_node()))->get_node(NodePath(track_path));
ERR_CONTINUE(!node); // Silently skips ALL animation tracks!
Fix: Falls back to find_child() when unique name resolution fails. Without this fix, rest poses change but animation keyframe values stay in the old coordinate system.
Current Status (2026-05-18)
Working:
- Bone renaming (Kevin → Humanoid, BoZo → Humanoid) ✓
- Rest pose overwrite to Humanoid reference ✓
- Skeleton node resolution fix (find_child fallback) ✓
- Animation conversion runs for spine/chest bones ✓
NOT working:
- Animation conversion appears to be a NO-OP for limb bones (arms, legs)
- Spine keys → near identity (correct). Arm/leg keys → near rest (unconverted)
- Root cause: unknown. Possibly old_rest captured AFTER partial overwrite, or formula output matches input for bones with specific rest orientations
Visual symptoms:
- Arms cross behind back during animation
- Legs may be double-rotated (rest * rest)
- Spine animates correctly
Bone Mapping
Kevin → Humanoid
| Humanoid | Kevin |
|---|---|
| Hips | B-hips |
| Spine | B-spine |
| Chest | B-chest |
| UpperChest | B-upperChest |
| Neck | B-neck |
| Head | B-head |
| LeftShoulder | B-shoulder.L |
| LeftUpperArm | B-upper_arm.L |
| LeftLowerArm | B-forearm.L |
| LeftHand | B-hand.L |
| Right* | B-*.R (mirror) |
| LeftUpperLeg | B-thigh.L |
| LeftLowerLeg | B-shin.L |
| LeftFoot | B-foot.L |
| LeftToes | B-toe.L |
| Right* | B-*.R (mirror) |
BoZo → Humanoid
| Humanoid | BoZo |
|---|---|
| Hips | pelvis |
| Spine | spine_01 |
| Chest | spine_03 |
| UpperChest | spine_05 |
| Neck | neck_01 |
| Head | head |
| LeftShoulder | clavicle_l |
| LeftUpperArm | upperarm_l |
| LeftLowerArm | lowerarm_l |
| LeftHand | hand_l |
| Right* | *_r (mirror) |
| LeftUpperLeg | thigh_l |
| LeftLowerLeg | calf_l |
| LeftFoot | foot_l |
| LeftToes | ball_l |
| Right* | *_r (mirror) |
BoZo intermediate bones (spine_02, spine_04, neck_02) have no Kevin equivalent and keep global rest.
Key Files
| File | Purpose |
|---|---|
setup_retarget.gd |
Headless script: patches .import files with BoneMap + retarget config |
run_retarget.gd |
EditorScript: same but runs inside Godot editor GUI |
addons/retarget_setup/plugin.gd |
EditorPlugin: auto-runs on editor start |
assets/retarget/kevin_bonemap.tres |
Kevin → Humanoid BoneMap resource |
assets/retarget/bozo_bonemap.tres |
BoZo → Humanoid BoneMap resource |
inspect_fbx.gd |
Debug: prints bone names, rest poses, animation values |
src/Viewer/PlayerController.cs |
Character: loads animation, remaps %GeneralSkeleton paths |
Godot Engine Source (for debugging)
| File | What |
|---|---|
editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp |
Overwrite Axis + animation conversion |
editor/import/3d/post_import_plugin_skeleton_renamer.cpp |
Bone renaming |
scene/3d/retarget_modifier_3d.cpp |
Runtime retargeting (RetargetModifier3D) |
scene/resources/bone_map.cpp |
BoneMap resource |
scene/resources/skeleton_profile.cpp |
SkeletonProfile + Humanoid preset |
What NOT to do
- Manual quaternion retargeting in C# — tried 5 different formulas, all failed. The formula requires parent GLOBAL rest transforms for the entire bone chain. Only Godot's engine code handles this correctly.
- Rename BoZo bones at runtime — breaks outfit/clothing FBX loading (bone name mismatch).
- BoneAttachment3D for head without inverse rest compensation — double-transforms the head.
- Headless import without deleting .scn cache — Godot skips reimport if source FBX unchanged.