Files
VoxelForge/Standalone/Research/WorldAssemblerM3/Linux54/CaptureNativeCavesL54.py
T
Fr0zkaandClaude Opus 5.5 9458217d34 feat(core): native Core caves generator, slice 1 -- spine + room, whole view 0.73 s (L54); research R23
Core.Caves.PrimitiveField v1, opt-in per strate (legacy TunnelNetwork assets stay legacy): solid host rock
and one smooth union of two elliptical spine tubes and an ellipsoid room, each intersected with its rising
floor by cubic smooth-max (W 2.4 m, measured fillet 0.70 m, no trailing floor cap). Bound in the L40 field
table and L42 capabilities, BVH feature candidates, isTileShapeFree aware, exact interval boxes (0 misses).
Capsule flood fill arrival -> departure passes (headroom >= 0.3 m, grade <= 15 deg); the generalized
whole-surface audit passes with its controls failing. Cold whole view 0.727 s, near ring 0.19 s. Graph
ordering/serialization changes are scoped to native caves (the flagged L47 demo is unchanged); verify
tiers write captures under --out only. fast/medium/full PASS, Clang and GCC.
Research R23 (deepened): per-tile LOD0 kernel speed plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
2026-10-25 04:10:19 +01:00

229 lines
11 KiB
Python

#!/usr/bin/env python3
"""Export and capture the L54 native cave spine and chamber from reviewed views."""
from __future__ import annotations
import argparse
import json
import math
import os
from pathlib import Path
import struct
import subprocess
import sys
import time
ROOT = Path(__file__).resolve().parents[4]
LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"]
Q = 1_000_000.0
sys.path.insert(0, str(ROOT / "Standalone/Tools/verify"))
from runner import bounded_run, current_stamp, first_stamp
def bezier(points: list[list[float]], t: float) -> tuple[float, float, float]:
one = 1.0 - t
weights = (one ** 3, 3.0 * one * one * t, 3.0 * one * t * t, t ** 3)
return tuple(sum(weights[i] * points[i][axis] for i in range(4)) for axis in range(3))
def tangent(points: list[list[float]], t: float) -> tuple[float, float, float]:
one = 1.0 - t
return tuple(3.0 * one ** 2 * (points[1][axis] - points[0][axis])
+ 6.0 * one * t * (points[2][axis] - points[1][axis])
+ 3.0 * t ** 2 * (points[3][axis] - points[2][axis]) for axis in range(3))
def camera_angles(camera: tuple[float, float, float],
target: tuple[float, float, float]) -> tuple[float, float]:
dx, dy, dz = (target[i] - camera[i] for i in range(3))
return math.degrees(math.atan2(dx, dy)), math.degrees(math.atan2(dz, math.hypot(dx, dy)))
def fmt(values: tuple[float, ...]) -> str:
return ",".join(f"{value:.6f}" for value in values)
def filter_mesh_y_leq(source: Path, destination: Path, cut_y: float) -> int:
"""Keep triangles on the negative-Y side for an uncapped, inspectable cutaway."""
kept = 0
with source.open("rb") as src, destination.open("wb") as dst:
prefix = src.read(60)
if len(prefix) != 60 or prefix[:8] != b"VFMSH001":
raise ValueError("cutaway requires a VFMSH001 Core mesh")
version, voxel_um, tile_count = struct.unpack_from("<3I", prefix, 8)
if version != 1 or voxel_um <= 0:
raise ValueError("cutaway mesh version or voxel size is invalid")
dst.write(prefix)
for _ in range(tile_count):
header = src.read(36)
if len(header) != 36:
raise ValueError("cutaway mesh tile header is truncated")
key = struct.unpack_from("<4i", header, 0)
surface_count, _skirt_count, vertex_count, index_count, mask_count = \
struct.unpack_from("<5I", header, 16)
positions = src.read(vertex_count * 12)
normals = src.read(vertex_count * 12)
index_bytes = src.read(index_count * 4)
masks = src.read(mask_count)
if (len(positions) != vertex_count * 12
or len(normals) != vertex_count * 12
or len(index_bytes) != index_count * 4
or len(masks) != mask_count):
raise ValueError("cutaway mesh tile payload is truncated")
coords = list(struct.iter_unpack("<3f", positions))
indices = struct.unpack(f"<{index_count}I", index_bytes) if index_count else ()
kept_indices = []
kept_masks = bytearray()
for triangle in range(index_count // 3):
ids = indices[triangle * 3:triangle * 3 + 3]
if max(ids) >= vertex_count:
raise ValueError("cutaway triangle references an invalid vertex")
if sum(coords[index][1] for index in ids) / 3.0 > cut_y:
continue
kept_indices.extend(ids)
kept += 1
if masks:
kept_masks.append(masks[triangle])
skirt_count = sum(kept_masks)
output_header = struct.pack("<4i5I", *key, surface_count, skirt_count,
vertex_count, len(kept_indices), len(kept_masks))
dst.write(output_header)
dst.write(positions)
dst.write(normals)
if kept_indices:
dst.write(struct.pack(f"<{len(kept_indices)}I", *kept_indices))
dst.write(kept_masks)
if src.read(1):
raise ValueError("cutaway mesh contains trailing bytes")
if kept == 0:
destination.unlink(missing_ok=True)
raise ValueError("cutaway plane retained no triangles")
return kept
def run_step(name: str, command: list[str], log: Path, *, env: dict[str, str],
stamped: bool = False) -> str:
expected = current_stamp() if stamped else None
if stamped:
binary = Path(command[0])
probe = bounded_run([str(binary), "--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 an unstamped or stale executable: {binary}")
started = time.monotonic()
log.parent.mkdir(parents=True, exist_ok=True)
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")
if stamped and (first_stamp(output) != expected or current_stamp() != expected):
raise RuntimeError(f"{name} source stamp mismatch; see {log}")
print(f"[L54CavesCaptureRun] step={name} elapsed={elapsed:.1f}s "
f"exit={result.returncode} log={log}", 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, required=True)
parser.add_argument("--fixture", type=Path, required=True)
parser.add_argument("--layout", type=Path, required=True)
parser.add_argument("--headless", type=Path, required=True)
parser.add_argument("--renderer", type=Path, required=True)
parser.add_argument("--artifact-dir", type=Path, default=Path(__file__).resolve().parent / "captures")
args = parser.parse_args()
out, artifact_dir = args.out.resolve(), args.artifact_dir.resolve()
capture_dir, mesh_dir = out / "capture-png", out / "caves-meshes"
for directory in (capture_dir, mesh_dir, artifact_dir):
directory.mkdir(parents=True, exist_ok=True)
layout = json.loads(args.layout.read_text(encoding="utf-8"))
edges = sorted(layout.get("cavern_edges", []), key=lambda row: row["stable_id"])
rooms = layout.get("cavern_rooms", [])
if len(edges) != 2 or len(rooms) != 1:
raise RuntimeError("expected the resolved one-room, two-edge cave spine")
controls = [[value / Q for value in point] for point in edges[0]["control_points_um"]]
room = rooms[0]
room_center = tuple(value / Q for value in room["center_um"])
room_floor = room["floor_um"] / Q
mesh = mesh_dir / "caves-whole-view.vfmesh"
mesh_layout = out / "layouts" / "caves-capture-layout.json"
env = os.environ.copy()
env["LP_NUM_THREADS"] = "12"
env["XDG_CACHE_HOME"] = str(out / "xdg-cache")
run_step("whole-cave-export", [args.headless, args.fixture,
"--workers=12", "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", "--force-generate", "--clip-radius=4",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
"--recipe=caves", "--camera=41,-4,-160,0,0",
f"--resolved-layout-output={mesh_layout}", f"--mesh-export={mesh}"],
out / "capture-caves-export.log", env=env, stamped=True)
if not mesh.is_file() or mesh.stat().st_size == 0:
raise RuntimeError("whole-cave export produced no mesh")
cutaway_mesh = mesh_dir / "caves-cutaway-y-minus5.vfmesh"
cutaway_triangles = filter_mesh_y_leq(mesh, cutaway_mesh, -5.0)
print(f"[L54CavesCutaway] plane_y_m=-5.000 retained_triangles={cutaway_triangles} "
f"mesh={cutaway_mesh}", flush=True)
eye_t = 0.50
eye_floor = bezier(controls, eye_t)
eye_direction = tangent(controls, eye_t)
eye = (eye_floor[0], eye_floor[1], eye_floor[2] + 1.45)
eye_yaw = math.degrees(math.atan2(eye_direction[0], eye_direction[1]))
eye_target = (eye[0] + 10.0 * math.sin(math.radians(eye_yaw)),
eye[1] + 10.0 * math.cos(math.radians(eye_yaw)), eye[2])
arrival_portal = [value / Q for value in edges[0]["control_points_um"][-1]]
entrance = (arrival_portal[0], arrival_portal[1], room_floor + 1.45)
entrance_target = (room_center[0], room_center[1], room_floor + 1.45)
overview_target = (room_center[0] - 8.0, room_center[1], room_floor + 1.5)
overview = (room_center[0] - 23.0, room_center[1] + 27.0, room_floor + 19.0)
views = (
("spine-eye", cutaway_mesh, eye, eye_target, 20.0, 80.0),
("room-from-entrance", mesh, entrance, entrance_target, 18.0, 90.0),
("cutaway-overview", cutaway_mesh, overview, overview_target, 48.0, 65.0),
)
quality = ROOT / "Standalone/Tools/verify/capture_quality.py"
for name, render_mesh, camera, target, focus_radius, fov in views:
yaw, pitch = camera_angles(camera, target)
if name == "spine-eye":
yaw, pitch = eye_yaw, 0.0
png = capture_dir / f"caves-{name}.png"
image = artifact_dir / f"caves-{name}.jpg"
command = [args.renderer, render_mesh, png, "--size=1600x900",
f"--fov-deg={fov:.1f}",
f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}",
f"--pitch-deg={pitch - 4.0 if name == 'spine-eye' else pitch:.6f}",
"--tile-skirts=off", "--shade=readable", "--headlamp=off",
"--light-direction=1,-0.6,0.8", "--height-tint=on",
f"--height-center-m={room_floor:.6f}",
"--height-range-m=12", "--tile-edges=off",
f"--focus-region={fmt((*target, focus_radius))}"]
run_step(f"{name}-render", command, out / f"capture-{name}-render.log", env=env,
stamped=True)
run_step(f"{name}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel",
"error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image],
out / f"capture-{name}-jpeg.log", env=env)
quality_output = run_step(f"{name}-quality", [sys.executable, quality, image],
out / f"capture-{name}-quality.log", env=env)
quality_lines = [line for line in quality_output.splitlines()
if line.startswith("[CaptureQuality]")]
if not quality_lines or not quality_lines[-1].endswith("status=PASS"):
raise RuntimeError(f"capture quality gate failed for {name}")
print(f"[L54CavesCapture] view={name} file={image} camera_m=({fmt(camera)}) "
f"target_m=({fmt(target)}) bytes={image.stat().st_size} status=PASS", flush=True)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as error:
print(f"[L54CavesCapture] status=FAIL error={error}", file=sys.stderr, flush=True)
raise SystemExit(1)