Files
AIGame/Tools/summarize_lmgirl_mixamo41.py

78 lines
8.1 KiB
Python

"""Record provenance, controlled comparisons and limits of the LmGirl trial."""
import hashlib
import json
from pathlib import Path
root=Path(__file__).resolve().parents[1]
folder=root/'Tools/output/lmgirl_tpose_studio/rig_mixamo41'
def read(name):return json.loads((folder/name).read_text(encoding='utf-8'))
def digest(path):return hashlib.sha256(path.read_bytes()).hexdigest()
comparison=read('walking_comparison.json');fit=read('input_manifest.json')
topology=read('topology_audit.json')
native=read('unity_verification.json');exports=read('export_verification.json')
original=json.loads((folder.parent/'static_export.json').read_text(encoding='utf-8'))
report={
'conclusion':'LmGirl reuses the exact CampGuide Walking clip through bind-translation adaptation. Character-specific locality constraints eliminate the tested large hand/leg stretches without editing mesh geometry or UVs.',
'source':'Tools/output/lmgirl_tpose_studio/static/LmGirlTpose.fbx',
'source_sha256':topology['source_sha256'],
'skeleton_reference':'AIClient/Assets/Bundles/Characters/Human/test/Boy_mixamo/CampGuideStudio.fbx',
'bones':41,'triangles':4999,'vertices':4205,'website_weights_used':False,
'geometry_modified':False,'uv_preserved':topology['source_uv_sha256']==original['uvHashAfter'],
'fit':{'method':fit['fit'],'max_preserved_axis_rotation_error_radians':fit['max_preserved_axis_rotation_error_radians'],
'translation_scale':1.23711741,'source_rotation_curves_modified':False},
'animation':{'source':'AIClient/Assets/Review/CharacterAnimationLab/Generated/Walking.anim','same_native_asset':True,'frames':32,'fps':30,
'adaptation':'After shared clip sampling, local translation = source translation * scale + target-bind/source-bind offset. In-place removal uses the same scale. All rotation curves unchanged.'},
'remote':{'host':'DGXA','job':'/home/spark/SkinTokens/tmp_jobs/lmgirl_mixamo41_20261023_a1','seed':20261023,
'flags':['use_skeleton','use_transfer','use_postprocess','skeleton_template=original','rig_cls=vroid'],
'same_prediction_for_raw_and_voxel':True,'installed_demo_sha256':(folder/'installed_demo.sha256').read_text().strip(),
'instrumentation':'Tools/tokenrig_lmgirl_trial_remote.py; shared TokenRig code unchanged; raw and post weight snapshots retained',
'texture_note':'Input GLB is weight-blind geometry+skeleton without texture payload. Final Unity textures use local original UVs and baked source maps; texture transfer itself was not separately tested.'},
'comparisons':{k:{n:v[n] for n in ['maxStretch','maxEdgesOver2x','maxP99','handMaxLowerBodyInfluence','maxInfluences','minimumNonzeroWeight','floorMinRange']} for k,v in comparison.items()},
'optimization_assessment':{
'use_postprocess':'Official voxel-distance multiplicative reweighting. Suppresses distant leaks but worsened neck and upper-tail edge distribution on this mesh; not enabled in the selected local variant.',
'clean_weights':'Third-party skeleton-hop + Euclidean-distance heuristic, not mesh-connectivity repair. Default min_hops=5 removed Head influence from braid vertices and worsened maximum stretch. Not selected globally.',
'use_transfer':'Enabled in inference. Exact original geometry and UVs are additionally restored in local outputs; local texture maps retained.',
'epsilon_and_top4':'Official transfer/export already uses group_per_vertex=4. Selected local variant also drops weights <0.01 and renormalizes. Epsilon alone cannot remove 0.2868 or 0.4509 contamination.',
'topology':'Below-crotch graph test found no connection between lower pant legs. Initial visual suspicion of welded trousers was rejected; opposite-leg weight leakage was corrected without topology changes.'},
'selected':'local','scene':'AIClient/Assets/Review/CharacterAnimationLab/LmGirl/LmGirlAnimationLab.unity',
'limits':['Character-specific T-pose geometric masks; not a universal cleanup for arbitrary models or poses.',
'41 bones retained; hands currently follow the wrist rigidly, so finger articulation is intentionally not preserved.',
'Edge stretch excludes rest edges shorter than 0.2% of height and does not score volume preservation, penetration or aesthetics.',
'Walking floor min spans about -10.6 to +23.7mm at source scale; foot IK, contact and sliding not solved.',
'Breathing and Happy Idle controls reuse the original clips, but quantitative deformation audit here covers Walking only.'],
'validation':{'native':native,'exports':exports,'controls':read('unity_controls.json')},
'references':['https://github.com/VAST-AI-Research/SkinTokens/blob/main/demo.py',
'https://github.com/VAST-AI-Research/SkinTokens/blob/main/src/data/vertex_group.py',
'https://github.com/stevelittlefish/ComfyUI-SkinTokens-NoBlender/blob/main/skintokens/weight_repair.py'],
'artifacts_sha256':{name:digest(folder/name) for name in ['source.glb','rigged_raw.glb','rigged_post.glb','raw_prediction.npz','post_prediction.npz','weight_repair_upstream.py','Walking_local.glb','lmgirl_local.blend']}}
if (folder/'website/walking_comparison.json').exists():
website=read('website/walking_comparison.json')
report['website_comparison']={k:v for k,v in website.items() if k!='samples'}
report['website_comparison']['limitation']='This compares delivered website binding (33 bones) with the fitted TokenRig binding (41 bones), not a weights-only controlled comparison. Both sample the same source clip and time, with bind-aware rotation/translation adaptation.'
report['scene_lineup']=['Mixamo website (33 bones, up to 5 influences)','TokenRig raw (41 bones)','Voxel postprocess (41 bones)','Local constraints (41 bones)']
report['artifacts_sha256']['website_source_fbx']=digest(root/'AIClient/Assets/Bundles/Characters/Human/test/girl/LmGirlTpose.fbx')
report['artifacts_sha256']['website_review_data']=digest(folder/'website/unity_review_data.json')
if (folder/'unity_gait_verification.json').exists():
gait=read('gait_correction.json');before=read('gait_diagnosis_before.json')
report['conclusion']='Girl ankle crossing was caused by angle-only retargeting from the boy wide-leg bind to the girl nearly-parallel bind. Active girl playback now uses target clips with proportionally mapped source ankle trajectories and analytic two-bone IK; skin weights and the boy source clip are unchanged.'
report['animation']['same_native_asset']=False
report['animation']['source_clip_unmodified']=True
report['animation']['target_clips']=['AIClient/Assets/Review/CharacterAnimationLab/LmGirl/Generated/Walking_LmGirl41.anim',
'AIClient/Assets/Review/CharacterAnimationLab/LmGirl/Generated/Walking_LmGirlMixamo33.anim']
report['animation']['adaptation']=gait['method']
report['baseline_comparisons']=report.pop('comparisons')
report['active_comparisons']=gait['deformation']
report['gait_before']={k:{n:v for n,v in d.items() if n!='samples'} for k,d in before.items()}
report['gait_after']={k:{n:v for n,v in d.items() if n!='tracks'} for k,d in gait['reports'].items()}
report['validation']['baseline_native']=report['validation'].pop('native')
report['validation']['baseline_exports']=report['validation'].pop('exports')
report['validation']['gait']=read('unity_gait_verification.json')
report['validation']['gait_exports']=read('gait_export_verification.json')
report['limits']=[x for x in report['limits'] if not x.startswith('Walking floor min')]
report['limits'].append('Leg IK fixes stance/ankle paths, but ground contact locking and zero foot sliding remain unverified. Local skin floor min spans about -14.5 to +13.8mm at source scale.')
for tag in ['raw','post','clean','clean_eps','local']:
name='Walking_'+tag+'_corrected.glb';report['artifacts_sha256'][name]=digest(folder/name)
assert native['passed'] and exports['passed'] and report['uv_preserved']
(folder/'summary.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
print('PASS summary:',folder/'summary.json')