39 lines
1.5 KiB
Python
39 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Dump a GLB's baseColor + metallicRoughness atlas images side by side, so the
|
|
bake's colour fidelity can be eyeballed without any renderer in the way.
|
|
|
|
python3 scripts/glb_atlas.py in.glb [out.png]
|
|
"""
|
|
import sys, numpy as np, trimesh
|
|
from PIL import Image
|
|
|
|
path = sys.argv[1]; out = sys.argv[2] if len(sys.argv) > 2 else "glb_atlas.png"
|
|
scene = trimesh.load(path, process=False)
|
|
mesh = scene if isinstance(scene, trimesh.Trimesh) else list(scene.geometry.values())[0]
|
|
attrs = getattr(mesh.visual, "vertex_attributes", {})
|
|
if "color" in attrs:
|
|
color = np.asarray(attrs["color"])
|
|
print(f"vertex-colour GLB: {len(color):,} COLOR_0 values ({color.dtype}); no UV atlas")
|
|
sys.exit(0)
|
|
mat = mesh.visual.material
|
|
bc = mat.baseColorTexture.convert("RGB")
|
|
try:
|
|
mr = mat.metallicRoughnessTexture.convert("RGB")
|
|
except Exception:
|
|
mr = Image.new("RGB", bc.size)
|
|
W, H = bc.size
|
|
# downscale for a quick look if huge
|
|
scale = 1024 / max(W, H)
|
|
if scale < 1:
|
|
bc = bc.resize((int(W*scale), int(H*scale)))
|
|
mr = mr.resize((int(W*scale), int(H*scale)))
|
|
w, h = bc.size
|
|
canvas = Image.new("RGB", (w*2 + 16, h), (30, 30, 30))
|
|
canvas.paste(bc, (0, 0)); canvas.paste(mr, (w + 16, 0))
|
|
canvas.save(out)
|
|
a = np.asarray(bc, np.float64) / 255
|
|
nz = a.reshape(-1, 3); nz = nz[nz.sum(1) > 0.05]
|
|
print(f"atlas {W}x{H} baseColor mean(nonblack)={nz.mean(0).round(3) if len(nz) else 'n/a'} "
|
|
f"filled={len(nz)/(w*h)*100:.0f}%", flush=True)
|
|
print("wrote", out, flush=True)
|