Files

132 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

# 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).
```bash
# 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
1. **Bone renamer:** Renames Kevin bones (`B-hips``Hips`) and BoZo bones (`pelvis``Hips`) to Humanoid standard
2. **Overwrite Axis (method 1):** Changes skeleton rest poses to match SkeletonProfileHumanoid reference
3. **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:
```cpp
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
1. **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.
2. **Rename BoZo bones at runtime** — breaks outfit/clothing FBX loading (bone name mismatch).
3. **BoneAttachment3D for head without inverse rest compensation** — double-transforms the head.
4. **Headless import without deleting .scn cache** — Godot skips reimport if source FBX unchanged.