#!/usr/bin/env python3 """Robust BGF (DIV-BIZ2) parser for the cockpit-shell reconstruction harness. Handles the vertex-format chunks the engine loader (bgfload.cpp) does: 0x80 XYZ(12) 0x81 XYZ_N(24) 0x82 XYZ_RGBA(28) 0x88 XYZ_UV(20) 0x89 XYZ_N_UV(32) 0x8A XYZ_RGBA_UV(36) Faces: 0x47 index list (u32 tri indices), 0x4d poly list (ppf-prefixed u32). Tree: 0x40 container / 0x41 object / 0x42 patch / 0x46 mesh; 0x2037 SV_SPECIAL (carries "PUNCH"); 0x2030 material name. Face indices are patch-local (base=patch vert start). Returns per-patch geometry so we see frame vs glass vs punch.""" import struct VSTRIDE = {0x80:12, 0x81:24, 0x82:28, 0x88:20, 0x89:32, 0x8A:36} VHASN = {0x81, 0x89} VHASUV = {0x88, 0x89, 0x8A} CONTAINERS = {0x40,0x41,0x42,0x46,0x48,0x70,0x10,0x20,0x30,0x3} def parse(path): d = open(path,"rb").read() patches = [] # each: dict(material, punch, verts[list (x,y,z,has_n,nx,ny,nz,u,v)], faces[list (a,b,c)]) cur = {"material":"", "punch":False} def read_chunk(p, end): if p+2 > end: return None tw = struct.unpack_from(" end: return None if lw==1: ln = d[p+2] elif lw==2: ln = struct.unpack_from(" PUNCH? if patch is not None and b"PUNCH" in d[body:body+ln]: patch["punch"] = True elif cid in VSTRIDE: # vertex chunk -> this submesh's face indices are st = VSTRIDE[cid]; hasn = cid in VHASN; hasuv = cid in VHASUV patch["_base"] = len(patch["verts"]) # local to THIS chunk (base offset) n = ln // st for i in range(n): o = body + i*st x,y,z = struct.unpack_from("=1: b = patch.get("_base",0); ppf = d[body]; n=(ln-1)//4 idx=[struct.unpack_from("1 else "content/VIDEO/GEO/MAX_COP.BGF" P = parse(path) print(f"{path}: {len(P)} patches") allV=[]; ec=Counter(); tot_faces=0; punch_faces=0 for i,pt in enumerate(P): V=np.array([(v[0],v[1],v[2]) for v in pt["verts"]]) hasuv = any(v[7]!=0 or v[8]!=0 for v in pt["verts"]) hasn = any(v[3] for v in pt["verts"]) F=pt["faces"] lo=V.min(0); hi=V.max(0); cen=V.mean(0) for a,b,c in F: if max(a,b,c)>=len(V): continue for e in ((a,b),(b,c),(c,a)): ec[tuple(sorted(e))]+=1 tot_faces+=len(F) if pt["punch"]: punch_faces+=len(F) print(f" patch{i}: mtl='{pt['material'][:30]}' punch={pt['punch']} " f"verts={len(V)} faces={len(F)} uv={hasuv} n={hasn} " f"cen=({cen[0]:.2f},{cen[1]:.2f},{cen[2]:.2f}) " f"bbox=[{lo[0]:.2f},{lo[1]:.2f},{lo[2]:.2f}]..[{hi[0]:.2f},{hi[1]:.2f},{hi[2]:.2f}]") bound=sum(1 for k,vv in ec.items() if vv==1) print(f"TOTAL faces={tot_faces} punch_faces={punch_faces} boundary_edges={bound}/{len(ec)}")