"""Export unretargeted Mixamo FBX rest/animated joint positions for Unity comparison.""" import sys,json,hashlib from pathlib import Path import bpy import numpy as np ROOT=Path(__file__).resolve().parents[2] OUT=ROOT/'Tools/output/campguide_studio/playback_audit';OUT.mkdir(parents=True,exist_ok=True) paths=[ROOT/'AIClient/Assets/Bundles/Characters/Human/test/Boy_mixamo/CampGuideStudio.fbx',ROOT/'AIClient/Assets/Bundles/Characters/Human/Common/Walking.fbx'] report=[] for path in paths: bpy.ops.wm.read_factory_settings(use_empty=True);bpy.ops.import_scene.fbx(filepath=str(path),use_anim=True) arm=next(o for o in bpy.context.scene.objects if o.type=='ARMATURE') action=arm.animation_data.action if arm.animation_data else None start,end=action.frame_range if action else (1,1) rest={b.name:dict(parent=b.parent.name if b.parent else None,world=list(arm.matrix_world@b.head_local),matrix=[list(r) for r in arm.matrix_world@b.matrix_local]) for b in arm.data.bones} samples=[] for frame in np.linspace(start,end,32) if action else [1]: whole=int(frame);bpy.context.scene.frame_set(whole,subframe=float(frame-whole));bpy.context.view_layer.update() samples.append(dict(frame=float(frame),world={b.name:list(arm.matrix_world@b.head) for b in arm.pose.bones})) entry=dict(path=str(path.relative_to(ROOT)),sha256=hashlib.sha256(path.read_bytes()).hexdigest(),bones=len(rest),rest=rest,frame_start=float(start),frame_end=float(end),fps=bpy.context.scene.render.fps,samples=samples) report.append(entry);print('FBX_REFERENCE',path.name,len(rest),start,end) (OUT/'fbx_reference.json').write_text(json.dumps(report,indent=2),encoding='utf-8')