"""Remove only zero-area triangle indices from final uncompressed GLBs.
Positions, normals, UVs, skinning and every animation accessor are unchanged.
"""
from pathlib import Path
import struct,json,numpy as np
P=Path('/opt/creature-lib-20261017');changes=[]
for p in (P/'glb').glob('*.glb'):
 raw=p.read_bytes();jl=struct.unpack_from('<I',raw,12)[0];g=json.loads(raw[20:20+jl]);bl=struct.unpack_from('<I',raw,20+jl)[0];binary=bytearray(raw[28+jl:28+jl+bl]);removed=0
 def arr(ai):
  a=g['accessors'][ai];v=g['bufferViews'][a['bufferView']];dtype=np.dtype({5121:'u1',5123:'<u2',5125:'<u4',5126:'<f4'}[a['componentType']]);w={'SCALAR':1,'VEC2':2,'VEC3':3,'VEC4':4}[a['type']]
  return np.ndarray((a['count'],w),dtype=dtype,buffer=binary,offset=v.get('byteOffset',0)+a.get('byteOffset',0),strides=(v.get('byteStride',w*dtype.itemsize),dtype.itemsize)).copy()
 for m in g['meshes']:
  for pr in m['primitives']:
   idx=arr(pr['indices']).reshape(-1,3);pos=arr(pr['attributes']['POSITION']);t=pos[idx].astype(float);ok=np.linalg.norm(np.cross(t[:,1]-t[:,0],t[:,2]-t[:,0]),axis=1)>=1e-12;n=int((~ok).sum())
   if not n:continue
   removed+=n;out=idx[ok].reshape(-1).astype('<u4');binary.extend(b'\0'*(-len(binary)%4));offset=len(binary);binary.extend(out.tobytes());vi=len(g['bufferViews']);g['bufferViews'].append({'buffer':0,'byteOffset':offset,'byteLength':out.nbytes,'target':34963});ai=len(g['accessors']);g['accessors'].append({'bufferView':vi,'componentType':5125,'count':len(out),'type':'SCALAR','min':[int(out.min())],'max':[int(out.max())]});pr['indices']=ai
 if removed:
  g['buffers'][0]['byteLength']=len(binary);js=json.dumps(g,separators=(',',':')).encode();js+=b' '*(-len(js)%4);binary.extend(b'\0'*(-len(binary)%4));out=struct.pack('<III',0x46546c67,2,28+len(js)+len(binary))+struct.pack('<II',len(js),0x4e4f534a)+js+struct.pack('<II',len(binary),0x004e4942)+binary;p.write_bytes(out);changes.append({'file':p.name,'removed_zero_area_triangles':removed});print(changes[-1])
(P/'evidence/degenerate-cleanup.json').write_text(json.dumps(changes,indent=2))
