File size: 2,315 Bytes
61c0834
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
"""Inventory every extracted MD3 occurrence, preserving archive/case variants."""
import hashlib
from collections import defaultdict
from pathlib import Path
from md3 import MD3
from analyze_qvm import write_json

def paths():return sorted(p for p in Path('assets/extracted').rglob('*') if p.is_file() and p.suffix.lower()=='.md3')
def virtual(p):
    parts=p.parts;j=parts.index('members');return '/'.join(parts[j+2:])
def main():
    rows=[];groups=defaultdict(list)
    for p in paths():
        raw=p.read_bytes();r={'path':str(p),'virtual_path':virtual(p),'sha256':hashlib.sha256(raw).hexdigest(),'bytes':len(raw)}
        try:
            m=MD3(raw);surfaces=[];changes=[];first=[m.tag(0,j)['name'] for j in range(m.tags)] if m.frames else []
            for frame in range(m.frames):
                m.frame(frame)
                for j in range(m.tags):
                    tag=m.tag(frame,j)
                    if tag['name']!=first[j]:changes.append([frame,j,tag['name']])
            for s in m.surfaces:
                uv=[m.uv(s,j) for j in range(s.vertices)];surfaces.append({'name':s.name,'frames':s.frames,'vertices':s.vertices,'triangles':s.triangles,'uv_bounds':[[min(v[j] for v in uv),max(v[j] for v in uv)] for j in range(2)] if uv else None,'shaders':[m.shader(s,j) for j in range(s.shaders)]})
            r.update({'frames':m.frames,'tag_names':first,'tag_name_changes':changes,'surfaces':surfaces,'status':'validated'})
        except (ValueError,IndexError) as e:r.update({'status':'rejected','error':str(e)})
        rows.append(r);groups[r['virtual_path'].casefold()].append({'path':str(p),'sha256':r['sha256'],'stored_virtual_path':r['virtual_path']})
    duplicates={k:v for k,v in groups.items() if len(v)>1};write_json(Path('docs/research/md3-inventory.json'),{'models':rows,'totals':{'occurrences':len(rows),'validated':sum(r['status']=='validated' for r in rows),'bytes':sum(r['bytes'] for r in rows),'casefold_paths':len(groups)},'path_variants':duplicates,'limits':'Every extracted occurrence retained; casefold groups are comparisons, not VFS precedence or asset renames. Frames/tags/UVs validated finite, triangle bounds and packed regions validated. Normal interpretation/rendering/runtime resolution remain separate.'})
if __name__=='__main__':main()