Reach = 0.75 shell + 0.21 relief + 0.50/6 smooth-max support + 0.01 = 1.0533 m, used by proof, feature, fallback, off-grid bounds and the sweep cutoff. Removes the dead 4 m term (v225 added metres to core-voxel coordinates). Captures and mouth close-ups byte-identical; proof audit 0 misses over 25,728 shell/crest samples; floor 7.884 mm; seams, walkability, fast tier, Clang/GCC W1/W8/W12 green; timing equal within noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
99 lines
4.5 KiB
Python
99 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Render the 23 L125 camera poses with the L130 evaluator and compare them."""
|
|
from __future__ import annotations
|
|
|
|
import html
|
|
import importlib.util
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[4]
|
|
RESEARCH = Path(__file__).resolve().parent
|
|
CAPTURES = RESEARCH / "captures"
|
|
SAVED = ROOT / "Saved/Linux/l130/captures"
|
|
BASELINE_INDEX = (ROOT / "Standalone/Research/WorldAssemblerM3/Linux119"
|
|
/ "captures/L119/capture-index.json")
|
|
REFERENCE = ROOT / "Standalone/Research/WorldAssemblerM3/Linux125/captures/L125"
|
|
LAYOUT = ROOT / "Saved/Linux/l130/hashes/owner4-surface-world-w12-clang.layout.json"
|
|
HEADLESS = ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-clang"
|
|
RENDERER = ROOT / "Saved/Linux/l130/bin/VoxelForgeOffscreenCapture-l130-clang"
|
|
HELPER_PATH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py"
|
|
|
|
|
|
def main() -> int:
|
|
if any(not path.is_file() for path in
|
|
(BASELINE_INDEX, REFERENCE / "passage-0-1-0-rock-floor-station-1.png",
|
|
LAYOUT, HEADLESS, RENDERER)):
|
|
raise SystemExit("missing pose, layout, or L130 capture input")
|
|
spec = importlib.util.spec_from_file_location("l125_capture_runner",
|
|
ROOT / "Standalone/Research/WorldAssemblerM3/Linux125/RunL125Captures.py")
|
|
if spec is None or spec.loader is None:
|
|
raise SystemExit("cannot load the verified L125 pose set")
|
|
runner = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(runner)
|
|
runner.RESEARCH = RESEARCH
|
|
runner.CAPTURES = CAPTURES
|
|
runner.SAVED = SAVED
|
|
runner.LAYOUT = LAYOUT
|
|
runner.CLANG = HEADLESS
|
|
runner.RENDERER = RENDERER
|
|
runner.HELPERS.RESEARCH = RESEARCH
|
|
runner.HELPERS.CAPTURES = CAPTURES
|
|
runner.HELPERS.SAVED = SAVED
|
|
runner.HELPERS.BINARIES = {"L125": HEADLESS}
|
|
runner.HELPERS.RENDERERS = {"L125": RENDERER}
|
|
if runner.main() != 0:
|
|
raise SystemExit("L130 pose generation failed")
|
|
|
|
new_captures = CAPTURES / "L125"
|
|
new_saved = SAVED / "L125"
|
|
index_path = new_captures / "capture-index.json"
|
|
data = json.loads(index_path.read_text())
|
|
if len(data["captures"]) != 23:
|
|
raise SystemExit(f"expected 23 poses, found {len(data['captures'])}")
|
|
identical = 0
|
|
sections = []
|
|
for row in data["captures"]:
|
|
name = row["name"]
|
|
old_image = REFERENCE / f"{name}.png"
|
|
new_image = new_captures / f"{name}.png"
|
|
if not old_image.is_file() or not new_image.is_file():
|
|
raise SystemExit(f"missing comparison image for {name}")
|
|
same = old_image.read_bytes() == new_image.read_bytes()
|
|
identical += int(same)
|
|
row["variant"] = "L130-v227"
|
|
row["capture"] = row["capture"].replace("captures/L125/", "captures/L130/")
|
|
row["scene"] = row["scene"].replace("captures/L125/", "captures/L130/")
|
|
row["logs"] = [path.replace("captures/L125/", "captures/L130/")
|
|
for path in row.get("logs", [])]
|
|
sections.append(f"<section><h2>{html.escape(row['passage'])} — "
|
|
f"{html.escape(row.get('station', ''))}</h2><p>{html.escape(row['kind'])} · "
|
|
f"byte identical: {str(same).lower()}</p><div>"
|
|
f"<figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/{html.escape(name)}.png'></figure>"
|
|
f"<figure><figcaption>L130 v227</figcaption><img src='L130/{html.escape(name)}.png'></figure>"
|
|
"</div></section>")
|
|
if identical != 23:
|
|
raise SystemExit(f"only {identical}/23 L125 pose captures are byte-identical")
|
|
|
|
index_path.write_text(json.dumps(data, indent=2) + "\n")
|
|
old_captures, old_saved = CAPTURES / "L130", SAVED / "L130"
|
|
if old_captures.exists():
|
|
shutil.rmtree(old_captures)
|
|
if old_saved.exists():
|
|
shutil.rmtree(old_saved)
|
|
new_captures.rename(old_captures)
|
|
new_saved.rename(old_saved)
|
|
page = ("<!doctype html><meta charset='utf-8'><title>L130 passage captures</title>"
|
|
"<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}"
|
|
"section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}"
|
|
"img{width:100%;height:auto}p{color:#bbb}</style>"
|
|
"<h1>L125 v225 vs L130 v227: passage captures</h1>" + "\n".join(sections))
|
|
(CAPTURES / "COMPARE.html").write_text(page)
|
|
print(f"[L130PoseCapture] poses=23 byte_identical={identical}/23", flush=True)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|