Spaces:
Running on Zero
Running on Zero
| # 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. | |