"""Per-finger-bone territory audit: how many verts does each finger bone actually OWN (dominant weight) and how much total weight mass does it carry? Why: fin_bones classifies exp05's fist tears as hand<->thumb_02 and hand<->index_02 — the chain skips the _01 joints. If the _01 bones own no territory, every curl lands as a hard one-edge step from the palm to phalanx 2, which must stretch. This measures that directly instead of inferring it. usage: bone_territory.py body.glb """ import json import struct import sys from pathlib import Path DIGITS = ("thumb", "index", "middle", "ring", "pinky") def read_glb(path): d = Path(path).read_bytes() ln = struct.unpack_from("1% for ji, wi in zip(J, W): ws = [w * sc for w in wi] best, bw = None, 0.0 for jj, w in zip(ji, ws): n = names[jj] mass[n] += w if w > 0.01: any_w[n] += 1 if w > bw: best, bw = n, w if best is not None and bw > 0: own[best] += 1 print(f"{Path(sys.argv[1]).name} {len(J)} verts, {len(joints)} joints") print(f"{'bone':16s} {'owns':>7s} {'any>1%':>8s} {'mass':>9s}") for side in ("l", "r"): print(f"--- hand_{side} chain ---") for nm in [f"hand_{side}"] + [f"{d}_{p}_{side}" for d in DIGITS for p in ("01", "02", "03")]: if nm not in own: print(f"{nm:16s} (absent from skin)") continue flag = " <-- STARVED" if own[nm] == 0 else "" print(f"{nm:16s} {own[nm]:7d} {any_w[nm]:8d} {mass[nm]:9.1f}{flag}")