"""Pure-python linear-blend skinning check: skin a GLB's verts with its current node TRS (what Godot would render) and report max displacement of finger-weighted verts vs the original file. usage: skin_check.py posed.glb original.glb""" import json, struct, sys, math from pathlib import Path FING = ("thumb", "index", "middle", "ring", "pinky") def read_glb(path): d = Path(path).read_bytes() length = struct.unpack_from("0): continue x=y=z=0.0 for j,w in zip(jr,wr): w*=wsc if w<=0: continue M=JM[j] x+=w*(M[0][0]*p[0]+M[0][1]*p[1]+M[0][2]*p[2]+M[0][3]) y+=w*(M[1][0]*p[0]+M[1][1]*p[1]+M[1][2]*p[2]+M[1][3]) z+=w*(M[2][0]*p[0]+M[2][1]*p[1]+M[2][2]*p[2]+M[2][3]) out[vi]=(x,y,z) return out, names, joints posed_g, posed_b = read_glb(sys.argv[1]) orig_g, orig_b = read_glb(sys.argv[2]) a, names, joints = skinned_positions(posed_g, posed_b) c, _, _ = skinned_positions(orig_g, orig_b) dmax = 0; worst = None for vi in a: d = math.dist(a[vi], c[vi]) if d > dmax: dmax, worst = d, vi print(f"finger-weighted verts: {len(a)}; max displacement posed-vs-original: {dmax*100:.1f} cm (vert {worst})") import statistics ds = sorted(math.dist(a[vi], c[vi]) for vi in a) print(f"median: {ds[len(ds)//2]*100:.2f} cm, p95: {ds[int(len(ds)*0.95)]*100:.2f} cm")