mantrakp's picture
Split worker coordinator with targeted texture repair and verified Blender mirrors
f2003dc verified
Raw History Blame Contribute Delete
2.43 kB
import json
import math
from functools import lru_cache
import os
from pathlib import Path
import shutil
import subprocess
from PIL import Image, ImageDraw
ROOT = Path(__file__).resolve().parents[1]
def blender():
path = os.environ.get("BLENDER_BIN") or shutil.which("blender")
local = Path("/Applications/Blender.app/Contents/MacOS/Blender")
if not path and local.exists():
path = str(local)
if not path:
raise RuntimeError("Install Blender or set BLENDER_BIN to render refinement evidence.")
return path
@lru_cache(maxsize=1)
def check_renderer():
subprocess.run([blender(), "--background", "--factory-startup", "--python-exit-code", "1",
"--python-expr", "import numpy; import _cycles; import io_scene_gltf2.blender.imp.mesh; "
"print('GLTF renderer ready; CPU denoising:', _cycles.with_openimagedenoise)"],
check=True, timeout=60, capture_output=True, text=True)
def render(model, folder, components=False, *, material_mode="original"):
if material_mode not in {"original", "clay", "basecolor"}:
raise ValueError("material_mode must be original, clay or basecolor")
model, folder = Path(model), Path(folder)
folder.mkdir(parents=True, exist_ok=True)
command = [blender(), "--background", "--factory-startup", "--python-exit-code", "1",
"--python", str(ROOT / "scripts/render_views.py"), "--",
"--input", str(model), "--output", str(folder), "--material-mode", material_mode]
if components:
command.append("--components")
with (folder / "render.log").open("w") as log:
subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=True, timeout=300)
manifest = json.loads((folder / "render-manifest.json").read_text())
paths = [(folder / item["file"], item["label"]) for item in manifest["images"]]
if not paths:
raise RuntimeError("Blender produced no review images.")
sheet = Image.new("RGB", (384 * 3, 410 * math.ceil(len(paths) / 3)), "#20252b")
draw = ImageDraw.Draw(sheet)
for index, (path, label) in enumerate(paths):
x, y = index % 3 * 384, index // 3 * 410
with Image.open(path) as image:
sheet.paste(image.convert("RGB"), (x, y + 26))
draw.text((x + 10, y + 7), label, fill="white")
sheet.save(folder / "contact.png")
return folder / "contact.png"