35 lines
1.8 KiB
Python
35 lines
1.8 KiB
Python
"""Controlled local-influence cleanup of TokenRig-41 hand weights only."""
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import bpy
|
|
|
|
folder=Path(sys.argv[sys.argv.index('--')+1])
|
|
bpy.ops.wm.open_mainfile(filepath=str(folder/'tokenrig_mixamo41.blend'))
|
|
arm=next(o for o in bpy.context.scene.objects if o.type=='ARMATURE')
|
|
mesh=next(o for o in bpy.context.scene.objects if o.type=='MESH')
|
|
height=max((mesh.matrix_world@v.co).z for v in mesh.data.vertices)
|
|
changes=[]
|
|
for v in mesh.data.vertices:
|
|
p=mesh.matrix_world@v.co
|
|
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['mixamorig:LeftHand'].head_local).x>0 else 'Right'
|
|
old={mesh.vertex_groups[g.group].name:g.weight for g in v.groups}
|
|
allowed={n:w for n,w in old.items() if n in (f'mixamorig:{side}Arm',f'mixamorig:{side}ForeArm') or n.startswith(f'mixamorig:{side}Hand')}
|
|
total=sum(allowed.values())
|
|
rejected=sum(w for n,w in old.items() if n not in allowed)
|
|
assert total>1e-8
|
|
for g in list(v.groups):
|
|
mesh.vertex_groups[g.group].remove([v.index])
|
|
for n,w in allowed.items():
|
|
mesh.vertex_groups[n].add([v.index],w/total,'REPLACE')
|
|
if rejected>.001:
|
|
changes.append({'vertex':v.index,'removed':rejected,'old':old})
|
|
(folder/'local_cleanup.json').write_text(json.dumps({'method':'CampGuide-specific T-pose hand-region whitelist; same-side Arm/ForeArm/Hand/fingers only; renormalize; no reference weights',
|
|
'changed_vertices_over_0_001':len(changes),'changes':changes},indent=2),encoding='utf-8')
|
|
bpy.ops.wm.save_as_mainfile(filepath=str(folder/'tokenrig_mixamo41_local.blend'),compress=True)
|
|
bpy.ops.export_scene.gltf(filepath=str(folder/'tokenrig_mixamo41_local.glb'),export_format='GLB',export_skins=True,export_animations=False,export_def_bones=False)
|
|
print('LOCAL_CLEANUP',len(changes))
|