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
This commit is contained in:
1 parent
20f6c98ec5
commit
9458217d34
24 files changed
+471136
-59
No files matched your search
@@ -0,0 +1,228 @@
|
||||
#!/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)
|
||||
Reference in new issue
Block a user