feat(core): slab + sparse motifs, slice 1 -- flat field, monolith, platform at 0.52 s (L56); research R25
Motif vocabulary v3: version-1 records keyed by (seed, strate, stable ID) with route keepouts, band clearance and pairwise spacing. A rounded capped-cylinder monolith (r 1.4 m, 24 m tall) and a rounded-box plinth, smooth-unioned into a flatField floor with a 0.55 m geometric rounding (measured fillets 0.73-1.17 m). Exact radial/box interval bounds, a BVH, isTileShapeFree aware (0 brute-force misses, false-proof controls rejected). Final-field route passes; whole-surface audit covers foot, cap and platform edges. Cold whole view 0.524 s. Owner world unchanged. fast/medium/full PASS (Clang and GCC). Research R25 (self-checked): FloatingIslands LOD0 column cache conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
aee1487410
commit
4e64b75044
15 files changed
+1560
-12
No files matched your search
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Capture two checked views of the R24 flat field and sparse motifs."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l56"))
|
||||
LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"]
|
||||
Q_PER_METRE = 1024.0
|
||||
|
||||
sys.path.insert(0, str(ROOT / "Standalone/Tools/verify"))
|
||||
from runner import bounded_run, current_stamp, first_stamp
|
||||
|
||||
|
||||
def fmt(values):
|
||||
return ",".join(f"{value:.6f}" for value in values)
|
||||
|
||||
|
||||
def camera_angles(camera, target):
|
||||
dx, dy, dz = (target[index] - camera[index] for index in range(3))
|
||||
return math.degrees(math.atan2(dx, dy)), math.degrees(math.atan2(dz, math.hypot(dx, dy)))
|
||||
|
||||
|
||||
def read_scene(layout_path):
|
||||
layout = json.loads(layout_path.read_text(encoding="utf-8"))
|
||||
motifs = layout["stamps"]
|
||||
monolith = next(row for row in motifs if row["kind"] == 5)
|
||||
platform = next(row for row in motifs if row["kind"] == 6)
|
||||
route = [tuple(float(value) / Q_PER_METRE for value in anchor["values"][:3])
|
||||
for strate in layout["strates"] for anchor in strate.get("anchors", [])
|
||||
if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3]
|
||||
if len(route) < 2:
|
||||
raise RuntimeError("motif fixture did not resolve a surface route")
|
||||
mono = tuple(value / 1_000_000.0 for value in monolith["position_um"])
|
||||
dais = tuple(value / 1_000_000.0 for value in platform["position_um"])
|
||||
floor = monolith["floor_um"] / 1_000_000.0
|
||||
center = tuple(sum(point[axis] for point in route) / len(route) for axis in range(3))
|
||||
dx, dy = route[-1][0] - route[0][0], route[-1][1] - route[0][1]
|
||||
length = math.hypot(dx, dy)
|
||||
if length <= 1.0e-6:
|
||||
raise RuntimeError("resolved surface route tangent is degenerate")
|
||||
tx, ty = dx / length, dy / length
|
||||
eye_camera = (mono[0] - tx * 30.0, mono[1] - ty * 30.0, floor + 1.65)
|
||||
eye_target = (mono[0] + tx * 1.5, mono[1] + ty * 1.5, floor + 12.0)
|
||||
scene_x = (center[0] + mono[0] + dais[0]) / 3.0
|
||||
scene_y = (center[1] + mono[1] + dais[1]) / 3.0
|
||||
overview_camera = (scene_x + tx * 45.0, scene_y + ty * 45.0, floor + 43.0)
|
||||
overview_target = (scene_x, scene_y, floor + 5.0)
|
||||
return layout, {
|
||||
"eye": (eye_camera, eye_target, 5),
|
||||
"overview": (overview_camera, overview_target, 7),
|
||||
}
|
||||
|
||||
|
||||
def run_step(name, command, log, *, env, stamped=False):
|
||||
expected = current_stamp() if stamped else None
|
||||
if stamped:
|
||||
probe = bounded_run([str(command[0]), "--print-source-stamp"], timeout=15)
|
||||
if probe is None or probe.returncode != 0 or first_stamp(probe.stdout or "") != expected:
|
||||
raise RuntimeError(f"{name} refused a stale executable: {command[0]}")
|
||||
started = time.monotonic()
|
||||
with log.open("w", encoding="utf-8") as stream:
|
||||
result = subprocess.run([*LIMIT, "timeout", "1740s", *map(str, command)],
|
||||
cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT,
|
||||
timeout=1745, check=False)
|
||||
elapsed = time.monotonic() - started
|
||||
output = log.read_text(encoding="utf-8", errors="replace")
|
||||
print(f"[L56CaptureRun] step={name} elapsed={elapsed:.1f}s "
|
||||
f"exit={result.returncode} log={log}", flush=True)
|
||||
if stamped and (first_stamp(output) != expected or current_stamp() != expected):
|
||||
raise RuntimeError(f"{name} source stamp mismatch; see {log}")
|
||||
if name.endswith("-quality") or name.endswith("-surface-audit"):
|
||||
for line in output.splitlines():
|
||||
if line.startswith(("[CaptureQuality]", "[MotifSurfaceROI]",
|
||||
"[MotifFilletMeasure]", "[MotifSurfaceAudit]")):
|
||||
print(line, flush=True)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(f"{name} failed; see {log}")
|
||||
return output
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--out", type=Path, default=OUT_DEFAULT)
|
||||
parser.add_argument("--fixture-dir", type=Path)
|
||||
parser.add_argument("--artifact-dir", type=Path, required=True)
|
||||
parser.add_argument("--headless", type=Path, required=True)
|
||||
parser.add_argument("--renderer", type=Path, required=True)
|
||||
parser.add_argument("--auditor", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
out = args.out.resolve()
|
||||
fixture_dir = (args.fixture_dir or out / "fixtures").resolve()
|
||||
artifact_dir = args.artifact_dir.resolve()
|
||||
png_dir, mesh_dir = out / "capture-png", out / "motif-meshes"
|
||||
for directory in (out, png_dir, mesh_dir, artifact_dir):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
fixture = fixture_dir / "style-override-motifs-slice1.json"
|
||||
layout = out / "layouts" / "motif-slice1-capsule-reachability-clang.json"
|
||||
if not fixture.is_file() or not layout.is_file():
|
||||
raise RuntimeError("missing fixture or resolved motif records")
|
||||
encoded, views = read_scene(layout)
|
||||
floor = next(row["floor_um"] for row in encoded["stamps"] if row["kind"] == 5) / 1_000_000.0
|
||||
env = os.environ.copy()
|
||||
env["LP_NUM_THREADS"] = "12"
|
||||
env["XDG_CACHE_HOME"] = str(out / "xdg-cache")
|
||||
|
||||
mesh_paths = []
|
||||
for view, (camera, target, clip_radius) in views.items():
|
||||
yaw, pitch = camera_angles(camera, target)
|
||||
camera_spec = (*camera, yaw, pitch)
|
||||
stem = f"motifs-slice1-{view}"
|
||||
mesh = mesh_dir / f"{stem}.vfmesh"
|
||||
png = png_dir / f"{stem}.png"
|
||||
image = artifact_dir / f"{stem}.jpg"
|
||||
manifest = fixture_dir / f"{stem}-manifest.json"
|
||||
headless = [args.headless, fixture, "--workers=12",
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--force-generate", f"--clip-radius={clip_radius}",
|
||||
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
|
||||
f"--camera={fmt(camera_spec)}", f"--mesh-export={mesh}",
|
||||
f"--world-assembler-manifest-output={manifest}"]
|
||||
run_step(f"{stem}-export", headless, out / f"capture-{stem}-export.log",
|
||||
env=env, stamped=True)
|
||||
if not mesh.is_file() or mesh.stat().st_size == 0:
|
||||
raise RuntimeError(f"headless export produced no mesh for {view}")
|
||||
focus = (*target, 42.0 if view == "overview" else 34.0)
|
||||
height_center = floor + 12.0 if view == "overview" else camera[2]
|
||||
renderer = [args.renderer, mesh, png, "--size=1600x900", "--fov-deg=72",
|
||||
f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}",
|
||||
f"--pitch-deg={pitch:.6f}", "--tile-skirts=off", "--shade=readable",
|
||||
"--headlamp=on", "--height-tint=on", f"--height-center-m={height_center:.6f}",
|
||||
"--height-range-m=34", "--tile-edges=off", f"--focus-region={fmt(focus)}"]
|
||||
run_step(f"{stem}-render", renderer, out / f"capture-{stem}-render.log",
|
||||
env=env, stamped=True)
|
||||
run_step(f"{stem}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel",
|
||||
"error", "-y", "-i", png, "-frames:v", "1", "-q:v", "5", image],
|
||||
out / f"capture-{stem}-jpeg.log", env=env)
|
||||
run_step(f"{stem}-quality", [sys.executable,
|
||||
ROOT / "Standalone/Tools/verify/capture_quality.py", image],
|
||||
out / f"capture-{stem}-quality.log", env=env)
|
||||
mesh_paths.append(mesh)
|
||||
if not image.is_file() or not 0 < image.stat().st_size <= 300_000:
|
||||
raise RuntimeError(f"capture size must be <=300 KB: {image}")
|
||||
print(f"[L56MotifCapture] view={view} file={image} bytes={image.stat().st_size} "
|
||||
f"camera_m=({fmt(camera)}) target_m=({fmt(target)}) status=PASS", flush=True)
|
||||
audit_output = run_step("motifs-surface-audit",
|
||||
[sys.executable, args.auditor, *mesh_paths, layout, "--view=combined"],
|
||||
out / "capture-motifs-surface-audit.log", env=env)
|
||||
if "[MotifSurfaceAudit] view=combined" not in audit_output:
|
||||
raise RuntimeError("surface audit produced no whole-surface summary")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except Exception as error:
|
||||
print(f"[L56MotifCapture] status=FAIL error={error}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
Reference in new issue
Block a user