Files
AIGame/Tools/model_tools/bl_audit_mixamo_playback.py

24 lines
1.7 KiB
Python

"""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')