chatcad / blender_render.py
Samarjithbiswas's picture
chat_cad live (Docker app + weights)
32c7c43 verified
Raw
History Blame Contribute Delete
2.99 kB
"""Drive Blender to photorealistically render the generated DrivAer car.
Generates the part-labelled car mesh, dumps it to an npz, and runs Blender
(Cycles, GPU) headless to produce a studio render of the REAL geometry -
metallic paint, glass, chrome rims, rubber tyres, emissive lamps.
This is the photoreal render of the actual 3D model (not a diffusion image),
so it matches the car you can rotate / simulate / inspect.
"""
from __future__ import annotations
import glob
import os
import subprocess
import tempfile
from pathlib import Path
from typing import Optional
import numpy as np
HERE = Path(__file__).parent
SCRIPT = HERE / "render_car_blender.py"
_BLENDER = None
def find_blender() -> Optional[str]:
global _BLENDER
if _BLENDER:
return _BLENDER
cands = []
import shutil
p = shutil.which("blender")
if p:
cands.append(p)
cands += sorted(glob.glob(
r"C:\Program Files\Blender Foundation\Blender *\blender.exe"), reverse=True)
cands += sorted(glob.glob(
r"C:\Program Files\Blender Foundation\*\blender.exe"), reverse=True)
for c in cands:
if c and os.path.exists(c):
_BLENDER = c
return c
return None
def available() -> bool:
return find_blender() is not None
def _hex(color) -> str:
import vehicle_realgen as G
rgb = G.resolve_color(color) if isinstance(color, str) else color
if rgb is None:
rgb = (0.69, 0.71, 0.74)
return "".join(f"{int(max(0,min(1,c))*255):02x}" for c in rgb[:3])
def render(length_mm=4700.0, width_mm=1900.0, height_mm=1450.0,
roof=0.0, nose=0.0, rake=0.0, target_cd=None,
color="silver", out_path: Optional[str] = None,
timeout=600, mode="photoreal") -> Optional[str]:
blender = find_blender()
if blender is None:
return None
import drivaer_meshgen as MG
d = MG.generate(length_mm=length_mm, width_mm=width_mm, height_mm=height_mm,
roof=roof, nose=nose, rake=rake, target_cd=target_cd)
if d is None:
return None
tmp = Path(tempfile.gettempdir()) / "chatcad_car_mesh.npz"
np.savez(tmp, verts=d["verts"].astype(np.float32),
faces=np.asarray(d["faces"], np.int32),
region=np.asarray(d["region"], np.int32))
out_path = out_path or str(HERE / "output" / "blender_car.png")
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
cmd = [blender, "-b", "-noaudio", "-P", str(SCRIPT), "--",
str(tmp), out_path, _hex(color), mode]
try:
subprocess.run(cmd, timeout=timeout, capture_output=True)
except Exception:
return None
return out_path if os.path.exists(out_path) else None
if __name__ == "__main__":
print("blender:", find_blender())
import time
t = time.time()
p = render(length_mm=4600, height_mm=1350, roof=0.6, nose=0.4,
target_cd=0.24, color="red")
print("rendered:", p, "in %.1fs" % (time.time() - t))