File size: 4,314 Bytes
8f1bcd9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# rig_retarget

Pure-Python rig retargeting library. No Blender required.

Based on **[KeeMap Blender Rig Retargeting Addon](https://github.com/nkeeline/Keemap-Blender-Rig-ReTargeting-Addon)** by [Nick Keeline](https://github.com/nkeeline) (GPL v2).
All core retargeting math is a direct port of his work. Mapping JSON files are fully compatible with KeeMap.

---

## File layout

```
rig_retarget/
β”œβ”€β”€ math3d.py        # Quaternion / matrix math (numpy + scipy), replaces mathutils
β”œβ”€β”€ skeleton.py      # Armature + PoseBone with FK, replaces bpy armature objects
β”œβ”€β”€ retarget.py      # Core retargeting logic β€” faithful port of KeeMapBoneOperators.py
β”œβ”€β”€ cli.py           # CLI entry point
└── io/
    β”œβ”€β”€ bvh.py       # BVH mocap reader (source animation)
    β”œβ”€β”€ gltf_io.py   # glTF/GLB reader + animation writer (UniRig destination)
    └── mapping.py   # JSON bone mapping β€” same format as KeeMap
```

---

## Install

```bash
pip install numpy scipy pygltflib
```

---

## CLI

```bash
# Retarget BVH onto UniRig GLB
python -m rig_retarget.cli \
    --source  motion.bvh \
    --dest    unirig_character.glb \
    --mapping radical2unirig.json \
    --output  animated_character.glb \
    --fps 30 --start 0 --frames 200 --step 1

# Auto-calculate bone correction factors and save back to the mapping file
python -m rig_retarget.cli --calc-corrections \
    --source motion.bvh \
    --dest   unirig_character.glb \
    --mapping mymap.json
```

---

## Python API

```python
from rig_retarget.io.bvh     import load_bvh
from rig_retarget.io.gltf_io import load_gltf, write_gltf_animation
from rig_retarget.io.mapping  import load_mapping
from rig_retarget.retarget    import transfer_animation, calc_all_corrections

# Load
settings, bone_items = load_mapping("my_map.json")
src_anim = load_bvh("motion.bvh")
dst_arm  = load_gltf("unirig_char.glb")

# Optional: auto-calc corrections at first frame
src_anim.apply_frame(0)
calc_all_corrections(bone_items, src_anim.armature, dst_arm, settings)

# Transfer
settings.number_of_frames_to_apply = src_anim.num_frames
keyframes = transfer_animation(src_anim, dst_arm, bone_items, settings)

# Write output GLB
write_gltf_animation("unirig_char.glb", dst_arm, keyframes, "output.glb")
```

---

## Mapping JSON format

100% compatible with KeeMap's `.json` files. Use KeeMap in Blender to create
and tune mappings, then use this library offline for batch processing.

Key fields per bone:

| Field | Description |
|---|---|
| `SourceBoneName` | Bone name in the source rig (BVH joint name) |
| `DestinationBoneName` | Bone name in the UniRig skeleton (glTF node name) |
| `set_bone_rotation` | Drive rotation from source |
| `set_bone_position` | Drive position from source |
| `bone_rotation_application_axis` | Mask axes: `X` `Y` `Z` `XY` `XZ` `YZ` `XYZ` |
| `bone_transpose_axis` | Swap axes: `NONE` `ZYX` `ZXY` `XZY` `YZX` `YXZ` |
| `CorrectionFactorX/Y/Z` | Euler correction (radians) |
| `postion_type` | `SINGLE_BONE_OFFSET` or `POLE` |
| `position_pole_distance` | IK pole distance |

---

## Blender β†’ pure-Python mapping

| Blender | rig_retarget |
|---|---|
| `bpy.data.objects[name]` | `Armature` + `load_gltf()` / `load_bvh()` |
| `arm.pose.bones[name]` | `arm.get_bone(name)` β†’ `PoseBone` |
| `bone.matrix` (pose space) | `bone.matrix_armature` |
| `arm.matrix_world` | `arm.world_matrix` |
| `arm.convert_space(...)` | `arm.world_matrix @ bone.matrix_armature` |
| `bone.rotation_quaternion` | `bone.pose_rotation_quat` |
| `bone.location` | `bone.pose_location` |
| `bone.keyframe_insert(...)` | returned in `keyframes` list from `transfer_frame()` |
| `bpy.context.scene.frame_set(i)` | `src_anim.apply_frame(i)` |
| `mathutils.Quaternion` | `np.ndarray [w,x,y,z]` + `math3d.*` |
| `mathutils.Matrix` | `np.ndarray (4,4)` |

---

## Limitations / TODO

- **glTF source animation** reading not yet implemented (BVH only for now).
  Add `io/gltf_anim_reader.py` reading `gltf.animations[0]` sampler data.
- FBX source support: use `pyassimp` or `bpy` offline with `--background`.
- IK solving: pole bone positioning is FK-only; a full IK solver (FABRIK/CCD)
  would improve accuracy for limb targets.
- Quaternion mode twist bones: parity with Blender not guaranteed for complex twist rigs.