﻿"""
merged.glb → 브라우저용 bin 변환 (positions + indices)
open3d로 버텍스/페이스 모두 축소 → 약 5만 페이스 목표
"""
import open3d as o3d
import numpy as np
import struct
from pathlib import Path

GLB = Path("E:/도진팩토리/3D스캔및티칭시스템/output/merged.glb")
OUT = Path("E:/도진팩토리/3D스캔및티칭시스템/output/mesh.bin")

print("open3d로 GLB 로드...")
mesh = o3d.io.read_triangle_mesh(str(GLB))
print(f"원본: 버텍스 {len(mesh.vertices):,} / 페이스 {len(mesh.triangles):,}")

# 중복 제거 + 법선 재계산
mesh.remove_duplicated_vertices()
mesh.remove_degenerate_triangles()
print(f"정리 후: 버텍스 {len(mesh.vertices):,} / 페이스 {len(mesh.triangles):,}")

# 50,000 페이스로 축소
target = 50_000
print(f"축소 중... → {target:,} 페이스")
mesh = mesh.simplify_quadric_decimation(target)
mesh.compute_vertex_normals()
print(f"축소 완료: 버텍스 {len(mesh.vertices):,} / 페이스 {len(mesh.triangles):,}")

verts = np.asarray(mesh.vertices, dtype=np.float32)   # Nx3
faces = np.asarray(mesh.triangles, dtype=np.uint32)   # Mx3
norms = np.asarray(mesh.vertex_normals, dtype=np.float32)

# 바이너리 포맷: [n_verts:4][n_faces:4][verts:n*12][norms:n*12][faces:m*12]
n_v = len(verts); n_f = len(faces)
with open(OUT, 'wb') as f:
    f.write(struct.pack('<II', n_v, n_f))
    f.write(verts.tobytes())
    f.write(norms.tobytes())
    f.write(faces.tobytes())

size = OUT.stat().st_size
print(f"저장: {OUT} ({size//1024}KB)")
print(f"X: {verts[:,0].min():.3f}~{verts[:,0].max():.3f}")
print(f"Y: {verts[:,1].min():.3f}~{verts[:,1].max():.3f}")
print(f"Z: {verts[:,2].min():.3f}~{verts[:,2].max():.3f}")
