Route planning for an upper SurfaceWorld failed on long candidate chords over steep relief; chords are now capped to the arrival/departure radii on an 8 m centre grid with an origin-proximity cost (21.5 m walk, about 4 deg). The departure passage starts at the SW ground and tunnels down through rock. FI -> SW -> TN fixture: all 4 styles pass every passage audit on both compilers. FloorProfileBlend now checks endpoint height/tangent seams (step and tangent-step negative controls detected). Owner world hashes unchanged; 30/30 determinism; cost within noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Export and render two bounded SurfaceWorld departure views."""
|
|
import os
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[4]
|
|
OUT = ROOT / "Saved/Linux/l33"
|
|
FIXTURE = OUT / "fixtures/sw-upper-tunnel-network-style0.json"
|
|
HEADLESS = OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final"
|
|
CAPTURE = OUT / "bin/VoxelForgeOffscreenCapture-clang-l33-final"
|
|
PNG_DIR = OUT / "capture-png"
|
|
DEST = Path(__file__).resolve().parent / "captures"
|
|
PNG_DIR.mkdir(parents=True, exist_ok=True)
|
|
DEST.mkdir(parents=True, exist_ok=True)
|
|
env = os.environ.copy()
|
|
env["LP_NUM_THREADS"] = "12"
|
|
env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache")
|
|
|
|
views = (
|
|
{
|
|
"name": "sw-departure-mouth",
|
|
"export_camera": "18.75,-12,-499,0,-22",
|
|
"render_camera": "18.75,0,-490",
|
|
"yaw": "0",
|
|
"pitch": "-90",
|
|
"fov": "38",
|
|
"height_center": "-503.166",
|
|
"height_range": "4",
|
|
"light": "0,-1,0.2",
|
|
"headlamp": "off",
|
|
"clip": None,
|
|
},
|
|
{
|
|
"name": "sw-departure-rock-entry",
|
|
"export_camera": "26,-16,-499,64,-16",
|
|
"render_camera": "14,-4,-500",
|
|
"yaw": "78",
|
|
"pitch": "-16",
|
|
"fov": "32",
|
|
"height_center": "-503.166",
|
|
"height_range": "4",
|
|
"light": "0,-1,0.2",
|
|
"headlamp": "off",
|
|
"clip": "1,0,0,-18.75",
|
|
},
|
|
)
|
|
|
|
|
|
def run(name, command):
|
|
logfile = OUT / f"capture-{name}.log"
|
|
wrapped = [
|
|
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
|
"timeout", "1800s", *command,
|
|
]
|
|
started = time.monotonic()
|
|
with logfile.open("w", encoding="utf-8") as stream:
|
|
result = subprocess.run(wrapped, cwd=ROOT, env=env, stdout=stream,
|
|
stderr=subprocess.STDOUT, timeout=1800, check=False)
|
|
print(f"[L33CaptureRun] step={name} elapsed={time.monotonic()-started:.1f}s "
|
|
f"exit={result.returncode} log={logfile}", flush=True)
|
|
if result.returncode != 0:
|
|
raise SystemExit(f"{name} failed; see {logfile}")
|
|
|
|
|
|
for view in views:
|
|
name = view["name"]
|
|
mesh = OUT / f"{name}.vfmesh"
|
|
png = PNG_DIR / f"{name}.png"
|
|
jpg = DEST / f"{name}.jpg"
|
|
run(f"{name}-export", [
|
|
str(HEADLESS), str(FIXTURE), "--workers=12", "--world-assembler-prototype",
|
|
"--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=2",
|
|
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
|
|
"--recipe=floating-islands",
|
|
f"--camera={view['export_camera']}", f"--mesh-export={mesh}",
|
|
])
|
|
command = [
|
|
str(CAPTURE), str(mesh), str(png), "--size=1600x900", f"--fov-deg={view['fov']}",
|
|
f"--camera-m={view['render_camera']}", f"--yaw-deg={view['yaw']}",
|
|
f"--pitch-deg={view['pitch']}", "--shade=readable",
|
|
f"--headlamp={view['headlamp']}", f"--light-direction={view['light']}",
|
|
"--height-tint=on", f"--height-center-m={view['height_center']}",
|
|
f"--height-range-m={view['height_range']}", "--tile-edges=off",
|
|
]
|
|
if view["clip"]:
|
|
command.append(f"--clip-plane={view['clip']}")
|
|
run(f"{name}-render", command)
|
|
run(f"{name}-jpeg", [
|
|
"ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error", "-y",
|
|
"-i", str(png), "-frames:v", "1", "-q:v", "4", str(jpg),
|
|
])
|
|
size = jpg.stat().st_size if jpg.exists() else 0
|
|
ok = 0 < size <= 300_000
|
|
print(f"[L33CaptureJPEG] file={jpg.relative_to(ROOT)} bytes={size} "
|
|
f"status={'PASS' if ok else 'FAIL'}", flush=True)
|
|
if not ok:
|
|
raise SystemExit(f"{jpg.name} is missing or exceeds 300 KB")
|