git init + .gitignore (weights/capture/queue/out/media excluded), docs/LICENSES.md skeleton with the SMPL gate, PROGRESS.md ledger, and spec/mixamorig_bones.json — 65 mixamorig bones (colon-prefixed) dumped from character_kit/female/female_game.glb via headless Blender. This bone file is the retarget ground truth for Lane C. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
34 lines
1.2 KiB
Python
34 lines
1.2 KiB
Python
# Lane 0: dump the mixamorig armature (names + rest pose) from character_kit → ground truth.
|
|
# Run: Blender --background --python spec/dump_bones.py
|
|
import bpy, json, os, sys
|
|
|
|
GLB = os.path.expanduser("~/Documents/character_kit/female/female_game.glb")
|
|
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "mixamorig_bones.json")
|
|
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
bpy.ops.import_scene.gltf(filepath=GLB)
|
|
|
|
arm = next((o for o in bpy.data.objects if o.type == "ARMATURE"), None)
|
|
if arm is None:
|
|
sys.exit("no armature in " + GLB)
|
|
|
|
def v(x): # round rest coords, they're the reference not gospel
|
|
return [round(c, 6) for c in x]
|
|
|
|
bones = [{
|
|
"name": b.name,
|
|
"parent": b.parent.name if b.parent else None,
|
|
"head": v(b.head_local), # armature-space rest pose
|
|
"tail": v(b.tail_local),
|
|
} for b in arm.data.bones]
|
|
|
|
json.dump({
|
|
"source": os.path.relpath(GLB, os.path.expanduser("~/Documents")),
|
|
"armature": arm.name,
|
|
"count": len(bones),
|
|
"units": "metres, Y-up (Blender Z-up native; glTF import applies +90X)",
|
|
"joint_order": [b["name"] for b in bones],
|
|
"bones": bones,
|
|
}, open(OUT, "w"), indent=1)
|
|
print("===DUMP=== %d bones -> %s" % (len(bones), OUT))
|