Files
AIGame/Tools/model_tools/bl_soma_hand_cleanup_trial.py

44 lines
2.1 KiB
Python

"""CampGuide-only hand influence isolation experiment, preserving the fitted rig.
This intentionally does not fix joint placement, facing, feet, or neck weights.
Usage: blender -b --python <script> -- <skinned.glb> <out.glb>
"""
import json
import sys
from pathlib import Path
import bpy
src, dst = map(Path, sys.argv[sys.argv.index('--')+1:])
bpy.ops.wm.read_factory_settings(use_empty=True)
bpy.ops.import_scene.gltf(filepath=str(src))
mesh = max((o for o in bpy.context.scene.objects if o.type == 'MESH'), key=lambda o: len(o.data.vertices))
arm = next(o for o in bpy.context.scene.objects if o.type == 'ARMATURE')
height = max((mesh.matrix_world @ v.co).z for v in mesh.data.vertices)
changed = []
for v in mesh.data.vertices:
p = mesh.matrix_world @ v.co
# Restrict to the hands in this particular T-pose mesh.
if not (abs(p.x) > height*.255 and height*.55 < p.z < height*.67):
continue
side = 'Left' if p.x * (arm.matrix_world @ arm.data.bones['LeftHand'].head_local).x > 0 else 'Right'
allowed = {side+'Arm', side+'ForeArm', side+'Hand'}
old = {mesh.vertex_groups[g.group].name: g.weight for g in v.groups}
new = {name: value for name, value in old.items() if name in allowed}
total = sum(new.values())
if total < 1e-8:
new, total = {side+'Hand': 1.0}, 1.0
rejected = sum(value for name, value in old.items() if name not in allowed)
for g in list(v.groups):
mesh.vertex_groups[g.group].remove([v.index])
for name, value in new.items():
mesh.vertex_groups[name].add([v.index], value/total, 'REPLACE')
if rejected > .001:
changed.append({'vertex': v.index, 'rejected': rejected, 'old': old})
dst.parent.mkdir(parents=True, exist_ok=True)
bpy.ops.export_scene.gltf(filepath=str(dst), export_format='GLB', export_yup=True, export_skins=True, export_animations=False)
dst.with_suffix('.json').write_text(json.dumps({'purpose': 'hand-only nonlocal influence isolation; not production-ready',
'source': str(src), 'changed_over_0_001': len(changed), 'changes': changed}, indent=2), encoding='utf-8')
print('HAND_CLEANUP', len(changed))