31 lines
1.8 KiB
Python
31 lines
1.8 KiB
Python
"""Compare Unity evaluation against raw FBX joint trajectories, pelvis-relative."""
|
|
import json,math
|
|
from pathlib import Path
|
|
|
|
ROOT=Path(__file__).resolve().parents[2]
|
|
OUT=ROOT/'Tools/output/campguide_studio/playback_audit'
|
|
reference=json.loads((OUT/'fbx_reference.json').read_text(encoding='utf-8'))[1]
|
|
comparison=json.loads((OUT/'comparison.json').read_text(encoding='utf-8'))
|
|
def sub(a,b):return [a[i]-b[i] for i in range(3)]
|
|
def length(a):return math.sqrt(sum(v*v for v in a))
|
|
def unity(p):return [-p[0],p[2],-p[1]]
|
|
def angle(a,b):return math.degrees(math.acos(max(-1,min(1,sum(a[i]*b[i] for i in range(3))/(length(a)*length(b))))))
|
|
report=[]
|
|
for entry in comparison['samples']:
|
|
maximum=0;feet_max=0;angles=[];gaps=[]
|
|
for frame,pose in enumerate(entry['frames']):
|
|
raw={name:unity(p) for name,p in reference['samples'][frame]['world'].items()}
|
|
for name,p in pose.items():
|
|
delta=sub(sub(p,pose['mixamorig:Hips']),sub(raw[name],raw['mixamorig:Hips']))
|
|
error=length(delta);maximum=max(maximum,error)
|
|
if name.endswith('Foot'):feet_max=max(feet_max,error)
|
|
for side in ('Left','Right'):
|
|
ankle='mixamorig:'+side+'Foot';toe='mixamorig:'+side+'ToeBase'
|
|
angles.append(angle(sub(pose[toe],pose[ankle]),sub(raw[toe],raw[ankle])))
|
|
gaps.append(pose['mixamorig:RightFoot'][0]-pose['mixamorig:LeftFoot'][0])
|
|
report.append(dict(variant=entry['tag'],max_joint_error_m=maximum,max_ankle_error_m=feet_max,
|
|
max_foot_direction_error_degrees=max(angles),min_signed_ankle_gap_m=min(gaps),crossed_frames=sum(g<0 for g in gaps)))
|
|
print(json.dumps(report,indent=2))
|
|
assert report[0]['max_joint_error_m']<.001,'Generic reference does not match the original FBX'
|
|
(OUT/'summary.json').write_text(json.dumps(report,indent=2),encoding='utf-8')
|