From 9c6d261d017ea4c2afa8373c814d29f8124a4dc7 Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sun, 1 Nov 2026 08:43:24 +0100 Subject: [PATCH 1/7] proto: first liminal fixtures - flat field + monolith, periodic hills, raised road in fog (L141) Standalone only: fixtures, liminal_road_override (fillDais), --audit-liminal-road-walk, capture-only distance fog. Road 65 m x 6 m, 22 m up, capsule walk 127/127. Owner hashes unchanged (v227), fast tier, Clang/GCC green. Hills repeat every 80 m but the capture reaches 56 m, so only one rise shows. Also R48 (who owns the tunnel mouth): recommends a bounded joint plan of passage ports and layer landing candidates. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../Linux141/BuildL141Fixtures.py | 84 ++++ .../WorldAssemblerM3/Linux141/CaptureL141.py | 389 ++++++++++++++++++ .../WorldAssemblerM3/Linux141/REPORT.md | 40 ++ .../captures/flatField-monolith-eye.jpg | Bin 0 -> 26770 bytes .../captures/flatField-monolith-wide.jpg | Bin 0 -> 24016 bytes .../Linux141/captures/periodicHills-eye.jpg | Bin 0 -> 23693 bytes .../Linux141/captures/periodicHills-wide.jpg | Bin 0 -> 24629 bytes .../Linux141/captures/raised-road-eye.jpg | Bin 0 -> 24503 bytes .../Linux141/captures/raised-road-wide.jpg | Bin 0 -> 33966 bytes .../WorldAssemblerM3/Research48/PROMPT.md | 36 ++ .../WorldAssemblerM3/Research48/REPORT.md | 43 ++ Standalone/Source/LinuxOffscreenCapture.cpp | 76 +++- Standalone/Source/StreamBenchmarkHeadless.cpp | 32 +- Standalone/Source/StreamBenchmarkPipeline.h | 72 +++- Standalone/Source/WorldAssemblyPrototype.h | 63 +++ 15 files changed, 823 insertions(+), 12 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/BuildL141Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/CaptureL141.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/raised-road-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux141/captures/raised-road-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Research48/PROMPT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Research48/REPORT.md diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/BuildL141Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux141/BuildL141Fixtures.py new file mode 100644 index 0000000..8274c45 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux141/BuildL141Fixtures.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Build three standalone liminal SurfaceWorld fixtures from the owner input.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l141")) + +FLAT_FIELD = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, +} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + base = json.loads(OWNER.read_text(encoding="utf-8")) + + flat = dict(base) + flat["surface_profile_override"] = dict(FLAT_FIELD) + flat["motif_family_override"] = { + "version": 1, + "strate_index": 0, + "placement_policy": "seed,strate,stable_id", + "motifs": [ + { + "stable_id": "liminal/oversized-familiar-monolith-v1", + "kind": "cappedCylinder", + "radius_m": 1.6, + "height_m": 26.0, + "route_side_offset_m": 42.0, + "placement_radius_m": 0.0, + "fillet_radius_m": 0.6, + "blend_width_m": 1.2, + "minimum_spacing_m": 0.0, + "yaw_quarter_turns": 0, + "attachment": "seated_floor", + }, + ], + } + + hills = dict(base) + hills["surface_profile_override"] = { + "version": 1, + "kind": "periodicHills", + "amplitude_x_m": 2.2, + "amplitude_y_m": 2.2, + "wavelength_x_m": 80.0, + "wavelength_y_m": 80.0, + "minimum_arena_clearance_m": 0.0, + } + + road = dict(base) + road["surface_profile_override"] = dict(FLAT_FIELD) + road["liminal_road_override"] = { + "stable_id": "liminal/raised-road-v1", + "strate_index": 0, + "position_xy_m": [240.0, 180.0], + "half_extents_m": [32.5, 3.0, 0.75], + "deck_height_above_field_m": 22.0, + "yaw_quarter_turns": 0, + } + + for name, fixture in (("flatField-monolith", flat), + ("periodicHills", hills), + ("raised-road", road)): + path = args.out / f"liminal-{name}.json" + path.write_text(json.dumps(fixture, indent=2) + "\n", encoding="utf-8") + print(f"[L141Fixture] name={name} file={path} status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/CaptureL141.py b/Standalone/Research/WorldAssemblerM3/Linux141/CaptureL141.py new file mode 100644 index 0000000..5d295a6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux141/CaptureL141.py @@ -0,0 +1,389 @@ +#!/usr/bin/env python3 +"""Run L141 prototype determinism checks and create eye-level/wide captures.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +from pathlib import Path +import re +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l141")) +CAPTURE_DEFAULT = Path(__file__).resolve().parent / "captures" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +Q_PER_METRE = 1024.0 +FOG_COLOR = "0.66,0.73,0.77" + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import bounded_run, current_stamp, first_stamp + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, *, env: dict[str, str], + stamped: bool = False, timeout_seconds: int = 1740) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(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_stamp: + raise RuntimeError(f"{name} refused a 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, f"timeout", f"{timeout_seconds}s", + *map(str, command)], cwd=ROOT, env=env, + stdout=stream, stderr=subprocess.STDOUT, + timeout=timeout_seconds + 5, check=False) + elapsed = time.monotonic() - started + output = log.read_text(encoding="utf-8", errors="replace") + print(f"[L141Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != 0: + raise RuntimeError(f"{name} failed; see {log}") + return output + + +def route_frame(manifest_path: Path) -> tuple[tuple[float, float, float], + tuple[float, float, float]]: + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + strata = [entry for entry in manifest["plan"]["strates"] + if entry.get("route") and len(entry["route"]) >= 2] + if not strata: + raise RuntimeError(f"no planned SurfaceWorld route in {manifest_path}") + route = strata[0]["route"] + points = [tuple(float(value) / Q_PER_METRE for value in item["position_q"]) + for item in route] + lengths = [math.dist(a, b) for a, b in zip(points, points[1:])] + total = sum(lengths) + if total <= 1.0e-6: + raise RuntimeError(f"degenerate planned route in {manifest_path}") + + def at(distance: float) -> tuple[float, float, float]: + remaining = max(0.0, min(total, distance)) + for index, (a, b, length) in enumerate(zip(points, points[1:], lengths)): + if remaining <= length or index == len(lengths) - 1: + if length <= 1.0e-9: + return b + t = remaining / length + return tuple(a[axis] + (b[axis] - a[axis]) * t for axis in range(3)) + remaining -= length + return points[-1] + + center = at(total * 0.5) + before, after = at(total * 0.5 - 1.0), at(total * 0.5 + 1.0) + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-9: + raise RuntimeError(f"degenerate route tangent in {manifest_path}") + return center, (dx / length, dy / length, 0.0) + + +def camera_angles(camera, target) -> tuple[float, float]: + 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 point_toward(camera, target) -> tuple[float, ...]: + yaw, pitch = camera_angles(camera, target) + return (*camera, yaw, pitch) + + +def stamp(layout: dict, stable_id: str) -> dict: + for record in layout.get("stamps", []): + if record.get("stable_id") == stable_id: + return record + raise RuntimeError(f"missing resolved stamp {stable_id}") + + +def make_views(name: str, manifest_path: Path, layout_path: Path): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + center, tangent = route_frame(manifest_path) + tx, ty, _ = tangent + nx, ny = -ty, tx + base_height = manifest["recipe"]["surface_profile"]["h0_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = stamp(layout, "liminal/oversized-familiar-monolith-v1") + sx, sy, _ = (value / 1.0e6 for value in monolith["position_um"]) + floor = monolith["floor_um"] / 1.0e6 + eye_camera = (sx - tx * 36.0, sy - ty * 36.0, floor + 1.6) + eye_target = (sx, sy, floor + 10.5) + wide_camera = (sx - tx * 42.0 - nx * 18.0, + sy - ty * 42.0 - ny * 18.0, floor + 42.0) + wide_target = (sx, sy, floor + 8.0) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 24), + "height_center": floor, + "height_range": 38.0, + } + if name == "periodicHills": + # Route points are capsule centers: +0.72 m places the view at 1.60 m above ground. + eye_camera = (center[0], center[1], center[2] + 0.72) + eye_target = (center[0] - tx * 45.0, center[1] - ty * 45.0, + center[2] + 0.72) + wide_camera = (center[0] - tx * 20.0 - nx * 20.0, + center[1] - ty * 20.0 - ny * 20.0, center[2] + 34.0) + wide_target = (center[0] - tx * 45.0, center[1] - ty * 45.0, + center[2] + 0.72) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 28), + "height_center": base_height, + "height_range": 5.0, + } + road = stamp(layout, "liminal/raised-road-v1") + rx, ry, rz = (value / 1.0e6 for value in road["position_um"]) + half_length, half_width, half_thickness = ( + value / 1.0e6 for value in road["half_extents_um"]) + deck = rz + half_thickness + eye_camera = (rx - half_length + 14.0, ry, deck + 1.6) + eye_target = (rx + half_length, ry, base_height) + wide_camera = (rx, ry - 28.0, deck + 24.0) + wide_target = (rx + 4.0, ry, base_height + 4.0) + return { + "eye": (eye_camera, eye_target, 24), + "wide": (wide_camera, wide_target, 26), + "height_center": base_height + 11.0, + "height_range": 32.0, + "road_deck": deck, + "road_width": 2.0 * half_width, + } + + +def headless_command(binary: Path, fixture: Path, camera, mesh: Path, + manifest: Path, layout: Path, workers: int, + clip_radius: int, *, hash_tiles: bool = False, + audit_road: bool = False, max_level: int = 0) -> list[object]: + command: list[object] = [binary, fixture, f"--workers={workers}", + "--seed=0", "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={clip_radius}", + f"--max-clip-level={max_level}", + f"--max-level={max_level}", "--render-distance-chunks=0", + f"--camera={fmt(point_toward(camera, (camera[0], camera[1] + 1.0, camera[2])))}", + f"--mesh-export={mesh}", f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if hash_tiles: + command.append("--stream-hash-tiles") + if audit_road: + command.append("--audit-liminal-road-walk") + return command + + +def determinism_digest(output: str, manifest_path: Path, + layout_path: Path) -> tuple[str, str, str]: + tile_hashes = sorted(line for line in output.splitlines() + if line.startswith("[PipelineTileHash] ")) + if not manifest_path.is_file() or not layout_path.is_file() or not tile_hashes: + raise RuntimeError("determinism run omitted manifest, layout or per-tile hashes") + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + manifest_digest = (manifest["content_hash"],manifest["recipe"]["content_hash"], + manifest["plan"]["content_hash"]) + return ("|".join(manifest_digest),layout["stable_identity"],"\n".join(tile_hashes)) + + +def run_determinism(name: str, fixture: Path, view, *, binaries: dict[str, Path], + out: Path, env: dict[str, str]) -> None: + camera, _, _ = view["eye"] + clip_radius = 1 + max_clip = 0 + baseline = None + cells = 0 + for compiler, workers in ((compiler, workers) + for compiler in ("clang", "gcc") + for workers in (1, 8, 12)): + tag = f"{name}-{compiler}-w{workers}" + run_dir = out / "determinism" / tag + run_dir.mkdir(parents=True, exist_ok=True) + mesh = run_dir / "feature.vfmesh" + manifest = run_dir / "manifest.json" + layout = run_dir / "layout.json" + command = headless_command(binaries[compiler], fixture,camera,mesh,manifest, + layout,workers,max_clip,hash_tiles=True) + output = run_step(tag,command,out/"logs"/f"determinism-{tag}.log", + env=env,stamped=True) + digest = determinism_digest(output,manifest,layout) + if baseline is None: + baseline = digest + elif digest != baseline: + raise RuntimeError(f"{name} diverged at {compiler} W{workers}; see determinism logs") + cells += 1 + print(f"[L141Determinism] fixture={name} compiler_worker_cells={cells} identical=yes status=PASS", + flush=True) + + +def export_and_capture(name: str, fixture: Path, views: dict, *, + headless: Path, renderer: Path, out: Path, + artifact_dir: Path, env: dict[str, str]) -> None: + for view_name in ("eye", "wide"): + camera, target, clip_radius = views[view_name] + clip_radius = min(clip_radius,7) + stem = f"{name}-{view_name}" + mesh = out / "capture-meshes" / f"{stem}.vfmesh" + manifest = out / "capture-manifests" / f"{stem}.json" + layout = out / "capture-layouts" / f"{stem}.json" + png = out / "capture-png" / f"{stem}.png" + image = artifact_dir / f"{stem}.jpg" + for path in (mesh,manifest,layout,png,image): + path.parent.mkdir(parents=True,exist_ok=True) + command = headless_command(headless,fixture,camera,mesh,manifest,layout,12, + clip_radius,max_level=0) + output = run_step(f"capture-{stem}-export",command, + out/"logs"/f"capture-{stem}-export.log",env=env,stamped=True) + if not mesh.is_file() or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem} produced an empty mesh") + yaw, pitch = camera_angles(camera,target) + height_center = views["height_center"] + height_range = views["height_range"] + renderer_command = [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=off","--height-tint=on",f"--height-center-m={height_center:.6f}", + f"--height-range-m={height_range:.6f}","--light-direction=-0.42,-0.58,0.70", + "--fog=on","--fog-start-m=30","--fog-end-m=105",f"--fog-color={FOG_COLOR}"] + run_step(f"capture-{stem}-render",renderer_command, + out/"logs"/f"capture-{stem}-render.log",env=env,stamped=True) + run_step(f"capture-{stem}-jpeg",["ffmpeg","-nostdin","-hide_banner","-loglevel", + "error","-y","-i",png,"-frames:v","1","-q:v","4",image], + out/"logs"/f"capture-{stem}-jpeg.log",env=env) + quality = run_step(f"capture-{stem}-quality", + [sys.executable,ROOT/"Standalone/Tools/verify/capture_quality.py",image], + out/"logs"/f"capture-{stem}-quality.log",env=env) + if "[CaptureQuality]" not in quality or not image.is_file() \ + or image.stat().st_size > 300_000: + raise RuntimeError(f"{stem} capture failed quality or size checks") + eye_height = "1.600m" if view_name == "eye" else "wide" + print(f"[L141Capture] fixture={name} view={view_name} eye_height={eye_height} " + f"camera_m=({fmt(camera)}) target_m=({fmt(target)}) bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS",flush=True) + + +def run_road_walk_audit(fixture: Path, view, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + camera = view["eye"][0] + run_dir = out / "road-walk-audit" + run_dir.mkdir(parents=True,exist_ok=True) + output = run_step("road-walk-audit",headless_command(headless,fixture,camera, + run_dir/"audit.vfmesh",run_dir/"manifest.json",run_dir/"layout.json",12,1, + audit_road=True),out/"logs"/"road-walk-audit.log",env=env,stamped=True) + if not re.search(r"\[LiminalRoadWalkAudit\].*status=PASS",output): + raise RuntimeError("raised road failed the Core capsule walk audit") + + +def measure_near_ready(fixture: Path, views: dict, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + uptime = subprocess.run(["uptime"],cwd=ROOT,capture_output=True,text=True,check=True).stdout.strip() + load_match = re.search(r"load average:\s*([0-9.]+)",uptime) + if not load_match or float(load_match.group(1)) >= 1.5: + raise RuntimeError(f"near-ready timing requires a quiet machine: {uptime}") + print(f"[L141TimingEnvironment] window=one W12 run after one warmup uptime='{uptime}' " + f"status=PASS",flush=True) + camera = views["eye"][0] + warm_dir = out / "near-ready" / "warmup" + timed_dir = out / "near-ready" / "measured" + warm_dir.mkdir(parents=True,exist_ok=True) + timed_dir.mkdir(parents=True,exist_ok=True) + + def command(directory: Path) -> list[object]: + return [headless,fixture,"--workers=12","--world-assembler-prototype", + "--seed=0","--stream-benchmark","--stream-pipeline","--force-generate", + "--clip-radius=1","--max-clip-level=2","--max-level=2", + "--render-distance-chunks=0", + f"--camera={fmt(point_toward(camera,(camera[0],camera[1]+1.0,camera[2])))}", + f"--world-assembler-manifest-output={directory/'manifest.json'}", + f"--resolved-layout-output={directory/'layout.json'}"] + + run_step("near-ready-warmup",command(warm_dir), + out/"logs"/"near-ready-warmup.log",env=env,stamped=True) + output = run_step("near-ready-measured",command(timed_dir), + out/"logs"/"near-ready-measured.log",env=env,stamped=True) + match = re.search(r"^\[WorldAssemblerNearLODPipelineReady\] lods=0-2 " + r"tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$",output,re.M) + if not match or match.group(1)!=match.group(2): + raise RuntimeError("near-ready run did not complete the full LOD 0-2 set") + print(f"[L141NearReady] window=one W12 run after one warmup clip_radius=1 " + f"tiles={match.group(1)}/{match.group(2)} cold_ready_s={match.group(3)} status=PASS", + flush=True) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT) + parser.add_argument("--artifact-dir", type=Path, default=CAPTURE_DEFAULT) + parser.add_argument("--headless-clang", type=Path, required=True) + parser.add_argument("--headless-gcc", type=Path, required=True) + parser.add_argument("--renderer", type=Path, required=True) + args = parser.parse_args() + + out = args.out.resolve() + artifact_dir = args.artifact_dir.resolve() + fixture_dir = out / "fixtures" + for directory in (out,fixture_dir,artifact_dir): + directory.mkdir(parents=True,exist_ok=True) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(out) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT/"Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(out/"xdg-cache") + run_step("build-fixtures",[sys.executable, + ROOT/"Standalone/Research/WorldAssemblerM3/Linux141/BuildL141Fixtures.py", + f"--out={fixture_dir}"],out/"logs"/"build-fixtures.log",env=env) + + binaries = {"clang":args.headless_clang.resolve(),"gcc":args.headless_gcc.resolve()} + fixtures = { + "flatField-monolith":fixture_dir/"liminal-flatField-monolith.json", + "periodicHills":fixture_dir/"liminal-periodicHills.json", + "raised-road":fixture_dir/"liminal-raised-road.json", + } + probed = {} + for name,fixture in fixtures.items(): + probe_dir=out/"plan-probes"/name + probe_dir.mkdir(parents=True,exist_ok=True) + camera=(0.0,0.0,-500.0) + output=run_step(f"plan-probe-{name}",headless_command(binaries["clang"],fixture, + camera,probe_dir/"probe.vfmesh",probe_dir/"manifest.json", + probe_dir/"layout.json",12,1),out/"logs"/f"plan-probe-{name}.log", + env=env,stamped=True) + if "[WorldAssemblerFullManifest]" not in output: + raise RuntimeError(f"{name} probe omitted its full plan manifest") + probed[name]=make_views(name,probe_dir/"manifest.json",probe_dir/"layout.json") + + for name,fixture in fixtures.items(): + run_determinism(name,fixture,probed[name],binaries=binaries,out=out,env=env) + run_road_walk_audit(fixtures["raised-road"],probed["raised-road"], + headless=binaries["clang"],out=out,env=env) + for name,fixture in fixtures.items(): + export_and_capture(name,fixture,probed[name],headless=binaries["clang"], + renderer=args.renderer.resolve(),out=out,artifact_dir=artifact_dir,env=env) + measure_near_ready(fixtures["raised-road"],probed["raised-road"], + headless=binaries["clang"],out=out,env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L141Capture] status=FAIL error={error}",file=sys.stderr,flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux141/REPORT.md new file mode 100644 index 0000000..0f608c8 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux141/REPORT.md @@ -0,0 +1,40 @@ +# L141 — first liminal layer + +![flatField monolith, eye level](captures/flatField-monolith-eye.jpg) +![periodicHills, eye level](captures/periodicHills-eye.jpg) +![raised road, eye level](captures/raised-road-eye.jpg) + +![flatField monolith, wide](captures/flatField-monolith-wide.jpg) +![periodicHills, wide](captures/periodicHills-wide.jpg) +![raised road, wide](captures/raised-road-wide.jpg) + +The standalone fixtures and six captures are ready for review. The flat field has one oversized capped-cylinder monolith. The road is a 65 m `fillDais` platform, 6 m wide, with its deck 22 m above a flat field. Fog supplies the road's cloud-sea backdrop in these standalone images. + +The `periodicHills` fixture uses the validated 80 m periods and 2.2 m amplitudes on both axes. Its field repeats exactly, but these captures show one broad rise rather than hills repeating to the horizon. The validated period is longer than the 56 m eye-level capture radius; the wider full-detail capture exceeded Core's 160-million-node interval bound. Smaller periods fail the existing profile validator. A capture extent that trims vertical tiles independently from horizontal tiles is the next useful step; this round leaves the Core profile limits unchanged. + +## Changes + +- Reused Core's `flatField`, `periodicHills`, `fillMonolith`, and `fillDais` support. Added standalone fixture inputs and runners in `BuildL141Fixtures.py` and `CaptureL141.py`. +- Added `liminal_road_override` as a standalone adapter to the existing free-placement `fillDais` stamp, plus `--audit-liminal-road-walk`. The walk audit samples the Core field with the existing capsule sampler and checks width and grade. +- Added optional distance fog to `LinuxOffscreenCapture` for the screenshots. The fog is capture-only; Unreal cloud rendering remains Unreal-side. +- No evaluator change or Unreal `Source/` change. Owner output hashes match their pinned L130/v227 canonical rows in the fast tier. + +## Measurements + +- Determinism: each fixture matched across Clang and GCC at W1, W8, and W12 (six cells per fixture). The matrix used LOD0, clip radius 1; each cell compares recipe/plan hashes, resolved-layout identity, and per-tile hashes. Individual logs are in `Saved/Linux/l141/logs/determinism-*.log`. +- Raised-road capsule walk: 127 stations, 8,001 capsule samples, zero blocked samples, zero unsupported stations, 6.000 m width against a 0.680 m capsule diameter, and 0.000° grade. See `Saved/Linux/l141/logs/road-walk-audit.log`. +- Near-ready: one W12 LOD0–2 sample after one warm-up, clip radius 1, 139/139 tiles. The measured `cold_ready_s` was **0.173886 s**. The window was one run after one warm-up; `uptime` showed a 1-minute load average of 1.31 and no other build was running. See `Saved/Linux/l141/logs/near-ready-measured.log`. +- Each capture is 1600×900 and passed `capture_quality.py`. Eye views place the camera 1.6 m above the field or road deck. Camera coordinates and image hashes are recorded in the capture runner output; export and render logs are under `Saved/Linux/l141/logs/`. + +## Checks + +- Clang 19 and GCC standalone builds passed with FP contraction off, four jobs, and source stamp `0a2828c398aa62870690667901d44f2daf5b1a5547b9640da6dbb01df721af8b`. +- `python3 Standalone/Tools/verify/verify.py fast --out Saved/Linux/l141 --overall-timeout 1740` passed in 285.7 s. Owner SurfaceWorld and FloatingIslands W1/W12 canonical hashes matched the L130/v227 baselines. +- Fixture determinism, dedicated road walk audit, six standalone captures, and all six image-quality checks passed. +- Python bytecode compilation and `git diff --check` passed. +- An exploratory broad `--audit-resolved-layout-passages` invocation also ran unrelated passage ripple checks and reported 2/3 passage ripple records passing, with `passage/1-2/0` failing. The focused liminal road audit passes; no legacy threshold was changed. +- No Unreal build was run because no Unreal `Source/` file changed. No timing matrix was requested or run. + +## Remaining risk + +The hill screenshots do not yet show multiple full repeats to the horizon. The profile itself is exactly periodic; the standalone capture volume is too short at the current full-detail safety bound. The raised road is geometric and walk-audited, while its clouds are represented by fog in the capture renderer. diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..547cc0f60f3ce67648e140676136bcaf7ff4a571 GIT binary patch literal 26770 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 ScwoZ=8y@)2^?*2``o91bh?GJA literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux141/captures/flatField-monolith-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43b92bc28587b54a2329ca7d5fb986d4aec11dbd GIT binary patch literal 24016 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e76c43327ebcb925325eab50e0706f66120ada66 GIT binary patch literal 23693 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 M`tmiOf2s9<0hlOPvH$=8 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux141/captures/periodicHills-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c8097adb590ffc777af3a860017904505940bdf GIT binary patch literal 24629 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 e>`KkYx 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
-na6?O89 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 z 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.0) { vec2 local=mod(vWorldPosition.xy-vTileData.xy,vTileData.z); @@ -707,7 +717,8 @@ void main() bool HeightTint,bool Headlamp,bool TileEdges, double TileEdgeWidthMeters,bool HasLightDirection, const std::array& LightDirection,bool ClipPlaneEnabled, - const std::array& ClipPlane) + const std::array& ClipPlane,bool FogEnabled, + double FogStartMeters,double FogEndMeters,const std::array& FogColor) { EGLDisplay Display=MakeDisplay(); EGLint Major=0,Minor=0; @@ -796,7 +807,10 @@ void main() glViewport(0,0,Width,Height);glDisable(GL_CULL_FACE);glEnable(GL_DEPTH_TEST); // A covered empty ray represents open air. Keep it visibly blue so it cannot // be mistaken for the old near-black result from a scene that lacked tiles. - glDepthFunc(GL_LEQUAL);glClearColor(0.30f,0.48f,0.62f,1.0f); + glDepthFunc(GL_LEQUAL); + glClearColor(FogEnabled?static_cast(FogColor[0]):0.30f, + FogEnabled?static_cast(FogColor[1]):0.48f, + FogEnabled?static_cast(FogColor[2]):0.62f,1.0f); glClearDepthf(1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glUseProgram(Program); glUniform1f(glGetUniformLocation(Program,"uTanHalfHorizontal"),static_cast(TanHalfHorizontal)); @@ -825,6 +839,18 @@ void main() static_cast(ActiveLightDirection[0]), static_cast(ActiveLightDirection[1]), static_cast(ActiveLightDirection[2])); + glUniform3f(glGetUniformLocation(Program,"uCameraWorld"), + static_cast(Scene.CameraMeters[0]), + static_cast(Scene.CameraMeters[1]), + static_cast(Scene.CameraMeters[2])); + glUniform3f(glGetUniformLocation(Program,"uFogColor"), + static_cast(FogColor[0]),static_cast(FogColor[1]), + static_cast(FogColor[2])); + glUniform1f(glGetUniformLocation(Program,"uFogStart"), + static_cast(FogStartMeters)); + glUniform1f(glGetUniformLocation(Program,"uFogEnd"), + static_cast(FogEndMeters)); + glUniform1i(glGetUniformLocation(Program,"uFogEnabled"),FogEnabled?1:0); glDrawElements(GL_TRIANGLES,static_cast(Scene.Indices.size()),GL_UNSIGNED_INT,nullptr); glFinish(); std::vector Pixels(static_cast(Width)*Height*4); @@ -863,7 +889,7 @@ int main(int argc,char** argv) if(argc==2&&std::string_view(argv[1])=="--print-source-stamp")return 0; if(argc<3) { - std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--height-range-m=N] [--height-center-m=N] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N] [--shade=readable|normal] [--height-tint=on|off] [--headlamp=on|off] [--light-direction=X,Y,Z] [--tile-edges=on|off] [--tile-skirts=on|off] [--tile-edge-width-m=N] [--clip-plane=NX,NY,NZ,D] [--focus-region=X,Y,Z,R]\n",argv[0]); + std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--height-range-m=N] [--height-center-m=N] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N] [--shade=readable|normal] [--height-tint=on|off] [--headlamp=on|off] [--light-direction=X,Y,Z] [--fog=on|off] [--fog-start-m=N] [--fog-end-m=N] [--fog-color=R,G,B] [--tile-edges=on|off] [--tile-skirts=on|off] [--tile-edge-width-m=N] [--clip-plane=NX,NY,NZ,D] [--focus-region=X,Y,Z,R]\n",argv[0]); return 2; } int Width=2560,Height=1440;double Fov=90.0,HeightRangeMeters=64.0; @@ -871,6 +897,8 @@ int main(int argc,char** argv) bool HasYaw=false,HasPitch=false;double Yaw=0.0,Pitch=0.0; bool HasCamera=false;std::array Camera{}; bool HasLightDirection=false;std::array LightDirection{}; + bool FogEnabled=false;double FogStartMeters=50.0,FogEndMeters=200.0; + std::array FogColor={0.62,0.70,0.75}; bool ReadableMode=true,HeightTint=true,TileEdges=false,TileSkirts=true,Headlamp=false; double TileEdgeWidthMeters=0.15; bool ClipPlaneEnabled=false;std::array ClipPlane{}; @@ -967,6 +995,38 @@ int main(int argc,char** argv) {std::fprintf(stderr,"Invalid light direction; use X,Y,Z with non-zero length\n");return 2;} HasLightDirection=true; } + else if(Arg.starts_with("--fog=")) + { + const std::string_view Mode=Arg.substr(6); + if(Mode=="on")FogEnabled=true; + else if(Mode=="off")FogEnabled=false; + else {std::fprintf(stderr,"Invalid fog mode\n");return 2;} + } + else if(Arg.starts_with("--fog-start-m=")) + { + char* End=nullptr;const std::string Value(Arg.substr(14)); + FogStartMeters=std::strtod(Value.c_str(),&End); + if(End==Value.c_str()||*End!='\0'||!std::isfinite(FogStartMeters) + ||FogStartMeters<0.0||FogStartMeters>20000.0) + {std::fprintf(stderr,"Invalid fog start distance\n");return 2;} + } + else if(Arg.starts_with("--fog-end-m=")) + { + char* End=nullptr;const std::string Value(Arg.substr(12)); + FogEndMeters=std::strtod(Value.c_str(),&End); + if(End==Value.c_str()||*End!='\0'||!std::isfinite(FogEndMeters) + ||FogEndMeters<=0.0||FogEndMeters>20000.0) + {std::fprintf(stderr,"Invalid fog end distance\n");return 2;} + } + else if(Arg.starts_with("--fog-color=")) + { + const std::string Value(Arg.substr(12)); + if(std::sscanf(Value.c_str(),"%lf,%lf,%lf",&FogColor[0],&FogColor[1], + &FogColor[2])!=3 + ||std::any_of(FogColor.begin(),FogColor.end(),[](double Channel) + {return !std::isfinite(Channel)||Channel<0.0||Channel>1.0;})) + {std::fprintf(stderr,"Invalid fog color; use R,G,B in 0..1\n");return 2;} + } else if(Arg.starts_with("--tile-edges=")) { const std::string_view Mode=Arg.substr(13); @@ -1002,6 +1062,8 @@ int main(int argc,char** argv) } else {std::fprintf(stderr,"Unknown option: %.*s\n",static_cast(Arg.size()),Arg.data());return 2;} } + if(FogEnabled&&FogEndMeters<=FogStartMeters) + {std::fprintf(stderr,"Fog end distance must be greater than fog start distance\n");return 2;} FScene Scene;std::string Error; if(!LoadScene(argv[1],Scene,Error)) {std::fprintf(stderr,"[OffscreenCapture] FAIL: %s\n",Error.c_str());return 2;} @@ -1077,14 +1139,16 @@ int main(int argc,char** argv) FocusRadius,static_cast(Scene.DrawnTriangles)); } } - std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f height_m=%.3f..%.3f height_center_m=%.3f shade=%s height_tint=%s tile_edges=%s vertices=%zu triangles=%llu\n", + std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f height_m=%.3f..%.3f height_center_m=%.3f shade=%s height_tint=%s tile_edges=%s fog=%s fog_distance_m=%.1f..%.1f fog_color=(%.2f,%.2f,%.2f) vertices=%zu triangles=%llu\n", 1000000.0/Scene.VoxelSizeMicrons,Scene.CameraMeters[0],Scene.CameraMeters[1],Scene.CameraMeters[2], Scene.YawDegrees,Scene.PitchDegrees,Scene.MinimumHeight,Scene.MaximumHeight, HeightCenterMeters, ReadableMode?"readable":"normal",HeightTint?"on":"off", - TileEdges?"on":"off",Scene.Vertices.size(), + TileEdges?"on":"off",FogEnabled?"on":"off",FogStartMeters,FogEndMeters, + FogColor[0],FogColor[1],FogColor[2],Scene.Vertices.size(), static_cast(Scene.Triangles)); return Render(Scene,argv[2],Width,Height,Fov,HeightRangeMeters,HeightCenterMeters,ReadableMode, HeightTint,Headlamp,TileEdges, - TileEdgeWidthMeters,HasLightDirection,LightDirection,ClipPlaneEnabled,ClipPlane)?0:3; + TileEdgeWidthMeters,HasLightDirection,LightDirection,ClipPlaneEnabled,ClipPlane, + FogEnabled,FogStartMeters,FogEndMeters,FogColor)?0:3; } diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index a0cb0a7..bc48c9d 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -108,6 +108,7 @@ namespace bool ResolvedLayoutOnly=false; bool AuditResolvedLayoutBoundaries=false; bool AuditResolvedLayoutPassages=false; + bool AuditLiminalRoadWalk=false; bool AuditSurfaceClearance=false; bool AuditStrateTransitions=false; int TransitionModeOverride=-1; @@ -1447,6 +1448,7 @@ namespace " --audit-strate-transitions (measure interface crossing, band thickness and holes)\n" " --transition-mode=hard|gradient|interleaved --transition-width-chunks=N (fixture override)\n" " --audit-resolved-layout-passages (capsule, support, route-binding and blocked-control audit)\n" + " --audit-liminal-road-walk (capsule, support, width and grade audit for the liminal road)\n" " --audit-heightfield-profile (brute-force the profiled field intervals and route)\n" " --audit-motif-intervals (brute-force motif bounds, BVH and shape-free guards)\n" " --audit-landmark-reachability (capsule, support, grade and buried-L43 control)\n" @@ -1494,6 +1496,7 @@ namespace else if(arg=="--resolved-layout-only")options.ResolvedLayoutOnly=true; else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true; else if(arg=="--audit-resolved-layout-passages")options.AuditResolvedLayoutPassages=true; + else if(arg=="--audit-liminal-road-walk")options.AuditLiminalRoadWalk=true; else if(arg=="--native-owner-fi")options.NativeOwnerFloatingIslandsRecipe=true; else if(arg=="--density-dispatch-report") {options.DensityDispatchReport=true;options.StreamHash=true;options.StreamHashTiles=true;} @@ -1875,7 +1878,13 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::ValidateExportedCorePlanMatchesOwner( *ownerWorld,worldAssembly,resolvedLayout,error)) {std::fprintf(stderr,"Unreal-resolved Core plan/owner slot validation failed: %s\n",error.c_str());return 2;} - if(!std::holds_alternative(ownerJsonRoot.Get("motif_family_override").Data)) + const bool hasMotifFamily=!std::holds_alternative( + ownerJsonRoot.Get("motif_family_override").Data); + const bool hasLiminalRoad=!std::holds_alternative( + ownerJsonRoot.Get("liminal_road_override").Data); + if(hasMotifFamily&&hasLiminalRoad) + {std::fprintf(stderr,"motif_family_override and liminal_road_override cannot be combined\n");return 2;} + if(hasMotifFamily) { std::vector requests; if(!StandaloneWorldAssemblyPrototype::BuildMotifFamilyRequests(ownerJsonRoot, @@ -1903,6 +1912,25 @@ int main(int argc,char** argv) static_cast(motif.irregularitySeed)); } } + if(hasLiminalRoad) + { + std::vector requests(1); + if(!StandaloneWorldAssemblyPrototype::BuildLiminalRoadRequest(ownerJsonRoot, + *ownerWorld,worldAssembly,resolvedLayout,requests.front(),error) + ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( + resolvedLayout,seed,requests,error)) + {std::fprintf(stderr,"Liminal road resolution failed: %s\n",error.c_str());return 2;} + const auto& road=resolvedLayout.stamps.front(); + std::printf("[LiminalRoadResolved] vocabulary=%u id=%s strate=%d shape=rounded_dais " + "center_m=(%.3f,%.3f,%.3f) top_m=%.3f span_m=%.3f width_m=%.3f " + "grade_deg=0.000 placement=free route_keepout=PASS band_clearance=PASS status=PASS\n", + resolvedLayout.stampVocabularyVersion,road.stableId.c_str(),road.strateIndex, + road.positionMicrometres[0]/1.0e6,road.positionMicrometres[1]/1.0e6, + road.positionMicrometres[2]/1.0e6, + (road.positionMicrometres[2]+road.halfExtentsMicrometres[2])/1.0e6, + 2.0*road.halfExtentsMicrometres[0]/1.0e6, + 2.0*road.halfExtentsMicrometres[1]/1.0e6); + } if(options.LandmarkChamberDemo) { std::vector requests; @@ -2404,5 +2432,5 @@ int main(int argc,char** argv) options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds, options.MovingCameraDwellSeconds,options.ColdWorkerTimeline, options.AuditPassageSourceClamp,options.AuditPassageCarveReach, - options.AuditPassageTileSeams); + options.AuditPassageTileSeams,options.AuditLiminalRoadWalk); } diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 06626c9..e151fbd 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2384,7 +2384,8 @@ namespace StandaloneStreamBenchmark bool bMovingCameraTrace=false,double MovingCameraSpeedMetersPerSecond=0.0, double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0, bool bColdWorkerTimeline=false,bool bAuditPassageSourceClamp=false, - bool bAuditPassageCarveReach=false,bool bAuditPassageTileSeams=false) + bool bAuditPassageCarveReach=false,bool bAuditPassageTileSeams=false, + bool bAuditLiminalRoadWalk=false) { using Clock=std::chrono::steady_clock; const std::clock_t ColdCpuOrigin=std::clock(); @@ -2554,7 +2555,7 @@ namespace StandaloneStreamBenchmark ||bAuditOreVeinYield||bAuditLandmarkReachability||bAuditStrateTransitions ||bAuditResolvedLayoutPassages||bAuditResolvedLayoutBoundaries ||bAuditTileShapeReadiness||bAuditBasePageEquivalence||bAuditRouteParity - ||bAuditPassageSourceClamp||bAuditPassageCarveReach; + ||bAuditPassageSourceClamp||bAuditPassageCarveReach||bAuditLiminalRoadWalk; const bool bDeferFarWorld=bIncludeFarWorld&&!bMovingCameraTrace&&!bFarWorldAudit; VoxelForgeCore::ShapeBuildRequest ShapeRequest; ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z}; @@ -2820,10 +2821,10 @@ namespace StandaloneStreamBenchmark Streamer.Stop(); return passed?0:11; } - if(bAuditResolvedLayoutPassages) + if(bAuditResolvedLayoutPassages||bAuditLiminalRoadWalk) { if(ResolvedLayout==nullptr||!CoreSnapshot.resolvedLayout()) - {Streamer.Stop();std::fprintf(stderr,"[ResolvedPassageAudit] missing resolved-layout snapshot\n");return 2;} + {Streamer.Stop();std::fprintf(stderr,"[ResolvedWalkAudit] missing resolved-layout snapshot\n");return 2;} struct FWalkAudit { std::uint64_t segments=0,centers=0,capsuleSamples=0,blocked=0; @@ -2961,6 +2962,67 @@ namespace StandaloneStreamBenchmark &&audit.gradeFailures==0; return audit; }; + const auto auditLiminalRoadWalk=[&](bool required) + { + bool found=false; + bool passed=true; + for(const auto& road:ResolvedLayout->stamps) + { + if(road.stableId!="liminal/raised-road-v1")continue; + found=true; + const bool longAxisX=(road.yawQuarterTurns&1u)==0; + const double centerX=road.positionMicrometres[0]/1.0e6; + const double centerY=road.positionMicrometres[1]/1.0e6; + const double centerZ=road.positionMicrometres[2]/1.0e6; + const double halfLength=road.halfExtentsMicrometres[longAxisX?0:1]/1.0e6; + const double halfWidth=road.halfExtentsMicrometres[longAxisX?1:0]/1.0e6; + const double deckZ=centerZ+road.halfExtentsMicrometres[2]/1.0e6; + constexpr double CapsuleRadiusMetres=0.34; + constexpr double CapsuleHeightMetres=1.76; + constexpr double HalfCapsuleHeightMetres=CapsuleHeightMetres*0.5; + constexpr double EndInsetMetres=1.0; + std::vector> roadPath; + const double inset=std::min(EndInsetMetres,halfLength*0.25); + for(const double along:{-halfLength+inset,halfLength-inset}) + roadPath.push_back({(centerX+(longAxisX?along:0.0))/coreMetres, + (centerY+(longAxisX?0.0:along))/coreMetres, + (deckZ+HalfCapsuleHeightMetres)/coreMetres}); + const FWalkAudit roadAudit=auditPlayerPath(Shape,roadPath, + 0.125,0.125,1.125,3,0.45); + const double widthMetres=2.0*halfWidth; + const double horizontal=std::hypot(roadPath[1][0]-roadPath[0][0], + roadPath[1][1]-roadPath[0][1])*coreMetres; + const double vertical=std::abs(roadPath[1][2]-roadPath[0][2])*coreMetres; + const double gradeDegrees=std::atan2(vertical,horizontal)* + 57.29577951308232; + passed=road.kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillDais + &&widthMetres>=2.0*CapsuleRadiusMetres + &&gradeDegrees<=15.0&&roadAudit.passed; + std::printf("[LiminalRoadWalkAudit] id=%s stations=%llu capsule_samples=%llu " + "blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu " + "width_m=%.3f capsule_diameter_m=%.3f grade_deg=%.3f grade_limit_deg=15.000 " + "status=%s\n",road.stableId.c_str(), + static_cast(roadAudit.centers), + static_cast(roadAudit.capsuleSamples), + static_cast(roadAudit.blocked), + static_cast(roadAudit.supportSamples), + static_cast(roadAudit.unsupported), + static_cast(roadAudit.gradeFailures),widthMetres, + 2.0*CapsuleRadiusMetres,gradeDegrees,passed?"PASS":"FAIL"); + } + if(!found&&required) + { + std::printf("[LiminalRoadWalkAudit] status=FAIL reason=road_stamp_missing\n"); + return false; + } + return passed; + }; + if(bAuditLiminalRoadWalk&&!bAuditResolvedLayoutPassages) + { + const bool passed=auditLiminalRoadWalk(true); + Streamer.Stop(); + return passed?0:14; + } const auto qToMetres=[&](std::int64_t q) {return static_cast(q)*World.CoreVoxelSizeMicrons /(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel*1000000.0);}; @@ -4919,6 +4981,7 @@ namespace StandaloneStreamBenchmark routeAudit.firstUnsupported[i][1],routeAudit.firstUnsupported[i][2], routeAudit.firstUnsupported[i][3]); } + const bool liminalRoadAuditPassed=auditLiminalRoadWalk(false); for(std::size_t passageIndex=0; passageIndexpassages.size();++passageIndex) { @@ -4984,6 +5047,7 @@ namespace StandaloneStreamBenchmark &&shellAuditPassed &&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings &&routeBindingFailures==0 + &&liminalRoadAuditPassed &&blockedCompiled&&blockedControls==passageCount; std::printf("[ResolvedPassageAuditSummary] interfaces=%llu passed=%llu natural=%llu/%llu strate_routes=%llu route_walkable=%llu route_points=%llu route_bindings=%llu route_binding_failures=%llu blocked_controls=%llu/%llu status=%s\n", static_cast(passageCount),static_cast(passagePasses), diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index dbe2a7c..bafe419 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -587,6 +587,69 @@ namespace StandaloneWorldAssemblyPrototype return true; } + inline bool BuildLiminalRoadRequest(const VFJson::Value& root, + const FStandaloneOwnerWorld& owner, + const VoxelForgeCore::WorldAssemblyManifest& assembly, + const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout, + VoxelForgeCore::ResolvedLayoutStampRequestV1& request,std::string& error) + { + using namespace VoxelForgeCore; + const VFJson::Value& overrideValue=root.Get("liminal_road_override"); + if(!overrideValue.IsObject()) + {error="liminal_road_override must be an object";return false;} + if(assembly.recipe.surfaceProfile.version!=1 + ||assembly.recipe.surfaceProfile.kind!=WorldAssemblySurfaceProfileKindV1::flatField + ||owner.CoreVoxelSizeMicrons==0) + {error="the liminal road requires a valid flatField SurfaceWorld recipe";return false;} + + const VFJson::Value& strateValue=overrideValue.Get("strate_index"); + const auto* id=std::get_if(&overrideValue.Get("stable_id").Data); + const auto& position=overrideValue.Get("position_xy_m").AsArray(); + const auto& extents=overrideValue.Get("half_extents_m").AsArray(); + const VFJson::Value& heightValue=overrideValue.Get("deck_height_above_field_m"); + const VFJson::Value& yawValue=overrideValue.Get("yaw_quarter_turns"); + if(!strateValue.IsNumber()||!id||id->empty()||position.size()!=2||extents.size()!=3 + ||!heightValue.IsNumber()||!std::isfinite(heightValue.Number()) + ||!yawValue.IsNumber()||yawValue.Integer()<0||yawValue.Integer()>3) + {error="liminal road requires stable_id, strate_index, position, extents, deck height and yaw";return false;} + for(const auto& value:position) + if(!value.IsNumber()||!std::isfinite(value.Number())) + {error="liminal road position_xy_m must contain finite metre values";return false;} + for(const auto& value:extents) + if(!value.IsNumber()||!std::isfinite(value.Number()) + ||value.Number()<0.5||value.Number()>100.0) + {error="liminal road half_extents_m must contain values from 0.5 to 100 metres";return false;} + if(heightValue.Number()<1.0||heightValue.Number()>100.0) + {error="liminal road deck height must be from 1 to 100 metres above the field";return false;} + const auto strateIndex=static_cast(strateValue.Integer()); + const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), + [strateIndex](const auto& value){return value.strateIndex==strateIndex + &&value.generatorKind=="SurfaceWorld";}); + if(strate==layout.strates.end()) + {error="liminal_road_override must select a resolved SurfaceWorld strate";return false;} + if(extents[0].Number()<10.0||extents[1].Number()<0.75 + ||extents[0].Number()<=extents[1].Number()*4.0) + {error="liminal road must be long and narrow, with at least 1.5 metres half-width";return false;} + + const auto metresToMicrometres=[](double value) + {return static_cast(std::llround(value*1000000.0));}; + const std::int64_t fieldFloorMicrometres=static_cast(std::llround( + static_cast(assembly.recipe.surfaceProfile.h0Subvoxels) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel)); + request={}; + request.stableId=*id; + request.strateIndex=strateIndex; + request.kind=ResolvedSdfStampKindV1::fillDais; + request.anchorPositionMicrometres={metresToMicrometres(position[0].Number()), + metresToMicrometres(position[1].Number()), + fieldFloorMicrometres+metresToMicrometres(heightValue.Number()) + -metresToMicrometres(extents[2].Number())}; + request.halfExtentsMicrometres={metresToMicrometres(extents[0].Number()), + metresToMicrometres(extents[1].Number()),metresToMicrometres(extents[2].Number())}; + request.yawQuarterTurns=static_cast(yawValue.Integer()); + return true; + } + inline bool AttachRound1WorldAssemblyPrototype(FStandaloneOwnerWorld& owner,VFJson::Value& root, std::string& error,const std::string& manifestOutputPath, VoxelForgeCore::WorldAssemblyManifest* outManifest=nullptr) From 6cd9e4da76911b82c06933e79266bc788057eedb Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sun, 1 Nov 2026 09:31:56 +0100 Subject: [PATCH 2/7] proto: liminal pass 2 - hills to the horizon, swept road over a cloud floor, pillar grid (L142) Captures stream LOD0-8 (hills repeat at 80 m to the horizon). Road: cubic swept solid deck, 376.8 m, 8 m wide, max 12.06 deg, 17 supports, cloud floor ~45 m below; walk audit 0 blocked/unsupported, 300 m negative control fails as expected. 15x15 identical pillar grid at 76 m. Owner canonical hashes unchanged; fast tier, Clang/GCC green. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 7 +- Standalone/Core/src/ResolvedLayoutInternal.h | 146 +++++- Standalone/Core/src/ShapeWorldInternal.h | 36 ++ .../Linux142/BuildL142Fixtures.py | 113 +++++ .../WorldAssemblerM3/Linux142/CaptureL142.py | 433 ++++++++++++++++++ .../WorldAssemblerM3/Linux142/REPORT.md | 46 ++ .../captures/flatField-monolith-eye.jpg | Bin 0 -> 26523 bytes .../captures/flatField-monolith-wide.jpg | Bin 0 -> 23358 bytes .../Linux142/captures/periodicHills-eye.jpg | Bin 0 -> 25065 bytes .../Linux142/captures/periodicHills-wide.jpg | Bin 0 -> 60906 bytes .../Linux142/captures/pillar-grid-eye.jpg | Bin 0 -> 43604 bytes .../Linux142/captures/pillar-grid-wide.jpg | Bin 0 -> 39595 bytes .../Linux142/captures/road-in-clouds-eye.jpg | Bin 0 -> 34408 bytes .../Linux142/captures/road-in-clouds-wide.jpg | Bin 0 -> 39598 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 73 ++- Standalone/Source/StreamBenchmarkPipeline.h | 129 ++++-- Standalone/Source/WorldAssemblyPrototype.h | 244 ++++++++-- 17 files changed, 1129 insertions(+), 98 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/BuildL142Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/CaptureL142.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/pillar-grid-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/pillar-grid-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/road-in-clouds-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux142/captures/road-in-clouds-wide.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index cb2b2dd..204242d 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -891,6 +891,7 @@ namespace VoxelForgeCore inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV2 = 2; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV3 = 3; + inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV4 = 4; inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1; enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict }; @@ -904,7 +905,8 @@ namespace VoxelForgeCore fillPillar = 3, fillDais = 4, fillMonolith = 5, - fillPlatform = 6 + fillPlatform = 6, + fillSweptDeckSegment = 7 }; struct ResolvedLayoutStampRequestV1 @@ -914,6 +916,8 @@ namespace VoxelForgeCore ResolvedSdfStampKindV1 kind = ResolvedSdfStampKindV1::carveEllipsoid; // A preferred center and a bounded deterministic search radius. std::array anchorPositionMicrometres{}; + // Present only for fillSweptDeckSegment; defines its directed centerline. + std::array, 2> sweepEndpointsMicrometres{}; std::int64_t placementRadiusMicrometres = 0; std::array halfExtentsMicrometres{}; std::int64_t smoothWidthMicrometres = 0; @@ -933,6 +937,7 @@ namespace VoxelForgeCore std::int32_t strateIndex = -1; ResolvedSdfStampKindV1 kind = ResolvedSdfStampKindV1::carveEllipsoid; std::array positionMicrometres{}; + std::array, 2> sweepEndpointsMicrometres{}; std::array boundsMinimumMicrometres{}; std::array boundsMaximumMicrometres{}; std::array halfExtentsMicrometres{}; diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 5fcb719..5074335 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -176,7 +176,7 @@ namespace { const auto value=static_cast(kind); return value>=static_cast(ResolvedSdfStampKindV1::carveEllipsoid) - &&value<=static_cast(ResolvedSdfStampKindV1::fillPlatform); + &&value<=static_cast(ResolvedSdfStampKindV1::fillSweptDeckSegment); } bool LayoutStampIsMotif(ResolvedSdfStampKindV1 kind) {return kind==ResolvedSdfStampKindV1::fillMonolith @@ -598,6 +598,14 @@ namespace <<",\"irregularity_wavelength_um\":"<(stamp.yawQuarterTurns); + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + out<<",\"sweep_endpoints_um\":[[" + <=ResolvedLayoutStampVocabularyVersionV3) out<<",\"rounding_radius_um\":"< stampIds; for(const auto& stamp:stamps) { @@ -1145,6 +1154,8 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, else stampIds.push_back(stamp.stableId); const bool motif=LayoutStampIsMotif(stamp.kind); if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3 + ||(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + &&stampVocabularyVersion0 &&stamp.irregularityWavelengthMicrometres<=0)) add("stamp_parameters",stamp.stableId+" has invalid or unbounded geometry parameters"); + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + double lengthSquared=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const auto a=stamp.sweepEndpointsMicrometres[0][axis]; + const auto b=stamp.sweepEndpointsMicrometres[1][axis]; + if(a<-1000000000000ll||a>1000000000000ll + ||b<-1000000000000ll||b>1000000000000ll) + add("stamp_sweep",stamp.stableId+" has an unbounded endpoint"); + const double delta=static_cast(stamp.sweepEndpointsMicrometres[1][axis]) + -stamp.sweepEndpointsMicrometres[0][axis]; + lengthSquared+=delta*delta; + } + if(!(lengthSquared>0.0) + ||std::sqrt(lengthSquared)>2.0*stamp.halfExtentsMicrometres[0]+1.0) + add("stamp_sweep",stamp.stableId+" has invalid endpoints or longitudinal extent"); + } if(motif) { const auto minimumExtent=*std::min_element(stamp.halfExtentsMicrometres.begin(), @@ -1186,16 +1215,39 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, const std::int64_t pad=motif ?(stamp.smoothWidthMicrometres+5)/6+stamp.irregularityAmplitudeMicrometres :stamp.smoothWidthMicrometres+stamp.irregularityAmplitudeMicrometres; - const std::array extents={ - stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad, - stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad, - stamp.halfExtentsMicrometres[2]+pad}; - for(std::size_t axis=0;axis<3;++axis) - if(stamp.boundsMinimumMicrometres[axis] - !=stamp.positionMicrometres[axis]-extents[axis] - ||stamp.boundsMaximumMicrometres[axis] - !=stamp.positionMicrometres[axis]+extents[axis]) - add("stamp_bounds",stamp.stableId+" conservative bounds do not match its parameters"); + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + double radiusSquared=0.0; + for(const auto extent:stamp.halfExtentsMicrometres) + { + const double expanded=static_cast(extent+pad); + radiusSquared+=expanded*expanded; + } + const auto radius=static_cast(std::ceil(std::sqrt(radiusSquared))); + for(std::size_t axis=0;axis<3;++axis) + { + const auto minimum=std::min(stamp.sweepEndpointsMicrometres[0][axis], + stamp.sweepEndpointsMicrometres[1][axis]); + const auto maximum=std::max(stamp.sweepEndpointsMicrometres[0][axis], + stamp.sweepEndpointsMicrometres[1][axis]); + if(stamp.boundsMinimumMicrometres[axis]!=minimum-radius + ||stamp.boundsMaximumMicrometres[axis]!=maximum+radius) + add("stamp_bounds",stamp.stableId+" conservative sweep bounds do not match its parameters"); + } + } + else + { + const std::array extents={ + stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad, + stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad, + stamp.halfExtentsMicrometres[2]+pad}; + for(std::size_t axis=0;axis<3;++axis) + if(stamp.boundsMinimumMicrometres[axis] + !=stamp.positionMicrometres[axis]-extents[axis] + ||stamp.boundsMaximumMicrometres[axis] + !=stamp.positionMicrometres[axis]+extents[axis]) + add("stamp_bounds",stamp.stableId+" conservative bounds do not match its parameters"); + } std::string safetyReason; if(!LayoutStampSafe(*this,stamp,&safetyReason)) add("stamp_placement",stamp.stableId+" is unsafe: "+safetyReason); @@ -1497,6 +1549,13 @@ std::optional ResolvedLayoutSnapshotV3::FromJson( target[axis]=values[axis].Integer(); }; readTriplet("position_um",stamp.positionMicrometres); + const auto& sweepEndpoints=v.Get("sweep_endpoints_um").AsArray(); + for(std::size_t endpoint=0;endpoint<2&&endpoint3 ||request.placementRadiusMicrometres<0 ||request.placementRadiusMicrometres>100000000 + ||(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + &&request.placementRadiusMicrometres!=0) ||request.smoothWidthMicrometres<0||request.smoothWidthMicrometres>10000000 ||request.irregularityAmplitudeMicrometres<0 ||request.irregularityAmplitudeMicrometres>10000000 @@ -1648,6 +1712,23 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t for(const auto coordinate:request.anchorPositionMicrometres) if(coordinate<-1000000000000ll||coordinate>1000000000000ll) {error="stamp request "+request.stableId+" has an unbounded anchor";return false;} + if(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + double lengthSquared=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const auto a=request.sweepEndpointsMicrometres[0][axis]; + const auto b=request.sweepEndpointsMicrometres[1][axis]; + if(a<-1000000000000ll||a>1000000000000ll + ||b<-1000000000000ll||b>1000000000000ll) + {error="stamp request "+request.stableId+" has an unbounded sweep endpoint";return false;} + const double delta=static_cast(b)-a; + lengthSquared+=delta*delta; + } + if(!(lengthSquared>0.0) + ||std::sqrt(lengthSquared)>2.0*request.halfExtentsMicrometres[0]+1.0) + {error="stamp request "+request.stableId+" has invalid swept-segment extents";return false;} + } // The shared JSON value type stores numbers as IEEE-754 doubles; keep the // serialized seed in its exact integer range so the canonical round trip holds. @@ -1666,6 +1747,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t { ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId; stamp.strateIndex=request.strateIndex;stamp.kind=request.kind; + stamp.sweepEndpointsMicrometres=request.sweepEndpointsMicrometres; stamp.halfExtentsMicrometres=request.halfExtentsMicrometres; stamp.smoothWidthMicrometres=request.smoothWidthMicrometres; stamp.irregularityAmplitudeMicrometres=request.irregularityAmplitudeMicrometres; @@ -1687,14 +1769,36 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.positionMicrometres[axis]=request.anchorPositionMicrometres[axis]+offset[axis]; const std::int64_t pad=stamp.smoothWidthMicrometres +stamp.irregularityAmplitudeMicrometres; - const std::array extents={ - stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad, - stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad, - stamp.halfExtentsMicrometres[2]+pad}; - for(std::size_t axis=0;axis<3;++axis) + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) { - stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis]; - stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis]; + double radiusSquared=0.0; + for(const auto extent:stamp.halfExtentsMicrometres) + { + const double expanded=static_cast(extent+pad); + radiusSquared+=expanded*expanded; + } + const std::int64_t radius=static_cast(std::ceil(std::sqrt(radiusSquared))); + for(std::size_t axis=0;axis<3;++axis) + { + const auto minimum=std::min(stamp.sweepEndpointsMicrometres[0][axis], + stamp.sweepEndpointsMicrometres[1][axis]); + const auto maximum=std::max(stamp.sweepEndpointsMicrometres[0][axis], + stamp.sweepEndpointsMicrometres[1][axis]); + stamp.boundsMinimumMicrometres[axis]=minimum-radius; + stamp.boundsMaximumMicrometres[axis]=maximum+radius; + } + } + else + { + const std::array extents={ + stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad, + stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad, + stamp.halfExtentsMicrometres[2]+pad}; + for(std::size_t axis=0;axis<3;++axis) + { + stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis]; + stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis]; + } } if(!LayoutStampSafe(candidate,stamp))continue; candidate.stamps.push_back(std::move(stamp));placed=true;break; diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index 37bad31..b9a8c8a 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -3535,6 +3535,7 @@ private: { const VoxelForgeCore::ResolvedLayoutStampV1* record=nullptr; std::array positionVoxels{},halfExtentsVoxels{}; + std::array,2> sweepEndpointsVoxels{}; float smoothWidthVoxels=0.0f; float irregularityAmplitudeVoxels=0.0f; float irregularityWavelengthVoxels=0.0f; @@ -3700,9 +3701,15 @@ private: StampSpatialBounds.push_back(bound); FStampRuntime runtime;runtime.record=&stamp; for(std::size_t axis=0;axis<3;++axis) + { runtime.positionVoxels[axis]=static_cast( static_cast(stamp.positionMicrometres[axis]) /Owner->CoreVoxelSizeMicrons); + for(std::size_t endpoint=0;endpoint<2;++endpoint) + runtime.sweepEndpointsVoxels[endpoint][axis]=static_cast( + static_cast(stamp.sweepEndpointsMicrometres[endpoint][axis]) + /Owner->CoreVoxelSizeMicrons); + } const std::size_t xAxis=stamp.yawQuarterTurns%2?1:0; const std::size_t yAxis=stamp.yawQuarterTurns%2?0:1; runtime.halfExtentsVoxels={ @@ -7152,6 +7159,35 @@ private: std::min(0.35f,std::min({stamp.halfExtentsVoxels[0], stamp.halfExtentsVoxels[1],stamp.halfExtentsVoxels[2]})*0.15f)); break; + case VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment: + { + std::array tangent{},side{},up{},delta{}; + float lengthSquared=0.0f,horizontalSquared=0.0f; + for(std::size_t axis=0;axis<3;++axis) + { + delta[axis]=stamp.sweepEndpointsVoxels[1][axis] + -stamp.sweepEndpointsVoxels[0][axis]; + lengthSquared+=delta[axis]*delta[axis]; + if(axis<2)horizontalSquared+=delta[axis]*delta[axis]; + } + const float segmentLength=std::sqrt(lengthSquared); + const float horizontalLength=std::sqrt(horizontalSquared); + if(!(segmentLength>1.0e-5f&&horizontalLength>1.0e-5f)) + return std::numeric_limits::infinity(); + for(std::size_t axis=0;axis<3;++axis)tangent[axis]=delta[axis]/segmentLength; + side={-delta[1]/horizontalLength,delta[0]/horizontalLength,0.0f}; + up={-tangent[2]*side[1],tangent[2]*side[0], + tangent[0]*side[1]-tangent[1]*side[0]}; + const std::array offset={ + x-stamp.positionVoxels[0],y-stamp.positionVoxels[1],z-stamp.positionVoxels[2]}; + const auto dot=[&](const std::array& axis) + {return offset[0]*axis[0]+offset[1]*axis[1]+offset[2]*axis[2];}; + const float rounded=std::min(0.35f, + std::min(stamp.halfExtentsVoxels[1],stamp.halfExtentsVoxels[2])*0.15f); + distance=StampRoundedBoxSdf(dot(tangent),dot(side),dot(up), + stamp.halfExtentsVoxels,rounded); + break; + } default:return std::numeric_limits::infinity(); } if(stamp.irregularityAmplitudeVoxels>0.0f) diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/BuildL142Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux142/BuildL142Fixtures.py new file mode 100644 index 0000000..b07c54e --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux142/BuildL142Fixtures.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +"""Build the L142 liminal pictures and walk-audit controls.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l142")) + +FLAT_FIELD = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, +} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + base = json.loads(OWNER.read_text(encoding="utf-8")) + + monolith = dict(base) + monolith["surface_profile_override"] = dict(FLAT_FIELD) + monolith["motif_family_override"] = { + "version": 1, + "strate_index": 0, + "placement_policy": "seed,strate,stable_id", + "motifs": [{ + "stable_id": "liminal/oversized-familiar-monolith-v1", + "kind": "cappedCylinder", + "radius_m": 1.6, + "height_m": 26.0, + "route_side_offset_m": 42.0, + "placement_radius_m": 0.0, + "fillet_radius_m": 0.6, + "blend_width_m": 1.2, + "minimum_spacing_m": 0.0, + "yaw_quarter_turns": 0, + "attachment": "seated_floor", + }], + } + + hills = dict(base) + hills["surface_profile_override"] = { + "version": 1, + "kind": "periodicHills", + "amplitude_x_m": 2.2, + "amplitude_y_m": 2.2, + "wavelength_x_m": 80.0, + "wavelength_y_m": 80.0, + "minimum_arena_clearance_m": 0.0, + } + + road_override = { + "stable_id": "liminal/road-clouds-v2", + "strate_index": 0, + "start_xy_m": [120.0, 340.0], + "path_length_m": 360.0, + "curve_control_offset_m": 84.0, + "deck_height_above_field_m": 44.0, + "rise_control_m": 22.0, + "half_width_m": 4.0, + "half_thickness_m": 1.0, + "sample_spacing_m": 2.0, + "support_spacing_m": 24.0, + "support_radius_m": 0.55, + } + road = dict(base) + road["surface_profile_override"] = dict(FLAT_FIELD) + road["liminal_road_override"] = dict(road_override) + + short_control = dict(base) + short_control["surface_profile_override"] = dict(FLAT_FIELD) + short_override = dict(road_override) + short_override["path_length_m"] = 180.0 + short_control["liminal_road_override"] = short_override + + pillars = dict(base) + pillars["surface_profile_override"] = dict(FLAT_FIELD) + pillars["liminal_pillar_grid_override"] = { + "stable_id": "liminal/horizon-pillar-grid-v1", + "strate_index": 0, + "center_xy_m": [700.0, 800.0], + "rows": 15, + "columns": 15, + "spacing_m": 76.0, + "radius_m": 5.5, + "height_m": 40.0, + } + + fixtures = ( + ("flatField-monolith", monolith), + ("periodicHills", hills), + ("road-in-clouds", road), + ("road-short-control", short_control), + ("pillar-grid", pillars), + ) + for name, fixture in fixtures: + path = args.out / f"liminal-{name}.json" + path.write_text(json.dumps(fixture, indent=2) + "\n", encoding="utf-8") + print(f"[L142Fixture] name={name} file={path} status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/CaptureL142.py b/Standalone/Research/WorldAssemblerM3/Linux142/CaptureL142.py new file mode 100644 index 0000000..ced17b1 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux142/CaptureL142.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python3 +"""Run L142 liminal determinism checks, walk audits and multi-LOD captures.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +from pathlib import Path +import re +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l142")) +CAPTURE_DEFAULT = Path(__file__).resolve().parent / "captures" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +Q_PER_METRE = 1024.0 +FOG_COLOR = "0.66,0.73,0.77" + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import bounded_run, current_stamp, first_stamp + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, *, env: dict[str, str], + stamped: bool = False, timeout_seconds: int = 1740, + expected_exit: int = 0) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(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_stamp: + raise RuntimeError(f"{name} refused a 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, f"timeout", f"{timeout_seconds}s", + *map(str, command)], cwd=ROOT, env=env, + stdout=stream, stderr=subprocess.STDOUT, + timeout=timeout_seconds + 5, check=False) + elapsed = time.monotonic() - started + output = log.read_text(encoding="utf-8", errors="replace") + print(f"[L142Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != expected_exit: + raise RuntimeError(f"{name} exit={result.returncode}, expected={expected_exit}; see {log}") + return output + + +def route_frame(manifest_path: Path) -> tuple[tuple[float, float, float], + tuple[float, float, float]]: + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + strata = [entry for entry in manifest["plan"]["strates"] + if entry.get("route") and len(entry["route"]) >= 2] + if not strata: + raise RuntimeError(f"no planned SurfaceWorld route in {manifest_path}") + route = strata[0]["route"] + points = [tuple(float(value) / Q_PER_METRE for value in item["position_q"]) + for item in route] + lengths = [math.dist(a, b) for a, b in zip(points, points[1:])] + total = sum(lengths) + if total <= 1.0e-6: + raise RuntimeError(f"degenerate planned route in {manifest_path}") + + def at(distance: float) -> tuple[float, float, float]: + remaining = max(0.0, min(total, distance)) + for index, (a, b, length) in enumerate(zip(points, points[1:], lengths)): + if remaining <= length or index == len(lengths) - 1: + if length <= 1.0e-9: + return b + t = remaining / length + return tuple(a[axis] + (b[axis] - a[axis]) * t for axis in range(3)) + remaining -= length + return points[-1] + + center = at(total * 0.5) + before, after = at(total * 0.5 - 1.0), at(total * 0.5 + 1.0) + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-9: + raise RuntimeError(f"degenerate route tangent in {manifest_path}") + return center, (dx / length, dy / length, 0.0) + + +def camera_angles(camera, target) -> tuple[float, float]: + 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 point_toward(camera, target) -> tuple[float, ...]: + yaw, pitch = camera_angles(camera, target) + return (*camera, yaw, pitch) + + +def stamp(layout: dict, stable_id: str) -> dict: + for record in layout.get("stamps", []): + if record.get("stable_id") == stable_id: + return record + raise RuntimeError(f"missing resolved stamp {stable_id}") + + +def make_views(name: str, manifest_path: Path, layout_path: Path): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + center, tangent = route_frame(manifest_path) + tx, ty, _ = tangent + nx, ny = -ty, tx + base_height = manifest["recipe"]["surface_profile"]["h0_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = stamp(layout, "liminal/oversized-familiar-monolith-v1") + sx, sy, _ = (value / 1.0e6 for value in monolith["position_um"]) + floor = monolith["floor_um"] / 1.0e6 + eye_camera = (sx - tx * 36.0, sy - ty * 36.0, floor + 1.6) + eye_target = (sx, sy, floor + 10.5) + wide_camera = (sx - tx * 42.0 - nx * 18.0, + sy - ty * 42.0 - ny * 18.0, floor + 42.0) + wide_target = (sx, sy, floor + 8.0) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 24), + "height_center": floor, + "height_range": 38.0, + } + if name == "periodicHills": + # Route points are capsule centers: +0.72 m places the view at 1.60 m above ground. + eye_camera = (center[0], center[1], center[2] + 0.72) + eye_target = (center[0] - tx * 360.0, center[1] - ty * 360.0, + center[2] + 0.72) + wide_camera = (center[0] - tx * 36.0 - nx * 28.0, + center[1] - ty * 36.0 - ny * 28.0, center[2] + 30.0) + wide_target = (center[0] - tx * 310.0, center[1] - ty * 310.0, + center[2] + 0.72) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 28), + "height_center": base_height, + "height_range": 6.0, + } + if name == "road-in-clouds": + deck = sorted((row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("liminal/road-clouds-v2/deck/")), + key=lambda row: row["stable_id"]) + if len(deck) < 2: + raise RuntimeError("road layout has no resolved swept platform chain") + points = [tuple(value / 1.0e6 for value in row["position_um"]) + for row in deck] + tops = [point[2] + row["half_extents_um"][2] / 1.0e6 + for point, row in zip(points, deck)] + index = max(1, len(points) // 12) + camera_dx = points[index + 1][0] - points[index - 1][0] + camera_dy = points[index + 1][1] - points[index - 1][1] + camera_tangent_length = math.hypot(camera_dx, camera_dy) + camera_tx, camera_ty = (camera_dx / camera_tangent_length, + camera_dy / camera_tangent_length) + camera_nx, camera_ny = -camera_ty, camera_tx + eye_camera = (points[index][0] + camera_nx * 3.2, + points[index][1] + camera_ny * 3.2, tops[index] + 1.6) + eye_target = (points[index][0] + camera_tx * 90.0 + camera_nx * 60.0, + points[index][1] + camera_ty * 90.0 + camera_ny * 60.0, + tops[index] - 44.0) + middle = len(points) // 2 + dx = points[middle + 1][0] - points[middle - 1][0] + dy = points[middle + 1][1] - points[middle - 1][1] + tangent_length = math.hypot(dx, dy) + tx, ty = dx / tangent_length, dy / tangent_length + nx, ny = -ty, tx + wide_target_index = min(len(points) - 1, middle + 30) + wide_camera = (points[middle][0] - tx * 35.0 + nx * 30.0, + points[middle][1] - ty * 35.0 + ny * 30.0, + tops[middle] + 25.0) + wide_target = (points[wide_target_index][0], points[wide_target_index][1], + tops[wide_target_index] - 5.0) + return { + "eye": (eye_camera, eye_target, 3), + "wide": (wide_camera, wide_target, 3), + "height_center": base_height + 23.0, + "height_range": 60.0, + "road_deck": tops[middle], + "road_width": 2.0 * deck[middle]["half_extents_um"][1] / 1.0e6, + } + if name == "pillar-grid": + pillars = [row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("liminal/horizon-pillar-grid-v1/pillar/")] + if len(pillars) < 9: + raise RuntimeError("pillar-grid layout has too few resolved supports") + xs = [row["position_um"][0] / 1.0e6 for row in pillars] + ys = [row["position_um"][1] / 1.0e6 for row in pillars] + floor = min((row["position_um"][2] - row["half_extents_um"][2]) / 1.0e6 + for row in pillars) + cx, cy = (min(xs) + max(xs)) * 0.5, (min(ys) + max(ys)) * 0.5 + eye_camera = (min(xs) - 78.0, cy, floor + 1.6) + eye_target = (max(xs) + 90.0, cy, floor + 1.6) + wide_camera = (cx - 280.0, cy - 420.0, floor + 230.0) + wide_target = (cx, cy, floor + 6.0) + return { + "eye": (eye_camera, eye_target, 3), + "wide": (wide_camera, wide_target, 3), + "height_center": floor + 12.0, + "height_range": 42.0, + } + raise RuntimeError(f"no capture framing for fixture {name}") + + +def headless_command(binary: Path, fixture: Path, camera, mesh: Path, + manifest: Path, layout: Path, workers: int, + clip_radius: int, *, hash_tiles: bool = False, + audit_road: bool = False, max_level: int = 0, + far_lods: bool = False, + max_clip_override: int | None = None) -> list[object]: + max_clip_level = (max_clip_override if max_clip_override is not None else + 8 if far_lods else max_level) + command: list[object] = [binary, fixture, f"--workers={workers}", + "--seed=0", "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={clip_radius}", + f"--max-clip-level={max_clip_level}", + f"--max-level={max_level}", "--render-distance-chunks=0", + f"--camera={fmt(point_toward(camera, (camera[0], camera[1] + 1.0, camera[2])))}", + f"--mesh-export={mesh}", f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if hash_tiles: + command.append("--stream-hash-tiles") + if audit_road: + command.append("--audit-liminal-road-walk") + return command + + +def determinism_digest(output: str, manifest_path: Path, + layout_path: Path) -> tuple[str, str, str]: + tile_hashes = sorted(line for line in output.splitlines() + if line.startswith("[PipelineTileHash] ")) + if not manifest_path.is_file() or not layout_path.is_file() or not tile_hashes: + raise RuntimeError("determinism run omitted manifest, layout or per-tile hashes") + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + manifest_digest = (manifest["content_hash"],manifest["recipe"]["content_hash"], + manifest["plan"]["content_hash"]) + return ("|".join(manifest_digest),layout["stable_identity"],"\n".join(tile_hashes)) + + +def run_determinism(name: str, fixture: Path, view, *, binaries: dict[str, Path], + out: Path, env: dict[str, str]) -> None: + camera, _, _ = view["eye"] + clip_radius = 1 + max_clip = 0 + baseline = None + cells = 0 + for compiler, workers in ((compiler, workers) + for compiler in ("clang", "gcc") + for workers in (1, 8, 12)): + tag = f"{name}-{compiler}-w{workers}" + run_dir = out / "determinism" / tag + run_dir.mkdir(parents=True, exist_ok=True) + mesh = run_dir / "feature.vfmesh" + manifest = run_dir / "manifest.json" + layout = run_dir / "layout.json" + command = headless_command(binaries[compiler], fixture,camera,mesh,manifest, + layout,workers,max_clip,hash_tiles=True) + output = run_step(tag,command,out/"logs"/f"determinism-{tag}.log", + env=env,stamped=True) + digest = determinism_digest(output,manifest,layout) + if baseline is None: + baseline = digest + elif digest != baseline: + raise RuntimeError(f"{name} diverged at {compiler} W{workers}; see determinism logs") + cells += 1 + print(f"[L142Determinism] fixture={name} compiler_worker_cells={cells} identical=yes status=PASS", + flush=True) + + +def export_and_capture(name: str, fixture: Path, views: dict, *, + headless: Path, renderer: Path, out: Path, + artifact_dir: Path, env: dict[str, str]) -> None: + for view_name in ("eye", "wide"): + camera, target, clip_radius = views[view_name] + clip_radius = min(clip_radius,3) + stem = f"{name}-{view_name}" + mesh = out / "capture-meshes" / f"{stem}.vfmesh" + manifest = out / "capture-manifests" / f"{stem}.json" + layout = out / "capture-layouts" / f"{stem}.json" + png = out / "capture-png" / f"{stem}.png" + image = artifact_dir / f"{stem}.jpg" + for path in (mesh,manifest,layout,png,image): + path.parent.mkdir(parents=True,exist_ok=True) + command = headless_command(headless,fixture,camera,mesh,manifest,layout,12, + clip_radius,max_level=-1,far_lods=True, + max_clip_override=(2 if name == "road-in-clouds" and view_name == "wide" + else 3 if name == "road-in-clouds" else None)) + output = run_step(f"capture-{stem}-export",command, + out/"logs"/f"capture-{stem}-export.log",env=env,stamped=True) + if not mesh.is_file() or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem} produced an empty mesh") + yaw, pitch = camera_angles(camera,target) + height_center = views["height_center"] + height_range = views["height_range"] + if name == "road-in-clouds": + fog_start,fog_end,fog_color=(24,260,"0.88,0.93,0.95") + elif name == "pillar-grid": + fog_start,fog_end,fog_color=220,1250,"0.82,0.88,0.91" + elif name == "periodicHills": + fog_start,fog_end,fog_color=210,1000,"0.78,0.84,0.88" + else: + fog_start,fog_end,fog_color=30,105,FOG_COLOR + renderer_command = [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=on","--shade=readable", + "--headlamp=off","--height-tint=on",f"--height-center-m={height_center:.6f}", + f"--height-range-m={height_range:.6f}","--light-direction=-0.42,-0.58,0.70", + "--fog=on",f"--fog-start-m={fog_start}",f"--fog-end-m={fog_end}", + f"--fog-color={fog_color}"] + run_step(f"capture-{stem}-render",renderer_command, + out/"logs"/f"capture-{stem}-render.log",env=env,stamped=True) + run_step(f"capture-{stem}-jpeg",["ffmpeg","-nostdin","-hide_banner","-loglevel", + "error","-y","-i",png,"-frames:v","1","-q:v","4",image], + out/"logs"/f"capture-{stem}-jpeg.log",env=env) + quality = run_step(f"capture-{stem}-quality", + [sys.executable,ROOT/"Standalone/Tools/verify/capture_quality.py",image], + out/"logs"/f"capture-{stem}-quality.log",env=env) + if "[CaptureQuality]" not in quality or not image.is_file() \ + or image.stat().st_size > 300_000: + raise RuntimeError(f"{stem} capture failed quality or size checks") + eye_height = "1.600m" if view_name == "eye" else "wide" + print(f"[L142Capture] fixture={name} view={view_name} eye_height={eye_height} " + f"camera_m=({fmt(camera)}) target_m=({fmt(target)}) bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS",flush=True) + + +def run_road_walk_audit(fixture: Path, view, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + camera = view["eye"][0] + run_dir = out / "road-walk-audit" + run_dir.mkdir(parents=True,exist_ok=True) + output = run_step("road-walk-audit",headless_command(headless,fixture,camera, + run_dir/"audit.vfmesh",run_dir/"manifest.json",run_dir/"layout.json",12,1, + audit_road=True),out/"logs"/"road-walk-audit.log",env=env,stamped=True) + if not re.search(r"\[LiminalRoadWalkAudit\].*status=PASS",output): + raise RuntimeError("raised road failed the Core capsule walk audit") + + +def run_road_short_negative_control(fixture: Path, view, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + camera = view["eye"][0] + run_dir = out / "road-short-negative-control" + run_dir.mkdir(parents=True,exist_ok=True) + output = run_step("road-short-negative-control", + headless_command(headless,fixture,camera,run_dir/"control.vfmesh", + run_dir/"manifest.json",run_dir/"layout.json",12,1,audit_road=True), + out/"logs"/"road-short-negative-control.log",env=env,stamped=True, + expected_exit=14) + match = re.search(r"\[LiminalRoadWalkAudit\].*path_length_m=([0-9.]+).*status=FAIL",output) + if not match or float(match.group(1)) >= 300.0: + raise RuntimeError("short-road negative control did not falsify the length gate") + print(f"[L142RoadNegativeControl] path_length_m={match.group(1)} " + "expected=FAIL status=PASS",flush=True) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT) + parser.add_argument("--artifact-dir", type=Path, default=CAPTURE_DEFAULT) + parser.add_argument("--headless-clang", type=Path, required=True) + parser.add_argument("--headless-gcc", type=Path, required=True) + parser.add_argument("--renderer", type=Path, required=True) + args = parser.parse_args() + + out = args.out.resolve() + artifact_dir = args.artifact_dir.resolve() + fixture_dir = out / "fixtures" + for directory in (out,fixture_dir,artifact_dir): + directory.mkdir(parents=True,exist_ok=True) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(out) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT/"Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(out/"xdg-cache") + run_step("build-fixtures",[sys.executable, + ROOT/"Standalone/Research/WorldAssemblerM3/Linux142/BuildL142Fixtures.py", + f"--out={fixture_dir}"],out/"logs"/"build-fixtures.log",env=env) + + binaries = {"clang":args.headless_clang.resolve(),"gcc":args.headless_gcc.resolve()} + fixtures = { + "flatField-monolith":fixture_dir/"liminal-flatField-monolith.json", + "periodicHills":fixture_dir/"liminal-periodicHills.json", + "road-in-clouds":fixture_dir/"liminal-road-in-clouds.json", + "pillar-grid":fixture_dir/"liminal-pillar-grid.json", + } + probed = {} + for name,fixture in fixtures.items(): + probe_dir=out/"plan-probes"/name + probe_dir.mkdir(parents=True,exist_ok=True) + camera=(0.0,0.0,-500.0) + output=run_step(f"plan-probe-{name}",headless_command(binaries["clang"],fixture, + camera,probe_dir/"probe.vfmesh",probe_dir/"manifest.json", + probe_dir/"layout.json",12,1),out/"logs"/f"plan-probe-{name}.log", + env=env,stamped=True) + if "[WorldAssemblerFullManifest]" not in output: + raise RuntimeError(f"{name} probe omitted its full plan manifest") + probed[name]=make_views(name,probe_dir/"manifest.json",probe_dir/"layout.json") + + for name,fixture in fixtures.items(): + run_determinism(name,fixture,probed[name],binaries=binaries,out=out,env=env) + run_road_walk_audit(fixtures["road-in-clouds"],probed["road-in-clouds"], + headless=binaries["clang"],out=out,env=env) + run_road_short_negative_control(fixture_dir/"liminal-road-short-control.json", + probed["road-in-clouds"],headless=binaries["clang"],out=out,env=env) + for name,fixture in fixtures.items(): + export_and_capture(name,fixture,probed[name],headless=binaries["clang"], + renderer=args.renderer.resolve(),out=out,artifact_dir=artifact_dir,env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L142Capture] status=FAIL error={error}",file=sys.stderr,flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux142/REPORT.md new file mode 100644 index 0000000..44de717 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux142/REPORT.md @@ -0,0 +1,46 @@ +# L142 — liminal pass 2 + +| Hills: eye height | Hills: wide | +|---|---| +| ![Periodic hills from eye height](captures/periodicHills-eye.jpg) | ![Periodic hills to the horizon](captures/periodicHills-wide.jpg) | + +| Road: eye height | Road: wide | +|---|---| +| ![Road edge over the cloud floor](captures/road-in-clouds-eye.jpg) | ![Swept road deck and supports above the cloud floor](captures/road-in-clouds-wide.jpg) | + +| Pillar grid: eye height | Pillar grid: wide | +|---|---| +| ![Pillars repeating along the horizon](captures/pillar-grid-eye.jpg) | ![Pillar grid from above](captures/pillar-grid-wide.jpg) | + +| Monolith: eye height | Monolith: wide | +|---|---| +| ![The retained monolith slice at eye height](captures/flatField-monolith-eye.jpg) | ![The retained monolith slice wide](captures/flatField-monolith-wide.jpg) | + +## Result + +The wide hill capture shows the validated 80 m repeating profile continuing across the horizon. The capture now streams LOD 0–8; the profile period and validator are unchanged. + +The road is a cubic swept path made from overlapping solid deck segments, not a chain of platform stamps. The earlier platform chain produced top steps; the swept deck passes the surface-sampled walk audit. Its wide view is capped at LOD 2 to keep the deck legible, so that frame shows a local section; the full route length is measured by the audit. + +The R47 addition is a 15×15 grid of identical pillars, spaced 76 m apart across a 1,064 m span. The monolith eye and wide views are retained as the first liminal slice. + +## Measurements + +- **Road:** 376.827 m horizontal path length, 8.000 m width, and 12.061° maximum sampled surface grade against the 15° limit. The deck rises and falls along the cubic profile. It has 17 supports at about 24 m spacing; the flat cloud floor is 44 m below the deck centerline (about 45 m below the walking surface), with pale fog in both views. +- **Walk audit:** 901 surface stations at no more than 0.5 m spacing; 56,763 capsule samples; 0 blocked samples, 0 unsupported samples across 5,871 support probes, 0 grade failures, and 0 missed surface probes. The 180 m short-road control measured 210.341 m and failed the 300 m gate as expected. +- **Capture quality:** all eight fixtures/views passed the image-quality gate at 1600×900. Hills and pillars stream through LOD 8; road eye and wide views use caps 3 and 2 respectively. +- **Determinism:** the monolith, hills, road, and pillar fixtures each matched across Clang and GCC at W1, W8, and W12 (six compiler/worker cells per fixture), on source stamp `72f239e9534faa27e3796fe29207403b190558403841aeebc87d8e75e98e34c7`. + +## Checks + +- Clang 19 and GCC builds passed with floating-point contraction off, four build jobs, and the L142 source stamp. +- `Standalone/Tools/verify/verify.py fast --out Saved/Linux/l142 --overall-timeout 1740` passed. Both current owner fixtures produced all 12 canonical hash rows matching the pinned L130-v227 baseline; W1 and W12 also matched each other. +- The fast summary retains non-gating differences against older L46/L53 diagnostic baselines; the current pinned L130 canonical checks pass. +- The L142 capture runner passed the walk audit, the short-road negative control, all four determinism comparisons, and all eight image-quality checks. Final logs are in `Saved/Linux/l142/logs/`. +- No Unreal build or performance timing matrix was run. No Unreal `Source/` files changed. The inherited single-run near-ready timing step was removed from this picture-and-geometry runner rather than treated as a timing result. + +## Remaining limits + +The road wide capture frames a local section at LOD 2 to retain a continuous deck; the 376.827 m length is established by the full-route walk audit. Captures use the standalone Linux renderer rather than an Unreal viewport. + +Changed Unreal `Source/` files: none. diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..13eb05226c68fa203b35cb08c2c8e4b0d13fc301 GIT binary patch literal 26523 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/flatField-monolith-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3975e8ae20d5aff093f2c6b6a46c1988bb15d244 GIT binary patch literal 23358 zcmeHO2V7Lgx<9*sZmcv#4jqMCIsJu6NQ z-dLQzI`Miv=NnORV0q_~`M-|V_Rh<{kvaQTWzy9I%ims4eE#c;rOBO-cJr+(zPavD z!pn%hOK){a2w60^E+_wfidAUHuYor^>>b-Nu18$bW2fm=m3Kpjmwa27T#&N+QrRAl ztLbT>HFpZWvi%`wn{D)Owbeln>t-h0sT%xhp<_q+VwdGBmc@j2sC_sx`)NXP<}rKu zS(nk5pH=mHbbj8Uj>!|x>|K%f@Zpnr89^ufow;kdf!k*X?oKea8Js@-NG}@sbl*ItyXE99LG#>)4Gp|^H}U#l)y_QMh|%rWZQdUh_wBYB+jskVmX*W~7!-JXLDPVH zncK3LPVM#EjN%c?{i5>vYi;^&8k7;#zvt7nebXPz44#%2-+D{GMqe&{RQ_4X zmitDU`G0m{{gLatc)M5iJfE<8p3~yfK8pEmcU~sDD>D^+(GtR64O44|7}pukUaDD zuM&E;yEppe(X_tKP6M(lCpq|@J^*RB{(xJ3Bm9mPmiYHS*tPu1h6kA&_dR+wj<#M=r0|%ba2-_pm$heb(+R`aGhG@92$jlNVGyKDIjNOhxjF1snIwT2eG{`J9rv zh~^)CcH3!tMN^mJLG|46s>|o>%zp;SaGbrbq@w20>Sy+>QMr54W&{-c z;#=5*liUxdRx<0Cuv4>NrAO>McyPh2@j3guTnYQjR^BT6ne$2qEE{%QeKxRLc=u%+ zn+zD*FKymHc0<|^Dngz!a*M#2c=aAuZp&|u5YqHhM7n$L$f4x5GdFr0C zN6%k*ekJ;DP1LY5|E&CLU%YjR|9=UL{9_8oKP$Vp<80up@Hq=d-8dUK=(mkTI@Nn; zm%s0K@X@7nc9N_1aPP($bJk&VW+a_)%*jex*Cu$n@BWl_n_Kq^?;XeOKJK}wO`kq;fY?c)jy?DLtuyasJX0FB3(H$1uuUj4*5Lw3ydQe`)I{I0Eb zHjlEZ!zN!l+hk1T*K5r?-eujn_g9xztLg>>p6ft9W^WlEHf(&@g3_EH!usU-^tLkP z-|69`>IM&wHfqYNG%~F?Q!7yYpC?H<@$&Gxq?}TCAn?_Q9)oo&8tmGD5177RzemyW zj`7+}Q)XQE-?bn+e7@@F!pF;7+jTFxejsadQtIwkOKKk7J@INw*y^plsxmrEoc(ZW zz_auP*>~0@_5fgXl|-qXE|rxhpDMX_@#Ud?inDczW}=(kX&D$?7cjVP zQ?I3O40FC#(t5$H>W*&zgf)n_(D=7ne`h)dpf6jHqv!!rv~L@&R7o?9Ouzg8bctsZ zYo)e$E@63`PI#h42+d>{x)v#K6Q!@8`s#}4VYh-hD2>*w$!SYLIQ%3x{#yWMtv!MGG307V1j$C`p>(!^67j|#f)8{P9vn;v3|8!Pt zcDt2lx3o*?1Q1&0d39G=_8}k7iqOmr#R>_9Z&MdLH^L>}J0?GfT!)9@-Fm zXSMT%)8RWatqX1tB*(eLi#%`i0_Hx(UhvTUGIHVVDlkGcC?_;~Nf3b^e2IVb6gvNx zJ|vug`Dh#+E{gDwPM~X(>!vjHg3uxWsYEXE_LAdF4{mk6p_---1ExjpZ9AaqyVAU| z(d}Q2yM;tLu}WLA#ov18fM;D7uYY_lZSPJOhp~kTR!g^6tsbWa-{{rEVTjR%;Kx^P zZCMh(Zlh7+xxnbc+quzahJ5d8bkAwq%MtCa))a5u_Hs-IcptINHnEzN_jzEKoNoCw zPIP7sTLQcdj8kK(;x#Bs)Zq#bH2NwF3sI0U#NE}TN`z3nXn3{03G+Om{P)UZs(Y5mmVxUG`8jOLz(_AAmH#r&Rvq%^*K^8blA2}mTEe9E>y#^ zxHF&0n{F(*R<-nSi_E;i+5gB&=)LdE&3P5R-~VfzSJR>l=O=pxrazq7pT0x9<4he+ z#vd(AFORESY|R$p<749C>f___)<17|)`h(VYowZNNrD6~2pWXY4_P^(X90x}TM34( zGiz5M)iY{W53jdGS1gD@lQ1h3%nVgR66#6O#7u`ugp^n#HAF&0a}zUnUk|-MFV@aR zWgDZh5^EOT?Z;O2b=nX%wR`34TIHkc(-$_(jrRyw-gJuB7;H<88$~`;L=5B%Ky)shejzdj8+cDr z#0aI*DDCyC$FavA?EJ08_0AKn41MN%BD`~W5E69`5p|EtWAiFw64Tx{UA+C->cYXJ zB9r7M?j}tfIH!Zx?&b&QZfo)IgG~X$qGdl%>uP4}vVZ@fmaU2()Xd#7VD8ODYn-<_ zb{ul!8<1`8{!`ng<_zB9hK0`4i6%CT;GW2Ef)~TCjIKuLBXUq`-8T|)MQqxG)brCa7Z!b3J=)&- zyYRi;0zQr{Za;a-V~grRL5og|cK+z&dzVJ`3J<*Zani`R_~i2)hJ1ky+p3dScyLD1 zj*`Vg{jcU9ICFEsn3aAh_FwSk)e+kc&pql9pWABs><_z}Pv5`l=??Q9J+@8%+A({x zN|pSA;iTzPrES-MUgZljYcK@ON=69V0?K0i6AgFvO-iM zgAu8sGA5O(9foW$A1?+AY?)C!bA3!WWMn26C@HXbZ6XsvBN~$~ULXYlp`Bv`Ai)~S z6sZyzU%c$R(}8O9{G{yn<6NSCgrg7VGo=&nbg-mw)RsBJ zhAr{ymTDDH+@&~aOwx(2T{)LS)2@w6pIzMlf`8)XjxI}guT65=cj>{L{4X$UqU=o( zLzMX7C*Y&L=+$^1Sbl=cF%;{In@U>PK99RKE@V8IDTo)z2w9q-HyW8nYAbD?I8JGl zetC0L+L`{5T{>Mb^8w7DA+511LLfXi*t+@8+N-DKRUp#|;e$3141P9v(mcm2H$t zW220+i8}L{$>0qoetyH#ckawe{h(}Z%Ei57*3anq!3QSh)dk<5qMK!}#;-`c>2l?A zb6?@llH4bG!N0z=GyrZ4-Slwaffysv-J~@Nu_%CJd$)8Yi;)u+0VBN75FB)L#GT*Cg_fs5f@F-~&lNJQzNq z;vOe?L^0g z8?=s|Cy(_S68}T<_riVM-F?kG%-8OSOv(=4*88I?MWf2fR%Tg^8JptSYwU`t&A9hd zlfIm65EckUuu%Y&Hzvdk;lW23Q@{*-rKCdW7^y%k&>%~~4@NMsV(N7Ob4_*kPf{`s z>H!ZbC`EhLB(i3Z8ax1Zk!Y%O5);=ZLpZbyDU7C26ZsKhj*B!UmX69K%wa8p+yMtM ze!vPLA>Nizv>395VMd$N3Q zmR;ND#b<^-FFt)`kl!N9J25S{-~9X=RifsUM-z*EQm0)%7Y*J~(st34xSFbNmFKgD zRtL$|Px`m<_g-Q?t#tgUvGY|Q+bz{~Sq3?bl{)W4}$ho8%UYR;7Ei zR5VJC9%q?wRGeBS=z;Ljs6sIDf;=(vh){JJAW{*+U3zThIVOG<0TbSL?s1qEI#te~ZIR#H@nSrWNQGsScA1Kl2m4CB*BjKPMrO`&|TO{c%4_|v%~$4@ zZO#u-Kg*mr(%K?8!f8>TL)!S-~bnWB?-o?b#oZi3y+`2N4MEsJsiEvCMy&1TB;m8^w*#tqj z#M0PR2jDcEW&t?^ZWeEoz!;A!#Ms{MZGQQeWR1euf%D?rOrRc3M;sShHgRy!kF1xt zOyYH^fAw|u@pU(M15blIB0Q`sd7HucUf7GH1`V`OGHjS*AY{>x6;ZQ`>fH z+cRZUs$cpNYwrs`&c4vM{mkP{j6x?JzCYpRxc53&?O1F@kOJc&K}B)SF^wW`6i)HP zejs+C41kygJxVpZ!BJB@Wbsd=9=y{L36cXcE5TuDY`|vK4e>h>JSaY*LiQ%;j>6_n z)+l5)@JkBaqEur$XH~bdMAOP0TDFjRH5y z=Uey1_k0%6PEORK|=d&-|*E{}Q8KW*BEj7?cqLmiHEiVLb)>+U@L)EGQmRH}+W6=A?qHGwZpSoHb9IxfJc! ztXvWMd6oAs98%K89vT;!yRyg3kdz)T(d{X-JhV438qjQb zR*H_hVASZRJ#UC0eaty@mW78HC>(=LJX|4ob7l8Y65O5O09Yu#8b-Eg2J^vQ;ES29 zG3RA0fv^Ktvr60>XU1l7Ikt2U)D>O6nQ&ygq?wo;H8^U}#H1yNEi|;I3(*Y=g9%37 z_y?dC><`k1i!<&&9~}DL-LW9w9(x@wZ%S|5xvk@uNW60SAd8{4J=SZyt^I=nbCQz- z2dx>gP9Ef&65#xP$KW59{cU<(onv(L(`Ey&U%B{R$5QZ5M2+-Lj?BRHDiae0%Y^8L zJ?N03p?-uDj2asuha)9yeN@dcofcG^#GAZuVYMICDI!wh#KI*1lYJq7w7~- zp$A$_ITfc;*l6+oF(qUWgy};Q9fY(KoDew1I7i?8o)>1^9=ULugZ6k`RzgzupQ0D1 zE>2H!Pafb|&|U*|yWsvhr!C^m|n{eKOmHU3vXFH)+c3 zIwVfDbD@-SNe?}QI<{PRBgTmWRQT3tcq#-&uTm4lQ6RpdhhF>v^OZ;(baw=!2`=go zS`VAa-cfvoVkUiH#*;#e#uUjL#spqNj+7+wjhIRSRV_;-ksnXc5v>Ssod}E-pcdK@ zZlbLrB1novVgK~EK2(b-2m?^@cT-DkM#YJN@|5_c9n;2N-aTe-Nad*8=enELtnIYk z7wk}(q}`#Bl=oQ`KYaVHxb>BzlTO9nNXh?d;rFSh7hR|rxZA^baEx~0E9J&%KbHDF z^$n|(SRek~8KF@RcNsAXR@m_rfYZbbH84sK_(u-tpE=Mny)~rxi$}ot<;!6(^WcOV zb4wDeAQA?yXbgZ<4}`dIJf(<%C16=CUo4^KENPcmLs7HlkBbm|`2Q1UX74-vs%&limm4BK z^ovUiu?#u?FQZ*US2k^Xux}^h@CVb@pT28-W5xQ7a-Sw8Uk0ohr`okB_`>q)VXIeV z)Qq)>u#h^RmY-gl+o$a>V?8~cv@tVy8i42f{{L@R(SPa|QhSxWjNCIeV@w~MC1z6m@oTQ^k66iOxXR8pi4h`o3@ z2;B(0Vwi)v-<4nE(nCi|COLr<;)?<@751bwE>M#yQQpj$>mN7SVN%fi_5ZXgJrsAy zZn84j&$L&1QR?}OS&}qu`{I1te)9bpLv5oY&e{E_E|{EjKXabtH0_GRU0>{fWc&gA zk4#akZkw#g`(#77eBYItX{F|A{_R2@PqFbDJIhQIsR*+Yfw5cx^?FuHd_P{XPU5y| zp*wsa2Zc@}QeJ^B;Lvpu`6Iv4VK0Y%5(CCZV)Fzl+8B?}TN5S*+G=A|Piiv; z26CF>fS<~*`1a7WXg^LFk&`}tXtisg%N@@red;bJ|8w3Rzp_s^#;VPbR(_odC0b4l2bR5m0RfBd%A=^QThJ8GI0-eGZ&MxrD5@jG1@sioG z0LoO&1VTAqTEIo5nY zM|d#DrI_EqE;X>ymN$)3lM@YMAgoNxT@FV8WWC6J=v~ktT}C^B4iw*@05}E@OTay1 z_pAcFDNDsw^jq}L_23u^clIo6gqBnh2p5wIoy7i=5DP-!MdL9zQDLwk4QLDKA5CER zu{GsDErrOyR@|5J9jb_`(;o&ft8piR=`a>zyA1nmpciu)>o5U$%w#7&b#$%x$z7)Hnu%7pO@i;7VKZ8i^j_Pn025 zB`d*fgBnn6)F4i*3Dv>x?Sz+N0-~S_TqQ8ZKn|#}@iuX9JOsyh4O1yZ{YWFrvAXiY zpioWFLr`d)Bv2Q9Cx>8z*N;8)2~Zc56gZ77LYjUo`d0YeNBmob6vUk@Sn;?1M+$P;+OXrqb8tEa~iy%r!~JQV3H3dR}N z@et65j)yf9>M%=5IAX<3tW+E8gf)Y0%F*PVPc##tbgY+W4*$l2VxEwDN#GByp6JzbR;fM z(U{uuI%WPnrBwq@rHwICQyJSK$r3G$66^K#8sOmCzI<*d*`s1X(bAF;|ZizX!aXD7@F zrmcv(YN0>l8y@Ek0HDuE+!b~QZw3A)8DTA|RFeu2zQ8Im7m-E^4VbiX9%2TPp-@iX zfmoxS_;e)VFGgr+zOW{`RWUUTj~AiaDJBvDftagk^-Q(jq^Cf_Sc*_p6n&9-WhC5S z3MpC)tPhn0m_&ApYoJohM|MI(#3Ug~{e*@Gt0D;)j~-V1&%enykn?m5G>KTLa5d(r zFbQJDo3s>eO>kfh#ErWtG8L1X7*K&vrg#noSbb- zfJ!xL5hd}Eyr}-a@lzx-*rDOTqE+L?VQN^3zggm^~S&*$gs9(Hv{Xh{0B0v BeH{P* literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92ba34ac5a8a18214eabea40811f3d28c32b284d GIT binary patch literal 25065 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 b8d^9dSVcWNEtAsrTKpWq&bx? literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/periodicHills-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c066a5fcf6028b8c2de48ce7f842f6d8bffc31d GIT binary patch literal 60906 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

a*gkIH0^TluevPE-TKlgAflYj9P_sLo$j$ zpvot6ZB0%rS6^mb;j+j3?CzX0E1BI}GOH1FT-ZJl9yS9i3|md>C6U>^&lb<&$VKp2 zo-0Jkm+H-2;cF}?_y-jm6-88CL$A%qYR{|N9g+C!=hLero{sTMWC@tT#h*X)J@@F) zqoi}o>G>09d{xhS#SlwM_PYC;+uXkZxQs;R(+6bNW2_)S@q`qOWTs`7U6jBm*EYXYl`NPi(Rr~(Ez3DDxGnNrHLURw}0Sy&0D_S;f0bk;>=+?ZL z)QSj#MXT2P=>hXY)>Xmyr@{j|kFfPhS*O1*8(`GVtoqv;rB|z-Hq75^U#+auUvXo= zgIy78(l|Mue&o2Y4dAe#(9l0&i-v|_(A8R4s(i{#`IPSIshyR%z%u6t=*}AtbOehV zzOMP$_IUC?-fqvoyqIOgWTmSSY}|bId`A3e zTl>|df}f?k9et5Tb2wTs!hM()&}0aQH;=b~xKnvv`5fET8JE$Uk%%yje~rpQogn>H zeb2uvYh$RH8&O|jeW?g0kAV7mRpKaF4LB@C&`B#uVk+?5>RQ5aCm4Z=EmJM2Z{+^Y zi8v6uvz0i$P@{|G`EDDFZX10Veb8vBW)}>^*K31xeOs&4UWVsKrDk6k2{$io*1W8D zP67`Ig@E3dM>R2V)h3oF4*q^II`%tioIZS$vJL*+z#&uPvS5W2Emfc5^7R70}$M#dWtbgPyZTWq*1(5vA#7*)Uw#A;N zSv^I!fgVehTycEvi#@NW8eiGSXQ3*C&FUqS^Chh8VjU5o>`}##J$%vOkjD4Fzuk## z``3EJfKtfyW-;KREbFT*CFoV?&1re3Q>Dhwbk={48*l&1wURS*Iawb*Ey9TR(R}-q zi#wkI@&UC8hCS=j&*f2NwajCVGx##2E*ICL*_ZT zytd|By1t`iilFg)B8He((9GqV^#He+-5oI-W_gJte6ZGfV(a2iu2lvMv@<#i+8Jep zzL5i0RGktXjwtK5JAHK`fA7E9xB-X7XJLALssp-J(TVph9 z^3AV&q}FTqcK*_Ajnn7Q8~KV^2QnTl9UA_Z%(_+l3*)i!h6i_$j&ATVm?Elxl*0?h zfmK-uT%icVQWWaUQm(~=9b-kUbw^{<9qmx#rVI=lWTDh+V^d(jOD!ewU~t}P%$JQp z_%rPWHx8$5%}Yv&+s(>4_WTr_Th%_2j%y|#&=sd9JT&54+QlY)bw!1FH#3->1hKS> zn)(e`ig&vwUere?bFsew={UjZwtvwViti-E1AYnE6M97}D>%Vsd2%`Dg)Si1U6}}R zyAK6LFBu#UfUdfu?$O6CFhD!vtbwe$0jepd{M$!qfBy^E$lXKwY({Gl`z~D`k;xJ< zuv|XOn}*Hda;;xL+0fn3U_Qsi$uPQP5Jj&JA4glzOO$nlkV+j|(3GjLtq0!`Tywkl zQCZoDQ7c5Hd(I2A(Y>KNhG7haFpU4J=74Ioyr$c3W%T! zj5XIuhmc;lWrY)Wv$wyJE%JVqkanI%EJr|0vjwgqN(Nac5&V@cmXto~GvBXXWRo3g z#80@x$s|!oxn@onGA(P4PA*tBx8!;gnj4G<)$w%>e{Jh(){w&P=Behy>09N4a5x+O!%6c^H2D3b(_kj%x$sGfn-Y1076e zX2g{JI-$_qM*bfd=x~bDXSs#@`(H&btlq>6!v~H-GQZEuoKZSPo&GJ z0Ek{#C^I~m&8D(|pn{KgAt!TRBxNjUh7ihhxZ?GhfNY2jH2||u<|9gM#fCx@d0tU0 z7j}$7Yh*495yjNRi52)}gk_Ij!yO1B*S9T8m2x`$96NibQVy0Bf5VG#F(cip&gsj} zwvjv(gndLg`l9TZ^!#)p(X)*Q4cFF+PF}&HpMY}$W|RVVz9m{QI<>YD)%!jZ1lO$$ zVWJd9id_)Ct%&doj?hVtB6{9@<%siO0RvQh4#Mriptj+Q!5O5iMU@+wS*oG$sPG-6 zm(2K-mD7J2P+Im)=4Di61y|~l(ZZpsJ=Ja58{$pKErJkS$hEQm^tx%6{OD{eN*&B(m8i&DGS6(cf zGUAYN_xvUA=KJBrmc`=4uDOx^NC$c3Vmi$4GC9b6n1!o6pY;L~Utv3v)f|2y-Kze& zGIc_<(z|H1s+DUd556rm<8)>Y$E8!kpF79X#AAwCb7*D_OcCaE z`)DM>g4LLQ?p8`=^vnxM3wk`TOI55^Vor^fc9jR(q^ipO`_8Q)v2{8{buUim*|}MH zSlIZewgAdz3ajuqT0mH^JT5D6GVNru^gz|=kJ(*RmNA`qxo2@1w)iC9oEq23D5x7W z89J{BGc`E{O?c&}TuW>Br9$T}w?ya>k6JtJD;(J~7H*d2n8$Cu%XhVbCbbmf4LI2s z1lJ@|qsPpaK4Afq{XXqO8azSRC+Jgy~s%&#e6g*1LlV`+T zYzh_;C^*pKhG7`UBGn-+nniFwMbyPZE9bAZ&Yih68e%kTnkqU(W#TIm?!S->94@}# zsxWYvLSA;`t0Y>V0&bGAFuf-W{#kP-_!O3T%;aS6U&UeFP#3$B`$H&L~Q?s#BsyLxW2SP`s z0#ylwj*EPfOz32gk8FsO;U4INuet=n0rz~#Xb|R&+@nZhEXR8+V>xU@GC)R=qkAyH zuD21Vm>i3nPIwDiB-bQ(=}dj#NYjnh%9{=8@`9CIROU4OL%-DGuW~ z54cxEIu#0&4V~mew8A(BHa=I>5S8u0G8l2%!PjpwwcAcdhGoz!n?2`0ZF5Btx;fce zYV52gHj1}5N}&~w-oxmI1~{06n^#++@B)Q-0Thy**(27+uxIRQb6r(eZ<-(X1X@k_ z?_hqiXja^M#sz$`UVm#blFF(pbU}n0J?F7s!Qn0a^8#h4NUTH~4`Um_2P$ayByB_P zM-jWq`T&)mnaSfc&YjwtXX#Xwqw4EDs`S{Gmp^ujz0Vk3vA2{NGJ*;}zT~K%riyRm z^%R|OzSYgg8sq(ekZ~mC?*F1BKk)*lISrfeaK(~HMN;d4*Cx|?B6*mm9nh2Xy6FKX zS=U;eTjYZ>o}gOsD-w+OdK+SRAZD2=C09K-bH&>z-4;7PkvoT*>%aao)2RHFuk!r54enoP6RT2tE8~Rpt{X}`vUk4G^1SmhEb78h@F8n)2~My?V=kFxkkN6% z_*{B*fJJsjvy_J6!NPoxD5LibVg9kDCkbKDHyBMLFy6=w^#9IXL_mDs$Z=}F&v;GK zV#7ucF;F@g#DKs6)rLpe!qr{IXMa>pIuYy$w=wD>5fZI!wX{ITJ~VnKhIh0zLn=kj z>CAPajj{N|mdP>A66F0_Ri;A-CN9oHO02rCBAaD#;d5aPEpx`zXzm`BRbxgo2?&%7 zm|WTSLupZK+luq*e4GhPL0umdb4`X%2fLiSJ^X-G1-nO~VK6xI{S}Djv--~)3%IMR zCCiFYv9&wid-RJ%gL)Y(xxMXHsA9a;?e}j=Z>&AvaCxagf*4=k0hM7JFh85pN$;9d zS(|jz+N8@hpWa{ss2gDqT^)+}z9qhjsF$YAVFA~F2=qkJXg;AR@j%E>DPHj%7=cbn|`hJ_O;*|7}rj}E;z#U9j=W> z2x$fd#HU6NPdihX3N{rj?X+OE(QIa=#qfgGmkF}{=7QKx$#f`K=o-c(=^MF#!O=Oe z(m~luQ+nrO@v@cflEJWXS9)Wg3~K1|Y70*QmTD$jDtca;n<-mruxx)CCYP;DkmZu~ ze{rmb(G$!a`CF|}Mx>hG=&p$U=$&UI!n>7*yMI*z zz#=3Db26B3wrvM!(Ng|+|4(UFw|BqyUkg^@7BZaA%v=SikLEA_|M{rp+ZkEpgo%~) z5H{*0S|yD_sU3b+qYfFWsfDp4{DsvY?#mrNH#?O0p&>6xn?JZEt4 zn(SW9$VbKGT!aMru?)Sqw(X~3U>&F(0NG=2F6itCR5t|2J~q9F2ayRD6aY zBlo7&AH5du&HB~uks+Hd{em^^3JB;689D1OojgBC1rIzagZcmRKy|&#xS}A2d_fx@ zcj6C@iLL;Nxkq_fLCj~0By*Styy|u|#AhBK>_HCP$&$zVFIr^l3Rq<1&k2zUw;%*E z+id`PSm?#a#KIaM)@foirIm0*f>K@H^g?p6xL7n#u?i<^_oxLXApq7{W+P@S(g>kJNnP03+!Hh zz%c$FKKdcAdGC~gr@TF7Z+XjGbhHM1931OHkTU{NMnW0N(5=oUXs&=31l_1UBws92H*!_W*1o_;`VXuewX|bp8VQ6~ibM&)6(eifz)_1v)IQ0RtyK#&pM5Q< zE{bVhFVc>-I$Gkx?Zz+WEDB$uzV&x|%jyBU%#g9mb;keSk2XZa7agy*?-docU@D`< zuDL8AQ`L)?q!(M0#|vZD*yp}T(34Dwq6Ke-)dzNCOo2@`7NhR8H58e=;~}&aKi15Q3Fn=Jcqwfeb+Ztrs8-lG-sNcV2m6=7{l|B$R&t9x3_<3S@c243u z-XU)qUoX9FvD)tQ6=Fk!dVd~W@2g$w>R|oQ-ZtMn+7VV)UL}TnkIn>fdN&l7rVSic zm8h`aWXjAw+yk3TE7OnO4MO+3+|<`0FsK7Qg*2_on)n5uyVgj$OC%m;F`w$9 z@ISk<&8KZ5u!+DX0-FeIBCv_TCIXuXY$C9Uz$OBl2y7y-iNGcTn+R+ou!+DX0-FeI hBCv_TCIXuXY$C9Uz$OBl2y7y-iNOCl0$bh){|^gXbf5qL literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/pillar-grid-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/pillar-grid-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5b1a2cd5c611875b2a00da9e3d551a4e08b58235 GIT binary patch literal 39595 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 F`9Egh%>@7e literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux142/captures/road-in-clouds-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux142/captures/road-in-clouds-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5413752eb091f2829612777c0e500a4ea9218d76 GIT binary patch literal 34408 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 literal 0 HcmV?d00001 diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index bc48c9d..d8ed139 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -1882,8 +1882,11 @@ int main(int argc,char** argv) ownerJsonRoot.Get("motif_family_override").Data); const bool hasLiminalRoad=!std::holds_alternative( ownerJsonRoot.Get("liminal_road_override").Data); - if(hasMotifFamily&&hasLiminalRoad) - {std::fprintf(stderr,"motif_family_override and liminal_road_override cannot be combined\n");return 2;} + const bool hasLiminalPillarGrid=!std::holds_alternative( + ownerJsonRoot.Get("liminal_pillar_grid_override").Data); + if((hasMotifFamily&&hasLiminalRoad)||(hasMotifFamily&&hasLiminalPillarGrid) + ||(hasLiminalRoad&&hasLiminalPillarGrid)) + {std::fprintf(stderr,"liminal content overrides must be used in separate fixtures\n");return 2;} if(hasMotifFamily) { std::vector requests; @@ -1914,22 +1917,62 @@ int main(int argc,char** argv) } if(hasLiminalRoad) { - std::vector requests(1); - if(!StandaloneWorldAssemblyPrototype::BuildLiminalRoadRequest(ownerJsonRoot, - *ownerWorld,worldAssembly,resolvedLayout,requests.front(),error) + std::vector requests; + if(!StandaloneWorldAssemblyPrototype::BuildLiminalRoadRequests(ownerJsonRoot, + *ownerWorld,worldAssembly,resolvedLayout,requests,error) ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( resolvedLayout,seed,requests,error)) {std::fprintf(stderr,"Liminal road resolution failed: %s\n",error.c_str());return 2;} - const auto& road=resolvedLayout.stamps.front(); - std::printf("[LiminalRoadResolved] vocabulary=%u id=%s strate=%d shape=rounded_dais " - "center_m=(%.3f,%.3f,%.3f) top_m=%.3f span_m=%.3f width_m=%.3f " - "grade_deg=0.000 placement=free route_keepout=PASS band_clearance=PASS status=PASS\n", - resolvedLayout.stampVocabularyVersion,road.stableId.c_str(),road.strateIndex, - road.positionMicrometres[0]/1.0e6,road.positionMicrometres[1]/1.0e6, - road.positionMicrometres[2]/1.0e6, - (road.positionMicrometres[2]+road.halfExtentsMicrometres[2])/1.0e6, - 2.0*road.halfExtentsMicrometres[0]/1.0e6, - 2.0*road.halfExtentsMicrometres[1]/1.0e6); + std::vector deck; + std::size_t supportCount=0; + const std::string deckPrefix="liminal/road-clouds-v2/deck/"; + const std::string supportPrefix="liminal/road-clouds-v2/support/"; + for(const auto& stamp:resolvedLayout.stamps) + { + if(stamp.stableId.starts_with(deckPrefix))deck.push_back(&stamp); + else if(stamp.stableId.starts_with(supportPrefix))++supportCount; + } + std::sort(deck.begin(),deck.end(),[](const auto* a,const auto* b) + {return a->stableIdstableId;}); + double pathLength=0.0,maxGradeDegrees=0.0; + for(std::size_t i=0;isweepEndpointsMicrometres[1][0] + -segment->sweepEndpointsMicrometres[0][0])/1.0e6; + const double dy=(segment->sweepEndpointsMicrometres[1][1] + -segment->sweepEndpointsMicrometres[0][1])/1.0e6; + const double dz=std::abs(segment->sweepEndpointsMicrometres[1][2] + -segment->sweepEndpointsMicrometres[0][2])/1.0e6; + const double horizontal=std::hypot(dx,dy); + pathLength+=horizontal; + maxGradeDegrees=std::max(maxGradeDegrees, + std::atan2(dz,horizontal)*57.29577951308232); + } + const double width=deck.empty()?0.0: + 2.0*deck.front()->halfExtentsMicrometres[1]/1.0e6; + std::printf("[LiminalRoadResolved] vocabulary=%u id=liminal/road-clouds-v2 " + "strate=%d shape=swept_deck_segments deck_segments=%zu supports=%zu " + "path_length_m=%.3f width_m=%.3f grade_max_deg=%.3f " + "placement=free route_keepout=PASS band_clearance=PASS status=%s\n", + resolvedLayout.stampVocabularyVersion, + deck.empty()?-1:deck.front()->strateIndex,deck.size(),supportCount,pathLength, + width,maxGradeDegrees,deck.size()>1&&pathLength>=300.0&&width>=3.0 + &&maxGradeDegrees<=15.0?"PASS":"FAIL"); + if(deck.size()<2||pathLength<80.0||width<3.0||maxGradeDegrees>15.0) + {std::fprintf(stderr,"Liminal road resolved outside the walkable road bounds\n");return 2;} + } + if(hasLiminalPillarGrid) + { + std::vector requests; + if(!StandaloneWorldAssemblyPrototype::BuildLiminalPillarGridRequests(ownerJsonRoot, + *ownerWorld,worldAssembly,resolvedLayout,requests,error) + ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( + resolvedLayout,seed,requests,error)) + {std::fprintf(stderr,"Liminal pillar-grid resolution failed: %s\n",error.c_str());return 2;} + std::printf("[LiminalPillarGridResolved] vocabulary=%u pillars=%zu shape=identical_vertical_cylinders " + "placement=regular_grid route_keepout=PASS band_clearance=PASS status=PASS\n", + resolvedLayout.stampVocabularyVersion,resolvedLayout.stamps.size()); } if(options.LandmarkChamberDemo) { diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index e151fbd..dab5001 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2966,53 +2966,122 @@ namespace StandaloneStreamBenchmark { bool found=false; bool passed=true; + std::vector deck; + constexpr std::string_view DeckPrefix="liminal/road-clouds-v2/deck/"; for(const auto& road:ResolvedLayout->stamps) { - if(road.stableId!="liminal/raised-road-v1")continue; + if(road.stableId.starts_with(DeckPrefix))deck.push_back(&road); + } + if(!deck.empty()) + { found=true; - const bool longAxisX=(road.yawQuarterTurns&1u)==0; - const double centerX=road.positionMicrometres[0]/1.0e6; - const double centerY=road.positionMicrometres[1]/1.0e6; - const double centerZ=road.positionMicrometres[2]/1.0e6; - const double halfLength=road.halfExtentsMicrometres[longAxisX?0:1]/1.0e6; - const double halfWidth=road.halfExtentsMicrometres[longAxisX?1:0]/1.0e6; - const double deckZ=centerZ+road.halfExtentsMicrometres[2]/1.0e6; - constexpr double CapsuleRadiusMetres=0.34; + std::sort(deck.begin(),deck.end(),[](const auto* a,const auto* b) + {return a->stableIdstableId;}); constexpr double CapsuleHeightMetres=1.76; constexpr double HalfCapsuleHeightMetres=CapsuleHeightMetres*0.5; - constexpr double EndInsetMetres=1.0; + constexpr double SlopeCapsuleClearanceMetres=0.12; std::vector> roadPath; - const double inset=std::min(EndInsetMetres,halfLength*0.25); - for(const double along:{-halfLength+inset,halfLength-inset}) - roadPath.push_back({(centerX+(longAxisX?along:0.0))/coreMetres, - (centerY+(longAxisX?0.0:along))/coreMetres, - (deckZ+HalfCapsuleHeightMetres)/coreMetres}); + roadPath.reserve(deck.size()*4); + std::vector> centerline; + centerline.reserve(deck.size()+1); + bool surfacePathValid=true; + for(std::size_t i=0;ikind!=VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment) + surfacePathValid=false; + const auto point=[&](std::size_t endpoint) + {return std::array{ + segment->sweepEndpointsMicrometres[endpoint][0]/1.0e6, + segment->sweepEndpointsMicrometres[endpoint][1]/1.0e6, + segment->sweepEndpointsMicrometres[endpoint][2]/1.0e6};}; + const auto a=point(0),b=point(1); + if(i==0)centerline.push_back(a); + else if(std::abs(centerline.back()[0]-a[0])>1.0e-6 + ||std::abs(centerline.back()[1]-a[1])>1.0e-6 + ||std::abs(centerline.back()[2]-a[2])>1.0e-6) + surfacePathValid=false; + centerline.push_back(b); + } + double pathLengthMetres=0.0,maxGradeDegrees=0.0; + std::uint64_t surfaceProbes=0,surfaceMisses=0; + const auto surfaceTopAt=[&](double xMetres,double yMetres, + double nominalTop,double& surfaceTop) + { + ++surfaceProbes; + double low=nominalTop-0.25,high=nominalTop+1.0; + if(Shape.densityAt({xMetres/coreMetres,yMetres/coreMetres, + low/coreMetres})>=0.0f + ||Shape.densityAt({xMetres/coreMetres,yMetres/coreMetres, + high/coreMetres})<0.0f) + {++surfaceMisses;return false;} + for(int iteration=0;iteration<20;++iteration) + { + const double middle=(low+high)*0.5; + if(Shape.densityAt({xMetres/coreMetres,yMetres/coreMetres, + middle/coreMetres})<0.0f)low=middle; + else high=middle; + } + surfaceTop=high; + return true; + }; + const double halfThickness=deck.front()->halfExtentsMicrometres[2]/1.0e6; + for(std::size_t segment=1;segment(1, + static_cast(std::ceil(horizontal/0.5))); + for(std::uint64_t step=0;step<=intervals;++step) + { + if(segment>1&&step==0)continue; + const double t=static_cast(step)/intervals; + const double x=a[0]+dx*t,y=a[1]+dy*t; + const double nominalTop=a[2]+(b[2]-a[2])*t+halfThickness; + double actualTop=nominalTop; + if(!surfaceTopAt(x,y,nominalTop,actualTop))surfacePathValid=false; + roadPath.push_back({x/coreMetres,y/coreMetres, + (actualTop+HalfCapsuleHeightMetres + +SlopeCapsuleClearanceMetres)/coreMetres}); + } + } + for(std::size_t i=1;i=2.0*CapsuleRadiusMetres - &&gradeDegrees<=15.0&&roadAudit.passed; - std::printf("[LiminalRoadWalkAudit] id=%s stations=%llu capsule_samples=%llu " + const double widthMetres=2.0*deck.front()->halfExtentsMicrometres[1]/1.0e6; + passed=std::all_of(deck.begin(),deck.end(),[](const auto* road) + {return road->kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment;}) + &&pathLengthMetres>=300.0&&widthMetres>=3.0 + &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed; + std::printf("[LiminalRoadWalkAudit] id=liminal/road-clouds-v2 " + "deck_stamps=%zu path_length_m=%.3f stations=%llu capsule_samples=%llu " "blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu " - "width_m=%.3f capsule_diameter_m=%.3f grade_deg=%.3f grade_limit_deg=15.000 " - "status=%s\n",road.stableId.c_str(), + "surface_probes=%llu surface_misses=%llu width_m=%.3f minimum_width_m=3.000 " + "max_grade_deg=%.3f grade_limit_deg=15.000 status=%s\n", + deck.size(),pathLengthMetres, static_cast(roadAudit.centers), static_cast(roadAudit.capsuleSamples), static_cast(roadAudit.blocked), static_cast(roadAudit.supportSamples), static_cast(roadAudit.unsupported), - static_cast(roadAudit.gradeFailures),widthMetres, - 2.0*CapsuleRadiusMetres,gradeDegrees,passed?"PASS":"FAIL"); + static_cast(roadAudit.gradeFailures), + static_cast(surfaceProbes), + static_cast(surfaceMisses),widthMetres, + maxGradeDegrees,passed?"PASS":"FAIL"); } if(!found&&required) { - std::printf("[LiminalRoadWalkAudit] status=FAIL reason=road_stamp_missing\n"); + std::printf("[LiminalRoadWalkAudit] status=FAIL reason=road_path_missing\n"); return false; } return passed; diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index bafe419..8897078 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -587,13 +587,15 @@ namespace StandaloneWorldAssemblyPrototype return true; } - inline bool BuildLiminalRoadRequest(const VFJson::Value& root, + inline bool BuildLiminalRoadRequests(const VFJson::Value& root, const FStandaloneOwnerWorld& owner, const VoxelForgeCore::WorldAssemblyManifest& assembly, const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout, - VoxelForgeCore::ResolvedLayoutStampRequestV1& request,std::string& error) + std::vector& requests, + std::string& error) { using namespace VoxelForgeCore; + requests.clear(); const VFJson::Value& overrideValue=root.Get("liminal_road_override"); if(!overrideValue.IsObject()) {error="liminal_road_override must be an object";return false;} @@ -604,49 +606,229 @@ namespace StandaloneWorldAssemblyPrototype const VFJson::Value& strateValue=overrideValue.Get("strate_index"); const auto* id=std::get_if(&overrideValue.Get("stable_id").Data); - const auto& position=overrideValue.Get("position_xy_m").AsArray(); - const auto& extents=overrideValue.Get("half_extents_m").AsArray(); - const VFJson::Value& heightValue=overrideValue.Get("deck_height_above_field_m"); - const VFJson::Value& yawValue=overrideValue.Get("yaw_quarter_turns"); - if(!strateValue.IsNumber()||!id||id->empty()||position.size()!=2||extents.size()!=3 - ||!heightValue.IsNumber()||!std::isfinite(heightValue.Number()) - ||!yawValue.IsNumber()||yawValue.Integer()<0||yawValue.Integer()>3) - {error="liminal road requires stable_id, strate_index, position, extents, deck height and yaw";return false;} + const auto& position=overrideValue.Get("start_xy_m").AsArray(); + const auto readNumber=[&](const char* key,double fallback,double& result) + { + const VFJson::Value& value=overrideValue.Get(key); + if(std::holds_alternative(value.Data)) + {result=fallback;return true;} + if(!value.IsNumber()||!std::isfinite(value.Number()))return false; + result=value.Number();return true; + }; + double pathLength=0.0,curveControl=0.0,deckHeight=0.0,riseControl=0.0; + double halfWidth=0.0,halfThickness=0.0,sampleSpacing=0.0; + double supportSpacing=0.0,supportRadius=0.0; + if(!strateValue.IsNumber()||!id||id->empty()||position.size()!=2 + ||!readNumber("path_length_m",360.0,pathLength) + ||!readNumber("curve_control_offset_m",84.0,curveControl) + ||!readNumber("deck_height_above_field_m",44.0,deckHeight) + ||!readNumber("rise_control_m",22.0,riseControl) + ||!readNumber("half_width_m",3.2,halfWidth) + ||!readNumber("half_thickness_m",0.65,halfThickness) + ||!readNumber("sample_spacing_m",1.0,sampleSpacing) + ||!readNumber("support_spacing_m",24.0,supportSpacing) + ||!readNumber("support_radius_m",0.55,supportRadius)) + {error="liminal road requires a valid identity, start, and finite path parameters";return false;} for(const auto& value:position) if(!value.IsNumber()||!std::isfinite(value.Number())) - {error="liminal road position_xy_m must contain finite metre values";return false;} - for(const auto& value:extents) - if(!value.IsNumber()||!std::isfinite(value.Number()) - ||value.Number()<0.5||value.Number()>100.0) - {error="liminal road half_extents_m must contain values from 0.5 to 100 metres";return false;} - if(heightValue.Number()<1.0||heightValue.Number()>100.0) - {error="liminal road deck height must be from 1 to 100 metres above the field";return false;} + {error="liminal road start_xy_m must contain finite metre values";return false;} + if(std::abs(position[0].Number())>5000.0||std::abs(position[1].Number())>5000.0 + ||pathLength<80.0||pathLength>1000.0||curveControl<0.0||curveControl>200.0 + ||deckHeight<30.0||deckHeight>60.0||riseControl<0.0||riseControl>30.0 + ||halfWidth<1.5||halfWidth>10.0||halfThickness<0.5||halfThickness>3.0 + ||sampleSpacing<1.0||sampleSpacing>6.0 + ||supportSpacing<8.0||supportSpacing>60.0 + ||supportRadius<0.5||supportRadius>1.5) + {error="liminal road dimensions are outside the bounded walkable-road ranges";return false;} const auto strateIndex=static_cast(strateValue.Integer()); const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), [strateIndex](const auto& value){return value.strateIndex==strateIndex &&value.generatorKind=="SurfaceWorld";}); if(strate==layout.strates.end()) {error="liminal_road_override must select a resolved SurfaceWorld strate";return false;} - if(extents[0].Number()<10.0||extents[1].Number()<0.75 - ||extents[0].Number()<=extents[1].Number()*4.0) - {error="liminal road must be long and narrow, with at least 1.5 metres half-width";return false;} const auto metresToMicrometres=[](double value) {return static_cast(std::llround(value*1000000.0));}; const std::int64_t fieldFloorMicrometres=static_cast(std::llround( static_cast(assembly.recipe.surfaceProfile.h0Subvoxels) *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel)); - request={}; - request.stableId=*id; - request.strateIndex=strateIndex; - request.kind=ResolvedSdfStampKindV1::fillDais; - request.anchorPositionMicrometres={metresToMicrometres(position[0].Number()), - metresToMicrometres(position[1].Number()), - fieldFloorMicrometres+metresToMicrometres(heightValue.Number()) - -metresToMicrometres(extents[2].Number())}; - request.halfExtentsMicrometres={metresToMicrometres(extents[0].Number()), - metresToMicrometres(extents[1].Number()),metresToMicrometres(extents[2].Number())}; - request.yawQuarterTurns=static_cast(yawValue.Integer()); + const std::int64_t startX=metresToMicrometres(position[0].Number()); + const std::int64_t startY=metresToMicrometres(position[1].Number()); + const std::int64_t lengthUm=metresToMicrometres(pathLength); + const std::int64_t lateralUm=metresToMicrometres(curveControl); + const std::int64_t deckBaseUm=fieldFloorMicrometres+metresToMicrometres(deckHeight); + const std::int64_t riseUm=metresToMicrometres(riseControl); + const std::int64_t halfWidthUm=metresToMicrometres(halfWidth); + const std::int64_t halfThicknessUm=metresToMicrometres(halfThickness); + const std::uint32_t steps=static_cast(std::ceil(pathLength/sampleSpacing)); + const auto lerpInteger=[steps](std::int64_t a,std::int64_t b,std::uint32_t i) + { + const std::int64_t numerator=(b-a)*static_cast(i); + const std::int64_t rounded=numerator>=0 + ?numerator+static_cast(steps/2) + :numerator-static_cast(steps/2); + return a+rounded/static_cast(steps); + }; + const auto bezier=[&](const std::array& controls,std::uint32_t i) + { + const std::int64_t a=lerpInteger(controls[0],controls[1],i); + const std::int64_t b=lerpInteger(controls[1],controls[2],i); + const std::int64_t c=lerpInteger(controls[2],controls[3],i); + const std::int64_t d=lerpInteger(a,b,i); + const std::int64_t e=lerpInteger(b,c,i); + return lerpInteger(d,e,i); + }; + const std::array xControls={startX, + startX+lengthUm/3,startX+(2*lengthUm)/3,startX+lengthUm}; + const std::array yControls={startY,startY+lateralUm, + startY-lateralUm,startY}; + const std::array zControls={deckBaseUm,deckBaseUm+riseUm, + deckBaseUm-riseUm,deckBaseUm}; + std::vector> path; + path.reserve(static_cast(steps)+1); + const auto halfUp=[](std::int64_t numerator,std::int64_t denominator) + {return (numerator>=0?numerator+denominator/2:numerator-denominator/2)/denominator;}; + for(std::uint32_t i=0;i<=steps;++i) + { + const auto t=static_cast(i); + const auto n=static_cast(steps); + path.push_back({xControls[0]+halfUp(lengthUm*t,n), + bezier(yControls,i),bezier(zControls,i)}); + } + const auto makeStamp=[&](std::string stableId,ResolvedSdfStampKindV1 kind, + const std::array& positionUm, + const std::array& halfExtentsUm,std::int64_t smoothWidthUm) + { + ResolvedLayoutStampRequestV1 request; + request.stableId=std::move(stableId);request.strateIndex=strateIndex; + request.kind=kind;request.anchorPositionMicrometres=positionUm; + request.halfExtentsMicrometres=halfExtentsUm; + request.smoothWidthMicrometres=smoothWidthUm; + requests.push_back(std::move(request)); + }; + const std::int64_t deckSmoothUm=250000; + const std::int64_t segmentOverlapUm=350000; + for(std::uint32_t i=1;i(b[0]-a[0]); + const double dy=static_cast(b[1]-a[1]); + const double dz=static_cast(b[2]-a[2]); + const std::int64_t halfLengthUm=static_cast(std::ceil( + std::sqrt(dx*dx+dy*dy+dz*dz)*0.5))+segmentOverlapUm; + ResolvedLayoutStampRequestV1 request; + request.stableId=*id+"/deck/"+std::to_string(10000+i-1).substr(1); + request.strateIndex=strateIndex; + request.kind=ResolvedSdfStampKindV1::fillSweptDeckSegment; + request.anchorPositionMicrometres={ + (a[0]+b[0])/2,(a[1]+b[1])/2,(a[2]+b[2])/2}; + request.sweepEndpointsMicrometres={a,b}; + request.halfExtentsMicrometres={halfLengthUm,halfWidthUm,halfThicknessUm}; + request.smoothWidthMicrometres=deckSmoothUm; + requests.push_back(std::move(request)); + } + const std::int64_t supportBaseUm=fieldFloorMicrometres-2000000; + const std::int64_t supportRadiusUm=metresToMicrometres(supportRadius); + double distanceSinceSupport=supportSpacing; + std::uint32_t supportIndex=0; + for(std::uint32_t i=0;i0) + { + const auto& a=path[i-1];const auto& b=path[i]; + const double dx=static_cast(b[0]-a[0]); + const double dy=static_cast(b[1]-a[1]); + distanceSinceSupport+=std::hypot(dx,dy)/1000000.0; + } + if(i!=0&&i+1!=path.size()&&distanceSinceSupport& requests, + std::string& error) + { + using namespace VoxelForgeCore; + requests.clear(); + const VFJson::Value& overrideValue=root.Get("liminal_pillar_grid_override"); + if(!overrideValue.IsObject()) + {error="liminal_pillar_grid_override must be an object";return false;} + if(assembly.recipe.surfaceProfile.version!=1 + ||assembly.recipe.surfaceProfile.kind!=WorldAssemblySurfaceProfileKindV1::flatField + ||owner.CoreVoxelSizeMicrons==0) + {error="the liminal pillar grid requires a valid flatField SurfaceWorld recipe";return false;} + const auto* id=std::get_if(&overrideValue.Get("stable_id").Data); + const VFJson::Value& strateValue=overrideValue.Get("strate_index"); + const auto& center=overrideValue.Get("center_xy_m").AsArray(); + const auto readNumber=[&](const char* key,double fallback,double& result) + { + const VFJson::Value& value=overrideValue.Get(key); + if(std::holds_alternative(value.Data)) + {result=fallback;return true;} + if(!value.IsNumber()||!std::isfinite(value.Number()))return false; + result=value.Number();return true; + }; + double spacing=0.0,radius=0.0,height=0.0; + const VFJson::Value& rowsValue=overrideValue.Get("rows"); + const VFJson::Value& columnsValue=overrideValue.Get("columns"); + if(!id||id->empty()||!strateValue.IsNumber()||center.size()!=2 + ||!readNumber("spacing_m",76.0,spacing) + ||!readNumber("radius_m",4.0,radius) + ||!readNumber("height_m",28.0,height) + ||!rowsValue.IsNumber()||!columnsValue.IsNumber()) + {error="liminal pillar grid requires an identity, center, dimensions and counts";return false;} + for(const auto& value:center) + if(!value.IsNumber()||!std::isfinite(value.Number())) + {error="liminal pillar grid center_xy_m must contain finite metre values";return false;} + const int rows=static_cast(rowsValue.Integer()); + const int columns=static_cast(columnsValue.Integer()); + if(rows<3||rows>15||columns<3||columns>15||spacing<32.0||spacing>120.0 + ||radius<2.0||radius>12.0||height<12.0||height>60.0 + ||std::abs(center[0].Number())>5000.0||std::abs(center[1].Number())>5000) + {error="liminal pillar grid dimensions are outside their bounded ranges";return false;} + const auto strateIndex=static_cast(strateValue.Integer()); + const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), + [strateIndex](const auto& value){return value.strateIndex==strateIndex + &&value.generatorKind=="SurfaceWorld";}); + if(strate==layout.strates.end()) + {error="liminal_pillar_grid_override must select a resolved SurfaceWorld strate";return false;} + const auto toMicrometres=[](double value) + {return static_cast(std::llround(value*1000000.0));}; + const std::int64_t floorUm=static_cast(std::llround( + static_cast(assembly.recipe.surfaceProfile.h0Subvoxels) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel)); + const std::int64_t spacingUm=toMicrometres(spacing); + const std::int64_t radiusUm=toMicrometres(radius); + const std::int64_t halfHeightUm=toMicrometres(height*0.5); + const int rowStart=-(rows/2),columnStart=-(columns/2); + for(int row=0;row Date: Sun, 1 Nov 2026 10:08:37 +0100 Subject: [PATCH 3/7] proto: continuous swept road deck; coarse-LOD proxies keep thin pillars intact (L143) Road: one swept-deck stamp on a shared cubic-Hermite centerline (stamp vocabulary V5), 376.8 m, max 8.5 deg, walk audit clean, short-road control fails as expected. Pillars: regular fillPillar stamps get deterministic 24-sided capped-cylinder proxies once the LOD step exceeds their radius or half-height (applies to all worlds). Owner hashes unchanged (v227); five-fixture Clang/GCC determinism; fast tier green. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 5 + Standalone/Core/src/ResolvedLayoutInternal.h | 137 +++++- Standalone/Core/src/ShapeWorldInternal.h | 292 +++++++++++ Standalone/Core/src/VoxelForgeCore.cpp | 23 +- .../Linux143/BuildL143Fixtures.py | 113 +++++ .../WorldAssemblerM3/Linux143/CaptureL143.py | 463 ++++++++++++++++++ .../WorldAssemblerM3/Linux143/REPORT.md | 64 +++ .../captures/flatField-monolith-eye.jpg | Bin 0 -> 26523 bytes .../captures/flatField-monolith-wide.jpg | Bin 0 -> 23358 bytes .../Linux143/captures/periodicHills-eye.jpg | Bin 0 -> 25065 bytes .../Linux143/captures/periodicHills-wide.jpg | Bin 0 -> 60906 bytes .../Linux143/captures/pillar-grid-eye.jpg | Bin 0 -> 53780 bytes .../Linux143/captures/pillar-grid-wide.jpg | Bin 0 -> 74691 bytes .../captures/road-in-clouds-cloud-up.jpg | Bin 0 -> 36889 bytes .../Linux143/captures/road-in-clouds-eye.jpg | Bin 0 -> 27028 bytes .../Linux143/captures/road-in-clouds-wide.jpg | Bin 0 -> 45695 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 35 +- Standalone/Source/StreamBenchmarkPipeline.h | 78 ++- Standalone/Source/WorldAssemblyPrototype.h | 30 +- 19 files changed, 1167 insertions(+), 73 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/BuildL143Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/CaptureL143.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/pillar-grid-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/pillar-grid-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/road-in-clouds-cloud-up.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/road-in-clouds-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux143/captures/road-in-clouds-wide.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index 204242d..edeb226 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -892,6 +892,7 @@ namespace VoxelForgeCore inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV2 = 2; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV3 = 3; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV4 = 4; + inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV5 = 5; inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1; enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict }; @@ -918,6 +919,9 @@ namespace VoxelForgeCore std::array anchorPositionMicrometres{}; // Present only for fillSweptDeckSegment; defines its directed centerline. std::array, 2> sweepEndpointsMicrometres{}; + // V5 permits one continuous swept deck to carry its complete sampled centerline. + // Empty retains the V4 single-segment interpretation. + std::vector> sweepPathMicrometres; std::int64_t placementRadiusMicrometres = 0; std::array halfExtentsMicrometres{}; std::int64_t smoothWidthMicrometres = 0; @@ -938,6 +942,7 @@ namespace VoxelForgeCore ResolvedSdfStampKindV1 kind = ResolvedSdfStampKindV1::carveEllipsoid; std::array positionMicrometres{}; std::array, 2> sweepEndpointsMicrometres{}; + std::vector> sweepPathMicrometres; std::array boundsMinimumMicrometres{}; std::array boundsMaximumMicrometres{}; std::array halfExtentsMicrometres{}; diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 5074335..4a47b04 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -599,6 +599,7 @@ namespace <<",\"irregularity_seed\":"<(stamp.yawQuarterTurns); if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { out<<",\"sweep_endpoints_um\":[[" <=ResolvedLayoutStampVocabularyVersionV3) out<<",\"rounding_radius_um\":"< stampIds; for(const auto& stamp:stamps) { @@ -1184,9 +1199,30 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, -stamp.sweepEndpointsMicrometres[0][axis]; lengthSquared+=delta*delta; } - if(!(lengthSquared>0.0) - ||std::sqrt(lengthSquared)>2.0*stamp.halfExtentsMicrometres[0]+1.0) + if(stamp.sweepPathMicrometres.empty()&&(!(lengthSquared>0.0) + ||std::sqrt(lengthSquared)>2.0*stamp.halfExtentsMicrometres[0]+1.0)) add("stamp_sweep",stamp.stableId+" has invalid endpoints or longitudinal extent"); + if(!stamp.sweepPathMicrometres.empty()) + { + bool validPath=stampVocabularyVersion>=ResolvedLayoutStampVocabularyVersionV5 + &&stamp.sweepPathMicrometres.size()>=2 + &&stamp.sweepPathMicrometres.size()<=1025 + &&stamp.sweepPathMicrometres.front()==stamp.sweepEndpointsMicrometres[0] + &&stamp.sweepPathMicrometres.back()==stamp.sweepEndpointsMicrometres[1]; + for(std::size_t pointIndex=0;pointIndex=-1000000000000ll + &&coordinate<=1000000000000ll; + if(pointIndex>0) + validPath=validPath + &&stamp.sweepPathMicrometres[pointIndex-1][0](stamp.halfExtentsMicrometres[axis]+pad); + radiusSquared+=expanded*expanded; + } + const auto radius=static_cast(std::ceil(std::sqrt(radiusSquared))); + std::array minimum=stamp.sweepPathMicrometres.front(); + std::array maximum=minimum; + for(const auto& point:stamp.sweepPathMicrometres) + for(std::size_t axis=0;axis<3;++axis) + { + minimum[axis]=std::min(minimum[axis],point[axis]); + maximum[axis]=std::max(maximum[axis],point[axis]); + } + for(std::size_t axis=0;axis<3;++axis) + if(stamp.boundsMinimumMicrometres[axis]!=minimum[axis]-radius + ||stamp.boundsMaximumMicrometres[axis]!=maximum[axis]+radius) + add("stamp_bounds",stamp.stableId + +" conservative continuous-sweep bounds do not match its path"); + } else { const std::array extents={ @@ -1556,6 +1616,14 @@ std::optional ResolvedLayoutSnapshotV3::FromJson( for(std::size_t axis=0;axis<3&&axis point{}; + const auto& values=value.AsArray(); + for(std::size_t axis=0;axis<3&&axis1000000000000ll) {error="stamp request "+request.stableId+" has an unbounded anchor";return false;} - if(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + if(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + &&request.sweepPathMicrometres.empty()) { double lengthSquared=0.0; for(std::size_t axis=0;axis<3;++axis) @@ -1729,6 +1803,25 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t ||std::sqrt(lengthSquared)>2.0*request.halfExtentsMicrometres[0]+1.0) {error="stamp request "+request.stableId+" has invalid swept-segment extents";return false;} } + if(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + &&!request.sweepPathMicrometres.empty()) + { + if(request.sweepPathMicrometres.size()<2 + ||request.sweepPathMicrometres.size()>1025 + ||request.sweepPathMicrometres.front()!=request.sweepEndpointsMicrometres[0] + ||request.sweepPathMicrometres.back()!=request.sweepEndpointsMicrometres[1]) + {error="stamp request "+request.stableId+" has an invalid continuous deck path";return false;} + for(std::size_t pointIndex=0;pointIndex1000000000000ll) + {error="stamp request "+request.stableId+" has an unbounded path point";return false;} + if(pointIndex>0&&request.sweepPathMicrometres[pointIndex-1][0]>=point[0]) + {error="stamp request "+request.stableId+" path X coordinates must increase strictly";return false;} + } + } // The shared JSON value type stores numbers as IEEE-754 doubles; keep the // serialized seed in its exact integer range so the canonical round trip holds. @@ -1748,6 +1841,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId; stamp.strateIndex=request.strateIndex;stamp.kind=request.kind; stamp.sweepEndpointsMicrometres=request.sweepEndpointsMicrometres; + stamp.sweepPathMicrometres=request.sweepPathMicrometres; stamp.halfExtentsMicrometres=request.halfExtentsMicrometres; stamp.smoothWidthMicrometres=request.smoothWidthMicrometres; stamp.irregularityAmplitudeMicrometres=request.irregularityAmplitudeMicrometres; @@ -1769,7 +1863,8 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.positionMicrometres[axis]=request.anchorPositionMicrometres[axis]+offset[axis]; const std::int64_t pad=stamp.smoothWidthMicrometres +stamp.irregularityAmplitudeMicrometres; - if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + &&stamp.sweepPathMicrometres.empty()) { double radiusSquared=0.0; for(const auto extent:stamp.halfExtentsMicrometres) @@ -1788,6 +1883,30 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.boundsMaximumMicrometres[axis]=maximum+radius; } } + else if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + double radiusSquared=0.0; + for(std::size_t axis=1;axis<3;++axis) + { + const double expanded=static_cast(stamp.halfExtentsMicrometres[axis]+pad); + radiusSquared+=expanded*expanded; + } + const std::int64_t radius=static_cast( + std::ceil(std::sqrt(radiusSquared))); + std::array minimum=stamp.sweepPathMicrometres.front(); + std::array maximum=minimum; + for(const auto& point:stamp.sweepPathMicrometres) + for(std::size_t axis=0;axis<3;++axis) + { + minimum[axis]=std::min(minimum[axis],point[axis]); + maximum[axis]=std::max(maximum[axis],point[axis]); + } + for(std::size_t axis=0;axis<3;++axis) + { + stamp.boundsMinimumMicrometres[axis]=minimum[axis]-radius; + stamp.boundsMaximumMicrometres[axis]=maximum[axis]+radius; + } + } else { const std::array extents={ diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index b9a8c8a..ed036ec 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -3536,6 +3536,7 @@ private: const VoxelForgeCore::ResolvedLayoutStampV1* record=nullptr; std::array positionVoxels{},halfExtentsVoxels{}; std::array,2> sweepEndpointsVoxels{}; + std::vector> sweepPathVoxels; float smoothWidthVoxels=0.0f; float irregularityAmplitudeVoxels=0.0f; float irregularityWavelengthVoxels=0.0f; @@ -3710,6 +3711,15 @@ private: static_cast(stamp.sweepEndpointsMicrometres[endpoint][axis]) /Owner->CoreVoxelSizeMicrons); } + runtime.sweepPathVoxels.reserve(stamp.sweepPathMicrometres.size()); + for(const auto& pointMicrometres:stamp.sweepPathMicrometres) + { + std::array point{}; + for(std::size_t axis=0;axis<3;++axis) + point[axis]=static_cast(static_cast(pointMicrometres[axis]) + /Owner->CoreVoxelSizeMicrons); + runtime.sweepPathVoxels.push_back(point); + } const std::size_t xAxis=stamp.yawQuarterTurns%2?1:0; const std::size_t yAxis=stamp.yawQuarterTurns%2?0:1; runtime.halfExtentsVoxels={ @@ -5169,6 +5179,20 @@ private: } public: + static std::int32_t& CurrentStampSamplingStep() noexcept + { + static thread_local std::int32_t Step=0; + return Step; + } + struct FScopedStampSamplingStep + { + explicit FScopedStampSamplingStep(std::int32_t Step) + :Previous(CurrentStampSamplingStep()) + {CurrentStampSamplingStep()=std::max(0,Step);} + ~FScopedStampSamplingStep(){CurrentStampSamplingStep()=Previous;} + std::int32_t Previous=0; + }; + bool GetNativeSurfaceHeightsAt(float X,float Y,int32 ChunkZ, float& OutGroundZ,float& OutCeilingZ) const { @@ -7123,6 +7147,111 @@ private: const float top=std::max(StampEllipsoidSdf(x,y,z,halfSize),-z); return SmoothMinDistance(lower,top,round*2.0f); } + static float StampContinuousSweptDeckSdf(const FStampRuntime& stamp, + float x,float y,float z) + { + const auto& path=stamp.sweepPathVoxels; + if(path.size()<2)return std::numeric_limits::infinity(); + const float halfWidth=stamp.halfExtentsVoxels[1]; + const float halfThickness=stamp.halfExtentsVoxels[2]; + const float round=std::min(0.35f,std::min(halfWidth,halfThickness)*0.15f); + const float searchMargin=halfWidth+halfThickness+2.0f; + const auto first=std::lower_bound(path.begin(),path.end(),x-searchMargin, + [](const auto& point,float value){return point[0](first-path.begin()); + const std::size_t lastIndex=static_cast(last-path.begin()); + const std::size_t segmentBegin=std::min(path.size()-2, + firstIndex==0?std::size_t{0}:firstIndex-1); + const std::size_t segmentEnd=std::min(path.size()-2,lastIndex); + std::size_t nearestSegment=path.size(); + float nearestProjection=0.0f; + float nearestDistanceSquared=std::numeric_limits::infinity(); + for(std::size_t segment=segmentBegin;segment<=segmentEnd;++segment) + { + const auto& a=path[segment];const auto& b=path[segment+1]; + const float dx=b[0]-a[0],dy=b[1]-a[1]; + const float horizontalSquared=dx*dx+dy*dy; + if(!(horizontalSquared>1.0e-10f))continue; + const float projection=std::clamp(((x-a[0])*dx+(y-a[1])*dy) + /horizontalSquared,0.0f,1.0f); + const float nearestX=a[0]+projection*dx; + const float nearestY=a[1]+projection*dy; + const float offsetX=x-nearestX,offsetY=y-nearestY; + const float distanceSquared=offsetX*offsetX+offsetY*offsetY; + if(distanceSquared=path.size()-1)return std::numeric_limits::infinity(); + const auto evalCenterline=[&](float parameter,std::array& center, + std::array& tangent) + { + const auto& p0=path[nearestSegment]; + const auto& p1=path[nearestSegment+1]; + const auto& before=path[nearestSegment==0?nearestSegment:nearestSegment-1]; + const auto& after=path[nearestSegment+2=path.size()?p1[axis]-p0[axis] + :0.5f*(after[axis]-p0[axis]); + center[axis]=h00*p0[axis]+h10*m0+h01*p1[axis]+h11*m1; + tangent[axis]=d00*p0[axis]+d10*m0+d01*p1[axis]+d11*m1; + } + }; + std::array center{},tangent{}; + for(int refinement=0;refinement<2;++refinement) + { + evalCenterline(nearestProjection,center,tangent); + const float derivativeSquared=tangent[0]*tangent[0]+tangent[1]*tangent[1]; + if(!(derivativeSquared>1.0e-10f))return std::numeric_limits::infinity(); + const float offsetX=center[0]-x,offsetY=center[1]-y; + nearestProjection=std::clamp(nearestProjection + -(offsetX*tangent[0]+offsetY*tangent[1])/derivativeSquared,0.0f,1.0f); + } + evalCenterline(nearestProjection,center,tangent); + const float tangentLength=std::sqrt(tangent[0]*tangent[0] + +tangent[1]*tangent[1]+tangent[2]*tangent[2]); + if(!(tangentLength>1.0e-8f))return std::numeric_limits::infinity(); + for(float& component:tangent)component/=tangentLength; + const float horizontalLength=std::sqrt(tangent[0]*tangent[0] + +tangent[1]*tangent[1]); + if(!(horizontalLength>1.0e-8f))return std::numeric_limits::infinity(); + const std::array side={-tangent[1]/horizontalLength, + tangent[0]/horizontalLength,0.0f}; + const std::array up={-tangent[2]*side[1],tangent[2]*side[0], + tangent[0]*side[1]-tangent[1]*side[0]}; + const std::array relative={x-center[0],y-center[1],z-center[2]}; + const auto dot=[&](const std::array& axis) + {return relative[0]*axis[0]+relative[1]*axis[1]+relative[2]*axis[2];}; + const float lateral=dot(side),vertical=dot(up); + if((nearestSegment==0&&nearestProjection<=0.0f) + ||(nearestSegment+2==path.size()&&nearestProjection>=1.0f)) + return StampRoundedBoxSdf(dot(tangent),lateral,vertical, + {halfThickness+round,halfWidth,halfThickness},round); + const float qSide=std::abs(lateral)-halfWidth+round; + const float qUp=std::abs(vertical)-halfThickness+round; + const float outside=std::sqrt(std::max(qSide,0.0f)*std::max(qSide,0.0f) + +std::max(qUp,0.0f)*std::max(qUp,0.0f)); + return outside+std::min(std::max(qSide,qUp),0.0f)-round; + } float StampSdf(const FStampRuntime& stamp,float x,float y,float z) const { float localX=x-stamp.positionVoxels[0]; @@ -7161,6 +7290,11 @@ private: break; case VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment: { + if(!stamp.sweepPathVoxels.empty()) + { + distance=StampContinuousSweptDeckSdf(stamp,x,y,z); + break; + } std::array tangent{},side{},up{},delta{}; float lengthSquared=0.0f,horizontalSquared=0.0f; for(std::size_t axis=0;axis<3;++axis) @@ -7199,6 +7333,15 @@ private: static double StampAbsMinimum(double minimum,double maximum) {return minimum<=0.0&&maximum>=0.0?0.0:std::min(std::abs(minimum),std::abs(maximum));} + static bool UsesCoarsePillarProxy(const FStampRuntime& stamp,std::int32_t sampleStep) + { + if(!stamp.record||stamp.record->kind + !=VoxelForgeCore::ResolvedSdfStampKindV1::fillPillar + ||sampleStep<=0||stamp.irregularityAmplitudeVoxels>0.0f)return false; + return static_cast(sampleStep)>std::min(stamp.halfExtentsVoxels[0], + stamp.halfExtentsVoxels[1]) + ||static_cast(sampleStep)>stamp.halfExtentsVoxels[2]; + } static double StampRoundedBoxSdfDouble(const std::array& absolute, const std::array& halfSize,double rounding) { @@ -7300,6 +7443,7 @@ private: if(index>=StampRuntime.size())return; const auto& runtime=StampRuntime[index];const auto& record=*runtime.record; if(record.strateIndex!=bound->StrateIndex)return; + if(UsesCoarsePillarProxy(runtime,CurrentStampSamplingStep()))return; for(std::size_t axis=0;axis<3;++axis) if(worldMicrometres[axis]record.boundsMaximumMicrometres[axis])return; @@ -7317,6 +7461,154 @@ private: apply(static_cast(index)); return composed; } + +public: + std::uint32_t AppendCoarsePillarProxies(FVoxelMeshData& mesh, + const FIntVector& tileOrigin,std::int32_t tileExtent,std::int32_t sampleStep) const + { + if(!Owner||Owner->CoreVoxelSizeMicrons==0||tileExtent<=0||sampleStep<=0 + ||StampRuntime.empty())return 0; + constexpr int32 sideCount=24; + constexpr double TwoPi=6.2831853071795864769; + const int32 originalVertexCount=mesh.Vertices.Num(); + const int32 originalSurfaceVertices=std::clamp(mesh.NumSurfaceVertices,0, + originalVertexCount); + const bool hasNormals=mesh.Normals.Num()==originalVertexCount; + const bool hasUvs=mesh.UVs.Num()==originalVertexCount; + const bool hasColors=mesh.Colors.Num()==originalVertexCount; + const double voxelCentimetres=Owner->CoreVoxelSizeMicrons/10000.0; + const std::int64_t tileMinimum[3]={tileOrigin.X,tileOrigin.Y,tileOrigin.Z}; + const std::int64_t tileMaximum[3]={static_cast(tileOrigin.X)+tileExtent, + static_cast(tileOrigin.Y)+tileExtent, + static_cast(tileOrigin.Z)+tileExtent}; + std::vector proxyIndices; + std::uint32_t proxyCount=0; + const auto addVertex=[&](const FVector& position,const FVector& normal, + const FVector2f& uv) + { + const int32 index=mesh.Vertices.Add(position); + if(hasNormals)mesh.Normals.Add(normal); + if(hasUvs)mesh.UVs.Add(uv); + if(hasColors)mesh.Colors.Add(FColor::White); + return index; + }; + for(const auto& stamp:StampRuntime) + { + if(!UsesCoarsePillarProxy(stamp,sampleStep))continue; + const auto& center=stamp.positionVoxels; + if(center[0]=tileMaximum[0] + ||center[1]=tileMaximum[1] + ||center[2]=tileMaximum[2])continue; + const double radiusX=stamp.halfExtentsVoxels[0]; + const double radiusY=stamp.halfExtentsVoxels[1]; + const double bottomVoxel=center[2]-stamp.halfExtentsVoxels[2]-1.0; + const double topVoxel=center[2]+stamp.halfExtentsVoxels[2]; + const auto point=[&](double angle,double z) + { + return FVector((center[0]+radiusX*std::cos(angle))*voxelCentimetres, + (center[1]+radiusY*std::sin(angle))*voxelCentimetres, + z*voxelCentimetres); + }; + const int32 capTopCenter=addVertex(FVector(center[0]*voxelCentimetres, + center[1]*voxelCentimetres,topVoxel*voxelCentimetres), + FVector(0.0,0.0,1.0),FVector2f(0.5f,0.5f)); + const int32 capBottomCenter=addVertex(FVector(center[0]*voxelCentimetres, + center[1]*voxelCentimetres,bottomVoxel*voxelCentimetres), + FVector(0.0,0.0,-1.0),FVector2f(0.5f,0.5f)); + for(int32 sideIndex=0;sideIndex(sideIndex)/sideCount; + const double u1=static_cast(sideIndex+1)/sideCount; + const double a0=TwoPi*u0,a1=TwoPi*u1; + const FVector n0=FVector(std::cos(a0)/radiusX, + std::sin(a0)/radiusY,0.0).GetSafeNormal(); + const FVector n1=FVector(std::cos(a1)/radiusX, + std::sin(a1)/radiusY,0.0).GetSafeNormal(); + const int32 bottomA=addVertex(point(a0,bottomVoxel),n0,FVector2f(u0,0.0f)); + const int32 bottomB=addVertex(point(a1,bottomVoxel),n1,FVector2f(u1,0.0f)); + const int32 topB=addVertex(point(a1,topVoxel),n1,FVector2f(u1,1.0f)); + const int32 topA=addVertex(point(a0,topVoxel),n0,FVector2f(u0,1.0f)); + proxyIndices.insert(proxyIndices.end(),{bottomA,bottomB,topB, + bottomA,topB,topA}); + + const int32 topAIndex=addVertex(point(a0,topVoxel),FVector(0.0,0.0,1.0), + FVector2f(static_cast(0.5+0.5*std::cos(a0)), + static_cast(0.5+0.5*std::sin(a0)))); + const int32 topBIndex=addVertex(point(a1,topVoxel),FVector(0.0,0.0,1.0), + FVector2f(static_cast(0.5+0.5*std::cos(a1)), + static_cast(0.5+0.5*std::sin(a1)))); + proxyIndices.insert(proxyIndices.end(),{capTopCenter,topAIndex,topBIndex}); + + const int32 bottomAIndex=addVertex(point(a0,bottomVoxel),FVector(0.0,0.0,-1.0), + FVector2f(static_cast(0.5+0.5*std::cos(a0)), + static_cast(0.5+0.5*std::sin(a0)))); + const int32 bottomBIndex=addVertex(point(a1,bottomVoxel),FVector(0.0,0.0,-1.0), + FVector2f(static_cast(0.5+0.5*std::cos(a1)), + static_cast(0.5+0.5*std::sin(a1)))); + proxyIndices.insert(proxyIndices.end(), + {capBottomCenter,bottomBIndex,bottomAIndex}); + } + ++proxyCount; + } + if(proxyIndices.empty())return 0; + const int32 proxyVertexCount=mesh.Vertices.Num()-originalVertexCount; + const auto insertProxyVertices=[&](auto& values) + { + if(values.Num()!=originalVertexCount+proxyVertexCount)return; + using FArray=std::remove_reference_t; + FArray reordered; + reordered.Reserve(values.Num()); + for(int32 index=0;index(proxyIndices.size()/3); + TArray mergedIndices; + mergedIndices.Reserve(mesh.Triangles.Num()+static_cast(proxyIndices.size())); + for(int32 index=0;index=originalSurfaceVertices + ?oldIndex+proxyVertexCount:oldIndex); + } + for(const int32 index:proxyIndices) + mergedIndices.Add(originalSurfaceVertices+index-originalVertexCount); + for(int32 index=ceilingStart;index=originalSurfaceVertices + ?oldIndex+proxyVertexCount:oldIndex); + } + mesh.Triangles=MoveTemp(mergedIndices); + + TArray mergedMasks; + mergedMasks.Reserve(oldTriangleCount+proxyTriangleCount); + for(int32 triangle=0;triangle0) + std::printf("[CoarsePillarProxy] key=(%d,%d,%d,lod%d) sampling_step_vox=%d " + "pillars=%u mode=exact_capped_cylinder status=EMITTED\n", + key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,MeshStep, + coarsePillarProxyCount); l77RefineStage.Restore(); out.densitySampleCount=static_cast(std::max(0,sampleCount)); diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/BuildL143Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux143/BuildL143Fixtures.py new file mode 100644 index 0000000..4a78407 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux143/BuildL143Fixtures.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +"""Build the L143 liminal pictures and walk-audit controls.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l143")) + +FLAT_FIELD = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, +} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + base = json.loads(OWNER.read_text(encoding="utf-8")) + + monolith = dict(base) + monolith["surface_profile_override"] = dict(FLAT_FIELD) + monolith["motif_family_override"] = { + "version": 1, + "strate_index": 0, + "placement_policy": "seed,strate,stable_id", + "motifs": [{ + "stable_id": "liminal/oversized-familiar-monolith-v1", + "kind": "cappedCylinder", + "radius_m": 1.6, + "height_m": 26.0, + "route_side_offset_m": 42.0, + "placement_radius_m": 0.0, + "fillet_radius_m": 0.6, + "blend_width_m": 1.2, + "minimum_spacing_m": 0.0, + "yaw_quarter_turns": 0, + "attachment": "seated_floor", + }], + } + + hills = dict(base) + hills["surface_profile_override"] = { + "version": 1, + "kind": "periodicHills", + "amplitude_x_m": 2.2, + "amplitude_y_m": 2.2, + "wavelength_x_m": 80.0, + "wavelength_y_m": 80.0, + "minimum_arena_clearance_m": 0.0, + } + + road_override = { + "stable_id": "liminal/road-clouds-v2", + "strate_index": 0, + "start_xy_m": [120.0, 340.0], + "path_length_m": 360.0, + "curve_control_offset_m": 84.0, + "deck_height_above_field_m": 44.0, + "rise_control_m": 22.0, + "half_width_m": 4.0, + "half_thickness_m": 1.0, + "sample_spacing_m": 1.0, + "support_spacing_m": 24.0, + "support_radius_m": 0.55, + } + road = dict(base) + road["surface_profile_override"] = dict(FLAT_FIELD) + road["liminal_road_override"] = dict(road_override) + + short_control = dict(base) + short_control["surface_profile_override"] = dict(FLAT_FIELD) + short_override = dict(road_override) + short_override["path_length_m"] = 180.0 + short_control["liminal_road_override"] = short_override + + pillars = dict(base) + pillars["surface_profile_override"] = dict(FLAT_FIELD) + pillars["liminal_pillar_grid_override"] = { + "stable_id": "liminal/horizon-pillar-grid-v1", + "strate_index": 0, + "center_xy_m": [700.0, 800.0], + "rows": 15, + "columns": 15, + "spacing_m": 76.0, + "radius_m": 5.5, + "height_m": 40.0, + } + + fixtures = ( + ("flatField-monolith", monolith), + ("periodicHills", hills), + ("road-in-clouds", road), + ("road-short-control", short_control), + ("pillar-grid", pillars), + ) + for name, fixture in fixtures: + path = args.out / f"liminal-{name}.json" + path.write_text(json.dumps(fixture, indent=2) + "\n", encoding="utf-8") + print(f"[L143Fixture] name={name} file={path} status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/CaptureL143.py b/Standalone/Research/WorldAssemblerM3/Linux143/CaptureL143.py new file mode 100644 index 0000000..f9822eb --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux143/CaptureL143.py @@ -0,0 +1,463 @@ +#!/usr/bin/env python3 +"""Run L143 liminal determinism checks, walk audits and multi-LOD captures.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +from pathlib import Path +import re +import shutil +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l143")) +CAPTURE_DEFAULT = Path(__file__).resolve().parent / "captures" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +Q_PER_METRE = 1024.0 +FOG_COLOR = "0.66,0.73,0.77" + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import bounded_run, current_stamp, first_stamp + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, *, env: dict[str, str], + stamped: bool = False, timeout_seconds: int = 1740, + expected_exit: int = 0) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(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_stamp: + raise RuntimeError(f"{name} refused a 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, f"timeout", f"{timeout_seconds}s", + *map(str, command)], cwd=ROOT, env=env, + stdout=stream, stderr=subprocess.STDOUT, + timeout=timeout_seconds + 5, check=False) + elapsed = time.monotonic() - started + output = log.read_text(encoding="utf-8", errors="replace") + print(f"[L143Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != expected_exit: + raise RuntimeError(f"{name} exit={result.returncode}, expected={expected_exit}; see {log}") + return output + + +def route_frame(manifest_path: Path) -> tuple[tuple[float, float, float], + tuple[float, float, float]]: + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + strata = [entry for entry in manifest["plan"]["strates"] + if entry.get("route") and len(entry["route"]) >= 2] + if not strata: + raise RuntimeError(f"no planned SurfaceWorld route in {manifest_path}") + route = strata[0]["route"] + points = [tuple(float(value) / Q_PER_METRE for value in item["position_q"]) + for item in route] + lengths = [math.dist(a, b) for a, b in zip(points, points[1:])] + total = sum(lengths) + if total <= 1.0e-6: + raise RuntimeError(f"degenerate planned route in {manifest_path}") + + def at(distance: float) -> tuple[float, float, float]: + remaining = max(0.0, min(total, distance)) + for index, (a, b, length) in enumerate(zip(points, points[1:], lengths)): + if remaining <= length or index == len(lengths) - 1: + if length <= 1.0e-9: + return b + t = remaining / length + return tuple(a[axis] + (b[axis] - a[axis]) * t for axis in range(3)) + remaining -= length + return points[-1] + + center = at(total * 0.5) + before, after = at(total * 0.5 - 1.0), at(total * 0.5 + 1.0) + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-9: + raise RuntimeError(f"degenerate route tangent in {manifest_path}") + return center, (dx / length, dy / length, 0.0) + + +def camera_angles(camera, target) -> tuple[float, float]: + 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 point_toward(camera, target) -> tuple[float, ...]: + yaw, pitch = camera_angles(camera, target) + return (*camera, yaw, pitch) + + +def stamp(layout: dict, stable_id: str) -> dict: + for record in layout.get("stamps", []): + if record.get("stable_id") == stable_id: + return record + raise RuntimeError(f"missing resolved stamp {stable_id}") + + +def make_views(name: str, manifest_path: Path, layout_path: Path): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + center, tangent = route_frame(manifest_path) + tx, ty, _ = tangent + nx, ny = -ty, tx + base_height = manifest["recipe"]["surface_profile"]["h0_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = stamp(layout, "liminal/oversized-familiar-monolith-v1") + sx, sy, _ = (value / 1.0e6 for value in monolith["position_um"]) + floor = monolith["floor_um"] / 1.0e6 + eye_camera = (sx - tx * 36.0, sy - ty * 36.0, floor + 1.6) + eye_target = (sx, sy, floor + 10.5) + wide_camera = (sx - tx * 42.0 - nx * 18.0, + sy - ty * 42.0 - ny * 18.0, floor + 42.0) + wide_target = (sx, sy, floor + 8.0) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 24), + "height_center": floor, + "height_range": 38.0, + } + if name == "periodicHills": + # Route points are capsule centers: +0.72 m places the view at 1.60 m above ground. + eye_camera = (center[0], center[1], center[2] + 0.72) + eye_target = (center[0] - tx * 360.0, center[1] - ty * 360.0, + center[2] + 0.72) + wide_camera = (center[0] - tx * 36.0 - nx * 28.0, + center[1] - ty * 36.0 - ny * 28.0, center[2] + 30.0) + wide_target = (center[0] - tx * 310.0, center[1] - ty * 310.0, + center[2] + 0.72) + return { + "eye": (eye_camera, eye_target, 20), + "wide": (wide_camera, wide_target, 28), + "height_center": base_height, + "height_range": 6.0, + } + if name == "road-in-clouds": + deck = stamp(layout,"liminal/road-clouds-v2/deck/000") + path_um = deck.get("sweep_path_um", []) + if len(path_um) < 2: + raise RuntimeError("road layout has no resolved continuous swept path") + points = [tuple(value / 1.0e6 for value in point) for point in path_um] + half_thickness = deck["half_extents_um"][2] / 1.0e6 + top = lambda point: point[2] + half_thickness + index = max(1, len(points) // 12) + camera_dx = points[index + 1][0] - points[index - 1][0] + camera_dy = points[index + 1][1] - points[index - 1][1] + camera_tangent_length = math.hypot(camera_dx, camera_dy) + camera_tx, camera_ty = (camera_dx / camera_tangent_length, + camera_dy / camera_tangent_length) + camera_nx, camera_ny = -camera_ty, camera_tx + half_width = deck["half_extents_um"][1] / 1.0e6 + eye_target_index = min(len(points) - 1, index + 25) + eye_camera = (points[index][0] + camera_nx * (half_width + 2.0), + points[index][1] + camera_ny * (half_width + 2.0), + top(points[index]) + 1.6) + eye_target = (points[eye_target_index][0] + camera_nx * (half_width - 0.4), + points[eye_target_index][1] + camera_ny * (half_width - 0.4), + top(points[eye_target_index]) + 0.3) + middle = len(points) // 2 + dx = points[middle + 1][0] - points[middle - 1][0] + dy = points[middle + 1][1] - points[middle - 1][1] + tangent_length = math.hypot(dx, dy) + tx, ty = dx / tangent_length, dy / tangent_length + nx, ny = -ty, tx + wide_target_index = min(len(points) - 1, middle + 30) + wide_camera = (points[middle][0] - tx * 35.0 + nx * 30.0, + points[middle][1] - ty * 35.0 + ny * 30.0, + top(points[middle]) + 25.0) + wide_target = (points[wide_target_index][0], points[wide_target_index][1], + top(points[wide_target_index]) - 5.0) + cloud_camera = (points[middle][0] - tx * 18.0 + nx * 12.0, + points[middle][1] - ty * 18.0 + ny * 12.0, + base_height + 1.6) + cloud_target = (points[middle][0] + tx * 8.0, + points[middle][1] + ty * 8.0, + points[middle][2] - half_thickness * 0.35) + return { + "eye": (eye_camera, eye_target, 3), + "wide": (wide_camera, wide_target, 3), + "cloud-up": (cloud_camera, cloud_target, 3), + "height_center": base_height + 23.0, + "height_range": 60.0, + "road_deck": top(points[middle]), + "road_width": 2.0 * half_width, + } + if name == "pillar-grid": + pillars = [row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("liminal/horizon-pillar-grid-v1/pillar/")] + if len(pillars) < 9: + raise RuntimeError("pillar-grid layout has too few resolved supports") + xs = [row["position_um"][0] / 1.0e6 for row in pillars] + ys = [row["position_um"][1] / 1.0e6 for row in pillars] + floor = min((row["position_um"][2] - row["half_extents_um"][2]) / 1.0e6 + for row in pillars) + cx, cy = (min(xs) + max(xs)) * 0.5, (min(ys) + max(ys)) * 0.5 + eye_camera = (min(xs) - 78.0, cy, floor + 1.6) + eye_target = (max(xs) + 90.0, cy, floor + 1.6) + wide_camera = (cx - 280.0, cy - 420.0, floor + 230.0) + wide_target = (cx, cy, floor + 6.0) + return { + "eye": (eye_camera, eye_target, 3), + "wide": (wide_camera, wide_target, 3), + "height_center": floor + 12.0, + "height_range": 42.0, + } + raise RuntimeError(f"no capture framing for fixture {name}") + + +def headless_command(binary: Path, fixture: Path, camera, mesh: Path, + manifest: Path, layout: Path, workers: int, + clip_radius: int, *, hash_tiles: bool = False, + audit_road: bool = False, max_level: int = 0, + far_lods: bool = False, + max_clip_override: int | None = None) -> list[object]: + max_clip_level = (max_clip_override if max_clip_override is not None else + 8 if far_lods else max_level) + command: list[object] = [binary, fixture, f"--workers={workers}", + "--seed=0", "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={clip_radius}", + f"--max-clip-level={max_clip_level}", + f"--max-level={max_level}", "--render-distance-chunks=0", + f"--camera={fmt(point_toward(camera, (camera[0], camera[1] + 1.0, camera[2])))}", + f"--mesh-export={mesh}", f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if hash_tiles: + command.append("--stream-hash-tiles") + if audit_road: + command.append("--audit-liminal-road-walk") + return command + + +def determinism_digest(output: str, manifest_path: Path, + layout_path: Path) -> tuple[str, str, str]: + tile_hashes = sorted(line for line in output.splitlines() + if line.startswith("[PipelineTileHash] ")) + if not manifest_path.is_file() or not layout_path.is_file() or not tile_hashes: + raise RuntimeError("determinism run omitted manifest, layout or per-tile hashes") + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + manifest_digest = (manifest["content_hash"],manifest["recipe"]["content_hash"], + manifest["plan"]["content_hash"]) + return ("|".join(manifest_digest),layout["stable_identity"],"\n".join(tile_hashes)) + + +def run_determinism(name: str, fixture: Path, view, *, binaries: dict[str, Path], + out: Path, env: dict[str, str], max_level: int = 0, + far_lods: bool = False, max_clip_override: int | None = None) -> None: + camera, _, _ = view["eye"] + clip_radius = 1 + max_clip = 0 + baseline = None + cells = 0 + for compiler, workers in ((compiler, workers) + for compiler in ("clang", "gcc") + for workers in (1, 8, 12)): + tag = f"{name}-{compiler}-w{workers}" + run_dir = out / "determinism" / tag + run_dir.mkdir(parents=True, exist_ok=True) + mesh = run_dir / "feature.vfmesh" + manifest = run_dir / "manifest.json" + layout = run_dir / "layout.json" + command = headless_command(binaries[compiler], fixture,camera,mesh,manifest, + layout,workers,max_clip,hash_tiles=True,max_level=max_level, + far_lods=far_lods,max_clip_override=max_clip_override) + output = run_step(tag,command,out/"logs"/f"determinism-{tag}.log", + env=env,stamped=True) + digest = determinism_digest(output,manifest,layout) + if baseline is None: + baseline = digest + elif digest != baseline: + raise RuntimeError(f"{name} diverged at {compiler} W{workers}; see determinism logs") + cells += 1 + print(f"[L143Determinism] fixture={name} compiler_worker_cells={cells} identical=yes status=PASS", + flush=True) + + +def export_and_capture(name: str, fixture: Path, views: dict, *, + headless: Path, renderer: Path, out: Path, + artifact_dir: Path, env: dict[str, str]) -> None: + view_names = ("eye", "wide", "cloud-up") if name == "road-in-clouds" else ("eye", "wide") + for view_name in view_names: + camera, target, clip_radius = views[view_name] + clip_radius = min(clip_radius,3) + stem = f"{name}-{view_name}" + mesh = out / "capture-meshes" / f"{stem}.vfmesh" + manifest = out / "capture-manifests" / f"{stem}.json" + layout = out / "capture-layouts" / f"{stem}.json" + png = out / "capture-png" / f"{stem}.png" + image = artifact_dir / f"{stem}.jpg" + for path in (mesh,manifest,layout,png,image): + path.parent.mkdir(parents=True,exist_ok=True) + command = headless_command(headless,fixture,camera,mesh,manifest,layout,12, + clip_radius,max_level=-1,far_lods=True, + max_clip_override=2 if name == "road-in-clouds" else None) + output = run_step(f"capture-{stem}-export",command, + out/"logs"/f"capture-{stem}-export.log",env=env,stamped=True) + if not mesh.is_file() or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem} produced an empty mesh") + yaw, pitch = camera_angles(camera,target) + height_center = views["height_center"] + height_range = views["height_range"] + if name == "road-in-clouds": + fog_start,fog_end,fog_color=(24,260,"0.88,0.93,0.95") + elif name == "pillar-grid": + fog_start,fog_end,fog_color=220,1250,"0.82,0.88,0.91" + elif name == "periodicHills": + fog_start,fog_end,fog_color=210,1000,"0.78,0.84,0.88" + else: + fog_start,fog_end,fog_color=30,105,FOG_COLOR + renderer_command = [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=on","--shade=readable", + "--headlamp=off","--height-tint=on",f"--height-center-m={height_center:.6f}", + f"--height-range-m={height_range:.6f}","--light-direction=-0.42,-0.58,0.70", + "--fog=on",f"--fog-start-m={fog_start}",f"--fog-end-m={fog_end}", + f"--fog-color={fog_color}"] + run_step(f"capture-{stem}-render",renderer_command, + out/"logs"/f"capture-{stem}-render.log",env=env,stamped=True) + run_step(f"capture-{stem}-jpeg",["ffmpeg","-nostdin","-hide_banner","-loglevel", + "error","-y","-i",png,"-frames:v","1","-q:v","4",image], + out/"logs"/f"capture-{stem}-jpeg.log",env=env) + quality = run_step(f"capture-{stem}-quality", + [sys.executable,ROOT/"Standalone/Tools/verify/capture_quality.py",image], + out/"logs"/f"capture-{stem}-quality.log",env=env) + if "[CaptureQuality]" not in quality or not image.is_file() \ + or image.stat().st_size > 300_000: + raise RuntimeError(f"{stem} capture failed quality or size checks") + eye_height = "1.600m" if view_name in ("eye", "cloud-up") else "wide" + print(f"[L143Capture] fixture={name} view={view_name} eye_height={eye_height} " + f"camera_m=({fmt(camera)}) target_m=({fmt(target)}) bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS",flush=True) + + +def run_road_walk_audit(fixture: Path, view, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + camera = view["eye"][0] + run_dir = out / "road-walk-audit" + run_dir.mkdir(parents=True,exist_ok=True) + output = run_step("road-walk-audit",headless_command(headless,fixture,camera, + run_dir/"audit.vfmesh",run_dir/"manifest.json",run_dir/"layout.json",12,1, + audit_road=True),out/"logs"/"road-walk-audit.log",env=env,stamped=True) + if not re.search(r"\[LiminalRoadWalkAudit\].*status=PASS",output): + raise RuntimeError("raised road failed the Core capsule walk audit") + + +def run_road_short_negative_control(fixture: Path, view, *, headless: Path, + out: Path, env: dict[str, str]) -> None: + camera = view["eye"][0] + run_dir = out / "road-short-negative-control" + run_dir.mkdir(parents=True,exist_ok=True) + output = run_step("road-short-negative-control", + headless_command(headless,fixture,camera,run_dir/"control.vfmesh", + run_dir/"manifest.json",run_dir/"layout.json",12,1,audit_road=True), + out/"logs"/"road-short-negative-control.log",env=env,stamped=True, + expected_exit=14) + match = re.search(r"\[LiminalRoadWalkAudit\].*path_length_m=([0-9.]+).*status=FAIL",output) + if not match or float(match.group(1)) >= 300.0: + raise RuntimeError("short-road negative control did not falsify the length gate") + print(f"[L143RoadNegativeControl] path_length_m={match.group(1)} " + "expected=FAIL status=PASS",flush=True) + + +def retain_unchanged_captures(artifact_dir: Path) -> None: + reference_dir = Path(__file__).resolve().parents[1] / "Linux142" / "captures" + for name in ("flatField-monolith", "periodicHills"): + for view in ("eye", "wide"): + filename = f"{name}-{view}.jpg" + source, destination = reference_dir / filename, artifact_dir / filename + if not source.is_file(): + raise RuntimeError(f"missing L142 reference capture {source}") + shutil.copy2(source,destination) + if sha256(source) != sha256(destination): + raise RuntimeError(f"unchanged reference capture copy differs: {filename}") + print(f"[L143Capture] fixture={name} view={view} retained_from=Linux142 " + f"sha256={sha256(destination)} status=PASS",flush=True) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT) + parser.add_argument("--artifact-dir", type=Path, default=CAPTURE_DEFAULT) + parser.add_argument("--headless-clang", type=Path, required=True) + parser.add_argument("--headless-gcc", type=Path, required=True) + parser.add_argument("--renderer", type=Path, required=True) + args = parser.parse_args() + + out = args.out.resolve() + artifact_dir = args.artifact_dir.resolve() + fixture_dir = out / "fixtures" + for directory in (out,fixture_dir,artifact_dir): + directory.mkdir(parents=True,exist_ok=True) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(out) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT/"Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(out/"xdg-cache") + run_step("build-fixtures",[sys.executable, + ROOT/"Standalone/Research/WorldAssemblerM3/Linux143/BuildL143Fixtures.py", + f"--out={fixture_dir}"],out/"logs"/"build-fixtures.log",env=env) + + binaries = {"clang":args.headless_clang.resolve(),"gcc":args.headless_gcc.resolve()} + fixtures = { + "flatField-monolith":fixture_dir/"liminal-flatField-monolith.json", + "periodicHills":fixture_dir/"liminal-periodicHills.json", + "road-in-clouds":fixture_dir/"liminal-road-in-clouds.json", + "pillar-grid":fixture_dir/"liminal-pillar-grid.json", + } + probed = {} + for name,fixture in fixtures.items(): + probe_dir=out/"plan-probes"/name + probe_dir.mkdir(parents=True,exist_ok=True) + camera=(0.0,0.0,-500.0) + output=run_step(f"plan-probe-{name}",headless_command(binaries["clang"],fixture, + camera,probe_dir/"probe.vfmesh",probe_dir/"manifest.json", + probe_dir/"layout.json",12,1),out/"logs"/f"plan-probe-{name}.log", + env=env,stamped=True) + if "[WorldAssemblerFullManifest]" not in output: + raise RuntimeError(f"{name} probe omitted its full plan manifest") + probed[name]=make_views(name,probe_dir/"manifest.json",probe_dir/"layout.json") + + for name,fixture in fixtures.items(): + run_determinism(name,fixture,probed[name],binaries=binaries,out=out,env=env) + run_determinism("pillar-grid-far-lod",fixtures["pillar-grid"],probed["pillar-grid"], + binaries=binaries,out=out,env=env,max_level=-1,far_lods=True,max_clip_override=8) + run_road_walk_audit(fixtures["road-in-clouds"],probed["road-in-clouds"], + headless=binaries["clang"],out=out,env=env) + run_road_short_negative_control(fixture_dir/"liminal-road-short-control.json", + probed["road-in-clouds"],headless=binaries["clang"],out=out,env=env) + retain_unchanged_captures(artifact_dir) + for name in ("road-in-clouds", "pillar-grid"): + fixture=fixtures[name] + export_and_capture(name,fixture,probed[name],headless=binaries["clang"], + renderer=args.renderer.resolve(),out=out,artifact_dir=artifact_dir,env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L143Capture] status=FAIL error={error}",file=sys.stderr,flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux143/REPORT.md new file mode 100644 index 0000000..cd177f6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux143/REPORT.md @@ -0,0 +1,64 @@ +# L143 — liminal polish + +## Captures + +### Road + +Eye-height: + +![Road deck at eye height](captures/road-in-clouds-eye.jpg) + +Wide: + +![Road deck and supports, wide view](captures/road-in-clouds-wide.jpg) + +Looking up from the cloud floor: + +![Road deck underside from the cloud floor](captures/road-in-clouds-cloud-up.jpg) + +### Pillar grid + +Eye-height: + +![Pillar grid at eye height](captures/pillar-grid-eye.jpg) + +Wide: + +![Pillar grid, wide view](captures/pillar-grid-wide.jpg) + +### Kept from L142 + +These four captures are byte-identical to L142. + +![Monolith, eye view](captures/flatField-monolith-eye.jpg) + +![Monolith, wide view](captures/flatField-monolith-wide.jpg) + +![Periodic hills, eye view](captures/periodicHills-eye.jpg) + +![Periodic hills, wide view](captures/periodicHills-wide.jpg) + +## Result + +The road is one continuous swept deck, and the distant pillar silhouettes remain complete and consistent. The monolith and periodic hills were retained unchanged. + +## Changes and causes + +- The road edge broke where independently capped deck segments overlapped. The road now resolves to one swept-deck stamp with a shared cubic-Hermite centerline and continuous cross-section; the centerline is sampled at 1 m spacing (361 points). The 8 m deck is 376.829 m long and retains 17 support posts. The sweep path is serialized in stamp-vocabulary V5. +- Pillars disappeared or narrowed when the coarse marching-cubes lattice skipped their cross-section. The pillar stamp's interval proof is unsupported, so it conservatively kept tiles but did not protect the mesh from undersampling. At LOD4 the sample spacing is 32 voxels (8 m), already greater than the 5.5 m pillar radius; spacing rises to 64 and 128 voxels at LOD5 and LOD6. The shared meshing path now emits deterministic 24-sided capped-cylinder proxies for regular `fillPillar` stamps once the sample step exceeds their radius or half-height. The same rule applies outside the liminal fixture. The radial approximation error for this fixture is about 4.7 cm, below one 25 cm voxel. + +## Measurements + +- Road walk audit covered the full 376.829 m route at 1,081 surface stations, with 68,103 capsule samples and 7,096 support samples: 0 blocked, 0 unsupported, 0 grade failures, and 0 surface misses. Measured maximum grade was 8.512° against a 15° limit; deck width was 8 m against a 3 m minimum. `road-short-negative-control` failed the walk audit as expected at 210.351 m. +- Determinism covered five fixtures—monolith, periodic hills, road, pillar grid, and far-LOD pillar grid—across Clang/GCC and W1/W8/W12 (six compiler/worker cells per fixture). All five reported identical outputs. +- Clang and GCC builds passed on source stamp `1baa3a711f7f96df2e70fc93579f41ad0b0211eb42fcb51dabf522e33d888877`. The capture runner and capture-quality checks passed for all requested views. +- Fast tier passed in 292.3 s. Its pinned L130-v227 reach-unit owner hashes match exactly: 12/12 rows for each owner fixture, with W1 and W12 identical. Historical L46/L53 hash comparisons remain diagnostic-only and are not the current owner-hash gate. + +## Checks and limits + +- Passed: road audit and short-road negative control; five-fixture Clang/GCC determinism; Clang and GCC builds; capture quality; fast tier; `git diff --check`. +- Not run: Unreal build (no Unreal `Source/` files changed) and L80 performance timing (this round made no performance claim). +- The coarse proxy is limited to regular `fillPillar` stamps; irregular pillars and other stamp kinds continue through their existing SDF path. The proxy was exercised at LOD4–6 in the pillar-grid captures. +- Unreal `Source/` files changed: none. Changed standalone source files: `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`, `Standalone/Core/src/ResolvedLayoutInternal.h`, `Standalone/Core/src/ShapeWorldInternal.h`, `Standalone/Core/src/VoxelForgeCore.cpp`, `Standalone/Source/StreamBenchmarkHeadless.cpp`, `Standalone/Source/StreamBenchmarkPipeline.h`, and `Standalone/Source/WorldAssemblyPrototype.h`. + +Detailed logs are in `Saved/Linux/l143/`; the capture and audit transcript is `Saved/Linux/l143/logs/capture-runner.log`, the walk audit is `Saved/Linux/l143/logs/road-walk-audit.log`, and the fast-tier summary is `Saved/Linux/l143/fast-summary.json`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..13eb05226c68fa203b35cb08c2c8e4b0d13fc301 GIT binary patch literal 26523 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/flatField-monolith-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3975e8ae20d5aff093f2c6b6a46c1988bb15d244 GIT binary patch literal 23358 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 BeH{P* literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92ba34ac5a8a18214eabea40811f3d28c32b284d GIT binary patch literal 25065 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 b8d^9dSVcWNEtAsrTKpWq&bx? literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/periodicHills-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c066a5fcf6028b8c2de48ce7f842f6d8bffc31d GIT binary patch literal 60906 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/pillar-grid-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/pillar-grid-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94bc81e0cdcd9cc7967d00f093ec3c6d4ead00f4 GIT binary patch literal 74691 zcmeFYcT`hb_cj`jy?|1bCZYlYQX;(wSm+=iAOr#g1rlmNN&H@HP=iiWgMRgcuABy*M|GMC z^aynLnlAA5Kb`sa1Rp3yS?=avVc-xt)?r<4$RxBqJY=eG+~jDLOl`p+djh~n?_+b_8&UUCZkefj^- z<7sNt6DB6rcmX6T@_NXmD5SRuqtt~0+3#||PpA2m&Kdq>k{+C&xOwKi>^acy zfjMXNU^fb$FHxr#+JElPiChrd^S^f8a3<^=u|Nep15n<2{4@k?ZZ@MDKd7nxyL;zMXD`m*fX~1J(zIF{qVB{PJKrjrtYJ}# zl}xbx;m4W6Wc%Fw>woT`Pk5fd-VYD&=bFBoOJTkln1QC2&RmfF@u7p_lp;uht)#Wm zpwuX(xwEvVD1TnT7zJx>dob>+wJD_ z2fawXblA`ANk5v;J*DSi;`$*04hJON_wZ2aqMnCm?%kCf$*SIrV&ctzUJl>iJUb5_ z`K%!qzIo@)8_=c4KoeHRv9`r|+_6AwvzPiX=`VDGbd`!Bb{{amKv$cUMdZSj=5_;# z%C!&XpE%G82YhO$B{xzLHSBlmM?!efys={D1iwd2B=?1R11YweVpEUJ89?^(dMu1E0*W z!Y+$a{*VMdJSDNOG+X>h?Kw@)^=Hh>whur zcw4SDw|x6lk6H)oTBp4Tog0k+RZW8kZ^I=gq5soEAD|C;Kei?k5dB} zPRpA$phMgZ)AW#OTHsG^AJ{%^24$8~MXnis`1D~z0Hk>;Koi6apI2FZq(mp~!7HI>70A~;TmYINw;jB*$MB^mr#sv~Ja9DR+o^b>8u29w4CR1QoX_}lS^?@(WL9mc zG-Bl$c}LtpHu+{LhsKm$ceL+d2)8@!V*K+6TH^yvkIhvumxeW;ZNc8tseL^|Vpp2h z^UWic$Yys>pD8NjjV4#rTN%L9l5Ye3q;Kwjm%Xgy-@=K`k4Rr&<-KU$-yKL0u1C@O z$>)eH7k51P1)>8&6>G9d5*>~mH-M+ix6-Z4z&-{>D_MkWQbxg-=l%8@+@vmiceeog z#T}lSP8~DNzQ1<47l=%zC}oL=WZtC@&t%EB+&=dKqzR(^J|wRmcJJ#|`W8sgt5LsT zNam;fLy@?LucJ#=Cl@9E!Z!Sffd%CgMHQ>H?Qtoo$wbq99U)UtM+}Jk`RTOuJ@}kT z&fb+%<3Yi%>a&~lWJtFPtJg0$c%C-?k^2n$vTQF^?;M0A3y#>(Hnqk)&L%^Zih0=@wPvV2C?BbDX>M33njZ($jBLC-(!^>TTf* z)m-ry*$@LmObNB2KLg^@%6KMV(2ULnEbl4|BrZ3F zP;crAY*@(DtTD^+R*@uEEg}kp;1UgVBe27ZvMJVu=$X}~IkfO>l6hN_uSU=8I_nsU z<<5MNRa|_G!4emjz1UDGzPhlL0zDTPT~dDStsgFBYN9#(0`P30p^O6Oa*}Ub0SEu4 zXtt6M4a9!9*NRT{MI*Q&M=fve^WgvgTR02p(u3(2`Or#XZ$~`HnG91Z3I#<5a{vI(Tp7 z50L@osAm;c1sEk!=#Hg)bXd-hJhu1Ho~SPm$N`Q)di#jG^LwxAqwBEc&HIBrdHUy` zOhjN>!gPq~4k`TsBbr0y%*##G{_+l3g+Y2B zXm4X7Ma`Gn>OBlnnwdx*;zO~DB^Gb#cVY=W)hl)Fjyj<_p-G!yoe0tX`jTcVT?NvP zhcQ_HCl{V5<*$2A#P};o#6{Wi(#T7B%?%Q?KPY3~%xK!lRf+S+794W}h+)ywlPon` zf;7>w+McBgyy5{rWtThN~|N&+-t6>XP%@YL=Twt zw2tX%Xx?oTXr9P9%H)Q+5amS5yy#0o~Lj@j&ZB#Zp*894%bL8G($ zVKb%AatGwt92LArQ+>+}G`B|*uYqM7d;0vx2y1b=_SeO>GIGb+^OrL?8sZG3^W(~? z4f}tA61yOfr1H$3Hk4zY-GCrGi71RXX`|4qwU_42F4w87bX(OmJ-rAn{>yVCu1c;8 zwZj42ka%f1pSv-<$g2h(mEZhr_1vU8pZ9R0lBK9(z91St0Df!!J7Rn}O=z`W^r$kq z15cId{fdhgh=CIOY)#m{%Lf*2eHc)IBBk-qAr3V&9M9YIbDa-*dJ~OH22*G@^nbJf zq2L;b%s$AB!->YuH(j+7?wL4V6H`%UncUHu9b&A^ zhAv6Di7(d&q;G}{;ESoe z)PCF$|0X^;Rn;I#t)KoO)5vXmh3HPi;2~$*)8sj2iPEbN4d(luTg)GY9E5eu5QG+& z-$}I87>sQiR;;JzBN4HfSlhv0Ag&Ik(jI!wuvc8g0yi#P`W=G*nQXqm7lJRX=;uwc zyizT?xW=)nZo+(OvKDxgoJTr_{>?1%QXd97`y0ERH>u2VU#F10*B5Z8uF) zi&%nJhQp}Eew3JHee%75P(gTAFixVgaVOf)D3UXF65>nu^g1d6(fWRy`t7{O*tW2Z z+TLNK;jIr_u0#7018xKn&X$=Gx?ELv9~IVA@y?1H3z2#9`~Vk$)W5N!T01A4WHPb; zR0(9#33$mQX>1;)YsS@AuUAKhljRw@R(W9CMV_ilRDn*bRthl=>@&jRcjWk;Rro~De z%Mw09V%&n?uvA%|mE#AOH-~dPsIEij{oIp zb}{7x@K8oSr9|VV zvnFU`a_9s}dY~G5wX6nP^O+kx13i^ORnT**z7XlK?7$&I%UnjSF1}HD-liX@Lhhsn z(gGnftnLNa2A56J56=@pQ$E27zC4#z^M)aY^oZq4^P%~HN0k6FmHOiv+wS#Io_l`1 zEEz0S<>y}RQ7y=RSHMSpd0^A5dkW~@dF{iEeMrZXwA_ZBF4){YrF$#ZiQD(EoS`sT zyj;g%7{{H~*#s{Y(|67xE*8lj);>5SJ^IG-qzigIIligqN8SzdZ;`02N=0RVOT~m* zAT2>6nn3GPBfp$R+wE)%G+pO|bl=P!ibw5IMh|!k+263+brPt#acDU=ff6?ou?htj*)xvVs>wN{SCEhloK_`7yfA1-OIisPmfvee2UB2`b1phMpe1lxXRE`N==gcV&#`Y zTls1^haN0>OrJge-#YDL!}vLSe;eFr!d+bBd=H3;GxBn&)G%JCG&9oYvh)4_x^jh&1=*|{EFU(X+rd76MV|FUdGZv(vgr%013ARSa%`so;yJyJNXW@5laeq2e zS<}IAw}{#Zj48ykYb^F|@6gq*%Q|buWKs7ln11^9w|aVWf+5Fm`UlMZud(epNai+u z%4xaV^u6(N4F{K{w6?=qu@Q{QSMY`|tj|((C47y*Jn#{M$&^5nW25|l&5P9BL&Guz~a zLK1d6x$gAd=L2`1oX|flqy(fl68g5Tgw@fFCFC6{i(-^)NPff(M6Z6eK>M(ooRH=K z&C8L-=n6e%C-a1q^*(60c25UtS>jc)$c96kPD_KHAJ6rG-_CqYQ^~~I4@9w1amKA9 zygP#~9wwiLr&1EqubWc?9n4Hj7(&iybeNmEpPS{Fa>eyG8B1W1FfK!@qPxG}f5x4>bPsg9)uWQx6i7v^T z7A1}Cb-~uzQ+Gsmhy{cjkn_H=DcOC~LAtRJadf}P!e@otm}lw^VyzcZt^7{e0bO0+ z=ay1dyL-h7*gd%VY=#;qjZn!H+O5fcqe?0YB8b*+^O}rv;~qbnRg&hL{XMZih;m;-scx6-1F*Feoy^JJ{<~t%gUXD zvl8e%A%7tgySd!yO+7=AaDCn%1Bb2PZ&#B(`Yh!fUD%_{?DXx7?Zrpn%NJ^*kMWMZ zMY{6`W0gT*_OllF&$&_c;gKo9OQP9x^K_`{3>+~tn;@*SFxGhyy{AXAx9gs9>2Zpk z4zlz?bJIIn&o1Ul`XYaUDvApa_*eHiH?)z6@!Iv8sywIbeAfdhCnIw^bjhREY6NuX z`YgiqD37dz(la&nC>Us)=KL!%v^AY|17StKrO@9n)(^piZvj$-%mj`nBk+)*{=-4n zYvd0~2FpIng^$mcj+PAHIc?i7P<02UL~(E-tQT*-`~9w0={4@(k!%@$*d7|4{5$VE z<+3nOA9-OezkK=6JUV&y{F3xK%R!}VRJohy+Ww_&A!`yc_bMz&T0xq+YD3Gm(KBe{ zc~yvy6>?9yYO$P&`MSD}3gl%=2o(@P$pgo9jEK6Y1X`+ZP85G`AiR~>FBbb5C$S0n z*1)lVfJOXl*gzKGMWpWE3D<&T?!-I0YXwe%hdi0!CFT4Jgm)Gd;_@2)n&{qALLcJM zLHnYo9M)@S7~em8Md>{0BRv%Jt9Zi=VBZ%8$r-T@m{WG`@wUa7-}lE%wkH%FZXw zzr_!y*;p?0#r((Je)9*4z8H{1pU18TFn)$*ojVw+iy><4=G$`;rCH0=Z?)~+;`TDE zn#z;PXgXdo8xA^st&qm1)77XITbAbIrO$SBRL5i&h~o0DyQ@8IjTbKrA>i~2o4y%x z5CqHH^0*9F%ZehFdbEK+2ZPT zc=p9#pr=cSY*sL@i0de_!1{RsQFl{b1z z5>ov0*+Nlwho$8c>(e@+wd3AfF!D4qlI*{w=qsW2gqEWL|EJ+G~C!WLDT%YLj?v%U7_LBVa|U}nkPsj&O7 z5w-X##7BvwD0Gt(QERMjaj7@M&3e|_Of$P@xp$4OlV2N&jTCrxoW8w%_Bba_c2z)= zKKPx?C7<)ZJhjfsYQg@@1(n+ry(~UypcMxWSb2J59u8$nkl;>%J1O;RYg=2xjRY7S zG+`1mhZmwvdhVlI9Jb^5?J=nXmTWUMXsu6qK1V~sF*ltZLqiP_Vc0f%DU{dy!{TrnJh9C0X(ksue06PB zc>Pr>7nkQp$V~i0z1KF-l5s!nv93zFxaS?rg_4`fHi%|D^Uq}H`G>@lIsFL|0j)f@ zX+$l^i%%1jmcs-q@g%Je%%oJdY_UFn>s86}rO^uM7nU7_biEk7VN~4-DNfStBq8Vg zQ3$tp6Am0cPZ>}m8-?HsAlvD0!CWhH0NqZD$j?24dWsAW)M?gx`PsSAe%x-dv0$pQ zyH#cPAi$a-1t7fBG>REQy( ziPZ+nsWok|rSXhhn}->7na>Lc818T65v;_K#2%aKMKx7C3@%iO{ z1BswJC!hvZ*B19LG;k~Pq%_p41nbaLnNLm^bP68Ww)-y*jMbOqd+Z<7);*1amxdd+ z91E)Xu>wXnlD`S22@pH48*?mLE9O_x+AB{*w|d{>D;#ZXr3DHFE-730p}Lx;Z0x1Du+B852iRrLX)-qY8`^n%_clkdC56u z+6~!6*m}9cVee`I9}vSmk#1alP`&o*;?VUnRMPuYCz~!`!`Qx=;w?UiQ%vb7>8GQu zwzkgwjDb+GXs3qsB}A*guneHhOrGHQ5r75G3Ei>@R~W{61bu1p)F*>6{9zbC;=ESm z@7cb9PiVi0zcG2GpfDz!a|Bquyll0=Pux!>^C50|lJBzSCJ-;ZzgRZ+1(1VfPZQmG zcYgYr3a-+Pq$zhv05>U-M`_EmhD!nQ`Do03bV4TkTx@a*YD@K?d2VAyVy>{p@`yx^}9@&~*Hc;{eJnZ;xfYXfax zKxJl-G{gx%v=hD*plzWo$B-vU6`E8q-9LxlSu;A#^dT#Zu2EI4SIUt3eX4HF5ECj& zi(R`{+jOJyyaSkUb=Tb+(G?4Us*;x)7qQ5?8(KYUY{l0{C3zYd4AlRskPbJwJj2&J ziy#H0!BWc?TB6A*?&F~=Js!FnCQrsod#{w5Y;*(+&NFJeX{zMyR5ad^4v2}PP3%mo zP9cF`m~5(XE6?^kYhpY&@La1{@)JJ4IkM^zs*b3b*g{pF5yfyW%?>a0D(`=UFFqGV zSl7POF$Ml1s(~2r>aU^5Jixks{C~|O!Y2K#LT&bqCM0(AUfUEo+pK;Y@li%Yg!Q-G z_?`96Y*`jf{;c;|FB6N;ebszkGE_lfDf`^QY5l*n;NBEymzLO*fz#*8egZxB|ffci7 zb*UlhvN&)C+NpN5j+-wTT_3P`S|rZdQ0_u4>Fa<>^|RBFvTIdC;W;as3R-$b zB)TJATDDV{eu1=-Ej7z+g@&R>(aC6jJVU9Q#WLrrPMKH4B`+xTSCSCmu)u4{@N?6~ zsjk>_QX|OLsNZGW&4q)z6q`PTalMq*!28a4xjGnf7iU>38brb_$guE{eu4NAJysS~ zIoDkyk_0QjR)VJAPYCbHVolHB!-lgz2_r{7F>WrV2SVE(ngYD{x%&Pzseh}h8c;_v z4FZ1%V1E{tY^yJb@IR)@Cm3ix#$J}N(-&%0x4Vb z`lbZhz{%2cDsnQ%3x7h7Pm_j(S7R4kf-$CAbQ{eA)4aoCWx;P%fQtVPV8$3VL9L=HyDq`0JTn zH<=!)@Q>_FV}5lUT05@a3qH0;{LIykE|j(Pz3yD%(qe8EE$%h$JtVteV`33rL!WqW zAo6|pCvF@n0e(ho-%Ld40{mWxsMvQv)H#-``nJ-M%4tS5# z7%izBK;2V@?iE0VGdU=f<)Jqw*|9ni8b2rL9vaoqHxYk}}YzAWOjg#Ql z69q&;y%_$#j!)?M|H|!=uF?xQ15M_igq;;rzijVqDA^*f5wUNYP#j^O%@e@>9)Gj= zvScEkSgiq`V_7!(Lo3YA9XE3HzNz8SIUx5DYTJ7$f7^=RFwYH1QTqMk+STCi;mp=e zf!_z6J`u(=)$_b6mF4Y4uk1ws0=Yq|)Dm(cke0}KWhWu)4F?_5*_-3X62FCthfb^H&)IouN!K5M=cZA=KxZD>PHv!i=11FZ&bdAM z#&>QnMoH>n!9(rE#_5|wuj=C`ECp&F-as^+Icr%Df@A<4mcK93tIH3-z;P049adKA zQDtAhKYN()s!d`aZ#wTgV|2#EjlOLzcWOcl;0lI`Vf{*F*D5wwG%Z}OAWh@%8&ypt zAV(6z>z+yg)e&=xeST~YtiPTbErO1Rtsx;cm9IpvDtbKXFnh#rgfxoQKcw6o5UuUY z>s&&vu~fYdtQ9-3e?9!<{%nTa*6US^Ro{!At~CSTMAmfUojkKtWzl?_Wx1xln1|;% zkKM!c*h{Dlg$}e`E4%Uf>R$s=`d?u`VYaSSS-@|+euOh@g)H+J|CQmH5lR}kMKnH^ z%4GCeX+Fv$EB;oi-N*w8=r7RwWLM>76?74xg^9?`^2xd2HSq^|l(C5sM#$|b&(S>@ zTi`IhCpRFWk1px4*%Wlh7|IiYa+9;)$9!G@WX2~KNU5G#o*hInGT209QN1=8Rx65H zM=U=*Ea~)mk*bXxnC3NHn$%&n_CBzxSLv~HLQq$1~n^sTn-7G%kJ z5h~SAXZ=w76ArXY=0MsU?{fnU=gDz9tNs*D0B9^Q-EW^0bSJ5Q13w`js=-ef9Br!x z_yTtHP4Lbg%vLqi?|Nj;X9h`hmN;n&)f&NA0v{>S2+mfo*3Gh__q4~AkiA2&d(-j< zR0;A2%yqPrHN7u*fYgh+mIz2U^}1sCiA?~^`JElHp6BVnTJlODA2F##+N(!~!cp1= z58XdIRwD!g42M=1R7p8L<3{qb4PDB6ad9*qb#BcBC?TQenXn@;pRKZwj1=<4>FdNA zB%G>dw>mv75KNahNp|lA8X#$_xCfp_zd+|_KiZvSHo}p;w4)^NsSgc(d2B$(e?!j6 zfh=?KKqMeJHUF^&7< z8+V`StW6+C)L^yqKOB}U)%A@ElYvD&%4Bd4XH_#Fzyd|E9s)>=bd_=E<*~!1rmcA@ zWl2_LC-9PK(GWlgfkYE9WWT#{q8`>mLyaeY#%$BKqaJjpa`CBYT8%XoYSU_4yn?ev zSgIu}U8niV>e4K8$I+bACSm7IW@O)u+q{k%ZO031Ugd}?N zn-!k8Z&Oj-J`mO_UV`Xx4;>o}c)F@OR9P_;BM1-B0mN7Bo4>HObs7jEMobd@F@%Y; z#n^=ORG!9_Lb%dk{Y~&Q+5(|nQ6T~076STUlGg!kh;j$$b>X11&&u#p9$NE?VletoLh%d54 zMQ4Pq48XkP#2}X-NgH0vVkNC!+_&v^2iV4ZW_f9y98!L7an^U3K+vpJmNKf$pK;JR z-0X3!$b<~HpbYojnB$XM1+*%?eUu->sfEJxyuQs9Q#X77s5X${I>z}w8kMQ+F>EpJ zA7+qetr8qC?54G_aqgYns_#QnbI!T>gh#y<8Aa#$C>EaHj$ zq1m#^T05K=qgHWY#?@F(XF%^68ghI0diwj0CeqE)r|r4IzDfo~{k)NXHy%#XkgH8%)x%H=@|5?sL=7^2$qZvZ19 z4+v0J2m0FwESo`OE_v(`|MlgYtJL(}xqdD71d8*kk6ap1eg!dMH9e4M$mO5&@OKfc zoly0H>j>NnGZi~@DDPyx{|Z-zJyw;ydvE!N6?=!HQ?g;j&=OSJRkNZ_CU4!ics3Kd zQ>fDKRukVLx)CfkJrC?*&6#=8TT6x#yv+IhTToxciYprM(KvTUu2P3~@a z_t>)84t&jLO=eqR{3-0CN1q#Ssi0|#29PB?#Y}oux#mP`H;Q1^li_>lWH-xu(=fXyV;0Dam^!n+ z7*ODQwpz`>qdT!%Bv(Q5Yt#e^%>e0SoBFUT9jvH6pT4rQp)s{Y;sDd``tC0mj}&$g z&WK=WYf*`1O;0o7ytzYQ9;E3YH)<2fhjY_85-P8YZ&Z6&T$iakU{xWY*7L~7H%TEU+nvqf!VFEYVRS7Se-L>9b zez4fcV7H4$eDAWFztaTd{g>qiH5&qmAzJT{Yf4Jg{j-|SNx_4ieZ0JleeXUykk|eI zw_*75M{$ayol>J7Z(&#Two+)D$F(xMO3L&b%W5zY;zPkOGcV_otv&vgbf*AjYkbPg z+)*ZT$gaDA(DYHfd(Q45GkTH3jAn9|gQxTZvEPVK`M`)8vp#u!NlH;oFsn1$DA`ux zc@d1)<|u!1p`o4gHOQl*yU&r`L4YfAUqOWzlF z=Zs+4yt?uzmFmoAEbmC(4MkZS0ONoxYW=D45>G9@AMQeCsBM8opDsDq^2=NEq7paa zN7Mo;!ld{yDK&HPs8q-06w4v&5tpE?PkV}p{btWV7A2bgSxA7W6_D!<1V{vLOdQin z;T?q9>UTitoVi1P-{8$D_OqhdIMqjwoKUpD7ywzH#}s* ziW@zV{-GfjY0>$ljC4{I|0zMC9JP&^g5{1|OqInE*3!`eP@{M3$yQKST<_J)XRu6h zzVKH)Is`D!a(d8e^(-sHh&s#SosHm6*+Q{a0qhS)&6Rh=FZ094f=eHOtdEO%kK@d3 zatNxio?f?QhcMY^qrNX?#hl%=TTqArAZRBSQ#z`fY3*oFvnj9s0-qnlJDukjC|-D= zg+yxxR?@a0jk>e@fcc4p^r?uHTwf$j3|1CXw8rhDL_Z!P)OQZk#;-H2x;1Dj_Jd`B zlH>YQaRr;H8fU41)jxaZ%D7G;atc@--Cy>rSOfYt~_1e=QCXi=%Wd<&O*~~{8VIo0BGTF zM+XjVH$z^(pUCXiH#!4Ci4?Mb-?WAFw;;phXh&#Qh`~*T(hAH|ArXyl)s;+rBQQ#p z%5tI~NJ!pRDm}fhu_#Ibd#W%w@R{JQfns5tZK0-cb2X#N&In@5W0rH#uEldFVB zmBc3TI|INhw;_||TrF zT*aO!)p^^g(SpVv%OcP3-9|ZakA%Xq9uS~5kR5H0UOxLB3a$!$K*dr!B;p#KR&RZ28U3rL{tJi}G&n(MgOADi%?{K#a zm1lj!18yIA4E_Ld5&H#t5LWiQqVQg+kb2$s)fRA6v0EmW9HjgJnM-5Z_0D+l74%jl z$xCD)HNP&a7!vp{Hli#*2WiUf3vo_$sJLn)uTsNGUg!fz1o|at)-2){oMnq()w@pr zZag+M8^2C2D)X^r6ul)&t#q@1^meK_b1Y0`kqM)Rl_#h2MP7pbwk5DuXcjt^Q>Epk zp{7>csdFm5t#&ZPQcXg_qHDQVW(s|v6%*smC3r9h|5KSYebKgLusF7xf|t@UuKk-wU|*0)epHo7p4_5exDR4SSG&+ zC_i-I6YTA?zx@W-M&Yhry~xjnhZy}uKTzI;-WyMv*wXg&1>tWK0Wi}7e7D8>IEyQP#T=Mc6)sKJDFvOjOJqN4LdaN~-(ao=mD zt~=nR>L_mvI+qG$6W%441f*e>Zuom~0O|bjEiL>0>KB7HQn9=#arT{ol@UsulRnS{ zx+;}5fw`7C@1mbFa-zNw%mOM9dx0?>lN%p_lE>nB>+GeSp%Fhb-LPKxKzn9pXJ*vp zX3K-frl@hXu*gB)E13XN9EP4D@RsJs-10AN;tA(^;LfWZ%moKFW9kC`?$1f8J<4uzRiWXmSagSXjsNz@l_kbdZpN@wl7MS+0V% zZb&}wpU_L*qaz?4`)G3OW^9ce;mr2Dms1HE?6s4ahbhDc!|TUWR_5~U$LvHYwj_@D z#40wcCTA6!CsvnUH$bwJ3Ges7Kbp2sB0Gj$Lmj2DmV=W~c>oO|H`^>WB?(`0K@Ij{ zFemonQ|V%Di-^SW?+s=9Q|TDv@?RkJ5WfD&QRviRn+cw4rOSR)X`5{W^Kg4sU8dco zpxI{HVB7t{nA33W2;$*U_P23A9>FJSlwIW(*=h+AZXL6C3b{iqmvU^*q%-^*m$v3Hlbb5o9`Tt}l78}+E|Kv(mRYPBXV$I>rjg&mNiP2= zt)flYaSyffzyHAxGnhn%M{{*mp*Vsmazct}2ZW$gD3ujJe3 z0~Zff09GU~YCC5%=F|0&qBVf%&ZNwIpA|2)ib=D>q*HV@OU$)5rB>RAO>|kLTHqNy zIOAV!Yc80+GSHEa;g(-))QbV?KmWIC74jtxE18@y*=hBsO2vTHf~275i%K(=R92s8 zLP;4@^E`|aNK>qeyMt?n=f0F{`J*T+TaQ))CGU?=kGXY@B2)Xv2w&!ZftFUbnr0Md zCreOug@eOJ>4ry>Oosr8L;M2C@5e3n4p#g)WHab+c&8E{UmG=q5w3&gWWhdr`)OwJ zR5d3?#CYmo4eEf~*|NdA2_3SQMXB!zval&t`jg#D$Id`LB@K#vfm`I0#JiwEJFw4W zt&f-32Wz0|Eaq5SLp0MJ^>h{y?lj^fa$(v$nQHB&s;LK&LwK_#2h_6sN@b?cXwY9v z12bAC9fV8vHja1(D-RK%I!N*5??m891%A}=uBpioPd@4}qbmlu+OYOh9X~SPyHX%I ze07sn8y7j$@aXL1_}M0@+3B0y11;|QNe`c|7do-dL`EoSNj#Xu@AeuR1-R3~J6xYv zf^9`sHR~8x)JHNRg(5C_WU5q_w5jE%>OZV(fSS;+yoM3;oNRZN4W_{+>{W?C-6B92 z{-JAn?3_gv`MqV~AhVldLZw1Lz!Pf|uy=W&u%jOvy==gR(VH%_4_~4>q90e~+f^Fz zTuBNz31MG8*vJM|fzz0&CNgP*Os(oq)w#rv>FV6N_#$2fZ>gbyPSDneg*qOzs<~!8?@XrT z+Yik+q}49(sIz=XDzr)sU)1_k9XFxeS+P8_$X^I$^_@RkGS{azNlFut@Ds?M+j-4Z zsEsLD4pe)thD%8KWWcWy$5vjKToB`B_F^ta+c5O!U|se~z_877!JKIa0Gh`IM<9@}PUcB6P_U4EPl&c5;C#Hg-lOY={d63-KEm>fxQlP+e)tmUm4|^L6CK_O zH&CWlag_m2A*E3*^W}BvXYq!umR-vMUJ)U@o((+SJTIrBoCjB_^EqNCZ}=M z$cA7Su&PjWRCmAW_%{}Mpn4@DH!xf$5Ivkdij@Znkd6Zha3seSV6E@JPELM#3@W}B zNNq*$?OP_qzA=JPU)ZO-s6bs}SZd^uD;k}u@APdn&KzTkg2F1sqD|)xxsf?NHH);X zOWmPHSCTo4wNiWAB7_ws6TC;IZrRMH$x$)`m&X6PI@!lGpswp=6vIF!!KRb-q`W1 zv#a##3)rS*jCHiLRN4_*&YI~jGi0T_B+BiTDlN2U!tr|i?-FyMh>N^(ah$?QJ}&7x zR_6Y1Zn+rYb}DM0wf?nlvJnhhL`co5sOS}D^7qW`GN>onzd|sJLn5e3Bbq|ZAm2C} zi;XVl=}+1r6ui=3^w}x!y*wroR%9aK*c0Kakof6zn}lW!cR3v$5NI!ptyXE2i~;%a zB&M)PmFmGTlI1+{OZ?E7-Kso+4)UWF{G#>zYlR?WIV_orG{om8CCV*tt(dD?Xw=BG zE3SnkS+KhUayQ~Fal}gUAk)^*E=buwQFz=z^-KC9?UkD6}6Nc?T!2by{HJKczJ|B zYBf@3-)9_ohej=Fm#4dmIxgFLs{yry#^bmj1gP(MPte6$H6OGX-S4i~Xcp z=6%`-PdcNbtxRoRK0>u$L}=EF(n|2Xxp`>Gs^hw7Opt4tOqRXxVEMQ>)Twt@n70@V-`M2hrBiAcJzW_Mbh*C;aBvG?Lpa4iPKrGkHuIpI^o}WsY_o z3|(KuL}85n#OPZ=xpmMLnM|JAH=R@-%;6vrX`>r@)5Y%RATM$=;QeLgUmj)D?Xb?s zhp~mEgn#5qPRb{o%P2<%0IBxBE#Cn;8G-ddC53Z3yF3oId0z3Z<>QY}cKRg!`PFuAt!YzEi~rM*<-Gt^e$xfPGL0h?{H9FJ1~0`NC+0!{&0Yxgl@$-cp}q_Qg1owK!XwNN6POB~`= z${mi^gYq}l0i`)Bc^BbV@~*G5rc+{ zMzAHOI>NlEbzqKk{%~(wsG@22?>3de^GKeqvYZs&T4j=iI?9n_AD19Opf>WGN1B zIbSnU9waxF2kh;Lk6f=MFIM~)8x#P&W?)};>VqOb7o2TVqs1!!0<|DSkQ1S~5&-h| za%0OW4d=(+?+m0{7O_)O+8$F2IbyFC&AsgV+5H7Wy$c+YxMI;Q_q0VFGZ=RkyXX}uK zkr%+`x|pm)3x%j;(6KU8iQhe@^C34Uj&3b)UfYB$H;4Ba<4v8lS&QACm&4LjkEkBk>#~BhU=84m;`n3BMaJZCMl972qyl zz8|MF6JKIJoX$MWAdR~vg>k5uO71@575*U)@l~+j5y6Rs582u6ivmEg)@okUoWOpo8@KX2|7gic?(!db9M7juAR-S} zQos7Mf!*mvL1sC46wQF4z#BY`Xls#-2dk{iO%B>3nJ>X>!ihrt_PW8dXMhz!36qW; z=U^+oD*iy*%f$IWeJ5W?vD>X$>*7p#K;@bK#v5QK(v&Iay9>lSezegrJ??(ZkPBfr zXehqd(Nd@z(Vt#iO+T2v$5DIq{e zB81+12frOe$M>A`$Fw}HB40kpnezADY6z{y=dAd@WAobWYzxtn=m>2_911q>$*Obmf7Etqb zd*3C0`vhF`{x?lH&QJb!piL>AyUt>TvbLp4Jn`p+#!f`g${g&~{c3I~BL=^p-z4gsTe3d1;2~6KHM_CLa1Zs)pUp33X%Fq_#7&-N}S;wKf|Qi9!q|5 znOz!5i(K5$R*hKLmC!z`UjfRcZ{Mo#u-G*E!hwMq9&(fEX^jj>A<_*PT~)1#DmqHv z9{T%A{OX+c7Ujv}xh);!PgHD5c>IndySh@fq)vGSM5{hr*NeKOp`*Yx7;HXLm(#O$ zUJ=h5H1*gB7N+%ugFZBa`t*uMQKFvp7Y6a?9sAkt700(xVpUc##C?RRkK!Dz#poL9 zie~6)=nAT>7zO0Y@U2zd8jqrCYjDooU(q(yGBY8AKDvbLJlToZO}%REHkCG=yZjmH z(a-#g3=cl3VXwEK94S@TlBmi%!YgP0yKR>2-+AJT7bAahIBe7dp*3~@91feu`QLvJ zneJnVM9sH=YrpT|Hf4Ln4I(&Z*oGdTabnDc97)ZLJ;nxC6|Zz>y>+|qQ$33d0{Lz> z?C5Wwnz%`@D_avSvI%&_s1_Ipq_}fDD!hL`Waoz8{Ojsp{YRqy=x{eA+zI40+J<@q zFG+LN?78`LY&??8(_pGdYLIa)P8YJl6h&m0bm3id{o7J|){X0S?r#Y%ZI)+E?j{Jl z-v|=moOXQP_T)+DRPRiHv0R0Y(TeBP+wEPPp7GAL0Efj*6%az_$&I{1pZBC)>av}G zvS&f>C{{oR1Y6x=1P{BpE(Bi&SikZaqW7U*xPoRa zg^d?Z;@{{Q_YV(xF^>nIO)_F6%Z{E6qZMzo-7%hXwy}NM=;|I?UcGve^~HDJ!%Jvh*Uwen)H|Q3 z>WjR)c4nwSRCJ-FA1%M2(>|T9%TH)=HJ{*J-!X5a%NHIiaHEyqhZ)rS+E;X=Jx!)C z8&pc`Lzs*pmgM$$)5ok!rFHo;u3%Fhe~)?6PObvm3SH|$ITn=*@oy`Y%c_47taTVJgVNVN^0z%?UJfX5&RI$y&!H>-7S93eqD^XxuPa$4|uAOe&TIytAj0Enk-^JrCB`RDsYI;*D5_!Y8eb8 zCtyd~t^7-n^j51mmCsK>t=F=)Oo2f67CV6z!Nw2YK7mFeY>@R0K>*>vEsk4@{4dy1 z@0m`QKwS_&?4Lnqlo(6DJgn7xgQ(ypJ71!z7+xWV)y{4l%9@|jkwG)Bcd1&J_1_=r z&Ae<)8rjfr>^g>dJO72_NoELdQTlL~zMxGIqN$EuB{9y`7lT%Kxn%2JrEH7Cp+c1hn8B`z4?uX>=iVCO23Tj%#?$7*`p!guv zoHfak7Q?XGox+PKxSh+z--#+zOQ_;fLJxaAD4lpnzNE#&HRUI)fAV2}Nn&ZmME$j? zYP64_psDDIHkKekyk5WN@BR>7!Kikv6XBFvVyC`;anO<2zxOj8|J{t`8s{@Mfwb@a zo6l}etl~2w`Ynle$#bJo>XTb@v^>`t#H_aqjHb6b_k<>PQ9}o0(xM`V2Xjen?Q%0U zDUEFp#9iIX#&_>?*BFIv@k#en-VJ(1jYgn&32HaeF+X4YQzG{65w+K$)>tp1(TQ%; z$00LuR+}nY&B`y^U3sF)KeSl*%#pc>c4tx+Kvy2wDoVA3>-tiH^G5YOJSX(#@U}t+ zUBWC*lu_M<}1*Hk4G*5x%#v$|#;m2<47+ECL zrcJfk1722Vo1dv#9q5c9mZ|6Fk_T`?-lK~iYpZm>%AL(fqnUig;Oa@jwfj}Tqegze z4#BQ&4nSjf&M_1Dbc^dIFCM>~V2oG{R828Vp0G%&GKKWwm_ZxeX?%;mpD_xSArH70O|NFiO-)8$~&LsGdF`jihS>%l_s2& z=g6Io;vwvo>^8&n4jfvEUiH{CRw;LJ`%qa;_&mn!th5ApoOn6!sC#TW_1XWpE(W~A zaVv$aTn}kb-34S{w+xQbL+A5q0o3=qCJP+`2y3z~cLT3>$Rea$=ASA#m4#ir;-e7A zS#Oe#D;wnpaZnA1C*CJhf-cg?DhZ%gFUy0DkY&X5`#1z39z2vY>CG z%SR=st%pX@qHVri9M&B-HoDEoOWDQBB^#7lH#nT+_do`E#t|hm0r{^2G;{OCYWqY{ z_sA5V_gKR87mg_P-8FQTA9~{|GB=oR*cUT+w}a#84c_n92_D(MI{+aC&y_~cVBtAr!-77gjMivbJj2y~Kj&8;eNgWZ-RY+W~$>K1)&y$Z4}6dEfk1f@`7K=KZuk0641`LpF2f~+}f-J-rAYA6oI}hJhzfJw(3koREBwIyuRGC zyS3h8tjpBQ=?f-zSq%KP)lRN!ot>a!+~D0%Uu8x7)pOEYWFll3g9>&X}8R)Bi-;nK+%ML_!-`o=O&Zl!Tj zy57LaoMwge-a0z}K2Hrx?vaeKnGiW9_2-}8X;1y*5M^+E>YgE^+2)=$B)Wqtp&ReBUeFIzBRzT5UwhL>Vd2wgEU3dE*I(-T;?0A- zEudkyJju1SHAu1jid!9FRUk0myLyCnW_gC1#;qvp5AiRUYMCQH=?&dWM1D0XgbfW_ znwV6~AcR_%iQ6po3hWFtsf*O)DVYu@E%1QOB->+*{agTP5W3juQn+4E7k`v|x_yQu zJN%TZ945XLB+Rezl?V~l!+oXzaC7RsX|;^0=wo)ka+*V-(?!ZVV31!x?G6No9;1|TDAoNAKt({>h~T8Ksd2%V+SxOdrmUS6wcb(zFCp>&(g*V zmS;oQuA_1!%wda8<9_4oZd~XaPjv}M_2YV;RibnLB-#EiI@`0qSOSH~UZ=UCYdcZ~ zS(q7EOg#+KlFh_FfW4b~e1@PF6R$yXczvJ7@_$%nMO^V(U0O$LO2rP6PiBkkYz93y zf7tA4TM(NdcZ=Psb039#d!~QU$9`8c;J=7Xl0wQnF9L$kYw5o6mnu6V+%oe%gc7(N z%}0h=hrlreW@Bt8BIJ}`E72oLww6)kujv{fz~>D~NiPXOhSP504?dyr+h+r%CEW0tMSZon31M<9>ta`JW@3B|zr7;2@uDyj@n5u$$=fmUp^z zWhE!pwV^7!EsKy4siWb)CR`Ng)Ij6? z7wA^!ZiHQtkGOB6e?$9Tfqi!LgW5!gxRS_D=wwLkG9G^#fl_EakDj8_2GP1mpdQC@iYh$RW89LMF^Qy;2 z@V)bprHe{F5WTG(tMycm*t)6@qA=gD@{?s1A9+XWv0RPW$N`qcrsrN11DInT2_PE= ziTtdWDd7YOJ|BM(qnX#Y!;}a*1KrV>n*mV#Eib8O(~2r`?ajN~b$TAO6czJmSBl)- zkH17D9nil0P~!OB^_`VCCDBRd?&$)WLtc&dN|ze$$1#_s(4tN?9ataHMzq!i>(KHW z;Bx^o@#4eS&v6bm_)xlK;0GI#>t$k3@nOoIju(~MWaGR|baRJNv59~D*~k9Tivu|e zdZgyvqq?Mfo+@>*^ZK96s~`a$^J}8zpHQJ&2`;vZmm*Y*7w`dHr!e-eo8k*D1S5+? zBlYHvr1qv4rOA&7d?R5+t|5~uX_2EzIQ05_S_%)JUX#$@pd_Ua~oZ_DLyoSuh_P5 zh0tBg04O#X0x#Dziy8L3=gK`|YvU+Uulg~$$34!Tv5ZQ;TK9zm`lK`jo9NhnY}S>I zxPgq6^H+`$_z6JidmCY|XSHL?ySJsuCa9BWE5+d2g6b8-E+vSEzmnnR7P>+msidw0 z@+PkF5mM7Y8!VT;k?SvKVi9p~#dx@s5i3z{@Vm7dQV=U!+++Dfr7fq^N!vzcW!aSE zL|L3Om6?HkdO7J4?@g%RoGS-gZwGzh2=m)+lkqH1X)r2pd^OH_lGFsh_FiTP3kA@W zM^+TuvH&Ox__yJytbF{i+qwXAt zyDOcR|9a}L9Ydhu+jaF5_=N^qfs&W~pdpBX&IHG=(|VgOp82oli(la#g4U!pRwr0i zZ-ASShiN6YbAyJmm=qn<&}*Bf0s8`qFXP-xUScP1n?DMy_1NkB;HgQ45M(p#=3?6X z>@E`>WXl&8ueBH#6BPN0%%kU?y={!7=+c%STAJ6rqSF#$3Ib&YA42Cv2})CZT@3>> zr^h+J4g&yje#qvq@z3#*#&@h#UFdbWSe*BHe*x&ORlVi7 zA;r)AL%oQ2-!c*?^17J)J>D?2ruS~wPlP8u|FxWxW+6*SHd45@LfN|18$qgsYzXCu z0R+;T6ltI+4p@7d*K&h*$+K(eEz9tR`I*zphfV`@8*qI^T)@Wthus3?p%Un0s=+pp zUOMwNz0{^5G3%*kMM@N%4q&c=Wq3Zb<{gsz}Op?eb${k{e_j~ zQ_NSGMA$oAW-{#XPB)tQvq?4Anpr$Z{P}Nxn{e>TvC$oS4%kcBTd-3~B$wO9us>KP z*=SnT@m>M>?9tb^Ypp&y52yW={#QPGwSS#4ciPOZOX-rJ(%UjMXA=WwTC&Y%o{k~a z2caywv|Wo(!K59ErsIySQ&Lh|%?d|0bo_z*4XW}%D+n`alv`I8Wmf!fY9=#73HL4z zZSLow{FBGcYiH}Nw2_kYR%;>nUcW)x;!0>B_ec>bK6SVV;)lUid8A44-%uwk;^7F- z(@zm$b<7Wfc9yBC61^8YmFvDWPx zq}u3>rZafl2{lvo#h`Fu$r*fDo`QK$!bl)Vtfk*B9->XOu{PMYBE78l16ysBK_9MD zRf9~Z31}fds-XO>nt}I&J}J!K?!U9x4~4&Go!R>g=svwqUhk!g_e5z~99IQIs13}G z+f|p-!f-Q3fmSmWmXHreZ^=z(&%lHl4&Q@3Z_2A$AXivP%PiJiQsH2m}d zHzLNw2x@9kK8e_cB#%9MR~=dBeyyVH8U#yymiBSEM4S6f*IyDnqOP|9dv$9sBD#NN zkI?wRkN)(k{xSRF$YEzJBsfl~xk$9i2*Dw%uS?&rDedI5=+SgI0j@AfBbCOxFc0O} zUJs120o7(oE^gqj7)rfVNb*VQ$f@X3Ut1_Ex`Z}wR(di7J;~ve*TyDt>EBg#j!-X#`0f%##xn*Oer2#V?k=a2>$9LIj*+;{7w(u*9X? z)!U@w0z(wi=k0d0yIkhiN6RpN5>3xRXgCRmtN8iaAu3mrofWg+K>f}Iy*_2;SF=B3d$aeI{P>S}p66sY zU>OdjysL4`DkG)|e`>h~EJn6X(FJsVRi*|S^`_vWyH1e5MoN%B_xjC%eizHM(&+YG z%#Mu$GqSD97*4&djqE-v?8HBhJIzU(Z^yRiDNAt8*?czqK?-Cy{jat56%U~Aen4bu zyg0L~l0HsLlLG+29xDCniHQw-C(QnWEzaz&hpfPiHCY2YF<&@FyF*{pyQ7ZAxz$X5 z(i;??;=}XS>`~VHZ!rmES$vylLKzWK)+y*&d1i-A7+dc%^j`4;|2%S}kvz-}jN<(e zAzK6LMLRZOu>qA<9z$;B?(+D$*O3TAY?w(0|GYuor;*K|w%JqW#|86-X)fbk5|IsU=>yd_02(%0BVq8*6fQFW919q-w*{R8kqY!H~j zNPZaT+Csfa{BlWLj7>$}D$}@=ULteFtZT6D;KX8}iPyHkwJo07HVC$BBrR=Ixd8s5 zubH84>$|~Uik|g3XKE3xcI-x5N9l}%dNR)Os(*e>lJ$l6I>L>t;3{WYMTDQ&ByNP( zn#w0$a)bbtj>LV8^Ip&KugqpHAS#CzY|XnN=A9 zL6Z7#NOdbvJX2yN+#Z88>`k{AR*7g@)^jgncS8s?s7zE-(R5On>HfmOhub+rY3`AP zk`<&*&v`C!*AppowhjZ+uPV*h3y~c*eqB5qN0i@co5W^w(t?jTZwOkysC?s5=R9%* zP$qZ$sT3j;sU;AZ#ede|8r8Ie-4O8x*oy!0FeLPik+{Q%(hgs}HyKl!v@>f1Kcv|Fh%3?|WZ!7$O>u7#e1B4l^o53KqLrl~mz| z_hb`ekGEi}g=0gV>Bb~7>O{FwS=_XAz;IN6#!5JRnJ%eyG zkPJb9jy@_WHuV#@x!8`uVx0n(~RN-)J_w_jAP%Jqypm$SK9RB%@T5!J@jkG}0E_l*GWS1~NXi3M)jgSFJi{?z2-NWy zt5Ph49J(v~d?^L5u&7j$Z)|0BW}*lUVv77V`1d=rk&&1*zWG`|Cp!qVWY+qWnY*3|dUSS%`@X$# z=eyW8ze3hZ_UfkegzF_&aA%INt4zx_0|sK%atn%@q+mLc&Jr-qHCSyvi_p95kQ@-` z8KhhDDP`U6b!_>&*2Oj7Vf=HDb{^CSRhpa`@j(+4ZkVdR*0gKY_q@!e3J%oPV)Va?XvtT*#g~esw^$)5S-A zYcuM_Ust`%NY*R(~#VBSAO+34$#yM>Zo&Z|Fk^rZ@7Z&4{Qk<{TM*LDk$4+ZYDQNVef1R(WNY^sJ!ovEoWJMDJ)v^Qe-mm?mZqv>?i5T%4w^FY#9Q zn-}`ga!bwA^A?r!imMyQ8*yMcRn_$YORvL{iDIH7izaNN>_4_}5)7NFhBaM~T zc|TOTOWy!ea@l4L^FYC~df7rZkjlTFvd>><&aGd24R?TfHE1^1dbkH>Oo3?a! zF8fw~%npcYr4P*s#2Wx&P7%^b@EW%0Lbq@jrqv>_ujo^BsPeBHoU)#_JOrh8TFpjz z<0Y;Yq@F05;0oy!XUo9_!@~^Ox+BWBm4khx{iL2pok2sXXDh0}(I?{KO5aH2RNHVR zO=cSSL-`7)$5f4Pw^bkxsd!dCTBnx3t~%&Rv*YFvUt7U+|F>zA2`HSM)>D8ASWsf!0)%C-FJuvXI&0 zYywpMXt87$(8ShN-GZ%>R4oS6jbv8jb}2iD69J~|D^&!T-Er-hsEsdYK$oGB z?aVC$g8rpQYf|*Rs`1x^UG@D}F97KCmHY-w zaPIdyfII8)!DVHZz|j910?OL3R={1&jQ zcafbnT`6W4y)&O~8Z7CDhk=Fa^os`_WYD90FDXF}fG9fq*l_tg6Y-(7f#Thu=eRR! zF*Abig49|oz|Z7TZ%ALpfixdvO}YTVG{P$m?dPCc`!>|}V9B{CH53(IKO7! zfJe6feGl8!Yz)jQ$x;gxRp&pOn=|XCRf6w{qFN+i6jlTbUhXs>BSEh|JUdB%o0Tpj zR}op!LB(D=BFSD8Sx!y0udFVmh=rEx$VezG>QvCCG0R0)dOW;8$1dZAeqvZ@1_#KI zP*IXIwmUnilE^uw+;Vn3*HizLuI@x%p*13+m7kbe5tcLNLfD~>-6EaYzh1K6{}8Obgp@ukbU;L^6Mtwoip z$`ponVZphTa{7ARwbSUKOLy{Vqb$Yp0VApExa6E!lu7kS#F3IYTCg7o4o^Vp9Z#aQ9 zF@Q=F3a6SDN!L`C1quXqd|GWRmdXLNT}#%D58D`%ymIUPvgRTMOUX#nRLwPzDrETm z{muMltEHYwm7VAJL5HoAob=M5Bg#sp11dHm6z{GcW*rGp71d^Ks4$$2ewYx3FIXD; z991@Mey}b3fn_`}VYN30<1%1Zi{aq(Itj`C5HO#8<@~8}5m^zf`vLc#Y#g&qP z!e8a#)4xt;(&NXd;Hidk^NZHj-a92s%e8!G(};6%Ss5rmq!MVkM4XiJ_c2C_Ye;pxQT*Dm|uEt@F>dcZ7{)uYh}iDw)FLtM&y5ABS}JPLklB%GMusZ@QTNUwv-GT$K&11g5QJO&469bz%UubOWtb0q6k@ z%+=6kL%!@@Zwj`lY{e4YfN92jjgBGYo!g|6kn1Af9PeMjRGliKKQfO#fxPMoxpe)* z-R~}N|0V}l098O)>lJK+0@|cP*0vrDE@}QYJW9wexv&{RR11(@d7zvX0ML4=*3PP^ zU>puNklj25o+Br!U1=)A`uI_+h#^dw$aGic5Dh;aT@#yIo(S};R$IoT*-1Lq`9{~Y_~%)6}KXvKgC ze0@{Z3E+nqb9dSgUu+zyunb*!=+MQecuG8_KIs{K+o?-voZ&|Gab#@C4FF{mi`v0)q@gx1HNQD)h;Y zHeD``8x!flBv%D0uf)UnjE+g&^cX>SoZgFx0ajyRAhV{tiu+^Yxs;(wpqW(CmNQT$ zaSTx1G#xqq9V6@!uHUxp9`pJuM_eZ7$mJM4n!gCj+U@PQUyf0HVcX;^KmXL6(9bK2 zL+_r>ohcNza4tMUA&Ps=sM;_s=(M!FR` zsYv7dCKxyfXe8%47iO?(5kD;->0Tp=)q<1oD8I?Yl1R)Fk<>8wNUG~F)xorFR7Mpw zVh)QpC7I#2XC|-PUHXcx*nGinKcR!#V6UHCHUM9VwXwk!Lv854k_T@%Exj4r$@E5n z79$D6!`AKIl>am9 z#3B74Qp39l(Q6|OVBT;W^BU$^18lDDB&Hp`G{96vMjy>7)Mi9==NeY>4jMaG>LGEH z+!K}1mGr7WL@&V^Gge<@mOyb|2(p!4U(yNZXUXf1Z@|Jvi9AcmO6Gz=v#vew)9Slo zOVbGbhiqTT6nI&(<2dN4JE-O*V<|dbqu$0AFInH z$ykhRxUbInCxXv^qaHTeRazU8xj2`@hT=8KJq&!a3Xr#0sX7((`{V*WLtO0O2zm2&hqNBtqO@4U{z=7NU zxy5_LTa=kQHzTqEdsfYgPL9@wGL4#ddNw|l{2MViXP3EKrg(NM;h|N2c0A!eszAoxX69> z&fIw2LEGhllMN$%(61`%U(>4KRbebl5bs3?NZ`XVT<9x7Y<^KSf4|pT?EfA)?`;`|6ir8^c0{m?WMKq{6Y57xIa{Ux0wfacTPN*v7 z4Kg3?s6cRD01pe-m`&I9t1S>;j@|PS=rcz_Jc=Ec7Nszjp(y9Y&pw_TwhsFle?xZ0 z|IN^b^-LvZx9Caj+_}(grF;TB^wpr(v(cyPl#Wo_%?#yhw_ITj^7Tv&8)3RCb9-mjw$lYN#@7c5C&-~y7TpzCt_+V2=5iY2S3}M zkeFh6gdET?!E(9L$m72)`^ZdZ0x9dy416VH0;z1reKhpHLa+aF|A1+l9NNKb%7Itq z;x6i~J7#U6j>m7^YS->Jro>GTuIN6eNYo5~nt2QwFfG8TF&2O-6_BXzC*=R~xe_Pa z{u08aBg!bV!}mVA<|1eHp1#QY^~}E?es7(dhgd~jv~>i3@?>5GbnO#zUTsZ(YjY<; zBc%=Ou_-?ktyth23{5HU!hfj5p@v4?J-{b*&<@16Ig5*zUA2Ln)_@^HE}%)TLW<8| zt=Sk(TDP1i4zW(#70U9rK_iHZ`mvo*ChCxUpk!soXi0R)VB_f-e!zz8!ww*n`FE8A z=ZWcr|6=nxXE4eG(#+zbEUK*)fN%j$w#o%w6pa259lQjbXbS?B)HhBUYLerxUtX2W zh~hCp8uk}U4h;D5Op3F|rLuxA&un40i+8Q{i2hc+Mqkh`j`Sc3OTTn#Hm7ZuHeX_m zTBTLo$np&Px;y}9^}`dfAC2w7N|co576+G3v`N@3Ff`8l*G>)ws<-b{;-T{5^wEn& zHJ0rT5Qv+((ni^4ZfYGZ;3}PUx4~u0fkL+Zb?og&xq4^HHXua?7W>#24%8P8a$7}( z&Zg$h7mkG;Xt{HwV7?z6TkmW$dR|Oa9Uq{LUpkrc5$DU?;pY znGr0N7FS&A1JTJ{L+-E!-kDWGxcGn!H^gFDnPjxEfKwg}ihQ-Alk(L>)W6sV&HL}C z6s;PU&~wHxZm~vgPFK%-F3exRNI52T%qCEQmUa9z0XMF%PH=3ggoDT)$!p8hsRi~TSY=N^M} zW#nT@AzyW~DM{x2He*=*Obsxcr~jRBmfBFDsv$2aQRzmJt<>DgL+YCu4_6DtLzB8d zrvs^}F^J%9P9s^H?jSzdT&a>QZld$R<&Xfc)4E)~7(j%Bjf5^Wytd^U1k``+!sS{} z_&9a?65;i_=tRh?r|>XuUHbfW#>f4m<=GhfM*#KjJ&+XIg9?DiBzgGJQrmFa0o{hA zxC&Xgxmmx@8KCY%l(!{sQAmDv&Ce5V5<6HNYiy;Z(sip-@m)hBYaqdO#)f_;-&~Aa zv*g)}=^0k~?bk8=E~@K2&xZ0&7fQl;Y~!2zZ5P!a^y+^d9n;*nXAjb7FjZ~j1dupz zXm25(X>c1H&pXi3fja{{DO+>;rwS1`|3?@equT|4rZP`VNFY)Ra{v0c!LS$!KT2Aw zHUr8R)K!2}t$ec_`&mv}9euU=vw$3sljhV*p;EB!ps+@ePdguzU ztiOd;M}Nyj0_tQbR-aY4!fI}L4w{f29q)Ta(q%oR=y?uAPfwny!Uk=j=MPg&|D@kYB)e)B)pF)0Kf4lzv#H`G4x_A9^XhnJ zAA~Z3HP%2C*%$01A;f_V=rag`S&P0O0_wC{cv$|0BPlr(n}mpsvN6SQ0|&mQdvoRZHdQf%0PFJwcj+U!)G|?PP`AbJugH?+DM=n zb9T8I-`Z=Hd4c|MfeWgBUv6@i>p5^vOI*CEOTxw}*=G?mbAwK(-@@|FdIm$2$EN2E zhnYVakdx#5<=h}XT|S82-($n!;>u!+i@KuO^`Ohd336Dn`UPA2TQji!&!{6-0VyJ5 zx9&>W0Y~=yS0n+P^!md-`TlZxYQ~5KgMj8=3L`6VhnGI+4V7Q+Tvt(^CmdVEgGPsK zQo`N=LBlhcY;|m%_^`QqoFhKIj!{{xu2!$ea~gMKP~Dh3(SD*bSNcM#KFjy>m~$HU zQKFSal~$;vOVx{CPMv6mftmBoARmJ5v(^W?L+C~QaFzh1gnzsBfwS%1wS0R1Onc3) z{zgFkjNjM*-g!Z3y{qu$z-?52Czdp5;WKp4XrTd0u~{K+*JE3%7s7K_*W^91$Y;E2@&y3f5Y9F1PnfNmT| z&{)$iqfdI?|1Wm>r>J{J+Dcg-RpNT5%bPQ;dfh_L`7Vti9Rg*Ajm!c^YlVZ~c4KjvT^Z1O{B0Z&JoP#2+8^wNeXQ}%pRxb<;2>1frcl$F z%cF3_j`L1ja9q?$w`^OXge9ot{5Fk{FwP8D4vt(e4^(>w)L9P(wQOL@0OJfMCltw@%h?wt+lOi!7m&&YIQpl zTf^U;-x}j&pH2KDkHp3?hicrPzR%`g(VASsu<+ z#~UG>lgX-|pB6AK0`eD*JOA=mKj0@`SqW_k;Aj^SnoFmyr%UzU2SyZ{^gUB`bF!1A z*xZ0umra+T`O&9FGQqo33&o1^{?_KJ)W>&%wCN9{Z%f@s?Sqf!R+jTLHHJH7SKOs? z`RVQ4r33@#m~8O*yNOh+m%;2Ts-&0w#24Z>>{+`Bi$L>!*SYrj!O^*=@OI5ptN0{R zHMXh$Vvn*Gd$!nmxqk;~NwrC>+Tq&NBpx$hL*2YUuW@;9lXwV)q!h4lhPhJ7^HX@ERAvCk^}Fn0ew-u!^8>_s(&15pm+s)rF!JO|jH?Y&^?ZDa0Zi@_89!26qA^ugg*6oBD2w(B)6z9yN z!cHAG_=z*EmkeLTjl65PK|L#8T;L*?y8U`A#{6taJb(W~=uqOb(rs8_u(f1|=m2uD zaJg2UFbm^duE)N|q}Y5cQuC1@w$fJ_R$og8PIKfY*lMCQPQjkps8u<4rKW7(_|M{2 zL|Q*GQ54C!ZjV3vb^>0$+3y?c5_TtE4=ht4ZxF}>=?<6oq3Rd zM}p1(Su3^lxP$_k=&}}Qv(ezz)?w|k{4Cu1MVHgB{`t0;IR5-eu9W(GGjZhFwwIc# zW0mTAR;u#)3i9FP*u4&v_tw>|=E<=&ox=UP@1 zIXQMy!gIN+LC;a;r*7ja>3j=Y+qMy+Zzym3P_)m>jm6R%{3YzhIXv!sjpJ?glL~Lb z%(XIoSZYy$eCT?~m2@8F^8*;%uI4>TztON?0@v_R*2tlDTaj*498Pk!$`GAe>M~zp zOziGkzy`fO`B&S2feRqI{1Iz>|59AMv}ABoc5p0>wH%1JQhd+{b5zu z7U4m|QN!ytQU3bJUc2*+kGDf7I}&~`ynZ_tKP*|gLE1RGd0H(nvLqJC=k1#W$#9EQ zv<1hn3U~L8BQwbpLG79$*#il?C5+8W0tZsQ54Q>1gad#6%SPSe@LDqt^v%u&i<9`` z<(Hu-p9%Y&j7>SIfqaUnSw_8RHqy?Xfkq%*(;TRyFGOgW=|{kY%7q{6uOm?Xi5Pflc@+NpDsGW_2 zUK=zBR!R;2;|mATh#)j|$#Y4~$ALbVvm`WxLRR@SY}hkr9UC@;nX^duQNK$C@B!Z$ zbu*yOSkK57FRF_F9eneblKMGCKiLoSX0T{Y?}-T&+7}M<*a+tpy~BF*O{zpoWtaI< znj1eKK#GP@id2mz-UX9|I&=txPtn`(0ebb*5SHy&v_?v$8^eg*uz>h$tTBiEZ@*mo zKmOSpz7vN|sl}vjUGo0)IShaDJSbq+=<|aw93g3?LfDtJEeKSoXjLb{w&8FQJkt=# zeaU_p0R`3KB^TR}fLi@j2AjGU^TEwfdaI+1`bnAR1Z`)PNr1raWE(7qWWSpASZb1k8dN#Mh5$&hLlC#WFp6L9sYY{L)NDgQ>EHlsljn*Zb~fbXr)=%%IsUxOCE-B z@L@OGi%vHpuyr8J)+uUVh$2woPxt#*UF|)S6rSzOk&#rtDHl&a89iLKz)@Om0~; z)2WbByWu4%K0R%(%Xv=?IIY98*CMoGUnbB4F@ErDu$tG3kO3XJ3y7;A3Gwk{63r@cr0PGHSDNt z?BEv;IK_7&5RZGi+*f-OVTkDyvjI;O2K}OjgPYG@7EL$kfFBKb`7nZ4ZGG0jTNEEv zS>1JElNr7WQddBF$ZlnWn;U>?P8}TyewVQ|*!b}1+)Sk3*x+urr(D~ps>I}tx1N#T zqKpH|9@2NmUeotW3OtlZDlH3-`XMVZQL2V{s&1v7gYZh&L9xJt>DaN-N=pxYk&?LK zVcC_ZrrtpMUTpi441{1T4l7C9gmEg9313oj8USiPE~5W&Bg zm9^RWtoQ3YkW6sPG+|dx)>+N6xJyFw@RKkt=QPL<*E4B$@zyW^^5{PFK{0t)+=sxh8Rh%L-^;S%%&abSL`WT3d3 zhF27=3DfaRrl+DNaLt=jvmV(etzCJkm@T)7%)iy-9Nev>#6V5tr`b{q#A4_7k=JEA zW${NbF0>v)+3>g|-OKC*lmcz|^&EP8%}8`Whr}yBh200;=<^2dzy~d;L;cLk6nnJZ2rMC+Ge7xK|+r zE1c~vW9`=so=K%Egp+_WAe>&nGf{4JRTuzFpNQ_&<`Oy~3EUkC;LF58rL1kQq2MJl zT*7|ow%LTi{RkrUKzzVZ>T{S3_4A|o*yIpw9kGhL`^j66KmUD}Z^nDS()(ZcBFGnE zByDeWmmE&e#`Xs!di8YiG-Pyluv^OeIT-327+qI#w$%DWd&E$C-zwILa5tXREuL8$ ze><0G)oQsIRUDgtd~W*N|gnSlt@NOO5(A*`6j&o{Qq1C zp{)V>yB!;#+afRMG@(%fJj%A-ux^eARr}# z8deYx5CWluKmb=MN?p22TSY*K1gQZ6VFe*TDAI)x5JKpo_vW2Y)ZP8Q|GoD-c}^xL zConT-=I!tAt!}~jIr4FS9(I|#d|XZW^neG1Ml1F?ZG~79&B}BFaf>k1GZzLC(6+?a z>rgcve_apprCEAPTciiYQY<_MgP1?B33c}O-`30Sa4=o^bN|=VPMT9@4akpmi=B6) zNU*6BJ~;cj#MYRa*(tcj-Q*vurmFiUQO49{F5|_r%W8@#RHftx!#R^6p_N4MoSgN7 z*b?i+O$ZYNVvC-3VyyWy^p z-S@-g7|_xEmLLQE2Wcd@AGr-1VZY9Y5KWUhJ{5SaQ!5#(J<|x+49}?7Z>p^hK*2 zea@tQWjP2Gd7vP}?^QUEr^LI*WNfqhyR&XB^oX5!&p(xvtD0R;{KG694bTN%#_J#v z5r;>_*c>h;q(vQ`c%8E1o^$t)aBB$JVae(_kvj8$7L1?N$BSOuEcAHd#rN=gvE<=T zOh9SwqBy?96W=Qsti0+nh&Oki@8Etcp4Zti5FW_=_T8AhCVt*8v!BmDs$PWq#L+6f zdI_QGCYKTQ^nM#mkJt0Sv>1b(KeWd{_Wezw_^JeJM?4$eYR+#~h(aF|)o~bKBXWG8vf}9@fkJj9 zli3NO@k-?o22VwUD#>+&sslj&VX%#b z=+~%wNX_bX`ON?$bKSvwVeE<&GsJswTIhkpi7a(902=YVy1g@dAi?ejrXPTTXWN>= zU~mT)Y{^T$qYVXJ?^Byb&OSB3JB(;!0bj=Ip<`a zI9*a$GdDB3w#QNTKADCrUa)mV9=Fat=l|R(Wo`*}tjSEPTBx#P9`U$E3@vcJ%caJ$ ze#yH5<^HBlMqQd(uMT@r)6!Llc033Z&u+wln;?c$z> z#?-~)P<@99l;*wxJvPzU4Lc2r`q~PAY>x+;w_uDU)kXQ}W`@1dS;T)`deHB*9trk||kSL1@xAukJb ztqHc?$Jo33)Ko2gw9L|q4%>p&y)W$@%z>Q%DH{hEDH~Opv}qa&%M*V%g$q`Y=Hkvq zMP$LQc$t+?z+g0Qwq^atz6Ax#7&@-^k14Ldjd5G(XZpAg?BYFv?uS1ZjAWaOfT}~H z#TzDZa~^4_ty=?AXF2GvW*rZAv!RV`#SJ|Hmmp1 zR729>`VZW-vbF zGOvJ+HdivmEngxQUA)m}n{!wR2@30cVVeHJRHLHyZ1D?IdiQ39oDWP5^GFF7dEDDW zX4%r60;RZHgrJ!9(CNJxdIOv~joROJ&sslBqjWrHaE>gzP(P73MPQP8yT?#}{Y~iD zzh7SkOVB_$DN`jTM;45enip0pY*k*>I=Kme?3m?~qneeQb=Na^IhOwzQ>%%#9Zyvd z{HXR+*jU(Wwt&w`cTRE@=or8q>%ut=37gKUyA~D3a?LOql1}0sB&~Hvh-^jhI_Y%Q zE_yIx!18T3-07Y3I4>l<-Dv?J?*NT%TM^zBUUqf4@5%BJhviieC=$OICHM5Me;Tpg z+|hk0)+)FGtXuEvk*5PZjs52W%^llD^V`k~M5``LiBvX#g*-F2>}}*Rw0SSQ*YZ^i zlt0S+N$qH>N$x9-AO5&_D)8MuUq3%QdY`H0@#A@GR8jeJzu9D-yPWeERJNY@=AR`t zjxmhCTz!R~$7$~I2y_wf2TO98~I2m&LX9Mvl^m#OY0wH(c=d8OY>&*G4bufL|H3KBud z>PP?>w^;z=HgDTOe-#iE5byHW*GMeTV6dgH+~jsijimp*u_m)iBN$x-b}H1g>o1{x z$`&_1*3b)+UuK$*+sJ=2!tFPf+7`g3XgVS@y`D?qeU*{DDc(hI_SrO&sf@52{K5pS zSl`lJQ;g5vly0W4lE&X-PxheRjZCjo`+3tgVVVSV3O(M9P`Gd}F+%;IwnFT)KD)nS z1}?w^j0(?Q`ll_N>%jbRllLKq2X)SCy4TelF<6|9F)=6d0{m9wGu0!(d)jDcxm~qP zFQgoOF~@6VMXU!aM28+IsyP)&2D&HWR&6j%^)RO~T&#khB9j8y_%x z&uh*MZ!vUU846(MjuW&Mt$mGFzA$B|N$_e@P_wSCdIKEu%~hLk`r~YU&3GPyz|K7@ zh2rvIL{;pymEQBI+9_;Dvb+q-ZQtY;5Njr9WlQbSldde-tz7YOo3*N)($!j7T<UaQCKXe4Y1W=bARoC${v7LoCF(!Jg$YxzXk9azzR55>ExgrLkj8L-N38y) zy|*wO1P}A#UICdFq%i^&_?FHY-rE-oq`)t*A zLa>4SRIBN!l|v>!Zcy4XEVxC&3zT3Y_|R%K{V>5_-KP-Fj3>J}Pm;AOV!UemW?i zh>rW2`k_Arvyvz?H|2Brx1A^^8i-=j2y-8ItC=?lr!2~Wa*LXX0$kf4jCADh_|^BS zA-MicR{-s8e`fiuONJaraPYtsWkQ>5L1MfQqd?7PZ5hr|0`_>g{TWL9G0zP@Xd!1K zWa$l!mQ*@7K<{0yt8FjgD(ICr8bIo{B$H!b-n;eEnjqsUF}WUUj0vF)`HzpUSi5_5 zBonNUv3KA+O9?gqX)ZCwq}MGAYLe#Bo5_7>ZDhEx9@0tIOcLKg;9s0jx?+V2^Hdy4 zGm6E(=0CSbWI<^DjEIdWV~wI7Yl#jeB?1{`eYQq< zDhD+`-ore01g?KCOP`a?`-@XkjyU6m=SoW01kdeYKGMpXWDfCc-Q^6~MqHI#JIe0s z!37dwhOb@5ln$zQjM*l4vQ!sU9TJYYWEBECc2kgats&NowP?}f*8TUlnD&MJY?XYe zcD7tzSbeDo^T|D*KcDJ@&{D1~v`|mhQL$L&^IO|;gsYeznay!+9h#o3SoIaM5cCnA zLEIzO&XK%+I`-O1;@6%dF2JyOarI2vTw#*k`GN=^Wq6f_EM;vp&p8kt?0ikH+F2FU zLXEXardkEMB86j2J8xS5c1x(Fzldh0v%e8|w)eC%|P|#Zv%m1SEhN zE_Ya=#`7+v#cJWNP0lrsU0MQ+BnTwv!lWX(o-}<)VzpX`rFxGNsShi zf!o8LO`D}jy@fsmG1}UxwPS$XljqcaOmM2VR!F*m4sNadfEYyP8VesQ$Pi#NThlJM zR5BQ6rXk$l@OVYY)N6&m+o{1-w#%`#4<-lXH{Zj{@Ds615KMpBHQ4d1Jb0MVwr04e zpMT>`K%G`}t#Pf2x`@6U!=EZ*|GG`Rr$c|@>Vbw;?>Ozm!WeQ)a&T`FEY~R%uyD`p?j%OE(w{)eV98A`C{x=#l2oVsb9981keg*^ z7SPEgp~1PiZz;;EC%4*4NeQppN6r^BR5Dj|tnj#!BGAZaDV$;*$4}{x7UhCOpVA8e zF{2~ZaL8p&6m@FA<}?jv+$bEPnCF(k+7BOCy=CC)6!vBq;2SFxaz=fCH$QFxc{job ztPO=R`H#(TC_DjJd3R;93*VIG@0yJ0F@|fE@p>o~eD%t;eUHA^MfSaZ9P(^;@`cFhskwps&=B0V-L)T5JQhg!9)$ZQTZs`2WWcWZ+o=RM+CQR83;Nfd^ z7KCF56j7&M_1N_QREwcDrGqoM)#6vWMs4GcRw$fSj5Tu(9iJ+W?HIGJ{C#{c(C)vm zHHJ}CXg`B({07+Eo*n^cwRoQR;wVTVl)EzE%bfDaFD^nQG2%>roH8%HrGa>H1_u`r zXM>@D^pU2(_H?BU-ww>BLjyKE;Q*==)OE2jVK+$9cjUy?GXOV|CLJYfi!P|gP5Ma; zxqg}{U3(k-XtH&CFHk|4-tf!f-oZ}V87)r(P918S0n*X!PWOb%)ItM=LM=c^4nA4fli3Hj?Az&i2r1=j!S`3`b1ljEj#Tl-zXFYO+cyXz7g#o7mr1oF z;!1rAqZ#4qc1>pL_>rvOWu6MLkJDC!0?w=(fL2&$KT(-X>H)Vmm}DQP8+D+}bUM9ugGq zx5GW$bROo*jenlT~r1 z5#-@bE5Uee}kQ5&&wH#i)5hLZQADa;aS8Qi&VHpA3*Dvh;M!BC$bIPgo}Nv!2oW0R*|<}K3)>C z?oi!#zT+h)$NykEr_)2k;+}Iz?8BQ;))^qkz?v&^2cjP|NcwXIIIuYO)7SElvw36fI zBf5&8xunI&t^FeH&l zqwOqAT(p*dNe+$6tTH63Ve3yt_5kQhp;8@2kW$SlFH4i{{P?4IuE?jQH@AI<@rhpg z(K9VR6?Xv!H^i}`VY6M+UbgXVm}MlTT2@X5>p$Y9r6X@u9{GbDGrkSJtW>r$~AIDum?QnX?*Nu9!AT?NaYwgfr=? z9h%Z)G;EyfvO>Zny6Mf!Bd&Eq`h@~wow6DyTw^-g^_{xjMvbK2ruoGoG9Blwx`I#Y z5wPspEE6p?+9mc#CL)JzM{1o=W47n77)XMP)ighFCR+C$RH{EU`KGL=}1Nb3+pVB*0->ALQGOgdXu;BR>a@ za5&ETtR8>az{J=g;Iv2FceXxbG`q*%pmv}2&ee&joT2(?FCyhbPH)(Vdl27@fBDgj zXK(467Xnm#_*1JfT&= zPlxu=@7Go5s@}$(9GVYBdWX7AIs117{D)zy#|&DLAgCCCDFBLW8;35SOgo>~Pxv0^ zu_-8;=Rgvkai;>YoMFqubWPa%|w*m*W$`uJ#-JIC2GK3bfUKVT#7jt0PKDB@Og> z4Hq+$<++WZxUMM0ko3B-j=aPGwl@#|n6R#&&A2t!J7?2jeIbt?M_n?ujdv+=MQi7Z zS1-QcYbHgnlH;{gNa~By#dHgI3|$GPnyWXpfr}a?m5jI|6TtsU?8}{Y{ZT>f*Z-56 zvqU{YMC+X)NQ$ft2hOO2iMflGwZ%_PB7l9=ie8MsWK8z~ zI}xa11tJgvwrxc0$uXr1%ds^*aLk*)lK_RN@XuqvG5mZNw`cJVkkY;`{j2|@d2oA6 z?Cl#Cvy_Tnz3kDor8G0QaXR)&p-p?aLS%)C-%oH)1+_Rf!!qV1^9p9wAxv{nz-&e- z#>Tf;b%Wp#$@$`A*0a2x0o;jUkINs5MAJOTXpq$%I^{IbFdCN1D)}H08fml2V|501 zDo@DD$$V45B-`v&)NHBjM!3;sRTuXQbs7?C+Tv|p*Flb#@cid2=^@J7nvFP(l#FM@ zD7m}r)xEZ?7s?^&*&u?{>nF?J^I;DeWE3!NpdWTJZOhhHSHGFUnRerue%R3n)oZSH|b!!apRB_&T=?v9% z5?&o0owe4)@jW$1kvqe({PQ_x5D}5`;SWSBH!!5|-Z^VP`yhe_WMGt(`Q2|E@7tS_ z^;|$E$ge00v+KR7GKt2{XIQ1dD5_nD^ungX5)!T8*$14djQ{-q$`TkNB;&?^9?pHX zo2p&;5*h4h()1DqcnlKFh9jppxELq-RdZ{~svP5lNN~D^ce*uqPkl@m*u(CO|JojO z-L)>-eLPS1fo_p0@PWOIU&RO~L{y4 zt|~)Q8|0|7?Tm!PuUq$@4W{s{d!hUK?LGTsoP@h)Taj(iC{5 z+xcXC`~lld&TjEwIS{p&7iiWi$D$bg4#?U$5{lERC@0>Vv3GYu3OGO4+2y=-?<=;- zS{a*>$wT5I9&9B(rO%`jZ`fu@cJ%xhxIHspAN5{iZ@vy^CmkhNhd7i~;S$vE`M;(p zhYV^QBWOsZr^wrxpF7zb-s_`RrXP|Lk(C-|mCOU(it-mI@eH$}Bqpsn8Mn^PW(dCT z^J14+3w2$poUWOjBGvQNlCbVD)|Av1)C@8?DAQt*V|O*fzpdtw5VhQ?>xtbd78zS+ z%4mn-nZ6sV=AYcXDyT$SPTfT5$Xlvc%I(<_ZOZ{+GT~C}V8tSSa*poFtpEH|X3dD1 z03=~PYhy|Ai8mjK;r-Y>zA~W$AEs^RH`*@iA?~<5!jH~W3*EF3AfgM(wFyl+%Eq)P zXcQs=3l;P-A9Vqsa`&4sMYda_S6@=wLLN;#Rbh{~M;X-kFotxHPP z;_M8JVW&Gp>+v{?(|L)79ch#dljZdzK~vQ1zKTKQQc~Glmm>u7vUpF%uj6Bkcw2#D z3>@qN#vR*kslR?4cc_@WBn}+_Wo{L>ytvtsD3q_c*#{qQ#2j^Ile_nIsqVDv1I@M) z7+P7J+`%H=GME~feA7YC2X4DRCloYR;CO$LwdEnMUj#F^|9DgJl`8k}9X+X=0 zbeF*t%)DctdV+MFPH$fO>wmfie>0=((DmOL5;o&?WluWze*5n}-F+ib;_6U+LSIh7 zf@Dw6U7j0^5DN*eT=<(MMoav>FKnKWFc9I9=aZy~`-J$wfQ?UNS@koBRTUQIZc!JW z9iM2gY7?~xcIXAZi9y#t7N#wZ+On-}m~(A-R+<;O186_EX>1C{zIcQ^$BD)jI}?lQ z*zjv3u<c1S-n4d}ORl&x3P671lX&nh$VvCAzD56xrM3NA5^TXlR3 zU?W%4d)$%HkCS{xuB|GYLHj(X&E5@#-;$5vPh(3>Ps-5Iw)LnUgixnH=Qzz!``*@U z78uKu7OXDC0CxE;WjNg{wUOiNL*9PsyYsR0#t;O)>eArSzP7&-C5QG(*0Zw`U8B}k zOc*7?^<|M(%O;eb^`r#kQfoPW-7G`be?blek%cngWrj#8k%!Zsfm|dDiIRcvksn{T z8@O6J;?xDMkR9jL;$L9>@rSMlbcNVI9rHbk_xVGf2rRpM$Jdm$Jx%?;*k}Izm2AqT z^-Y|O#Yc%}K1==i5~Eyb291_UXjS^c6a*D{i?0wA11E7E$GT%Uew3uP!GawJ&ihT$ zO-4mTR9hjA!zXUupdr{3Y_Qb65p zdogSAZ2Cl{x;1OWxf7LIByRM_m<5YJCK;F5;Dn` z{RLAVflFAx!!j7)UkTO;qL!&1m>Y}Ori!4mh2c*Il5_>loa$Xq#Q#zgOfu4kU(<BeR{wNLhI};qG~3zScurzwvv7_jKz^OOjLY+33YYXTuNOQ5VDM!vglbpaA)M} z9@ypwyRJO2HTFmg!!rS_xQyGjBQBT@GXzgYF`Jz`m@XUxvx8wd_Gcnfo!z&B} z07FUz5iHw3-~PPc6Bax0a)hl)xj%ndEs~Muffws&sG7piHIirTXImIrp3>mdGV*(`?tCZN+pXT=+{fNk z_N%gvz!#18H)gqD>Nx8QJhr{_2Tg2mvma0-3$~yPjfUqo3sT*3YdBV@qbl6u;`nft zRVPGTjjmItVw*qeewJj;ta`bQsnh(y74JVjRpgfsH|2`VYI+f-Mn3*90CXd!??}ye zgZcXxAVxkd%Ayaz88cuLkm7kDnjvL0)(LuQD361W%~#_3FJ7na+5nFt3{`TpYzN*( z;@P}_OXS4x;lbLwih?nSks_2pyu%|`q|hKyNQo79iky}q`CxFMkX)Uf=whX%#9@C# zHAF;1iVrN(nfcc$t|?`3j}K7`J_}Fw)@YxR3$q2!jt8JN{dB``a7 zeU1U&jRN{-)4pECafx}&8($IIh>R1UCs_!b>EOe)6F}Ei_I0~ z=sNH;&K%{O@Cd|&qFB3()a^A}2|>IVB?li?GbKk~B8^ZKJ1LG+&aD%&lfQ9af5sRG z*e82($Ny?@Sum*fR`bV8gxchZ(@IVkU42<)G^rmw5c4K#6*I0}F51Z!>-gunoivY) zNNJGCW-eNaguFDImU$VsAXM1^KoN@RfPQllTWnP0RHN`vj|VF0K|qWRU3J}>*!Jj- z?i62IqPqc~E~wK;n08?}b~8K!9_3!$oALkt{;whY?Y5s}zc5{{i1!HgDL7L63DYtp&tq)l$qhQC>!`($8=^2Q|;AbH{_mI(*i z=y6XL$v|Q}r#YH&_Ba3}C`!K+JBk`{KP^;XD%SR1+gM=BnupH173uMX$s-9;B9jKg zrj!y6iCqE^4r^E%hV#-u7<^;_l}OoKG>=V*Sc5dckk&J+3QT2txlrG65ayWq zu@Vsf+WIoA(X)4`jWG2n=PA0`P8Oc*V!90!=gyT(3 zz^LuOeFAo}5_MhN^u${?he_TQf8Wtac&@&O>X{^w67racGsKc!mY^ahbPUR3gh*1h^a z*9@r4AOavXG3H7^yh*#qTWp2}Kb1PdK_}20Ys6b_7jc%gBtM*j>7j`{% zb9UJrmaExM`jkMZo%?K7spn0^dYAEng|7$=8IL6%QPM$_l!p*f>LJq^fpZdZeL0MB zFB4_VuA|foO`xi}C(Nfg2~%3ubs)ec24FRFR8dMve=WM)25Fv!O;e6D@%=Eb4c`(^ z38-rJS}CkBhmi~#P_p6 zR0jql@VdX}a@+RAvA~o$0<)n{VGBNYD#S%D#U>yDn2h1Fb_+Gw#Gxajc;2~`8iJ%j zG_N!nI9VGRGw>wXTu$~Y-pkNYh#}cA`w&stUmLW{c%fbv{0URiFEtDP>Q_{%%+7 zZS}907(8PCgE6Rl8|7u94;O$X?;2U|o?p*hXo7SjwXsgJ6avTKCcdw;w_F!P&no09 z$j8CVxJPP})Q+=MWpb6Ww~T=rc97E~G+|Bta&B38Xwk9Y5=rfdx#63~Y9>zOE>tow z_mKT(=VnNG~rqUdj}Phg%%d*3;2B)h1uG z#!Bz}(N1~~hC`8iF?Vls~f$F0c+sjn2fi$En{ zaqk~K_MLJiJNocx_Y7&jDtMR6RccydU`)kl8d%Iqam$U5erlz>SOHmS&#xo@n^k6ycmfLh*PZ*|o|=d1 z8W%xMQ?Pmw`E}GV869=$&lQVdt*XZIa8~y~A&7*D`}wxvF6P5s*<9CCmXbPe7giDF zny?eWS{<#W75k%ojpGzfHO(i`afXeSa&%LU8j;)uU;VP?LJgtW>zh$dakv(c-#0?i za=)E$3n7Q&(_4$OIAngp$3v`75rdV`Mwf%qGpUaRrE10$ETA!V4d%&4E&7hqN}BDz zwLC3|t2o|s-<;&$P|ThbdXy zSSFa@I{%>sBJO)jp>2T8QY0SZE-8lseB> zB38jR>#ZWx5yZRLzvZ{;w^5Qeu@wQ5XF&`jX)3j02#Hs>ieSs;W$ow*?-lAEK3ncN zO3KGo_J$xm1PX~J^fdyXD-U~O=n@KPY^Z2Iw6^xDlqT37KV%Xw7@DOf>yzFlvlK=U z#ho5Gh^qo$ZhC4ynOgap_E&O_reo2?Z4m&9LvO!lo5P4%z zucVL<8xF_kyv{r>K%FrT%7{gwXi|R!=rss>1e%?mlE2&qAls^i(@kXHf7DWgP`Ell z-M|Nk=#ExBt#T8pFT4bD;Ujnej>JBs1*NkfgSoH z<0L$Q+{=DPa#uKw$jtk%flECa-hR2H&DX46i-@OmvE+?aNk~H-C2LcwXLY|6UaZQXyHbYpaSb($##PJXdl+pa!eGQmmZ0b7Au4OVTQ=Gs}^I4@k-Py^lGoiSwFEz z`N?~^29s;kVFTkbe9(0ScPuXeuRs>{;)^o$r(Dtyhdb;q#08zpgQI**{uOpo3 zN^%JntAr}PAcs!B9-F9K9dpm&hbo!670F9Vj{6vivOe6QlG`z1U@8t=cD5hyAi(&o zg#*meJhM9c{5DmmIek))1G!=K<5~G0Q$sG#mwgR?v0r)NwcwUzP~e3}IxV!ux+e#4 z_6{w}UcVR-ud%*{Pt+_bF}fZ~m{^4(Exa>tIWQ@X#GTo+6QKLj-Z+WZSdXH&mK!Bs zce1|UvWbp|3cQ7ybZ-4D9!_yDG|2GL;Z>P`zHeVzxMxY zOR$QD@03$V!nd^*N+EJN3#DsQ_eU~l7-Z^!5bOOu=lW)+L< zTa|v=2LdVe%67Q)*7yd!j7D^cysvPp&zl95cI=9;9S=0ae2NDIov8%Qb94IK0VsWc z@9N)1@paoDy;ps-@B_9)xxkBw$2sT#YSf0KHy8H$@-Zi)iSjaA{*f%OtDr>UyGeFX zm-O#{^7~ILdb-+rcKq46SL*J#&(6wLrN+xAx^FJ%hvxTs3miNTY{W z=vAN7aD8_p)c9Y77xJh1xRK3ZZS;J{mzB+WT*EZ0spbgYSKX5JfYQ@xr6ciJhvO5U9C3bk+r-KzQQ?$LJhr zqMIYPBT@kPhd)XL0=OtRRC^3oRITXQSQK3Z}C z!H?SB6-U#dFR96p(~LUUiWpLrqt;No1>2Do{;sqaWQ+Q+<%-AA4xilS7N7J7H_nLi-+W28fCrC zY<4{RO2OL*Ar#GDDj;WeV#wp-hjfzhO@-o?Vpg)F6;C1v*1MsXrOs8_iZ)hZPTQJn z0IVP%7fIfen#uK5Erl>YByj=Z8vVf@)N;&_xU`F?{D7_S>dtf7))ao-?){EmA2jz% zj{6=5!m2vfRz`*y)=;syPT<(c8!IKH#-*fsl&zrspvvJ500j9+YuOcLYnw@xa72Xl z3Uax8L7FxZrdgEm;$!=hOP6YFo=(S}))zYBNbq*upI;myIhv}GErRx4=Dl2AMr;@l zd&vo+@)UUM$xlT~X6)Nv<%zk4gy_2Svb%`*(bNvmK#pMU^gEhcjIExd%$;~u?YN>> zWb+Z<>e$#i;#>1`@&uth~-@ZF!#|;ztjwFC7mHeC?jD zb8W%rlNc+bL*E5Y?Dg-T@86j#c8M3bWB<$IVAD`n93mvl-OYS`O?&G{N@?Tce8EvJ zMVcGDCVF@Qgo1U~_iL2>LMx0%(nxo`&QvZaV$$MuRI?A`Y|Nglvffn$NtZ5w+~UJ; zt43!z0yjfaWyPXWg_BOlZBYFkxsK8p8~WTvJm(DKFe{vrUv)}Cu7`!6%m9wDYn!Fr z{e7HS_P-BxUk$2( z#w^}6I97PZT}e>3M$_UCn&(nREnM&4ubTb8<0yZ-uAi3hZ)uDK21?;_?euiNAOjv)^ChPl{(KY)XKquAXgOh3GDU%y>0HKUm9 zdnQS98QN5FTLD$^hH+{jXIeHJ9WgSZ9<*W=c+_aMMGMSe2VK!=|-NxBkhV0v$TTC{mH)e2XK zaD1<-ZBkdy%`Q!+0Ohagz^a8(mGWuo>(nTbl@ykNcvz-05u>`uKu(1YVJsK1%Rf%A z6yiJ5mX+Ue?_gJK4`fFP-y0L-{hw<3&UXjG@Aqi=9a-s`HuQQ9uyTJ}ID7PboUZLz z?7fRGjBkDzu2OuVDz>Hs!tEHrg0l4Zc%p;Qz39O@fvU9DFp31{YqH<|NJ-2w$37z_ zCWFMJUvpd$3c4j4E9j~93p#Ko)2IdFCaQ-!AWVFY_!QqX1uEwG22W=Dt=0IR`OgG> z4)5GqjwE}buXytJ^LsSg==+1XNmsHvY`IbKO{Lyw&2%NUZyxhrVt;}6a^nMoa^=!y zUu9Wh<7Y+q*fKVMv?9)zqdZ<00G#6*){L4?j@C;Otvl9JWb}&r?5A>yicR0g2=K%> zmD!I?Q4BC_5ch7U=Ox5|l-t8JWRABzb`ev(+7GW9o?)BkgcOzpx307?jcwz2{v9Xb z`|139dw*(qsBe~!Jz8j4-Lx%!<`tZBosACt7}?xlXay63y8&nc3ySYSx*I-egZVlq z@|7Yv4X3?U=Bvz2?= z(G61*MF#lmcE_5+R``@8D*FwOx72>^%y(Si?^4sZkh|{|$=9FlHVy<%h`w{ow+@qu z;2O?}tr5dyeFV8>_(=>WM`H(yaG;)=NvG)!p%enCt&e|OH-FK>31Cj@&S^i(6NezU zZ(e&(oazgm?^6yDJe7K@j$PL0arwd*CTod|{k{+#>4DaQ+}CTZXu}*r>=I9eU~9$7 zmYuDjIVhMC^kTFtV({Z|PHNxq`yRQkJ^S8-uze9_TXn2P&MIk!RHc?$&}C)l6?WC- zVt2FCL}$c$RE`%;O;qiWKn%<%Lhp>0=&PK_gLkjwg}g}>vI&jHa8?A{N0RvrqM-L5 z?)-~?dXv8X2Sjyk#LbQLrV(I-G=A zR(8UU&zp%SAANaYA=RA<)$s!U)efcJlT*si2k7&7vS;JkM4rh6Ifp2b;+!*$w%}=k!jS4lO@hO=|3wi?5D^oa?oSn&KfhTylLIK~v{X znjI~fGee6NX7feVRfE-U8lrWjEghu(nZ1xN0wJ)<2lc}08{nj1!%edZdVY52QBd489&T20H;|<+O5;*+QUCOmS@)c;b@X{3 zn<;F(-sI+FJqBMbe-?7H?^M&=@?6SAQbq4H?fjNWvP>}Z%DMLVko0!_DDC2GtnHDF z3YGX_x!-6So=K`>8oDtK+C{0=eX+^$g0N?1XbHlitr*%H1RSlUL8<2LeU`;Y!l&&# zjen1J`^uih`75yiSNFB|rOk2L$;WU^q18=hS_)^+Z+7 zZ2D#Y&c0whaDQq+0^b)S520$2$GUL(BV}3geB^rSE5*i|#?kkYKE56I;f{4&Q5ptg z!B?i;Ps|DF963RH(ytt%h?{;@cP;K(WNfO4C+ddP`xox5C|T2~P<`|M56wD4LC49# z)5F?`No*K$4L7SKZb%?is8piMt>86NUznIxo>!EXo#-!XeqZ8`)1-JfN zINbUDDt!2D;bVAkIXVj9{~YXqxX-REa_P+ftdlg1X0;IhB}k!Mb~-M(9DUr^as`4K z`Hb=1`oeU$ax<9fk#9rj=k!5Fui};(bOSw7pX-&gkUAVPHETo)JtbZM$PSb@-Zx<& zqXeBC3d&E*ueVpPo%ldU%IRe)OZ7MRuTBmcUuerbj7QY)DT@yl4Mf_lrCVlh_n=CEBi7v9COhYlu;a<6Bxu^ACzAJie#r*jCB@NY7RxqoE5S_d_DAP; z=Wr=1ee&a?@iZg#ks}k7*wyu7recGyMvR9{o=&br$H(WP7Em@}cwmo->c+hV^GV5- zV_1p6c@T)ugRZgDH^Q*kNsW_Z`%My}+BDR7ABUV*6OuVkDWVjCsJ`KP+nP^BTtZk| zyW;@1`S^{KmA6VBoKSlA3Ikw@VkD=nR6jH7_ryppj$e|w#Ss35=Vll4e0hNoerXMd z&8~PC*Wfvl>n3tS&BN?cPZl!43lu;7bMJ{VWQV|Lz05_w6|okLbl5Z4P7P=`4bSsR_6QxZCOlqsP-*DVIT>4~?}q8{Uo`2& zi7OXv1|8bKCmZ1=c(QFmUv;!gC;Ol4^9ei0;m6hZRs5{wm*2WkOybdAgmxs)Hh>%}MoP@-eZ`s|oXcjVaflj(Y= z$>?F=#_9*PjM2udl8yvhYpKVLMXgb8!$7dORV;B#++>-DGm`{Q;W0|{9AO8BEe|Z_ zI^J?tc&P(M8602dN&tBlMNgaZjp)9AFdLx2Fu}3M55O+_zm6G-fEdA4eSv=wnq`<` zZ{LL)i#ozDaKN2^a3VP?w49@-BRsujLD!iY2Z~p#uu@kKJ8xsr2kEjgkVZi04#DZV z#5qRF+jU07+Q&#zc0|*QI2~Pu0S9BKz83Vz1i{+VI3ReAW=Rfqlr4%LaCaz~DauAl z2jANDU;ke{{6D{QR%tM{J{Am0UXsFDDt>a^PS%Q;=cmp|uS}OO%BmEwB#!a{oaCpv4Of+f5zvD$B_qBnDY3aFcnPY(XhPFqg(<0OSHQi z7SF5|D&KUd&uO}7&Y$w`Ed*-m;&Z%}E4&lH;oS?3YqP8W{FENRN*0rMRCv}h_Tx2@ z#*1!&+P}CJr$bVy86!*VKB6f>tssufBA0onH`E&r>MOZ_^RgRGZvGO37a3_E9ua)f z?&r?%v7en_zVe-zwy$MgtPJO^_$hTlLx>oM6;oF;j4H~S*32)n?zGFsROhaCcAa`P zt_~27I<9o->%3jht|1*Cn3bwhS$>^8W-hTTZoYLidXnHbq0*y&j^(VasR zu4Ev8dARVkaqJ{uPX0f|eRo__$=bi}uIt)xRS*#ftB8m|P>>Sp-c>;Q5(tqJxQa+K zp@$Y=_bR$ll@^h<3K$^}q$UsutJ14t*&jP?(jJGNGKF;};&F-g-hD|lV zMoqnyS!r~vIkkT^e7fmPo#sR%Qc*tnF+IB@TZ$+cgid|nMZR5w4p%#HVH`-;uxMEL z5HPJw-?LElO6+`Q1NG3$b6rg6fh1(sLE`kDn+r+t)jB2e3B$u&o>1Vtfa+SdC{(+; zV>huZ@iq=xf`K6t1}f{M3*=0n@XKC3;hPTZ-Xg`TP+W+mJ=BPP=oAKnWy z#^IlQSN8J;nVY-VW^L>Fr8?l_E08z*IK-|Go60sLAm~p4A2D;c4BNmJAByAgEnnL< zA~Cugq@>Y|tG8P=WJ660g*Z7l#wMD7#HP#o@= zPH0W(n=>;ic74`x+SS|CP6M!oh`(Iognkd8?EGzOP+u!-lXV{g#)FNs_wPCbM{#C> zs2nNjTt%~MBm+Ky89O_As!*{z6o|5Y7k|nv8m7`9Dim8yN$fL(HAq7}-?gfo>47y= z667s;lb&&rX(DYN{<7it7{v?hgVGd{2%fdk-Z^I%U;PeQH*n7p&)N93J$Xh zTy>rRoggZ>6+9JpG)cpK*fkTq!WHe@dylTc9v`9Wo4eiDemTGAUtf~C#aHbpd`l~h z^DUN}>05Fgjmq@$HL_UH+yHaD}*gEf&Je$6A!;L{l+oh|2$RCW4z~moE zeMz{4z(-FK-+pp{`;yYHvU!_bH`&0=I_C+f2;)}|QN9~$j>^#rI67c)k=djw=HbvD zA12!1_FMTv|DGAnlw(74vF+PScXsfxy!n zi)4eyjr(_-=GyIzAIm%6DZey!)tC1Z|FG+LDe5jVqxMy~(S#l~6(l7qfT{(O1dr0K z=QUQcCrjIyuG5@E!CdKv{+8ZDxmhnyw@ zxg7l7yW6}yP0)?Bs^wF~yWK0%4f4dS-S}vCF0CyTIm8+|9=ct+9aSB$MUyuLAED#2_%bZt(xhCiu*uZ zM5@Oy347IKls)otmYzR+|72ck7iv14fl0=#ljfWX&jXq9MXY?Zzr=d4HdMSblO?r=4D-8n}Q7 zS;_ViGF3KIRD0BDlKhr@xM5x)Ap7P$^=AgS#x~42*gYRHBj$tbrb$v26CTQEdd=ziKWCuC57U*s{Whq_GG4wS|U!|p~z)3!Fu z4gZ#H)NK_v6*^lDn}yv2ahm%)^C#eQyow}*xt?sV0i2Z^85edP-suk_M{4wK#mV2deCknwOl!a0r2_cI)#TTcx~HB7kAfEHaZe z)K25KAsv>)*067@fO%9ERP43;8B!HA<6=7o?MXLl(k23FUAwP{ZWw_gw+jPKfh$2;6a#Os?>}d5b;x|G7$AP|I7jjrh;Weu=s(MUT0CQEQb$ABr zIn24y=x%0}KvWIqM*n@AhW_iL+#A5(t*@dOtjKXi7KlQ>v%<#;*b8ZE`8;y%0O45dkuXw@tM08|R5fS6U$BX_uXNkAt%3;+F^ zMX}0W9qdwr)jWXfAeEfZvl7Dano`Zc(x@@WRPb%b8ued@>0 z9MZNZ`C9wO4jZol_w$fs4}1J%o?UH5TL)4$pM#%zF`pw$pzgS6r57ffPzs(cT`@PpSYLz&;=(;4IBeMgG9!bp14<9c_wY4YIYZ z6Sj{CwvP#B$u0W(A2fBmKVp3sfYp1JfDp$|DuT2kOqGeK;qezWDmqv74TD-l#%hgi1{N__ zq7|@E<0-@*nldp$6zlV1`fP7y>Nkf|!%ts+)X?^Z&--9;pj@mC>CnVk`Qq5y{Cl8h z7>n{*K+34BnaW6?<)o!j-I+xdAPmDvEQMSurS@d4@58P)kgV~E6-Ymt3;0lWT$|kJ z4*GxI(d9o>KK+HSb^JId)^gYS%OfQ+Gn}J(-Cp25Jks6(2(T=WkW@rypJ}Ba&N!iZ z?)kI9jyt@s_EEnf;SO2xd9At3}J(BAECB=nE`Z~*-bq;3-3 zT%!?B0N};c<$=U5=WKd^zhM;k*gQ(Q#pgtP8qYco1pEgV7nKj*!b(a6 z|M1BQhryA-=z=V?<&!D$`xGsTro9O03a;?bi=|XATq6tBh&GL;=M>>zKiYt-=xgum zK{JmK*2q)Dco%Sqfl;n+Qhe4LwHrZ%xt97V&x1QePiB>}C^h8D!Cu@?$QqhAnM~;( zx@`l~$cDiXQEvfKyjY^)Ac(=4p&u$2Qd*%zvx4TfQH&>BE$;QNz5-GYrbH99N$>;t z;gQ60eLWb=F&&}&e7IoVI#k3f+8aIZ&>Kn~qk6V!$`FmZDP2SGg^8xP7C`5}DrD@A zA-c}{O7JBR&l$&QSqwErrlvxGR0FK1`+Sm3rkWFcY}_Zlx$)Dd8QD-eZm;hsZ%EGWF^36SS$EA==&Iv>wW4NH-IO1G=?SsC9}l_@K0e?N8-5(i z!GQ&$mm5Oqrve}A0Ct#Vj$AP8e$zSeXbre=x@>4QPE~14Qzp`Ej88*MiG~lJ7qp^f zJi15s2sV$uE<5lmQfXo=eIW)pTIGRH%uF(Rzx$sV+lkuPP}h%n1sT=P*4ePYDY`g%{)0Zw7Ys!S72jZB{IgKK&ETPQcq z&9Cv*0S4lLfyO%-ZvTmBZ3 zV|!;RTg>_>R`1R8xnHZN1CCTY31)S{st;D~D0!uPgMmEw9=OBH=p?_H1J z)eh~M9x9UT^Rbd9mou}QCUWonF^;sZ%G!4}IJUcN_OGCIp4#<9Q!x-|2`C6H zM`JdkEWB(J)Dzt>rl<4iKAw(a;^~N!Kn{{r3@AJNAaru|eUpcY_#v2QTRIuuxI$!FJU-I^?d$}3D#8}`K(un#ITg%_b(q8J~|q%*kJ z-Db^71tPDR+4`*|GFhrZyr5MVygAu4aM8s-iff=^(-G0134z-x6{awf``=+_Gu$7qYE1HZyfR>2hmy4u4uQj8ZRSlysvEV zOx(Y15%J#?c2Adbwxw}kd4vR9TxHd+O|00eT}<^P253)MWq0)4o}GuNfoE?hm$p3^ z(T_|}8nUaPYI0qn%k_<` zR?iL2EZ27cPxLgk7hp%ER(q*f(Tl4kA9meyn)RgoCMX>L-;n zJy+T0p(7{GV!2pe!;$LPx3B^uEIszh1IeRiBF~hSbM(2ryPL_i@`B5T=|8QiUH@S+ z#eIe7@=W1u)L19?b*Hq-KpC%FPc&6J9n<6VRC1Iot~Nr?p6pkywPwq)2by(Kd7npw zr7=9^JKGgxk{w+K6pI-7&KX^qRmRC4-C8x1i^>pHltNAVVy1h9dwUwI?j!YV{ zZR9QzOS6Kyk}Z}P&Dw-utM*I&am=*t7Cs?ypTU_R-v4t(+Y z*A2|qmeJzl+$mVePIsbc2j4Y&|3oq?8Vv1vPTfC%oTI96*@fW6MEGAzVY^>dYNTbJ zWa=)7^;bUXHe1LPqAf%Z+^EBQyiCp(&{v^(836LJ<>dK|uRF)*L;^*99mdX5VaX_} z_>w`_+M5;u1zunDvTo>^PBY2hzNF+MK_BhjTeVLGj=^&43N;fuRAn+O!q3b=&(EKY z5*dxw$(at$z6a;_8t^zvQCF8Dd4j>Oe?^MUgJcDiOHk~_*gs&B= zCW*S-2@QMNUKOtO%(x6m5SK8xoh<>_Ts!t8DmPSkVWF4On~8O(r*-43>+A4>a^0Bn zS^<`1d3l$8i=L}JK@Su=1XUD^dfx5ST0jmg>K?2=neh;svOqF7t5~@)t~%qaR?Cl# zbc{Seexqb|{?}^cnfA;nF?oN$2g^SlKW>yQQNhfeX0x(Abv*IBi5<;<=P$9-wzM@1 zI}4jujGe9jPqlAp0gu;~t-FCV3VdTLZ^HD=Asrgh)yHR=jSTJKD#kXfbA5~n9W)6# zPN0k+J;=+4O@yr(W&P2j=g}H(@qXWNI2R7Y-qWb+s#pjRK4cu-#pi6^r|VQGW3AQ3 zYlkT6)0&UVS}L7BR<*_kl7Pe4F5|4T3dt&dHS$H|PI6n{(vOy3jRE>U5AT!wKNV2V z=SAel$TEI0BGW6+rxOT=LAhaU3|{TYtu%-R*9EvA=!evEDT^YiU^7b~lmX*V44|WB z$&}u~-5?v5vb5ql^qj}jWoUAi%7X!in@5G6^6d7fb<2)*hkDx%m5;bd*D=WAeRwpxP)Y!! zp!8dw$>+236@g{F+t=Q$Zxw%Xy6n&=tpDb_U6L)j_jy$gn{?pks5J||lguawLlPB% zz#uU3t4fbo+t>s(xP()ShaVO`=?QpwTuZfEOu_Mo_FCq95h)=y(DWkakb#!4?jH|F zhXKzy?I4YAl+YyuOcQ4Xn$w9tj-Wk{fP=+g1yoV;?>ztjQPXjC-8jb;a^WIB?Ry5~ z*+2%#y1W5g2qbAx@ss2_ek?}dQM{n`QD|^eOK{%USYsKZvsgzkoq3;EZv2+&0jco4 z%=?J~*^R-VYh9+N`0#Y72_ehqt&OEaR{rbm3`@{&Tc9{!3M1` z){i?fhtvMNC)cq?SpTaJyQ;z&)1W@52g9$vPtT^^O<1@zfb*-y?4Q3hahrK5*U57D zdiwjtD}8NHO%Xt8sb|LL_T%u?b-bX18H@X-H$(*n`Xrg>Veq!)c1 z_~Sl{;Pd7oM5gwIblP8Wk+-08g+hfShttEYjz#8 zHk{}aT784C%*{SpCe=@G{*-u2T?MiC$={6WW7Fq{?Dn2tdADPK+ji2)KWN1d-WYrC zwZfv}JXN3>V;vo{6KJ=Wvq(Cy@K)0pu936Ip}9%c+&~YFW;>Rs=7C{$^|Ftk!+Dfd zj9tr`()jco1<=Mm!&lPsYOMnsk5Mmawb&n!Wc$7l1e^5 zr`$C}&&q1h9Zv~q=XML|0G-#O8TST62)hrUa!8^qC5Os0Z{0DDm>qD{qu8IDl2q*M z%=ZreS4mu1b{7Dqt5be!{8sL}K3ptG)9P`7%LVcl7_MAGvOtbjrCrxqzv${P=c&15{x`=KkuH; zQkt5k_1`WewGy(QG!)Lw7dx4Y$3#~`%IB^#mJnXviTe~C&nVFZl@z%Q-l46qS>JXO z937S&D=4vEiNr`u0S(Qu$d&Xy3RCJ1Yw`9LEt zVt%1jw_lH6S?0YILE#)wOZWUM9~1axCQ;z7+#P- zk(Z)ak$FgFP4U3Mw*>_Yaih2HTQ@~rcS=RWd=ifiyB@ILPrS6uXTs}aVq=xYR;ok! zfSoQ!HT;P)WH2YhUw36l)MOO#BZ|@QNW5|jDJ+(r_=3F->3vX!kxuc;ul(n}Z2oiz z18~(}zTVaXL;|tFrq?PT3Hy!9^I>RZKiuZMG6 zRiMB*Fh0L#zt=8-dH8vFOgTEN%ELRot-B9qf)uC+yQVrG_16Ho%u4J#>MtK_WDU+) zOSB<83cbBYPQ34DNt>46oqP}Y=3PPAg#yk-nqa`u(&9xIkdqDh3UwO5){d3~@KkB@ z&Le2zg%MM|6ba&bLm-%En1gZB;iCrEsCQ$+3m?~l_@t})z!|Bo8Eq}drB)lh za&1X1t+P+iPcTm$pV%HA=EstzS3Hq}PREcUjFwP1^iB{lGdcedxz1nz68&0a?003K z4~$d)4;F(je!|&JzLy^EH#3S);!+@5xH(?!RSU*x$<1gAjsUztw?r{g{g$&cBQhST z#cWWPlvI20u%{>Ug+-S3+?%+BF!XZET`5=CNv2herM!@7-t=q`_iQA}$cHJ~7>B~1 z!#9h8lcTz-^^ahKl=XU-{C;jzK8>JqP({#1$3lxzA_#8u{ED$WIYX(c@7m3^vzh zUU3`G>(S}ub4TNgnfc!|q~%vP{crkxz0dk5`#0M1UEi`Nl;d-}30H}Z0xlKGdHVZd z)aFQ^1dswt-aDsUR^Vf96NFg_MqjTlIvFgFN+1Lo4j9wr41wSemnLql9E2`To~TLq z&d?qKPO+~VlKmz)g@uLkAgf2M#orQu7${F51}dOl+Ss&%DwPxm0%P@Ef(PiY`?4a3 zGb01RU16v+KC?{VMDMBS;4deZ@8voE6m$mPPQXe+dMUX*GuN+$!XxzgENwhT{@5|h z&5`YB+)?>=OMPRFf5t>@{`z34nG~gDfQ`V(%fd$SYzQIHYfZALmfGtv++c<4UBsc3 z?|OsW5O1W9?)et?@TQ3RX@%m^!s@20ov353g;;0(xT~g4alMi{MI-t_8kH>p=d~@A zUUa8SUCO#b70fF}h`-keh*p~q0OG2K73GTR3Hkg98g#ht``vagHp%$-{F2lEtiz7# zcbm1n$LI>Jb3y2qaxC|dCD`KRyfL+Gh8-~K>MvnM_+9g&X;gD=s!nJMQ{KnG*GU68y2Rak#8vEgSizuv2n%xbnM4j%mQsEG zmV8evMl9Rtv_S|}tDqWy+I(@uttv8pI$-o7kQeFpeE{zKAHhUX=1re&p`q}A;&&f* zar>^$vE@sv!4obeYg(SZ@sBs`I-8{b|9Ea~>x$hy5#@P3H}9lf=F(Ch9jiD5z%2Wp zRjynT?07HZpBd|8^}D1LpttOJAm~_;lyEyH^&MMNFoyXo$vofe^tktFyriO7!}Sx| z@AF1+{-@7;SDA>qQV*nsmhN+A4z~MP!Hw zu^^y^Krsnp0<{d0F){_2LL~%bHh}~P!O`+eX0+_(LoJWsOD&PmSRYp=cc z+P^iNwdZTApj}oMLp^lB$H4l>z{kO$wLZ{k&^zzEv-O>=@4Y^@Z`=O!v17*$DJd!7 zef#zuJ9h1olG-i38z_*Hmfo{x&%S+o_bMnTs;C@Zs|DqNHh|uGYvTsc&&P%>Z*Si8 z);k+Fygq&|2Z1(hd~4IL_3Jlm+^}iWwzsx!TL0ySw>C;`di%ic&0v)+(jTgx2ne?Q zNJbm7=i*6f;HQs+J}>_2wEYKmX0=bgy_S^x*{w?lYovhx0RHRkO&i``zXx!O4R1;9 z25$`b@Zt&EPY)C)J!yOO;;WBT0tFE1$7|n!q~6*1`Q}p_H|z$zwHvf?H)yRFv<p5>$^1qvwSp(G~$$mS}6v-<}P6QPRN09;EPtI`N+sx1b{tVk~c0 zak22g)2Z)Uzv=3|H`(z1)i=+6q<6S&x%PD2=x&rB)bLWntq?eC8HJ0DO`L`Fsxsyg zF*^+QHnNf*j^r~jLr==)E%?Lu?ln+*38i`nc77gR#MYjPswa+6+N^yu7R#9lMr zoYHo^bTtguKlvcD{6w=Ue5t?AgJuddPLe7o_EWc$UBNf3C>Z;+_kXO!o1gEpI!$)y zF(#~WX}(cMlgmrq6R)ywajGO_FyGf8uC($TJd-R#iEM23JUO@M)vkr_VWhNC(6YwtxIKp%)yvMA1y7 z>NNFw46@v^JA7aVu9e?sB|IC_lCJ)isj%alO(4+QKy!W^N?YU7XB58#H3%y5e2pnH z-75v|7ca z+Y#4tm(ub@T5?#)&5j3RXOwDV2TzU_LyhhYahk$%B**|>h}H8*#9+}fyl%+(;?4Gp z)UNT<*%2Knb@A;dq9$!0i1qV4>s9Nu6W2gKcM5!pxk=2$rckgqxs{9FUD>-}DblqW zN1mJ&@6WdtK5n*1$$xzB~|F!gnY{{t!lMDk> z!I(h{TUdkSHiM;RDcsb8>5`if0~k@(1yabzOGO2%(c@yVOy-OHPQh|aISWD#%heR6 zW?bsxHCEvaC)u~2Cl>f)VBRbjws~h^I{I4D^Q*ho*|OpNLvM2Do%i27`;p#g@~i@i zeArZXJqzlrUNUMcB?ZwTN^G5oQ{@ud6Q#^8&#HA_c@R^n`^DN_?qN#%bfu+uV8t0Q zze=Dj;8d22X=8Z)%NIrBh^e;jIuD0=te7&J-+`m_#nsh)%Nybi;q7HqQszxttB*vv z1ERz2D4c~HJMB{oQ&D~VnAVbqioEw@b$xQC7_HPQ}D% zAat~XTGv46!30i+&O%D|9f};7+fargLn1diq81@xf35 z*zkDIa7fX(+l{@vI*m6eTm+|2G5ayve|3VP?q=6<|RY^rUx<~;`O zhw3`C+@Ld;)BXu&oM}-jU9RB5W zf`-jawBl;Zf_Ik(eH0 z2o$UYE(lw8=<>LbIESC9tK3JcY3)VtX2|`ef$ILZ7^reuwL7R{>U|rfqTgMl%h)(I~bg)`{PcV4)lPF|vk66p<1vXtVBG{LL$7z8K4omLAkrFb-+fMaf{ zS7k57rN??U_*%epGk+MTH%+x~>nq;-zW=}6^Zn=R_YdEoeaA%$P_7!J68XL>HG43lR2Yt}8q5 z54~iX?A@zeqS|zH8l{=)Zj`4h)mK99H8l0Ftmt+v?yH^{c$pjQsJM_-h{4FPactwM z!l3z=O^K|ZtMM%C%BQyke;(u9Z)Fvlp4G7~xfy2JPK?hO#+I)p2#pEC2rEbY9gRqvy(_Je zEsUx{PRZBSdF~oTDf1o<_@>RtZWdqNcI&dxzdKE89wUx!(b{YcJu_GtF%ckpM{I{{ z8G|^-GEr!QsiQ4-h)vhm8~fJPH=CSJjO!0QwNbr(oOorvv|4$}L;BtKEZ3L0+CNz4 z9=!y9X8pqe9V;Y_bBQhKlqn-bv&95`-$)3=tI&z0XwEEsCG7Xn?HR?H*f#;=|0OWD zoncrW1>dpKiC~_dbAttz*~&c02wnqynik3uBcJxeGpBS&TMI|~N+#V=N}(N2DX+RJ z{K*kvh8LPl9$%6;Yf8uCI_Fy+6g^hO1z68M=<@`7kv1R8qbh0M57vLPY5$98xf_&- z(Gg@)GJlYj+{oP~S5oA5XsNlF+%6D~&HKA94%2nzQuN1XK1OsZp6f1{z+Y?HE2rX5 zw$n6m)vlsPG4rB(n_(Kx{oQ{0nt29aGwC*M0~(JIfbvS-Vd3-r>iJ9M^|RmQ&-R>- z%$@2NM%-Cakn%WMtv{dFk3~k-`lv3{kJ>5@2hCzTlw)k9)|bUK(9CDwE=G^7fqDe1 zSDNH#b>w(8P3dwxe0fS*O8O+hZxq+?MP`EHabBK*1>PIpUd#=F*Jm3p%xk|WB%`PH z$F8g@rN;uQ@!+;{O5Vu@5^=?7R{t(LEWq@4Yxmp2eT7AB;fg^7UxjAv>PoM?^A@c& zI-TN+4PeOG0W?Ic!=Xqk5*^YT3#`61S{`>hH5+l#Ex9%$NH2vl6X{c&L2xRi9#p|S zR-sDkgX=5dm~*Dan;OyADegU&1QTsaxpTT3DRr}gA%?Xlenjg`{EL=IL{roq4iy4{ z+UlccmitPxviE7<;lK2dO~($TPZ)1`FsC56k&#ftZVb3oP$#%d!91jED)&ZVWEf^- zzEl4R=eX+)(z|PZxtRbO_wM^DkJQxM!=&$nPDJ7I({`dG+g3T?AT$zBGbpJC}WZ-$D^wa$%0EX>%+_T zeLC4yPx0b9!`2*sBf(OZ3!pVyEW6faJHNQi@u(wrjVos_QB%H+E!@_ZFWFXEWzslr zKGZqmOU8Xps@BWLc4Els zG@EOC?VYc88Yo=-ZBPAIm$c#D4XO18H;e3OhtdpoUaPeU!;4T>4#RBMBg z2%Y=xluK6%Q$X(n?f+nX8}s9_>(r0bFF&o!mp`hR+mf&PP&k_T^gaS#M+@h45pVX; zdrijDS-qUNL2Loq&M;TornRk_aAPtc(wnfqucpo;LbqcLM68I`x>LODs6wwg+gVp^ z=dN}(JT9)ViEloLHbWeK(ECdWT&QoVtcHq96 zE43EM9v07uqvCmYE)I9#!k5LS@XGk%yfu)@>Qg#HjcVx5@z6RA=ylDS2^B{JLK5oMD1#*=6l?A5p~hm)rvWt89&HI>3y&@z@MO$V@7u z8}?$L(yr`MjI(L;aSV8O6+FgTl(r?!e}|c8oOdP+H3-==?XHSdq2Fm83FAB6H}&)F zYIaU|SWvnJjx5&z6m_3ol`c9;tt1X#Tg&o}BV4LbNc`rPLib;LcDyQQ9MT?PqMPPS zb5lBeGn9h%E_6xWC+KrrKxy3S%J7fQjJJH-LC>#es=z22{U&xQ>E;P89L z2C#fOej;d!bP06ARXxvhyuTvg6$hh}wIp#{!ilrm6!{@b${nJyyKcRK_7j0C08p`~ zyBEL*(wG*QaYO4|bwg8>rx*H(%NmHmlFW$~oa$!3*e}rRFPrbOze#Dl<^9+=u+tQ51AT!ZbnNyyE^3I82#mNi=2OR^nTy2;D$uv zLtiW)9HKki)L1$OVV+k~Fs-I$2<+u0sBt0S300% zMkJHxkXu}MeOn;g{ik~mC)>_`-9m>t1zK6Phrydy&(q1KER-hd#GK!^Y8Uxx%i|^= zhA0tc%N6{^RWe3JqteO%ge92CP$Dz^!lID2JZENhQcv>3LizFpQ`&*2FF~L^r+(9G zzaGQeK6$I=#x;;PQ;XvQb;Rr2 zE+0GFiCrm>C51w}OO-}Y(Ni3H;)2h}(T2{h@*Owc|4mc>%L=qf7eu|mN@-~yAnC*W z0^U$Z0AF9-R$qmRsI5Ol(ial;cfwF=&+?+t-6qB%QKVz5E`G;eebQBG8P4Wh#v|uQ z#29MCM3bU-S-&2W#v-5;QoD>5+bij&p-ce2@ z&OnSuTon>KLA$;*`-vwTHoa|j>Zh|`6S6k78P=7IH1HgWnY-K&74=cuTxL1!rJ@1Wq~NYhcTeU}zl69D8CLVc zgs@t;?5pXWd3-8U(*E7A@Ahw;Z}=*L@XXb)AZpq|e$_rBMnhc7e%f*?DsqHHMn_~0 z?!767`+G6w{R>g$!PA<@U+|9=wP9CwCIRZOPCgS*hiw{KWL~SoQsG@>i1-4RB4wO) zf8@&I%4tF}zJcZPJg~cduJp0TvX8ra2q3a>suUP}ywPJjqLzQ1t*Yr}E74`wi~9>x z{4?W?9^)FI_E{+l(akywRiVtW*iyX2T|@aqdtHBb+sgm|B(nZPkZ3sA;P;!qHSSL9 zQ1I2wHiS;$(3F3~zHhdC{a*dQ48tgCyH21SH>)L0HTV5}C~Q!?NoP8rtOx)0(~ zJOx?>l0+S)w8ZFXbE+o*wpd2HMz(tlHo0kX+I%DwE1&viEJkoGlyPA?_xi>wdwyDl zKHOmY6a70JdwVl$j9|kT?fkfK`=uhKtOa##6=>m|Oqd#XChIIgF8X2Oydb@xNb6ki z5nvD|D73E+!b^NNTVN0d?Hg%}tgYWidPhLopPpfA+UsgpkqaOttgaSHo>F9=!-~9; zQE<&U9t+-ny8w2(zzhxNXv!Jev+$-bHqe6SyJ&ufP9_No(SC1Wg_)P0oPXIz!P7|uY2;u4% zPDtsisC8UNVPpgi4>J4?>%{hT><4#fYZ4BkBal=;{Q>4;uXUXAwemA{ywzj7{5r^T zwKCe`)!-KO(ZGreRo2eJhUE_y>)-1eSUBD{AU0gcQ{g%Y(+i?1YSe>ZlSAA`XB$SY zh!ste)<=!6elY?VH6`lHzznYqj2ccG7!29{otNG>ztdSDS7uPXCc4Sk_BB*b*9eGU(Bs4WR8Jn_(iD` zUUVERPul}!RI>P_5_x3df}-2Q%i}AjlUo|(N+Mgbnfc!)Nx|&{;AV`&GDT@O&(q7N z>x+q9`sQu>ZXSB~dqn@Ux3cg3Av^AYwk_m^Lplw*x9n{ygi9o04VK|87=j{0XqL^L zWPO3DSb?^j<19vwEeEfDAllYez^E|wD5%SR{z~j$C6b<1)9{*tPMX#(x6{Qmiv;8m zKrbsCFnNR+qPC@JRlNtY&qhh~r2*RvfOT}xUfUkNp@ z5wCYHQ1&!D6zgYKkdErBsc6a3Q87m_F6<13b0j^heherLLVbWd!2dq#Y_=8H3w zD26+R!VcBG+4`_iC${$DDUgiJAJ5aTnej1bL-UwqhlL&AgBLL7OFV(Fm0Il~Wvi$% zn&)F@jIZT4-+;BfEV9N$jfzJK7a16YE|aHA9K5c#6g@_Wgm<||zs%G+hHt+TjNE)o zNjc(hIbGsTy*0n=SW>-&2NV+(U4xKw6L&+W=U^2cJNz+VUe73lpQMSaRnAe)}Raqk-R4gx*5UCmt#dOFl1HdfPYsL^5O zC#){Nty1OYh(=&}0brT#mSr%xl^?Emr_x(igc5GH3ag3qXh7J_(KvH7z}^50(FOnj zY3W|~$Xcexxbm4`_QxE|t!k<;vN`Yyr#RB)2HwL6J@HVk$UB{87J}fYIiE~#3bpmV zLF`k15Utr6ZJ3IShI%UXsHJ01c3-#V+R7G=JfA6gT3v$n-%2y@DOi_w_;bK!_0uuG ztMikePX6nNjl8GqgoJCyqDo$|uBSEJ>Lm(tHFN-DvQDO{zpeBU_K=&iSi!|uOJTVm zk7D=rTu)u9Sh&xsPOU;vvb)6a^e%k5u#dNSDx5sv5Q581Ba3#}=zieSGouqfPkPtX z%=>(ux9qF?uqq^2hcj9!SMTY-mp64ke(z6t@p=;9pxC!14=}ybJBvTbuS6~|N2p%8 z8dJ21HPEAJceM_wvgg2<^r)WSnh7SZfx2>EE#K>itINW{VS#*N;r{fvJ9fHz>Ct1I zyCq zdqPN#&uss+s{g?STddN@?xeDA(V1G#lrgUaSQpI)?bABs?m?@aPY(k*0OB5CZ916J zZWOS-BN1qUT_DplF5dAgE-g89EfX#7ln<-|u>)0@S;urS!Z*JV8pNoo%O@v34{|TX zkNNxB%mYRsAG8;dlI`w}IykOGeHIahe6kN)#*i50%bsiQIHm!w$gpc$$**tovEo!+ z$ULoq=9b&uOj6~E`f&Wqd4{{wFP&-~=iq^{MWsABz*}}18 z^)@$Oe}pirLy_*)b;F^sGTeL>GA35w_M&-)!6GMI{M;I71ev)X;vwJ%8c!yBbqP9z z0g;|=BDl75|9IPUsSe{pEy`mghNcaGR;?;H)$yl4-ueH<=LWZ>v}Z=gsJg=fH3rm` z63OkQy%>h0CmYU?$V8fHt5rbNe1_e8%GD8%W0_`O^Z(j*^Q+O|Rb~4pdivpDA-Hv= zKV|S{3#!V2M7OMkyK6ZoI7a7Y9dDyqJ537DwTrZBvMgl%8^*wX*8AyGMs5qw56cLb zD&c)>`MB7^D*qllGVEyPc|=)4#G~%0^qK4PtXn0yW8T2Pywh7!Fb)jNJT-M%?Lu6j zp(5zNc^9dyWFF<>vOkDldfn(`l~rmd8-LiDo_`^ZHm({GON7PjUSdBTdNCG0${j}Q z#0>n-d`=8ppU=z41CAlwVp5@K8>6}S#poj*OO{SfQ1rNviyB-5Y4~VJW9bYJUqg9> z1HTDgpZ*8({f2M@BGwd)OCym3AKs8b^=0}%Nh>PaTvViKBy6yz5Wi2)q;!}Nd6Ek@ zCmY-sER*XIBvoWM!DTEE2l5wMb7-MAjOjmvoc{kg$ocP$kj>=3q-7xNtS-Bn~ z#+5BYl&$$Bk`0knayC!ty!MOa(%WX_@)E-dq1M!$zHc#7rFlY+JRgM8InEptRhpZv ziGZ~|q>v5c;u1TgdoSLtm(z)B+I!{StLgvL)qjF+q*5lbVkVWc_-OT}YSkJ%VL&)5 zriyMa>%?;RHOyGk=WJ5(cLS|8)TS4CI)sWZ{)%QjN*f8}zl^Ol{eD;YtES$2=iaYM z40)`mQp#azG~8W9b&R;%b3>)>SnG|nBGJ((pLv#C!_(^9Fz?SwVi_EiW@YOTjj(?q zPc3?&aej_;swjWS*PZ4#f0H_^FN?QfPEu6bq@X7Wm;Br{b<(q@C*<HXJnfO}% z$_0AUu-G17f#p;|+=#dOx}qEV2I9Cg+6$;k1!S*BZP>YS(vETV(3S_9olBp;3TQ2p z$oEnoR&z!>&8B?Vc-*6?;ttxXOI_a4qMkqmgkX*dpNM6XPo4UiqaSa2{rb7!P3mpR ztBH<5h}Ni;h@cQz_)ezv%!369O1($AENegno}(zm2}ke0Qde|ODc$?_5FKxdvO%~k~=(R6{!n9s$1%Od5g!@H*fWiqc>9~tivXu zq*1uK0zy-j;KW#|CV?&MR2!+fH|-;9%|*QOxY(q+QJJIxRh=)S#+8b3<(*=Ma$!82 ztLKebLCS^ZMn%oY5D5_iXMs4C#-e|YoifNj#4XM{{_-#JbBlUh?QoEI-(tUSXj7Ud z!~5JaDy9n9QU{@}0541wO6Bd?r^$MkjrH43h*onG5|EvQf?-6X#>poLn3i@wB8+s1 zqFNt4hF`8sSsAPPlm#ebZ>4*~CCi*t{^dB~-SUt@*c}eeRSgC1wtWCNhe9A|SNj{; z^bTbQI;|cViEyC0MC~gp1AkKIwk_P-Dtw}xBxhF)ub+ZI9^m~@m*+#i9{n$!+y4@e z|IaVlYzQdbuB!P$KuSdVih2CZ_`tHDKlUh@C{z(trX;&uFst41n}V@d4`(fb?j{6SLZ+ zwqY@|1oQJ{IXunKs8fHX_8S_80*ad0Rt^*jy4e&~3_)A9zJ_JkUa`B)zF@v;x^E6O zQGLiQNf;sWUJPKI#1{ngDQBU8;ig8eRt^oYGF?b_S~2{BkoT%gVuge1f$fzhobJQj zjVBiCMY<(ZezRQ9AkD>`N_f4>fg4BXFGGmLAhTV6rFMVYYc?bTy1?EuV-f&m8@OVJ zk(p5nBd()tT=XawK-o|lO!h^!;Ci#z<`?!7%Lx<1QW&A2XE`zmS?!3Ni(3FA znnGxtL0xSsY8{Ky%NHw)w!9qjdk6N$}LL$QCMqJQH{SO7kia6fnzz^DAm4(r4(5Dc5^ z0DQ_{dzQheLPBJ?qhBW*c&OB(t~^{lC?aJx)U*rOl`M|$3bVY(ja(FAx|~koSM;L& zGall*oP`iR-*er*Aw)3&`$o1=QRI2RzG3DO1Tlz>^=R_Hdt#teCX(JG_!FjXx_aP! z5J*i074p``5~I+ji1wVpMOOjr^` zo>sdR68p4x|J@^6anYWm!Ygx(plN|9!^GbY-90|RO@fYSVEsz&^o@*rguwb+FNhfh zlDkPx)vCv=y5pxcWE-%wI(L*OBCC%`;<8c)^)55`fK<>3u>n{Ar8)Kt5Igtz)z_?l z2lQY^*!dTM1_a1XdBWNCJ-um6iRa7MSimbG+n7vvv5+5gk!SPqum>k<=_b^6P)RZR z(ZbZM?o_AE&CpCIab^`Fz)_NCfLm!PT?E8ZK#1w4V#hKKcb6i~=!$(_~q7ulK1%%8WOF)5I3|c}B#>UT*Rm428^UhLZ;;`#it- zb>-HDbq9~8d?@$ji?JN;!5kus%nLi(rRuXCd9ASJe!0~*L zA-j3?7G@9L%}bO@NUjI;H z!v)F5qjn7B-pxj+g(koA%tc{tKzl%UFh_JN5CQAA=xR1!#qZ^0A~QWHsD_04fKLhn zijfs0qDv^PMM93`wE3no+PgZfO_cgBH|ea62$8PfzjcuLa;2j8?g- za&^66TlMKN{fI%^n%caHy`>za_OwUhd?_}T7|YFx9@b4Kd`yZZ&iTdcWa=AD+l)fZ zF#Ghn2}y%)x=GG)gDdt{uK6$Hs&ay)yj&Hmk16ex->bacz3f#xt-wc>W>FF%B~S8g ztz?JZ4e8RKQih4}V5yftpxw&slm#j#443?_*_d-q!o-# z@d!f0L!_h>M?7gDjWrN*>CTEO0l8QDV6jjvBcu;e87^31L2p`r_%Ji4o+{;CV3t2X z+HddrTmJ{8lX*k5gm60zH?4gc=%4}8!D4~@*TiOizGBdn8POoU*-zSH|^q=i^Y!J@ySwl0Mw_A^4Y<}aj zIDFTUEZ^r)$-CK??8F7gaYiRRK_& zpqj$ir)|ItQ+7_(jzB_Pp)C{D3aNQKy9Z1(XANW|dhNA}1H4u{r&9%_f+jiUn8}GX z5K7dYYS0l-21I782Qu6L7>e~^$Cgk2oRixL?JGOgUB{hXS@=3|fZm3o<4f?1)9Rs_ zwJ>et(V#x}TA#boOIy7=_OD*{jWQgoE}qL6r5pJ-HdSlRu$A-#MVN6Te|=~yahW#g zea<7-`y3}_-HET(4DEzBHMQ^px_wvo4R4b3>a!k#jzB3%bm=b$=bzX8fAtj`ZAC>0 zNfQv=U%4pMM?AS^PwsAnQjhw~F`_D>GrDp5n&<0tZ6mrVtJrZd)KyX@asBQI*)O$o z1?AK=b5@+TtXs$^=49Y&68fw{JR*Iv631Na*1eTaT`~M~)@%@AmFJRDgA09Ub{8YahW}*5ZIc|0wQ`=5bXO) zdxDiRTpTGeUQH$tBi7C3!Pi?#J1D+ar2}J~OD*9Qri-~@D39A%ot9Lz6i@}54-Ux|2mUdp64-&U}|`Ek@txz z9mgeP=q%9bCx%Nrb1EDi0G9(*ve{|yy+3B&2OGA6K8n7#E#GXcyrT5uCv`PaIt~85 ztzG9mJr%?tg_Y#xzFT`-eGT92>wuHd5A<7*eJT=Sy)OncGJod}pQ^LIKeLo zfUTZo`@EACOl!je4Ll!L_oU=+4NduiEZrGi{TL;PO$UOuR!z!NMcP%>`19sDo7`fo zS}0yK%Q^KYr&GIj=!Iq#YVJ#ms$`izPOUkx_2+(4_JeA8wh&}AbW1EbDHL}U2k=T? zcR5_y1saH!8Y>^~XZJ$7R}q^jUfjI-%*EPh17hN8Yn$;nQ}W6Ktvpy5w}JFROBjYZA2$W93lZp&+h)@f0B6`?E7TCDIH$eKR*pvFG9(5ppPnbiF)Yre|>Su;e zH(nmY0dYj0S~pmQN4o7zEK1#$Ou-fK!1lsy1rz%i8J0wr)cka5DPxcSjV#S-BN&Sk z33V-H&Wwrga4NmSqp012tu;_D0egUbOwfjnv~-ledG*J8ZMZu(YF>>T4-Ze`?^^>o zXNjgx*0^G=tm?8g4dc55zMXV?MWs}sZQj;Db z1>-Et(~5{1LKhUf?I+3m@P`8QBs-u`6J^B!_c}K@yQ-&z86c9UzqbQO+yWdxBA8Z$ z=|y1Ew9f;Q_QC%XAHN@4_`l=eA#6sDr0asY6)yzMRZ#c!Eq zdh4Fl)Txc(Pv$iiES7F6yH^LtJRG@&_;ANwmpXo3U0T!R|A$*`i3*>|I0)uZfVeNf z4MPox`!a~<0J9oku>-kOzqeSWa4bfH9it01g32wMsAS=gh#CGYonp?2rk3=LA>)kS z%k|)KQGvrGQkFW)p(z5UmLed=#hbZT_KU5ometQM<_ul#(#SKZ+~F*a4T|(3P4@iL zP5$fL-%vX``*ko^4Tr>XjP}r{xW$m7%Nl$ijz6}`TN+$x^-hX zuYnR|82$^xbS;}jSlrpW=FWkAr33B|K*W%1pv$hE`aMf&S|%DsGis5&^E2MDgO5{$ zbjqIlKD0Pum-~Slz*gF*{o2p|hu;7BW5e!qS3iGCBb>KdNb1-kFLGE-$L4y5K07_y z1&-p9Qv13aON{PtB&GgoMgIP!%!PRQ?&;AsBJZuL6uCm zZ@K6G{hx2oXpfej9lcN&FJSCjtxQ@Lw0rbV`5*>~@qW|_F*bVRqk6K(%(Ecx4wsdT z!F$n%&$VYF0MliV;R_za;-;f5xPh|(fh-jr0(?s97n~C=<|`VqOQ)z%%Xvaf$3NTh z`#p~X^d*yux^bkmtPsN6nvr1zRuetv#Bh2BkRHUe*{@?4x$0m@b?01xuEbf4gaEF- zb^h`zVol4ARheu%PpMRwlBor!o2@_ucXf~BtoXGUY5lnvt!vw-c73_&wc7m~BIK6C zmXA02N!&VltLY&xR&$i+YS@OU12kXr)|HQ9)qvq7SqBq8h1D0+;CB^HZ9dLz#EMp&L!`ZN~wmb)%k`Q`@pSf+`I1E0scc%R!% zx`flpUoge#ujd`O60z|fZ%D8P(nG5Gr!}UR$}CG6+)bKFC#K(F^-M`mC44Yi+T7X_ zjwUStnGpxSTbvPW6H^GHMCy{iqE_B_V@5_UE;0p@8R#dV&~t7<670HV%3Li;aF7a0uNW>GrDQ4JYZs3!0H6g0y8&_V#L%_b~_B~!4F zIl*89aev;;%{l8{ME{EaioVXLLQXxwsE%2H#$4dMc`Iq9>9|KCPFpcl5Q1G7RAV!vi*-H%MpBQ{X%-em;ApPdg%&H zM=Lu=yJ_cXlrw50EAi7BlZmtP{VaMH`cc3F$y^fBp$wQR7sDghl}}tVR`U@~2Vaew z6diT}LVcWGJJ%LV!D|6?CE#3Z@%TW`z2<+axV_QtEz+cxnvQUy7(43p%C5UKqPCTJ zyC{Y1%pARN->QBJynW}8qivRn)svcnUUgzBYIO=lP1sD)CXyo5M-VbO^(JazCZ-L5 zHYQ}(8^cr~*YDcSlFT%oveQyBfZ#G=!<_{nxGYx4oLUbqlfgGHtEec;%H!vEy$ibf zMor!zfm!b8t{tDn>a1q0%bX%)5grq&(_b>BQS3@A)S3V$CIHgi`)xyu)rJAcqB?_aaJb1E}ZX0#q% z$4WM;ZLXcxKDRhAmcXSB+CCta`z;|lXmc|ghg-;i1DLtB`I!RK^YjO-vz^F*j%q?0 zmPn_&X_^5#Wq8y|HM#BF*bUvguqYf9&<4MldW1Oi@}KT5@wy+|n9-aVo!~fLdq@U} zf4#bLn`zWUST5O+lA~0Li1tkJ9M~^JNOi8~WHqxGFQkfR$s@zCu7`UPAsS;s!}Ug^5<@hdJ3Gd|_EVXsdp6=qi~w(Z zoJ(D{4`jGRRVfF^Y!>wL5%U5k1{&hqAK&__V?2BfG|VG*Rko)tHJyL#)5dqxQk+NM z^vBro0SNSmh{NA!@5bEK&w#DildT_Ay!(FdlEtgy1@=-~+ZyQl8fcy*dR)Q>gdl#h zsk=`ZtJMAOOQg}x?-mD#ht@!wpwU_f1Fz@-xr?CI25X=Qjs|qF4t#v!hi=vzJy~>S zmA!qvn=cICL=NBz!zZu&el7kId7znz5`0-HGLQmyY;<91yw090Qj?6Kuq2skJ??c25L24eSBpNG)ssnU@*AY z`6YF&tmvwn-*lpWbDMuy!NxqR+jW+g8hn6^F1-u1Iv}Hqt`0pP(5$e;sqNB3$`?wv z-0#LGuIlTTii3*uXy4uU*TR#*Qg7tW-!HUYAN+dFa}LmZ;|mkfHYUfSvQtYF2L_1PQ*E%X<)U`2ZM-a)r zAv7OPS-l!wav#&JHKZ)DO%`AK?Gq{R?D#EW+}()dpIz-)(i+FCSTpyE99Q$g`YS6^ zJa>H;e9XqWb;)M$lE0)$50^aCVIsz?${9zQNO*%2$HI-MKxj`aRzGTXYA%F5l1L)@ z)&%^+-K{}m$p^u9JtyFRhlmby3cMcI)b52I*h$kt*nK#z0v+umjqCgYf0v$NQo{1I#alfjZEZ~1M1#ECx` zI)9U|e&K98PhR-(_OeKVcXb;Oh7 zGT2wK1~O>VS1T)0h^QN#l*Gm(56h>=Tc2U_;Df0nDkyl(d##vb@^)aS(BDix-$xI= z`L0m4H~3gJL}LdVYP86S^&O|L?e!W6mLqHW8B*QDT!8bIe3O{J2k;rBAe^n9NO{)dZ4s zV?8Lk^4IUz&vzYL&%6En{dmx4yB|FG{LzsEN8)48WoQ4vNp|ed-T|K-Sl|T+g|kCX zu2*3p$g(llTEFg0Q$Li7A-e>n0!@)Q@pyHAu*4awP=(=zJ%PK|l*PqM2DJ?9C(25I z=eUr)7BJx?9~NM$E&6DztgMnE^b15WqZpXfUM?fQ2k-$8#n**BAbQs^7Cn~fz%&eX z&0)Q2obNjN64(yEb#IXZq@r8{S*?LsKgwc{FjU`An>QV>;PB3+llxZ_rW#f1f`1FNSy{^gMQd_ zpB>Mlif72EUvIjry-Uu+jmUgnRSPy{)S(;$ARIpj8vuNgI`#W63^eIw2ge}G0G<@( zly?FZN7^S2p<&H=-2Rz*?ZKcqi(n@_EOsI5Gpn%zcHbi)DRmz23sz$8(_Bwz#EL1r zL|Bu+IM1B2NOhXGvUtv+kgblUGA^uvw5TYf)TxC_>z(xOwV~3L{1w26qwt1Qc{V&B zp6n)+vj%K#)?d?Yi*b&rkZOxT#8jAw0xnY@ecAJ6bFePS6fj_uB!G2T(e@>2s9c#J zGn0c622LeRk^(Khy zY>G$=k;Uv324-HgO|(?@jum9>-)$6nu%LU|O(r=#=sNPW0f z%66-R!$%incBPn^9<;UHYHRvCZP=No;H7-{k4 z?@Hpw2hyLRDs(4`R*o^{Mf0m^I!C`g?WM4ztujJ=5pV_{W-q>cv1Boq2?Y{b9c$5x z;tr+S)m^Aik#CuBMJPUE4f(P=fK{v8?Cm^cAvevnjU=U*Ao*&op$ic@=__++EcfhHF;T zcH{O<%=sjF_pj&>GbiB1&a@ZnX;NE-Bbat*T!7B1$zhMp&hJ4IEzbR zt>~LPxfEeJSE4o6AgMIq&9bVWt-rOkNRp>S);1q3N5h_qb{_vn$lz}psl5{s;uGA8 z&rq(^$EK9ZD|*^bb1Rynv7BCtn!BcaEc0PmXQGx~Vors*XEtHN^`nR)dp^*?;0(>Y zEL(Ul*rGDNBtEjTP>lT6W$x5+!o2r0!cmC!vcy7vz59z2@Nmh)m)tELKXvK`gyiFuEi8%2 zULl0E$K*r6;GZ`>5`BnYti?_#2YFYgg?bY#w3cIsC7Y~%~*mBx< zj6qF!6fmOAZL$%5sQOJtKtObguqR?TKO9WNXKxj-y|{X(oHCbn&aD zorFc4*03k^5bhdpRXIVtzu(P2aM_SI_&jf10j0fPDNS+#H)dhAdgP&@^y4SnpKN2D z20yDl7huxLT0In1VeM4I<_(vKtWszbeUF-L{5?bPyn^U6i|MyB^Y16mO21bY!Mgps zO!#{jzNyT?IX@_K#2=tI`XYe?{SzqeR^;~ZoC@m13Vg-?;ph*zJmNJjU�|>&|P0 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux143/captures/road-in-clouds-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux143/captures/road-in-clouds-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80984a340b4eb45516fe4a64a6b30baed71f18d4 GIT binary patch literal 45695 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 G@V@|M3;?JA literal 0 HcmV?d00001 diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index d8ed139..8051136 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -1935,15 +1935,24 @@ int main(int argc,char** argv) std::sort(deck.begin(),deck.end(),[](const auto* a,const auto* b) {return a->stableIdstableId;}); double pathLength=0.0,maxGradeDegrees=0.0; - for(std::size_t i=0;i> centerline; + if(deck.size()==1&&!deck.front()->sweepPathMicrometres.empty()) + centerline=deck.front()->sweepPathMicrometres; + else { - const auto* segment=deck[i]; - const double dx=(segment->sweepEndpointsMicrometres[1][0] - -segment->sweepEndpointsMicrometres[0][0])/1.0e6; - const double dy=(segment->sweepEndpointsMicrometres[1][1] - -segment->sweepEndpointsMicrometres[0][1])/1.0e6; - const double dz=std::abs(segment->sweepEndpointsMicrometres[1][2] - -segment->sweepEndpointsMicrometres[0][2])/1.0e6; + for(std::size_t i=0;isweepEndpointsMicrometres[0]); + centerline.push_back(segment->sweepEndpointsMicrometres[1]); + } + } + for(std::size_t i=1;ihalfExtentsMicrometres[1]/1.0e6; std::printf("[LiminalRoadResolved] vocabulary=%u id=liminal/road-clouds-v2 " - "strate=%d shape=swept_deck_segments deck_segments=%zu supports=%zu " + "strate=%d shape=continuous_swept_deck deck_stamps=%zu centerline_points=%zu supports=%zu " "path_length_m=%.3f width_m=%.3f grade_max_deg=%.3f " "placement=free route_keepout=PASS band_clearance=PASS status=%s\n", resolvedLayout.stampVocabularyVersion, - deck.empty()?-1:deck.front()->strateIndex,deck.size(),supportCount,pathLength, - width,maxGradeDegrees,deck.size()>1&&pathLength>=300.0&&width>=3.0 + deck.empty()?-1:deck.front()->strateIndex,deck.size(),centerline.size(), + supportCount,pathLength,width,maxGradeDegrees, + deck.size()==1&¢erline.size()>=2&&pathLength>=300.0&&width>=3.0 &&maxGradeDegrees<=15.0?"PASS":"FAIL"); - if(deck.size()<2||pathLength<80.0||width<3.0||maxGradeDegrees>15.0) + if(deck.size()!=1||centerline.size()<2||pathLength<80.0 + ||width<3.0||maxGradeDegrees>15.0) {std::fprintf(stderr,"Liminal road resolved outside the walkable road bounds\n");return 2;} } if(hasLiminalPillarGrid) diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index dab5001..8cb1410 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2981,28 +2981,48 @@ namespace StandaloneStreamBenchmark constexpr double HalfCapsuleHeightMetres=CapsuleHeightMetres*0.5; constexpr double SlopeCapsuleClearanceMetres=0.12; std::vector> roadPath; - roadPath.reserve(deck.size()*4); std::vector> centerline; - centerline.reserve(deck.size()+1); - bool surfacePathValid=true; - for(std::size_t i=0;ikind + ==VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment + &&deck.front()->sweepPathMicrometres.size()>=2; + bool surfacePathValid=continuousDeck; + if(continuousDeck) { - const auto* segment=deck[i]; - if(segment->kind!=VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment) - surfacePathValid=false; - const auto point=[&](std::size_t endpoint) - {return std::array{ - segment->sweepEndpointsMicrometres[endpoint][0]/1.0e6, - segment->sweepEndpointsMicrometres[endpoint][1]/1.0e6, - segment->sweepEndpointsMicrometres[endpoint][2]/1.0e6};}; - const auto a=point(0),b=point(1); - if(i==0)centerline.push_back(a); - else if(std::abs(centerline.back()[0]-a[0])>1.0e-6 - ||std::abs(centerline.back()[1]-a[1])>1.0e-6 - ||std::abs(centerline.back()[2]-a[2])>1.0e-6) - surfacePathValid=false; - centerline.push_back(b); + centerline.reserve(deck.front()->sweepPathMicrometres.size()); + for(const auto& point:deck.front()->sweepPathMicrometres) + centerline.push_back({point[0]/1.0e6,point[1]/1.0e6,point[2]/1.0e6}); + surfacePathValid=surfacePathValid + &¢erline.front()[0] + ==deck.front()->sweepEndpointsMicrometres[0][0]/1.0e6 + &¢erline.back()[0] + ==deck.front()->sweepEndpointsMicrometres[1][0]/1.0e6; } + else + { + centerline.reserve(deck.size()+1); + surfacePathValid=true; + for(std::size_t i=0;ikind + !=VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment) + surfacePathValid=false; + const auto point=[&](std::size_t endpoint) + {return std::array{ + segment->sweepEndpointsMicrometres[endpoint][0]/1.0e6, + segment->sweepEndpointsMicrometres[endpoint][1]/1.0e6, + segment->sweepEndpointsMicrometres[endpoint][2]/1.0e6};}; + const auto a=point(0),b=point(1); + if(i==0)centerline.push_back(a); + else if(std::abs(centerline.back()[0]-a[0])>1.0e-6 + ||std::abs(centerline.back()[1]-a[1])>1.0e-6 + ||std::abs(centerline.back()[2]-a[2])>1.0e-6) + surfacePathValid=false; + centerline.push_back(b); + } + } + roadPath.reserve(centerline.size()*4); double pathLengthMetres=0.0,maxGradeDegrees=0.0; std::uint64_t surfaceProbes=0,surfaceMisses=0; const auto surfaceTopAt=[&](double xMetres,double yMetres, @@ -3010,11 +3030,18 @@ namespace StandaloneStreamBenchmark { ++surfaceProbes; double low=nominalTop-0.25,high=nominalTop+1.0; - if(Shape.densityAt({xMetres/coreMetres,yMetres/coreMetres, - low/coreMetres})>=0.0f - ||Shape.densityAt({xMetres/coreMetres,yMetres/coreMetres, - high/coreMetres})<0.0f) - {++surfaceMisses;return false;} + const float lowDensity=Shape.densityAt({xMetres/coreMetres, + yMetres/coreMetres,low/coreMetres}); + const float highDensity=Shape.densityAt({xMetres/coreMetres, + yMetres/coreMetres,high/coreMetres}); + if(lowDensity>=0.0f||highDensity<0.0f) + { + ++surfaceMisses; + std::printf("[LiminalRoadSurfaceProbeMiss] x_m=%.6f y_m=%.6f " + "nominal_top_m=%.6f low_density=%.6f high_density=%.6f\n", + xMetres,yMetres,nominalTop,lowDensity,highDensity); + return false; + } for(int iteration=0;iteration<20;++iteration) { const double middle=(low+high)*0.5; @@ -3059,8 +3086,7 @@ namespace StandaloneStreamBenchmark const FWalkAudit roadAudit=auditPlayerPath(Shape,roadPath, 0.125,0.125,1.125,3,0.45); const double widthMetres=2.0*deck.front()->halfExtentsMicrometres[1]/1.0e6; - passed=std::all_of(deck.begin(),deck.end(),[](const auto* road) - {return road->kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillSweptDeckSegment;}) + passed=continuousDeck &&pathLengthMetres>=300.0&&widthMetres>=3.0 &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed; std::printf("[LiminalRoadWalkAudit] id=liminal/road-clouds-v2 " diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index 8897078..b0aac21 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -707,26 +707,16 @@ namespace StandaloneWorldAssemblyPrototype requests.push_back(std::move(request)); }; const std::int64_t deckSmoothUm=250000; - const std::int64_t segmentOverlapUm=350000; - for(std::uint32_t i=1;i(b[0]-a[0]); - const double dy=static_cast(b[1]-a[1]); - const double dz=static_cast(b[2]-a[2]); - const std::int64_t halfLengthUm=static_cast(std::ceil( - std::sqrt(dx*dx+dy*dy+dz*dz)*0.5))+segmentOverlapUm; - ResolvedLayoutStampRequestV1 request; - request.stableId=*id+"/deck/"+std::to_string(10000+i-1).substr(1); - request.strateIndex=strateIndex; - request.kind=ResolvedSdfStampKindV1::fillSweptDeckSegment; - request.anchorPositionMicrometres={ - (a[0]+b[0])/2,(a[1]+b[1])/2,(a[2]+b[2])/2}; - request.sweepEndpointsMicrometres={a,b}; - request.halfExtentsMicrometres={halfLengthUm,halfWidthUm,halfThicknessUm}; - request.smoothWidthMicrometres=deckSmoothUm; - requests.push_back(std::move(request)); - } + ResolvedLayoutStampRequestV1 deck; + deck.stableId=*id+"/deck/000"; + deck.strateIndex=strateIndex; + deck.kind=ResolvedSdfStampKindV1::fillSweptDeckSegment; + deck.anchorPositionMicrometres=path[path.size()/2]; + deck.sweepEndpointsMicrometres={path.front(),path.back()}; + deck.sweepPathMicrometres=path; + deck.halfExtentsMicrometres={500000,halfWidthUm,halfThicknessUm}; + deck.smoothWidthMicrometres=deckSmoothUm; + requests.push_back(std::move(deck)); const std::int64_t supportBaseUm=fieldFloorMicrometres-2000000; const std::int64_t supportRadiusUm=metresToMicrometres(supportRadius); double distanceSinceSupport=supportSpacing; From a45ba9bb10fbb789ce2b8730db2b21874734594f Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sun, 1 Nov 2026 11:17:45 +0100 Subject: [PATCH 4/7] wip: Core.Liminal.Field v1 recipe, 4 seed-selected variants between fixed mouths (L144, fails mouth joins) Plans and draws flat field+monolith, repeating hills, road over cloud floor and pillar grid in a 3-strata fixture, binding passage/0-1 and 1-2 as fixed endpoints. Composed W1 probes: 3/4 seeds fail one passage interface, 4/4 fail the liminal walk audit near the mouths (support itself passes). Stopped per AGENTS.md. Same mouth-ownership failure class as FI (L133/L140) and VS seed 2 (L139). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 78 ++++ Standalone/Core/src/ResolvedLayoutInternal.h | 104 ++++- Standalone/Core/src/ShapeWorldInternal.h | 34 +- Standalone/Core/src/WorldAssemblerInternal.h | 416 ++++++++++++++++++ .../Linux144/BuildL144Fixtures.py | 58 +++ .../WorldAssemblerM3/Linux144/CaptureL144.py | 243 ++++++++++ .../WorldAssemblerM3/Linux144/REPORT.md | 44 ++ ...-liminal-flatField-monolith-seed00-eye.jpg | Bin 0 -> 35191 bytes ...liminal-flatField-monolith-seed00-wide.jpg | Bin 0 -> 26016 bytes .../core-liminal-periodicHills-seed01-eye.jpg | Bin 0 -> 31096 bytes ...core-liminal-periodicHills-seed01-wide.jpg | Bin 0 -> 45333 bytes .../core-liminal-pillar-grid-seed03-eye.jpg | Bin 0 -> 35478 bytes .../core-liminal-pillar-grid-seed03-wide.jpg | Bin 0 -> 37027 bytes ...minal-road-over-cloud-floor-seed02-eye.jpg | Bin 0 -> 31758 bytes ...inal-road-over-cloud-floor-seed02-wide.jpg | Bin 0 -> 30827 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 161 ++++++- Standalone/Source/StreamBenchmarkPipeline.h | 127 +++++- Standalone/Source/WorldAssemblyPrototype.h | 325 ++++++++++++++ 18 files changed, 1547 insertions(+), 43 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-wide.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index edeb226..9d74abc 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -597,6 +597,61 @@ namespace VoxelForgeCore } } + inline constexpr std::string_view CoreLiminalFieldRecipeIdV1 = "Core.Liminal.Field"; + inline constexpr std::uint32_t CoreLiminalFieldRecipeVersionV1 = 1; + inline constexpr std::uint32_t CoreLiminalFieldVariantCountV1 = 4; + + enum class WorldAssemblyLiminalVariantV1 : std::uint32_t + { + flatFieldMonolith = 0, + repeatingHills = 1, + roadOverCloudFloor = 2, + pillarGrid = 3 + }; + + struct WorldAssemblyLiminalVariantDefinitionV1 + { + WorldAssemblyLiminalVariantV1 variant = WorldAssemblyLiminalVariantV1::flatFieldMonolith; + std::string_view name; + WorldAssemblySurfaceProfileKindV1 surfaceKind = WorldAssemblySurfaceProfileKindV1::flatField; + std::int64_t hillAmplitudeMicrometres = 0; + std::int64_t hillWavelengthMicrometres = 0; + std::int64_t routeHalfWidthMicrometres = 0; + std::int64_t routeHalfThicknessMicrometres = 0; + std::int64_t supportSpacingMicrometres = 0; + std::int64_t supportRadiusMicrometres = 0; + std::int64_t monolithRadiusMicrometres = 0; + std::int64_t monolithHeightMicrometres = 0; + std::uint32_t pillarRows = 0; + std::uint32_t pillarColumns = 0; + std::int64_t pillarSpacingMicrometres = 0; + std::int64_t pillarRadiusMicrometres = 0; + std::int64_t pillarHeightMicrometres = 0; + }; + + inline constexpr std::array CoreLiminalFieldVariantsV1{{ + {WorldAssemblyLiminalVariantV1::flatFieldMonolith, "flatField-monolith", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 1750000, 500000, + 36000000, 550000, 1600000, 26000000, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::repeatingHills, "periodicHills", + WorldAssemblySurfaceProfileKindV1::periodicHills, 2200000, 80000000, + 1750000, 500000, 36000000, 550000, 0, 0, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::roadOverCloudFloor, "road-over-cloud-floor", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 2000000, 500000, + 24000000, 550000, 0, 0, 0, 0, 0, 0, 0}, + {WorldAssemblyLiminalVariantV1::pillarGrid, "pillar-grid", + WorldAssemblySurfaceProfileKindV1::flatField, 0, 0, 1750000, 500000, + 36000000, 550000, 0, 0, 15, 15, 76000000, 5500000, 40000000} + }}; + + inline constexpr WorldAssemblyLiminalVariantV1 SelectCoreLiminalFieldVariantV1( + std::uint32_t seed) noexcept + { + return static_cast( + seed % CoreLiminalFieldVariantCountV1); + } + struct WorldAssemblyRecipeV1 { std::uint32_t schemaVersion = WorldAssemblySchemaVersion; @@ -654,6 +709,23 @@ namespace VoxelForgeCore std::array parametersSubvoxels{}; }; + struct WorldAssemblyLiminalFieldPlanV1 + { + std::uint32_t version = 0; + WorldAssemblyLiminalVariantV1 variant = WorldAssemblyLiminalVariantV1::flatFieldMonolith; + std::uint32_t seed = 0; + std::array arrivalMouthSubvoxels{}; + std::array departureMouthSubvoxels{}; + // Fixed distance from each passage player-center anchor to its walk surface. + std::int64_t mouthFloorOffsetSubvoxels = 0; + std::int64_t floorHeightSubvoxels = 0; + std::int64_t routeHalfWidthSubvoxels = 0; + std::int64_t routeHalfThicknessSubvoxels = 0; + std::int64_t routeOffsetSubvoxels = 0; + std::int64_t supportSpacingSubvoxels = 0; + std::int64_t supportRadiusSubvoxels = 0; + }; + struct WorldAssemblyStratumPlanV1 { std::int32_t strateIndex = -1; @@ -678,6 +750,7 @@ namespace VoxelForgeCore std::vector features; WorldAssemblyRouteConstraintsV1 routeConstraints; std::vector route; + WorldAssemblyLiminalFieldPlanV1 liminalField; std::uint64_t contentHash = 0; }; @@ -893,6 +966,7 @@ namespace VoxelForgeCore inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV3 = 3; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV4 = 4; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV5 = 5; + inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV6 = 6; inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1; enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict }; @@ -920,6 +994,7 @@ namespace VoxelForgeCore // Present only for fillSweptDeckSegment; defines its directed centerline. std::array, 2> sweepEndpointsMicrometres{}; // V5 permits one continuous swept deck to carry its complete sampled centerline. + // V6 also permits a path whose X coordinates are not strictly increasing. // Empty retains the V4 single-segment interpretation. std::vector> sweepPathMicrometres; std::int64_t placementRadiusMicrometres = 0; @@ -1238,6 +1313,9 @@ namespace VoxelForgeCore ResolvedLayoutSnapshotV3& layout, std::int32_t seed, const std::vector& configs, std::string& error); + VFCORE_API bool PlanCoreLiminalFieldV1( + WorldAssemblyRecipeV1& recipe, WorldAssemblyStratumPlanV1& stratum, + const ResolvedLayoutSnapshotV3& layout, std::string& error); struct ResolvedLayoutStampPlacementAuditV1 { diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 4a47b04..1cddd4e 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -249,6 +249,71 @@ namespace /WorldAssemblySubvoxelsPerVoxel)); return result; }; + const bool liminalRouteStamp=strate->recipeId==CoreLiminalFieldRecipeIdV1 + &&stamp.stableId.starts_with("core/liminal-field/route/") + &&(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment + ||stamp.kind==ResolvedSdfStampKindV1::fillPillar); + if(liminalRouteStamp) + { + const auto variant=std::find_if(strate->anchors.begin(),strate->anchors.end(), + [](const auto& anchor){return anchor.kind=="liminal_variant" + &&anchor.values.size()>=6;}); + std::vector points; + for(const auto& anchor:strate->anchors) + if(anchor.kind=="liminal_route_point"&&anchor.values.size()>=4) + points.push_back(&anchor); + if(variant==strate->anchors.end()||points.size()<2) + {if(reason)*reason="Core.Liminal.Field route stamp has no versioned fixed-mouth route";return false;} + const auto routePoint=[&](const ResolvedLayoutAnchorV2& anchor) + { + std::array q={anchor.values[0],anchor.values[1],anchor.values[2]}; + return qToMicrometres(q); + }; + const std::int64_t halfThickness=static_cast(std::llround( + static_cast(variant->values[5])*coreMicrometres + /WorldAssemblySubvoxelsPerVoxel)); + if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment) + { + const auto first=routePoint(*points.front()); + const auto last=routePoint(*points.back()); + if(stamp.sweepPathMicrometres.size()<2 + ||stamp.sweepPathMicrometres.front()[0]!=first[0] + ||stamp.sweepPathMicrometres.front()[1]!=first[1] + ||stamp.sweepPathMicrometres.front()[2]!=first[2]-halfThickness + ||stamp.sweepPathMicrometres.back()[0]!=last[0] + ||stamp.sweepPathMicrometres.back()[1]!=last[1] + ||stamp.sweepPathMicrometres.back()[2]!=last[2]-halfThickness) + {if(reason)*reason="Core.Liminal.Field deck does not terminate at its fixed passage mouths";return false;} + return true; + } + const auto deck=std::find_if(layout.stamps.begin(),layout.stamps.end(), + [&](const auto& existing){return existing.strateIndex==stamp.strateIndex + &&existing.stableId=="core/liminal-field/route/deck/000" + &&existing.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;}); + if(deck==layout.stamps.end()||deck->sweepPathMicrometres.size()<2) + {if(reason)*reason="Core.Liminal.Field support has no previously resolved route deck";return false;} + double distance=std::numeric_limits::infinity(); + for(std::size_t i=1;isweepPathMicrometres.size();++i) + { + const auto& a=deck->sweepPathMicrometres[i-1]; + const auto& b=deck->sweepPathMicrometres[i]; + const double dx=static_cast(b[0]-a[0]); + const double dy=static_cast(b[1]-a[1]); + const double lengthSquared=dx*dx+dy*dy; + const double t=lengthSquared>0.0?std::clamp( + ((stamp.positionMicrometres[0]-a[0])*dx + +(stamp.positionMicrometres[1]-a[1])*dy)/lengthSquared, + 0.0,1.0):0.0; + const double offsetX=stamp.positionMicrometres[0]-(a[0]+t*dx); + const double offsetY=stamp.positionMicrometres[1]-(a[1]+t*dy); + distance=std::min(distance,std::hypot(offsetX,offsetY)); + } + const double corridorRadius=deck->halfExtentsMicrometres[1] + +stamp.halfExtentsMicrometres[0]+RouteClearanceMicrometres; + if(distance>corridorRadius) + {if(reason)*reason="Core.Liminal.Field route stamp is outside its versioned route corridor";return false;} + return true; + } for(const auto& passage:layout.passages) { if(passage.upperStrateIndex!=stamp.strateIndex @@ -1158,8 +1223,9 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV2 &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3 &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV4 - &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV5) - add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1 through 5"); + &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV5 + &&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV6) + add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1 through 6"); std::vector stampIds; for(const auto& stamp:stamps) { @@ -1217,11 +1283,15 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, validPath=validPath&&coordinate>=-1000000000000ll &&coordinate<=1000000000000ll; if(pointIndex>0) - validPath=validPath - &&stamp.sweepPathMicrometres[pointIndex-1][0]=ResolvedLayoutStampVocabularyVersionV6 + ||previous[0]=request.sweepPathMicrometres[i][0]) + return true; + return false; + }); const bool hasSweptDeck=std::any_of(ordered.begin(),ordered.end(),[](const auto& request) {return request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;}); candidate.stampVocabularyVersion=hasContinuousSweptDeck - ?ResolvedLayoutStampVocabularyVersionV5 + ?(hasNonMonotoneSweptDeck?ResolvedLayoutStampVocabularyVersionV6 + :ResolvedLayoutStampVocabularyVersionV5) :hasSweptDeck?ResolvedLayoutStampVocabularyVersionV4 :ResolvedLayoutStampVocabularyVersionV1; candidate.stamps.clear();candidate.stamps.reserve(ordered.size()); @@ -1818,8 +1898,8 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t for(const auto coordinate:point) if(coordinate<-1000000000000ll||coordinate>1000000000000ll) {error="stamp request "+request.stableId+" has an unbounded path point";return false;} - if(pointIndex>0&&request.sweepPathMicrometres[pointIndex-1][0]>=point[0]) - {error="stamp request "+request.stableId+" path X coordinates must increase strictly";return false;} + if(pointIndex>0&&request.sweepPathMicrometres[pointIndex-1]==point) + {error="stamp request "+request.stableId+" path contains a zero-length segment";return false;} } } @@ -1836,6 +1916,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t return static_cast(bits%span)-radius; }; bool placed=false; + std::string lastPlacementFailure; for(std::uint32_t attempt=0;attempt<(request.placementRadiusMicrometres==0?1u:512u);++attempt) { ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId; @@ -1919,11 +2000,14 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis]; } } - if(!LayoutStampSafe(candidate,stamp))continue; + std::string safetyReason; + if(!LayoutStampSafe(candidate,stamp,&safetyReason)) + {lastPlacementFailure=std::move(safetyReason);continue;} candidate.stamps.push_back(std::move(stamp));placed=true;break; } if(!placed) - {error="stamp request "+request.stableId+" has no deterministic passage-safe content placement";return false;} + {error="stamp request "+request.stableId+" has no deterministic passage-safe content placement" + +(lastPlacementFailure.empty()?std::string{}:": "+lastPlacementFailure);return false;} } if(!candidate.finalize(error))return false; std::vector issues;std::string strictError; diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index ed036ec..29d4977 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -1523,6 +1523,8 @@ public: &nativeLatticeFloorSupport); } const auto* bound=FindBoundStratumForManagerZ(Z); + const bool liminalRouteComposition=bound&&bound->Resolved + &&bound->Resolved->recipeId==VoxelForgeCore::CoreLiminalFieldRecipeIdV1; const bool nativeLattice=bound&&bound->Resolved &&VoxelForgeCore::IsNativeLatticeFieldStratum(*bound->Resolved) &&bound->Resolved->passageCapabilities.hasNativeLatticeField; @@ -1546,7 +1548,9 @@ public: VoxelForgeCore::Linux77Profiler::FScopedPhase l77StampPhase( VoxelForgeCore::Linux77Profiler::EPhase::Stamps); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerStamps); - stamped=ApplyResolvedSdfStamps(composed,X,Y,Z); + stamped=ApplyResolvedSdfStamps(composed,X,Y,Z, + liminalRouteComposition?std::string_view("core/liminal-field/route/") + :std::string_view{}); } static const bool bL75TraceTnComposition=[] { @@ -1598,6 +1602,12 @@ public: ELegacyFieldTerm::ComposerPassage); final=ApplyResolvedStratePassageCarves(final,X,Y,Z); } + // A liminal route is authored to terminate at fixed passage mouths. The + // passage carve owns the surrounding bore, while the deck/support stamps + // restore its walkable floor so the composed route crosses the interface. + if(liminalRouteComposition) + final=ApplyResolvedSdfStamps(final,X,Y,Z,{}, + "core/liminal-field/route/"); if(bTraceTnComposition) std::printf("[L75TNCompositionTrace] input=%.9g graph=%.9g boundary=%.9g passage=%.9g stamp=%.9g final=%.9g native=0\n", density,graphDensity,boundary,composed,stamped,final); @@ -7156,10 +7166,16 @@ private: const float halfThickness=stamp.halfExtentsVoxels[2]; const float round=std::min(0.35f,std::min(halfWidth,halfThickness)*0.15f); const float searchMargin=halfWidth+halfThickness+2.0f; - const auto first=std::lower_bound(path.begin(),path.end(),x-searchMargin, - [](const auto& point,float value){return point[0]=b[0];})==path.end(); + const auto first=increasingX + ?std::lower_bound(path.begin(),path.end(),x-searchMargin, + [](const auto& point,float value){return point[0](first-path.begin()); const std::size_t lastIndex=static_cast(last-path.begin()); const std::size_t segmentBegin=std::min(path.size()-2, @@ -7426,7 +7442,9 @@ private: std::nextafter(maximum+outwardPadding, std::numeric_limits::infinity()),true}; } - float ApplyResolvedSdfStamps(float density,float X,float Y,float Z) const + float ApplyResolvedSdfStamps(float density,float X,float Y,float Z, + std::string_view excludedStableIdPrefix={}, + std::string_view includedStableIdPrefix={}) const { if(StampRuntime.empty()||!Owner||Owner->CoreVoxelSizeMicrons==0)return density; const auto* tileQueries=ActivePassageTileQueries; @@ -7443,6 +7461,10 @@ private: if(index>=StampRuntime.size())return; const auto& runtime=StampRuntime[index];const auto& record=*runtime.record; if(record.strateIndex!=bound->StrateIndex)return; + if(!excludedStableIdPrefix.empty() + &&record.stableId.starts_with(excludedStableIdPrefix))return; + if(!includedStableIdPrefix.empty() + &&!record.stableId.starts_with(includedStableIdPrefix))return; if(UsesCoarsePillarProxy(runtime,CurrentStampSamplingStep()))return; for(std::size_t axis=0;axis<3;++axis) if(worldMicrometres[axis](liminal.variant) >= CoreLiminalFieldVariantCountV1 + || liminal.seed != effectiveRecipe.seed + || liminal.variant != SelectCoreLiminalFieldVariantV1(liminal.seed) + || stratum.route.size() < 2 + || liminal.mouthFloorOffsetSubvoxels <= 0 + || stratum.route.front().positionSubvoxels[0] != liminal.arrivalMouthSubvoxels[0] + || stratum.route.front().positionSubvoxels[1] != liminal.arrivalMouthSubvoxels[1] + || stratum.route.front().positionSubvoxels[2] + != liminal.arrivalMouthSubvoxels[2]-liminal.mouthFloorOffsetSubvoxels + || stratum.route.back().positionSubvoxels[0] != liminal.departureMouthSubvoxels[0] + || stratum.route.back().positionSubvoxels[1] != liminal.departureMouthSubvoxels[1] + || stratum.route.back().positionSubvoxels[2] + != liminal.departureMouthSubvoxels[2]-liminal.mouthFloorOffsetSubvoxels + || liminal.routeHalfWidthSubvoxels < stratum.routeConstraints.capsuleRadiusSubvoxels + || liminal.routeHalfThicknessSubvoxels <= 0 + || liminal.routeOffsetSubvoxels <= 0 + || liminal.supportSpacingSubvoxels <= 0 + || liminal.supportRadiusSubvoxels <= 0 + || stratum.surfaceProfile.version != 1) + { error = "Core.Liminal.Field plan has invalid version, seed-selected variant, route mouths or dimensions"; return false; } + const std::int64_t bottom = static_cast(stratum.bottomChunkZ) + * layoutChunkWidthSubvoxels; + const std::int64_t top = (static_cast(stratum.topChunkZ) + 1) + * layoutChunkWidthSubvoxels; + if (liminal.floorHeightSubvoxels <= bottom || liminal.floorHeightSubvoxels >= top) + { error = "Core.Liminal.Field floor escapes its finite stratum bounds"; return false; } + } const auto& constraints = stratum.routeConstraints; if (constraints.version == 0) { @@ -682,6 +713,24 @@ namespace world_assembly_detail for (const auto value : point.positionSubvoxels) HashWord(hash, static_cast(value), 8); HashWord(hash, static_cast(point.radiusSubvoxels), 8); } + if (stratum.liminalField.version != 0) + { + const auto& liminal = stratum.liminalField; + HashWord(hash, 0x4c494d494e414c31ull, 8); + HashWord(hash, liminal.version, 4); + HashWord(hash, static_cast(liminal.variant), 4); + HashWord(hash, liminal.seed, 4); + for (const auto value : liminal.arrivalMouthSubvoxels) + HashWord(hash, static_cast(value), 8); + for (const auto value : liminal.departureMouthSubvoxels) + HashWord(hash, static_cast(value), 8); + for (const auto value : {liminal.mouthFloorOffsetSubvoxels, + liminal.floorHeightSubvoxels, + liminal.routeHalfWidthSubvoxels, liminal.routeHalfThicknessSubvoxels, + liminal.routeOffsetSubvoxels, liminal.supportSpacingSubvoxels, + liminal.supportRadiusSubvoxels}) + HashWord(hash, static_cast(value), 8); + } if (stratum.surfaceProfile.version != 0) HashSurfaceProfile(hash, stratum.surfaceProfile); return hash; @@ -1059,6 +1108,30 @@ namespace world_assembly_detail { error = "world assembly route point is missing a fixed-scale field"; return false; } stratum.route.push_back(point); } + const VFJson::Value& liminalValue = item.Get("liminal_field"); + if (!std::holds_alternative(liminalValue.Data)) + { + auto& liminal = stratum.liminalField; + std::uint32_t variant = 0; + if (!liminalValue.IsObject() + || !ReadU32(liminalValue.Get("version"), liminal.version) + || !ReadU32(liminalValue.Get("variant"), variant) + || !ReadU32(liminalValue.Get("seed"), liminal.seed) + || !ReadArray(liminalValue.Get("arrival_mouth_q"), + liminal.arrivalMouthSubvoxels.data(), 3) + || !ReadArray(liminalValue.Get("departure_mouth_q"), + liminal.departureMouthSubvoxels.data(), 3) + || !ReadInteger(liminalValue.Get("mouth_floor_offset_q"), + liminal.mouthFloorOffsetSubvoxels) + || !ReadInteger(liminalValue.Get("floor_height_q"), liminal.floorHeightSubvoxels) + || !ReadInteger(liminalValue.Get("route_half_width_q"), liminal.routeHalfWidthSubvoxels) + || !ReadInteger(liminalValue.Get("route_half_thickness_q"), liminal.routeHalfThicknessSubvoxels) + || !ReadInteger(liminalValue.Get("route_offset_q"), liminal.routeOffsetSubvoxels) + || !ReadInteger(liminalValue.Get("support_spacing_q"), liminal.supportSpacingSubvoxels) + || !ReadInteger(liminalValue.Get("support_radius_q"), liminal.supportRadiusSubvoxels)) + { error = "Core.Liminal.Field plan is missing a fixed-scale field"; return false; } + liminal.variant = static_cast(variant); + } plan.strates.push_back(std::move(stratum)); } return true; @@ -2324,6 +2397,328 @@ bool WorldAssemblyManifest::validate(std::string& error) const return true; } +bool PlanCoreLiminalFieldV1(WorldAssemblyRecipeV1& recipe, + WorldAssemblyStratumPlanV1& stratum,const ResolvedLayoutSnapshotV3& layout, + std::string& error) +{ + error.clear(); + if(layout.coreVoxelSizeMicrometres==0||stratum.strateIndex<0 + ||stratum.topChunkZcontent.presentInCurrentField) + {error="Core.Liminal.Field must target a resolved SurfaceWorld content band";return false;} + const ResolvedLayoutPassageV1* arrival=nullptr; + const ResolvedLayoutPassageV1* departure=nullptr; + for(const auto& passage:layout.passages) + { + if(passage.lowerStrateIndex==stratum.strateIndex) + { + if(arrival){error="Core.Liminal.Field requires one fixed arrival passage mouth";return false;} + arrival=&passage; + } + if(passage.upperStrateIndex==stratum.strateIndex) + { + if(departure){error="Core.Liminal.Field requires one fixed departure passage mouth";return false;} + departure=&passage; + } + } + if(!arrival||!departure) + {error="Core.Liminal.Field requires an adjacent passage on both sides";return false;} + + constexpr std::int64_t Q=WorldAssemblySubvoxelsPerVoxel; + const std::int64_t coreMicrons=layout.coreVoxelSizeMicrometres; + const auto micrometresToQ=[&](std::int64_t micrometres) + { + const std::int64_t numerator=micrometres*Q; + return numerator>=0?(numerator+coreMicrons/2)/coreMicrons + :(numerator-coreMicrons/2)/coreMicrons; + }; + const std::int64_t qPerMetre=micrometresToQ(1000000); + if(qPerMetre<=0){error="Core.Liminal.Field could not resolve fixed-scale metres";return false;} + + const std::uint32_t seed=recipe.seed; + const WorldAssemblyLiminalVariantV1 variant=SelectCoreLiminalFieldVariantV1(seed); + const auto& definition=CoreLiminalFieldVariantsV1[static_cast(variant)]; + const auto& start=arrival->lowerMouthSubvoxels; + const auto& finish=departure->upperMouthSubvoxels; + constexpr std::int64_t MaximumMouthCoordinateQ=1000000000ll; + if(std::abs(start[0])>MaximumMouthCoordinateQ||std::abs(start[1])>MaximumMouthCoordinateQ + ||std::abs(start[2])>MaximumMouthCoordinateQ||std::abs(finish[0])>MaximumMouthCoordinateQ + ||std::abs(finish[1])>MaximumMouthCoordinateQ||std::abs(finish[2])>MaximumMouthCoordinateQ) + {error="Core.Liminal.Field passage mouth exceeds the supported fixed-coordinate range";return false;} + const std::int64_t mouthPlayerCenterHeight=micrometresToQ(1130000); + auto routeStart=start; + auto routeFinish=finish; + routeStart[2]-=mouthPlayerCenterHeight; + routeFinish[2]-=mouthPlayerCenterHeight; + const auto findMouthControl=[&](const ResolvedLayoutPassageV1& passage, + const std::array& mouth) + { + std::size_t found=passage.controlPoints.size(); + for(std::size_t i=0;icontrolPoints.size()<2||departure->controlPoints.size()<2 + ||arrivalControl>=arrival->controlPoints.size() + ||departureControl>=departure->controlPoints.size()) + {error="Core.Liminal.Field needs exact passage-control bindings at both fixed mouths";return false;} + const auto horizontalLengthQ=[](std::int64_t dx,std::int64_t dy) + { + const auto absX=static_cast(std::abs(dx)); + const auto absY=static_cast(std::abs(dy)); + return world_assembly_detail::IntegerSqrt(absX*absX+absY*absY); + }; + const auto roundRatio=[](std::int64_t numerator,std::uint64_t denominator) + { + if(denominator==0)return std::int64_t{0}; + const auto positiveDenominator=static_cast(denominator); + return numerator>=0 + ?(numerator+positiveDenominator/2)/positiveDenominator + :-((-numerator+positiveDenominator/2)/positiveDenominator); + }; + const auto passageSplineControls=[](const ResolvedLayoutPassageV1& passage) + { + std::vector controls; + controls.reserve(passage.controlPoints.size()); + for(const auto& point:passage.controlPoints) + controls.push_back({static_cast(point.positionSubvoxels[0]), + static_cast(point.positionSubvoxels[1]), + static_cast(point.positionSubvoxels[2]-point.radiusSubvoxels), + static_cast(point.radiusSubvoxels)}); + return controls; + }; + const auto arrivalSpline=passageSplineControls(*arrival); + const auto departureSpline=passageSplineControls(*departure); + constexpr double MouthTangentProbeParameter=0.5; + const std::size_t arrivalSegment=arrivalControl==0?0:arrivalControl-1; + const double arrivalAtT=arrivalControl==0?0.0:1.0; + const double arrivalNearT=arrivalControl==0?MouthTangentProbeParameter + :1.0-MouthTangentProbeParameter; + const auto arrivalNear=PassageSpline::EvaluateRaw(arrivalSpline,arrivalSegment, + arrivalNearT,static_cast(qPerMetre)); + const auto arrivalAt=PassageSpline::EvaluateRaw(arrivalSpline,arrivalSegment, + arrivalAtT,static_cast(qPerMetre)); + const std::size_t departureSegment=departureControl+1==departure->controlPoints.size() + ?departureControl-1:departureControl; + const double departureAtT=departureControl+1==departure->controlPoints.size()?1.0:0.0; + const double departureNearT=departureControl+1==departure->controlPoints.size() + ?1.0-MouthTangentProbeParameter:MouthTangentProbeParameter; + const auto departureAt=PassageSpline::EvaluateRaw(departureSpline,departureSegment, + departureAtT,static_cast(qPerMetre)); + const auto departureNear=PassageSpline::EvaluateRaw(departureSpline,departureSegment, + departureNearT,static_cast(qPerMetre)); + const auto roundedDelta=[](double startValue,double endValue) + {return static_cast(std::llround(endValue-startValue));}; + const std::int64_t arrivalDx=roundedDelta(arrivalNear[0],arrivalAt[0]); + const std::int64_t arrivalDy=roundedDelta(arrivalNear[1],arrivalAt[1]); + const std::int64_t arrivalFloorDelta=roundedDelta(arrivalNear[2],arrivalAt[2]); + const std::uint64_t arrivalLength=horizontalLengthQ(arrivalDx,arrivalDy); + const std::int64_t departureDx=roundedDelta(departureAt[0],departureNear[0]); + const std::int64_t departureDy=roundedDelta(departureAt[1],departureNear[1]); + const std::int64_t departureFloorDelta=roundedDelta(departureAt[2],departureNear[2]); + const std::uint64_t departureLength=horizontalLengthQ(departureDx,departureDy); + if(arrivalLength==0||departureLength==0) + {error="Core.Liminal.Field passage mouth tangent is too short for a stable connector";return false;} + const auto extendMouth=[&](const std::array& mouth, + std::int64_t dx,std::int64_t dy,std::int64_t dz,std::uint64_t horizontalLength, + std::int64_t distance,bool forward) + { + const std::int64_t sign=forward?1:-1; + return std::array{ + mouth[0]+roundRatio(sign*dx*distance,horizontalLength), + mouth[1]+roundRatio(sign*dy*distance,horizontalLength), + mouth[2]+roundRatio(sign*dz*distance,horizontalLength)}; + }; + constexpr std::int64_t MouthConnectorMidMetres=5; + constexpr std::int64_t MouthConnectorFullMetres=10; + const auto arrivalConnectorMid=extendMouth(routeStart,arrivalDx,arrivalDy, + arrivalFloorDelta,arrivalLength,MouthConnectorMidMetres*qPerMetre,true); + const auto arrivalConnector=extendMouth(routeStart,arrivalDx,arrivalDy, + arrivalFloorDelta,arrivalLength,MouthConnectorFullMetres*qPerMetre,true); + const auto departureConnector=extendMouth(routeFinish,departureDx,departureDy, + departureFloorDelta,departureLength,MouthConnectorFullMetres*qPerMetre,false); + const auto departureConnectorMid=extendMouth(routeFinish,departureDx,departureDy, + departureFloorDelta,departureLength,MouthConnectorMidMetres*qPerMetre,false); + const std::int64_t bottom=static_cast(stratum.bottomChunkZ) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t top=(static_cast(stratum.topChunkZ)+1) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t minRouteFloor=std::min({routeStart[2],routeFinish[2], + arrivalConnectorMid[2],arrivalConnector[2],departureConnector[2], + departureConnectorMid[2]}); + const std::int64_t contentBottom=micrometresToQ( + resolvedStratum->content.bottomMicrometres); + const std::int64_t profileRelief=variant==WorldAssemblyLiminalVariantV1::repeatingHills + ?2*micrometresToQ(definition.hillAmplitudeMicrometres):0; + const std::int64_t floorHeight=std::max(contentBottom+profileRelief+qPerMetre/4, + minRouteFloor-8*qPerMetre); + if(floorHeight>=minRouteFloor-2*qPerMetre||floorHeight<=bottom||top<=floorHeight+8*qPerMetre) + {error="Core.Liminal.Field has no room for its floor and passage route";return false;} + + stratum.hasRecipeOverride=true; + stratum.recipeOverride=recipe; + WorldAssemblySurfaceProfileV1 profile; + profile.version=1; + profile.kind=definition.surfaceKind; + profile.h0Subvoxels=floorHeight; + if(profile.kind==WorldAssemblySurfaceProfileKindV1::periodicHills) + { + profile.amplitudeXSubvoxels=micrometresToQ(definition.hillAmplitudeMicrometres); + profile.amplitudeYSubvoxels=profile.amplitudeXSubvoxels; + profile.wavelengthXSubvoxels=micrometresToQ(definition.hillWavelengthMicrometres); + profile.wavelengthYSubvoxels=profile.wavelengthXSubvoxels; + ResolveWorldAssemblySurfaceProfilePhasesV1(profile,seed); + } + stratum.recipeOverride.surfaceProfile=profile; + stratum.recipeOverride.contentHash=0; + stratum.surfaceProfile=profile; + stratum.capHeightSubvoxels=top-4*qPerMetre; + stratum.capUndulationSubvoxels=0; + stratum.capDetailAmplitudeSubvoxels=0; + stratum.capRidgeAmplitudeSubvoxels=0; + stratum.waterEnabled=false; + stratum.waterSurfaceSubvoxels=0; + + WorldAssemblyLiminalFieldPlanV1 liminal; + liminal.version=CoreLiminalFieldRecipeVersionV1; + liminal.variant=variant; + liminal.seed=seed; + liminal.arrivalMouthSubvoxels=start; + liminal.departureMouthSubvoxels=finish; + liminal.floorHeightSubvoxels=floorHeight; + liminal.routeHalfWidthSubvoxels=micrometresToQ(definition.routeHalfWidthMicrometres); + liminal.routeHalfThicknessSubvoxels=micrometresToQ(definition.routeHalfThicknessMicrometres); + liminal.supportSpacingSubvoxels=micrometresToQ(definition.supportSpacingMicrometres); + liminal.supportRadiusSubvoxels=micrometresToQ(definition.supportRadiusMicrometres); + liminal.mouthFloorOffsetSubvoxels=mouthPlayerCenterHeight; + + constexpr std::int64_t GradeQ16=17560; + constexpr std::int64_t MinimumPathOffsetMetres=150; + constexpr std::int64_t ConnectorSpanMetres=16; + const std::int64_t dx=departureConnector[0]-arrivalConnector[0]; + const std::int64_t dy=departureConnector[1]-arrivalConnector[1]; + const std::uint64_t chord=horizontalLengthQ(dx,dy); + std::int64_t directionX=dx,directionY=dy; + std::uint64_t directionLength=chord; + if(directionLength(qPerMetre/4)) + {directionX=Q;directionY=0;directionLength=static_cast(Q);} + const std::int64_t normalX=-directionY; + const std::int64_t normalY=directionX; + const std::int64_t vertical=std::abs(departureConnector[2]-arrivalConnector[2]); + const std::int64_t requiredHorizontal=(vertical*65536+GradeQ16-1)/GradeQ16; + std::int64_t routeOffset=std::max(MinimumPathOffsetMetres*qPerMetre, + (requiredHorizontal+1)/2+20*qPerMetre); + if(chord(qPerMetre)) + routeOffset=std::max(routeOffset,MinimumPathOffsetMetres*qPerMetre); + liminal.routeOffsetSubvoxels=routeOffset; + + const auto normalOffset=[&](std::int64_t scale) + { + return std::array{ + normalX*scale/static_cast(directionLength), + normalY*scale/static_cast(directionLength)}; + }; + const auto directionOffset=[&](std::int64_t scale) + { + return std::array{ + directionX*scale/static_cast(directionLength), + directionY*scale/static_cast(directionLength)}; + }; + const auto normal=normalOffset(routeOffset); + const auto connector=chord(qPerMetre) + ?directionOffset(ConnectorSpanMetres*qPerMetre):std::array{0,0}; + std::vector> horizontalPath; + horizontalPath.reserve(8); + horizontalPath.push_back(routeStart); + horizontalPath.push_back(arrivalConnectorMid); + horizontalPath.push_back(arrivalConnector); + horizontalPath.push_back({arrivalConnector[0]+normal[0], + arrivalConnector[1]+normal[1],0}); + horizontalPath.push_back({departureConnector[0]+normal[0]+connector[0], + departureConnector[1]+normal[1]+connector[1],0}); + horizontalPath.push_back(departureConnector); + horizontalPath.push_back(departureConnectorMid); + horizontalPath.push_back(routeFinish); + + std::vector route; + route.reserve(horizontalPath.size()); + std::vector cumulative(horizontalPath.size(),0); + std::uint64_t totalHorizontal=0; + for(std::size_t i=1;i(requiredHorizontal)) + {error="Core.Liminal.Field route cannot meet the 15-degree grade bound";return false;} + const std::uint64_t centralFirst=horizontalLengthQ( + horizontalPath[3][0]-horizontalPath[2][0], + horizontalPath[3][1]-horizontalPath[2][1]); + const std::uint64_t centralMiddle=horizontalLengthQ( + horizontalPath[4][0]-horizontalPath[3][0], + horizontalPath[4][1]-horizontalPath[3][1]); + const std::uint64_t centralLast=horizontalLengthQ( + horizontalPath[5][0]-horizontalPath[4][0], + horizontalPath[5][1]-horizontalPath[4][1]); + const std::uint64_t centralTotal=centralFirst+centralMiddle+centralLast; + if(centralTotal==0) + {error="Core.Liminal.Field central route has no horizontal span";return false;} + const std::int64_t centralVertical=departureConnector[2]-arrivalConnector[2]; + horizontalPath[3][2]=arrivalConnector[2]+roundRatio( + centralVertical*static_cast(centralFirst),centralTotal); + horizontalPath[4][2]=arrivalConnector[2]+roundRatio( + centralVertical*static_cast(centralFirst+centralMiddle),centralTotal); + for(std::size_t i=0;i(liminal.routeHalfWidthSubvoxels, + micrometresToQ(500000)); + std::uint64_t id=14695981039346656037ull; + const auto add=[&](std::uint64_t value,std::uint32_t bytes) + {for(std::uint32_t byte=0;byte(value>>(byte*8));id*=1099511628211ull;}}; + add(seed,4);add(static_cast(stratum.strateIndex),4);add(i,4); + routePoint.stableFeatureId=id?id:1; + route.push_back(routePoint); + } + stratum.route=std::move(route); + stratum.routeConstraints={1,micrometresToQ(340000),micrometresToQ(1760000), + GradeQ16,micrometresToQ(125000),micrometresToQ(250000), + micrometresToQ(1000000),micrometresToQ(120000),3}; + stratum.liminalField=liminal; + std::string validationError; + if(!world_assembly_detail::ValidateSurfaceProfile(stratum.surfaceProfile,seed,validationError) + ||!world_assembly_detail::ValidateStratum(stratum,recipe,validationError)) + {error=validationError.empty()?"Core.Liminal.Field produced an invalid plan":validationError;return false;} + std::printf("[CoreLiminalFieldPlan] recipe=%.*s version=%u variant=%.*s seed=%u arrival=%s departure=%s route_points=%zu route_offset_m=%.3f route_grade_limit_deg=15.000 status=PASS\n", + static_cast(CoreLiminalFieldRecipeIdV1.size()),CoreLiminalFieldRecipeIdV1.data(), + liminal.version,static_cast(definition.name.size()),definition.name.data(),seed, + arrival->stableId.c_str(),departure->stableId.c_str(),stratum.route.size(), + static_cast(routeOffset)/qPerMetre); + return true; +} + std::string WorldAssemblyManifest::ToJson() const { std::string error; @@ -2391,6 +2786,27 @@ std::string WorldAssemblyManifest::ToJson() const << ",\"minimum_clearance_q\":" << constraints.minimumClearanceSubvoxels << ",\"minimum_support_probes\":" << constraints.minimumSupportProbes << '}'; } + if (stratum.liminalField.version != 0) + { + const auto& liminal = stratum.liminalField; + out << ",\"liminal_field\":{\"version\":" << liminal.version + << ",\"variant\":" << static_cast(liminal.variant) + << ",\"seed\":" << liminal.seed << ",\"arrival_mouth_q\":[" + << liminal.arrivalMouthSubvoxels[0] << ',' + << liminal.arrivalMouthSubvoxels[1] << ',' + << liminal.arrivalMouthSubvoxels[2] << "],\"departure_mouth_q\":[" + << liminal.departureMouthSubvoxels[0] << ',' + << liminal.departureMouthSubvoxels[1] << ',' + << liminal.departureMouthSubvoxels[2] + << "],\"mouth_floor_offset_q\":" << liminal.mouthFloorOffsetSubvoxels + << ",\"floor_height_q\":" + << liminal.floorHeightSubvoxels + << ",\"route_half_width_q\":" << liminal.routeHalfWidthSubvoxels + << ",\"route_half_thickness_q\":" << liminal.routeHalfThicknessSubvoxels + << ",\"route_offset_q\":" << liminal.routeOffsetSubvoxels + << ",\"support_spacing_q\":" << liminal.supportSpacingSubvoxels + << ",\"support_radius_q\":" << liminal.supportRadiusSubvoxels << '}'; + } out << ",\"route\":["; for (std::size_t p = 0; p < stratum.route.size(); ++p) { diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py new file mode 100644 index 0000000..42a0a72 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/BuildL144Fixtures.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Build the 3-strata composed Core.Liminal.Field fixture.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l144")) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + world = json.loads(OWNER.read_text(encoding="utf-8")) + if len(world.get("strates", [])) < 3: + raise SystemExit("owner fixture needs at least three authored strate slots") + + world["strates"] = world["strates"][:3] + world["total_strates"] = 3 + world["settings_asset"]["TotalStrates"] = 3 + world["settings_asset"]["FixedStrates"] = world["settings_asset"]["FixedStrates"][:3] + # Keep the resolved arrival near the departure depth. The owner's 5000-unit + # reach clamps to liminal bedrock on most seeds and leaves no field floor. + world["strates"][0]["passage_config"]["ReachMin"] = 1536 + world["strates"][0]["passage_config"]["ReachMax"] = 1792 + world["surface_profile_override"] = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, + } + middle = world["strates"][1] + middle["asset"]["GeneratorType"] = 4 # ECaveGeneratorType::SurfaceWorld + middle["asset"]["StrateName"] = "Liminal Field" + # Keep the departure mouth 24–32 m above liminal bedrock so every variant + # has room for its floor, road landing and support footings. + middle["passage_config"]["ReachMin"] = 192 + middle["passage_config"]["ReachMax"] = 256 + world["core_liminal_field"] = { + "version": 1, + "strate_index": int(middle["index"]), + "variant_policy": "seed_modulo_4", + } + + output = args.out / "core-liminal-field-3-strata.json" + output.write_text(json.dumps(world, separators=(",", ":")) + "\n", encoding="utf-8") + print(f"[L144Fixture] path={output} strates=SurfaceWorld,Core.Liminal.Field,TunnelNetwork status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py b/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py new file mode 100644 index 0000000..bec3060 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/CaptureL144.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +"""Capture the four seed-selected Core.Liminal.Field v1 variants.""" +from __future__ import annotations + +import hashlib +import json +import math +import os +from pathlib import Path +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +HERE = Path(__file__).resolve().parent +OUT = ROOT / "Saved/Linux/l144" +CAPTURES = HERE / "captures" +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) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, env: dict[str, str], + stamped: bool = False) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(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_stamp: + raise RuntimeError(f"{name} refused a 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) + output = log.read_text(encoding="utf-8", errors="replace") + elapsed = time.monotonic() - started + print(f"[L144Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp + or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != 0: + raise RuntimeError(f"{name} exit={result.returncode}; see {log}") + return output + + +def camera_angles(camera, target): + 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 route_views(manifest_path: Path, layout_path: Path, name: str): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + plan = next(row for row in manifest["plan"]["strates"] + if row["strate_index"] == 1 and row.get("liminal_field", {}).get("version") == 1) + points = [tuple(value / Q_PER_METRE for value in row["position_q"]) + for row in plan["route"]] + first, second = points[0], points[1] + dx, dy = second[0] - first[0], second[1] - first[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field arrival tangent is degenerate") + tx, ty = dx / length, dy / length + eye_camera = (first[0] - tx * 1.5, first[1] - ty * 1.5, first[2] + 1.6) + third = points[min(2, len(points) - 1)] + dx, dy = third[0] - first[0], third[1] - first[1] + tangent_length = math.hypot(dx, dy) + tx, ty = dx / tangent_length, dy / tangent_length + dz_per_metre = (third[2] - first[2]) / tangent_length + eye_target = (first[0] + tx * 40.0, first[1] + ty * 40.0, + first[2] + dz_per_metre * 40.0 + 1.6) + + middle = len(points) // 2 + before, center, after = points[middle - 1], points[middle], points[middle + 1] + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field wide-view tangent is degenerate") + tx, ty = dx / length, dy / length + nx, ny = -ty, tx + floor = plan["liminal_field"]["floor_height_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = next(row for row in layout.get("stamps", []) + if row.get("stable_id") == "core/liminal-field/monolith/000") + monolith_center = tuple(value / 1.0e6 for value in monolith["position_um"]) + floor = monolith_center[2] - monolith["half_extents_um"][2] / 1.0e6 + wide_camera = (monolith_center[0] - tx * 30.0 + nx * 18.0, + monolith_center[1] - ty * 30.0 + ny * 18.0, floor + 25.0) + wide_target = monolith_center + elif name == "periodicHills": + wide_camera = (center[0] - 20.0, center[1] - 25.0, floor + 10.0) + wide_target = (center[0] + 10.0, center[1] + 8.0, floor + 1.0) + elif name == "pillar-grid": + pillars = [row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("core/liminal-field/pillars/")] + if not pillars: + raise RuntimeError("pillar-grid layout has no resolved grid stamps") + pairs = [] + for i, first_pillar in enumerate(pillars): + for second_pillar in pillars[i + 1:]: + a = first_pillar["position_um"] + b = second_pillar["position_um"] + dx, dy = (b[0] - a[0]) / 1.0e6, (b[1] - a[1]) / 1.0e6 + separation = math.hypot(dx, dy) + if 60.0 <= separation <= 90.0: + mx = (a[0] + b[0]) / 2.0e6 + my = (a[1] + b[1]) / 2.0e6 + pairs.append((math.hypot(mx - center[0], my - center[1]), + mx, my, dx / separation, dy / separation, + (a[2] + b[2]) / 2.0e6, + first_pillar["half_extents_um"][2] / 1.0e6)) + if not pairs: + raise RuntimeError("pillar-grid has no neighboring resolved columns") + _, mx, my, tx, ty, pillar_z, half_height = min(pairs) + floor = pillar_z - half_height + nx, ny = -ty, tx + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + else: + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + return {"eye": (eye_camera, eye_target), "wide": (wide_camera, wide_target)} + + +def capture_variant(seed: int, name: str, *, headless: Path, renderer: Path, + fixture: Path, env: dict[str, str]): + stem = f"core-liminal-{name}-seed{seed:02d}" + plan_dir = OUT / "capture-plans" / stem + plan_dir.mkdir(parents=True, exist_ok=True) + manifest = plan_dir / "manifest.json" + layout = plan_dir / "layout.json" + command = [headless, fixture, "--workers=1", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--camera=0,0,-540,0,0", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + output = run_step(f"plan-{stem}", command, OUT / "logs" / f"capture-{stem}-plan.log", + env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output: + raise RuntimeError(f"{stem} plan omitted its Core liminal deck") + views = route_views(manifest, layout, name) + for view, (eye, target) in views.items(): + work = OUT / "captures" / f"{stem}-{view}" + work.mkdir(parents=True, exist_ok=True) + view_manifest = work / "manifest.json" + view_layout = work / "layout.json" + mesh = work / "world.vfmesh" + yaw, pitch = camera_angles(eye, target) + camera = (*eye, yaw, pitch) + view_clip_radius = (5 if view == "wide" and name in { + "flatField-monolith", "periodicHills"} else + 3) + command = [headless, fixture, "--workers=12", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={view_clip_radius}", + "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--capture-skip-walkability", + f"--camera={fmt(camera)}", f"--mesh-export={mesh}", + f"--world-assembler-manifest-output={view_manifest}", + f"--resolved-layout-output={view_layout}"] + output = run_step(f"export-{stem}-{view}", command, + OUT / "logs" / f"capture-{stem}-{view}-export.log", env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output or not mesh.is_file() \ + or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem}-{view} export omitted its Core liminal deck or mesh") + png = work / f"{view}.png" + image = CAPTURES / f"{stem}-{view}.jpg" + fog = { + "flatField-monolith": (30, 180, "0.66,0.73,0.77", -708.0, 46.0), + "periodicHills": (140, 850, "0.78,0.84,0.88", -720.0, 14.0), + "road-over-cloud-floor": (24, 420, "0.88,0.93,0.95", -720.0, 65.0), + "pillar-grid": (180, 1200, "0.82,0.88,0.91", -720.0, 80.0), + }[name] + fog_start, fog_end, fog_color, height_center, height_range = fog + render = [renderer, mesh, png, "--size=1600x900", "--fov-deg=72", + f"--camera-m={fmt(eye)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}", + "--tile-skirts=on", "--shade=readable", "--headlamp=off", "--height-tint=on", + f"--height-center-m={height_center:.6f}", f"--height-range-m={height_range:.6f}", + "--light-direction=-0.42,-0.58,0.70", "--fog=on", f"--fog-start-m={fog_start}", + f"--fog-end-m={fog_end}", f"--fog-color={fog_color}"] + run_step(f"render-{stem}-{view}", render, + OUT / "logs" / f"capture-{stem}-{view}-render.log", env, stamped=True) + run_step(f"jpeg-{stem}-{view}", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel", + "error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image], + OUT / "logs" / f"capture-{stem}-{view}-jpeg.log", env) + run_step(f"quality-{stem}-{view}", [sys.executable, + ROOT / "Standalone/Tools/verify/capture_quality.py", image], + OUT / "logs" / f"capture-{stem}-{view}-quality.log", env) + print(f"[L144Capture] variant={name} seed={seed} view={view} " + f"eye_height={'1.600m' if view == 'eye' else 'wide'} bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS", flush=True) + + +def main() -> int: + headless = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-clang19" + renderer = ROOT / "Standalone/bin/linux/VoxelForgeOffscreenCapture-clang19" + fixture = OUT / "fixtures/core-liminal-field-3-strata.json" + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(OUT) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") + CAPTURES.mkdir(parents=True, exist_ok=True) + variants = ("flatField-monolith", "periodicHills", + "road-over-cloud-floor", "pillar-grid") + selected = set(os.environ.get("L144_CAPTURE_VARIANTS", "").split(",")) + for seed, name in enumerate(variants): + if selected and name not in selected: + continue + capture_variant(seed, name, headless=headless, renderer=renderer, + fixture=fixture, env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L144Capture] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md new file mode 100644 index 0000000..94f62e6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux144/REPORT.md @@ -0,0 +1,44 @@ +# Linux144 — Core.Liminal.Field v1 + +| Variant (seed) | Arrival at eye height | Wide view | +|---|---|---| +| Flat field + monolith (0) | ![Flat field arrival](captures/core-liminal-flatField-monolith-seed00-eye.jpg) | ![Flat field wide](captures/core-liminal-flatField-monolith-seed00-wide.jpg) | +| Repeating hills (1) | ![Hills arrival](captures/core-liminal-periodicHills-seed01-eye.jpg) | ![Hills wide](captures/core-liminal-periodicHills-seed01-wide.jpg) | +| Road over cloud floor (2) | ![Road arrival](captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg) | ![Road wide](captures/core-liminal-road-over-cloud-floor-seed02-wide.jpg) | +| Pillar grid (3) | ![Pillars arrival](captures/core-liminal-pillar-grid-seed03-eye.jpg) | ![Pillars wide](captures/core-liminal-pillar-grid-seed03-wide.jpg) | + +**Result: stopped at the mouth-join gate; this is not ready to ship.** The new `Core.Liminal.Field` v1 recipe plans and draws all four seed-selected looks between fixed mouths. In the final composed probe, three of four seeds failed one of their two passage interfaces, and all four failed the liminal walk audit. The requested eight-seed-per-variant matrix was not run after the stop condition was reached. + +## What changed + +- Added one data-driven recipe, `Core.Liminal.Field` v1. `seed % 4` selects flat field with monolith, repeating hills, road over cloud floor, or pillar grid. +- The liminal plan binds the existing `passage/0-1/0` arrival and `passage/1-2/0` departure as fixed endpoints. It draws an 8-point route deck and structural supports; the road variant uses that deck as its route. The pillar variant resolved 221 grid pillars after route clearance. +- Added a three-strata fixture: Surface World → liminal → Tunnel Network. `BuildL144Fixtures.py` and `CaptureL144.py` reproduce the fixture and the eight captures. + +## Composed probe + +The final composed audit window was one run for each seed 0–3 at W1, using Clang 19 source stamp `8acbb7c3dfdb0484100d3d55036db20743ce76d74097b69362bb7d1a1c1d6302`. These are audit counts, not timing comparisons. + +| Variant | Passage interfaces passed | Liminal walk audit | Passage shell / seam audit | Liminal negative control | +|---|---:|---|---|---| +| Flat field + monolith, seed 0 | 1/2 — FAIL | 222 blocked samples, 7 grade failures — FAIL | PASS | altered departure rejected — PASS | +| Repeating hills, seed 1 | 2/2; composed summary FAIL | 1 blocked sample — FAIL | PASS | altered departure rejected — PASS | +| Road over cloud floor, seed 2 | 1/2 — FAIL | 3 blocked samples — FAIL | FAIL, 1 floor violation | altered departure rejected — PASS | +| Pillar grid, seed 3 | 1/2 — FAIL | 289 blocked samples, 9 grade failures — FAIL | PASS | altered departure rejected — PASS | + +The three partial passage-interface failures reached the requested stop threshold. Every liminal walk probe reported zero unsupported samples and zero structural-support failures; support alone therefore does not explain the blocked routes. The top Surface World route audit passed all four seeds. Passage naturalness and mouth-profile negative controls also detected their injected faults in all four logs. + +## Captures and limits + +All eight 1600×900 images passed `capture_quality.py`. Arrival cameras are 1.6 m above the fixed arrival mouth and look along the route. Capture exports used `--capture-skip-walkability` to preserve render evidence despite the failing composed audits; this flag was not used for the audit runs. The wide pillar view shows the overhead deck and one support rather than a legible field of grid columns, and the other images also expose the current route/deck defects. + +No additional geometry change was attempted after the three-interface-failure threshold. Earlier diagnostics found the short terminal secant exaggerated the mouth grade; widening the tangent probe interval did not make the final composed walk pass. It remains unproven which combination of terminal connector geometry and nearby field solids accounts for the blocked capsule samples. + +## Checks + +- Clang 19 headless build completed; the final audit and capture executables report the source stamp above. +- Four composed probes ran at W1, one seed per variant. Planning/drawing and the per-audit results are in `Saved/Linux/l144/logs/probe8-seed00.log` through `probe8-seed03.log`. +- Eight capture quality checks passed. `git diff --check` passed. +- Not run after the stop gate: eight seeds per variant, GCC or W8/W12 determinism, owner canonical-hash comparison, fast tier, and one near-ready run. No performance timing window was collected. + +Changed Unreal `Source/` files: none. Changed standalone sources include `StreamBenchmarkHeadless.cpp`, `StreamBenchmarkPipeline.h`, and `WorldAssemblyPrototype.h`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-flatField-monolith-seed00-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7df7be7e05b3424d48cf28984166ae3a2cc66a61 GIT binary patch literal 35191 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-periodicHills-seed01-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c904988e016a35b7dfe08b585824714f52313b3 GIT binary patch literal 31096 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 ZO#7ttniT&CV3B^XhFcdm)%*GV{{wlh0`C9- literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2c3f6fa420d5d279a230d53ce6f261e21b8f1371 GIT binary patch literal 35478 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 TdOh^Z*?JZ||1Uq3KRo*npua(d literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-pillar-grid-seed03-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..57a163ab2defd081bef6a6b311ef2e0586653f65 GIT binary patch literal 37027 zcmeEu2V7Ixws-7hR79Fen+pmm%@FA&Izv%uBE2ghEdtV{g~ZWOIvGTP(4runkU=^m zWRwz-5+M|&Btj^X2q8cyAqn4^`@Q?-y<2|w{qA?)``)|nZs25}oqY~_ue0|$YyH=M z@12i30?={u+xNXR!Kz>#Rq#bHXlESsJ?P-UgNF_t`sVlP=#itprDMmA2@4AY$D>D& z9XozpSonm<37|k&L_}0n^yEni2`MRQIl1#Y9iR%(F3|2hyLRmY{cGB{|G?foyLTM~ z3jbX>2()X@?!Cu>`n!M4?Af<>@BX6)zX9#qy+?TO3GnasU9pziFA}1D`@nZUh|1qg zhtv-J7+&`*38&Fi8^4{e2k2JG6i z5A<70cJ00*3>G7f4TDuNciBMANOD0v+D$C_X*IR6QG?j(2+erbAmTK_8 z4(Mi#YlMSn=z>@xn(iFR@R>9KCk>axnn$4*NMK<-TH;8Y*F9`*@9ZsJw-hfs_--`Y zIjgv&v8rQaxZc;s#h&Wv2{(^SM8tDsjn~L_iD|wf$NY0TW9C|V#IP-e^?jCk^{K4R zKw&*h3Vz%`{Q4Sx<>N1#%^ySWw-K)`6S%mqqo}6}g4}lvk{oBms9X#?An-Ic^d>Ph z{W=F$q27l#>W$9I^%)gHnVtH|Egu>P+vpW5Vy6_3SX(<*e#WoSXLv_fa+%cI?v&J zNS3jgCuhmWAg(S#u1Fnd-ee+u#GEYPi)DY=?B)Tbhz%F_}tbYvCE zc@DIUDJUrDo15Ry#`wp-c5>Is3M?qOYJD#TrH6v5`gcpB7kXA%A-F!MzER|mvwSeD z#{g{+$-|?J+a(Lvsy=fcdTP9TV^BKRsW-tQbw{U~5V-T?+M%vk1bK6{z76->$7G6w zI2LG1O|r7G?XsYFl-ku_%cl9&2~zXS*)6Xl?!EVWDxG%uzj~hiH~D`z2{vD#CY*09 z&FvZws9DtOBXXv5!#nH)pLiA7jm&}hZP@<#u=?S?w+@zb_oMH<&11cY3yu$D2gm1I zR&)dmJko55)T~z@U+ge$^Eed>mNCRa?Y3=1L zqR_PA3Ovtc_Oo|mgMl}_vxINo_^F{pON1g;a{XpYssnvC_+D1~V3)6N zrgo{q*|TJ>(kKC1@v$70pJq72+Sd}=d45jeF|sov=s2Lly}gZX9l@)mlZQ@8eXU3~)~Uxt+;6tFby0eUB@9>i zWN(BnSO-kr#ZjL7{hBqP4{k1oV5L`G?%^8n_NK&SIe8o<5+bJcF zG-vOCpyNG~6C8($wZrVM$5RQ<`|f# zz4$yA8bt-)A$Zvcd-OR@02;Z4go#Qe;Lh}%2WsV};5)Z$JDK<-WMUdxPTpP1%$(Dt;-5#q$;|Io0;NN7~(w?U91$t@#>CV)NCB9 z<`~MseM}toV|{CxigNH`PMM1JC4 znQx+@z8{!W#p$hzLvNy}iKzCTHKZOz+pyF!%|lX1POcG)n3W5>iVvU#?SL>+{Y7)H zIyMt&@wvW*eblT1my>%WAY$9j5@b7m4x1%{w3u-@%Edxq=>}2tnyL29=RKOQ7RS^N zpYox~`RMob)xzRQFQ2W)*)X&GSk`M$mo+^P*5{t}g?ZMXqM{5;>kGDR*2|7jFif=I zbulGx4br`QA?I%nM1;wfQ;9j6eIxzpe#tM{F=feR!C7dM=lssJ63K(}o%3gwF`dD$-UT4t!!XuYap;;bV}S9`pVMR{Sfy`1x^vO<&aV z^UE+@OC{3l2Xnwc-2`#}@cY}a-5XRZA_4~MC89(`WZ2*CnXC;}K@jJnT}JSs5Mw0& zBhhjP8rb~sZghOcYht`m$$$HPu4TQjYrbYatE;GY)4Ehz zh59=t+AAVj1_r1H<)~40U$}q*n+&+-rJGw&lqfSRkQ%BS8_=?TMRAptq zd+(#>JU`9b0R>-*2=W-wwXS+ldjaZv(^OZ$b&F1knLN-u9= z!2Ih*Fnq6(OPHaC7^d^f9fQ}ayjz3ZCCt#agOFbGyM^uOnz2BFLkyk?m_C)U!HvNx zuD!+6wSeZ*jQ{R8iT|(2Rd7)Qh(`>t-n2t1BD>0anz?sGZqgk*V%Xcel~`Xh7Qvbp zFV#Bbri*r*eL^r>_wVT(MjTL*i2;oHf#geZRXM0j#lg~!tY6i}r~j)q>>Y$soyoo< zR=seR87J5To#r5Ecre*GW{%+KGlH|VZ>}6pqF^_%rOuciiIx{%cd?9K<5@jT1QX5@ z8P9rUZ~$YOd+**v^Zm+#wH3rpMYw?e+E`)6;MWN!+(G9^NS*FE5zVCB%kSOaU zj6!el(cah+DyFZBWEX*YF5-lZf%ndJx7rXho>8qAoY zymCIiHirPF_QgS*lHWNRtjq7&jlj-DnI&-4vl~GU>3%Sy!iqEHz1gOLV%9pAci}f$ zLo1S1bVAq;o~trnDw6L+gAEydVN`;~S>~6W_kjm{gQ{pwrfC4l?}H z(P{`Xw79*tiz0saBlK-ghEzmEKtpyF83l2tjA=FHlM=(6p6A(`ot?XIy`YvM$`ll< zn|FlsdqXJKQnwOF+9i=hy}EVwE7-Ngo|V2%4t?`Jt+6_$1K}~_%WltsZkgAe<^;d% z#$1o~%R!abb{64&s94f1!KalcZTH&W8&QZDQ}9Bb{H~E1b&FIy`+6XmVY!dnB3M5P z^9Yk7+i#37T3S-KN0Eo?I;;SPAsbJIS}DH#>F1Sup<3&&={=O{>f{kFEpV-u8Iuq0 zohl|2bl;hxN8hbscz5oR)yt2Mlgi5=Afi+9+hjvka8p zo{;?}s%o^_CzF9UMQU`5VX-oNh%mJED+f>@aQ!}R*!wxG7dMTlHA#1`IlZv$P<^dn zo54&0yG4zZjPqrl*o*(z1TpKS=Q z4;dmc731_X{HolW7osaQ)7(!RSy^#>zq-UEvRx;|vsbC|9+iy-A1A%y-I^^<;4TqD z?Hh{=hwF?h19~k2MI;k{RqoQoA7*0y^lAPhmh5uls1+NC4C|I^2}!HFELl<8`BM4O zdNXzOA@4SUUtUcVl^6XyQB}RN{CS#VQSP<|A!hLx&LKXnF*(Dky%J{#rGu+v50g8e zf1hJ42nWUF={nu@BKW3A5+nhQw30bM_bQ4ebKQ2A}})An3i*^1zAvm46h=>z6PPW+F1f4E>9csjG_T$JEFy!JK5S~->-19K?&_d zVrZiJJeGWzzJB#xwldHgoxyPkRfjvq57iDbLY0C>5{<3TiwBq(?P?W=84p}(6u*}& z_b5PlG+C}fOa2V0)uCL>`mCh|bLm6!w`IAdx^V--;daJJc^{vNdRsgWk0B_){3Ze-z~v|z>CxEZl8yw^p?k)j_+0n;eC8SZ)nL70oZoha$oOiI zd_zw4eC_$lc!?uHX_O|!%RU*%Eo@t`Cdt3LlD-i*+|1e@IPpWE0nJO?VR)t9^&XdY zKrPlqw3i`&)(4u#9Ck#F_(1J+77BWUEKyXj#knrJ09WxfL%r@j8Fo`*dLy1!Mr>5MlBZnF(htW2#(&+J6|hq$&FTU#*mlkJD^_n4u}r80{wpTt+KU( zCin4`9Z=W!cht&-dfo)}3_^!(x&yj47->~2C|svKZ#(zkA5qQxYoB(j4aG@N4D1zj z^2~KgU}DT1rm}qlBWYAaH*`dcC{|~*giwEGcGfPl!xMO_iEFs)Yi%A-6vEa+x~328 za#kg&Cd1%7WnN+;8ymR7IzvvFct6D<3yy{nhj&2K8c5G6g{4|P%r&gxD_v;pqKS-x z*=Tro`KIMGlt||PSbCUv=AsGxW(`9dDUilVj`pmY3tFldab3Ujqnq}9!@KMNj;TVd zsX43(6xA`K?dAn?x+NM>3Hc1Q(|8ks2wT&l)2=40#$$3cYi;f{Eehh@DT&S*)1B5D zQ<|$4maQ7|oo_kIxcC94~B(zz^wi2$aO~jg}(K^ z))TpDf$7i_*wK8rR=s*>4K+i9peEvCKb&t7=rq*Pv6+nlt4iNp5D%~Ya!0rU6KPmb8 z;l%gz{2T12ACk&2IC;)@CeZ*uQrZ1XG}PMGN$K4chYW6W_&1_HRWF$D_^vH`H`cz! z1NA~*Wailw^y$v?t*=n;8Jd2(Yx-Uf-Y4<+>5Q}wR7O?BZater$8z4kkk6$&d0lo? ze26VL@j}DR_bC12uI>#RkPxZ`1pn6o00+hWcJlku1O3@?psBD!!_+!PyAFaq-g0gSx*XVH%hxe}wYhuXXsKt&;^)lo*qwL9; zO5x33O<#j-+7UOJyUlyM9+|sNjq58nxh#rbLnC{r$0*ZX>G5llwb8#m&VPi=uJ8Co zzCFnw7OuP4k$c)vX95%}(p}MV`d##SlG8*099EmPs3<6cm48PSSY%ZHUIGh^nu6UN$5fnMwh_mA?_k1dh)p2RoH&oM1M`b(`l1mRN zE4drq?O10-vbAS}3FckfTX!#=T0WmgdqLQPZmvF(=it~rz@_& zS%VSf&D-eXnlWU}8s<|GcDj|0M2YBWiUxz7R(CaMp7lRv;COQPO=p_x)UQEI04jg(QR5su_&-1og}fvtn9EU#6*4zW@x6!F8F z@}z7KK26PXV?E5GWdj?51fSZ5k*utusXYC@ZTSzRwwipMkn;kMuN%V`gQD=&P=%Un z4LI>PnWL$^XE;vC7Q50##Vc&yTJqKimwDgjld#5&y|q47qMU2aM0b)O$_?Y(04Fyv zfMX2H$#=x+(vrp^%4z_4j$z*U2r-s9bJS_=0#s_IEaDZnK>cLlaK~!az?0 zM$=Cu9W6cA;{=LK%#KPndU0&v>4*8B_Ya4SogUw3^f>yc^ut1X{4?+C7Yal3623Ps z7PG#UX7p{5O3|d4wP(tQ2WiGH#f;O`-|p54JNV+Y$<=2^qcN3Pmw)DEvJM8U%1_T; zQPBqXSmu>s!f!+tXuWl>EI4!dUY^L&{-)=bP5aMZjRH(Oi$Ixf)ok0n&euam>~@`` z6|l?0^UjS;R*}a_Mc;f2>?F9YlJj~sd05-2^$yn8CA)0_N4Y;7xoKWT zwk1nezF&1!2XH5p+2~o%q543lMUCui3|;2roB|9ChKPtXWwXIx)`|5Mwm!<`%(*DO zS#ENi4ogokf*YS26(3!Wb-z|%uI!&$k3sdDCZ|YBK{{?R zC|@8Q;D1D6=Tfktap8ankR%gPV6Y)uHD3P9znA6zxU(a^+h()j>^NvL zh1mM8Er=lSsIe?4$d6`hk5lPx2Bm=>W4@aO>6?J2SUIx#dEJjPTFxA{nI^4Gu~KEv zfKMj|DZ|OGR=uEH)O*DAVR;BS87Yxw#LMLEyAsM(6gNj?Wp1RJ1lhZ0&xaV;CecYm z5&C>_kxeCQhjT`djGPz7C*F!3m_dsdp2YzQ_@LER5_$Z%*x1E0eje)-1WPH zlk4_<+w5DsMINqVx)_&5A$%`(-l?7yr0Q1;bDS6($qA5?@9kYjBt~xslU{zI#-a39 z(+mRvjG8aCLa;LHqEdauFn7(}LN4=j$bxVX?#t*_Y>=E+-{xxCsti)OpTL=# zjnVTZ6~{+#JFN2~I6^P{5tYk2%@?gWDkp14nroKegU|8Cp*PdV0)q*G0r1}FRjsz> zq7PlMhUGQ+l>9Z)5F%g1pYAnxQ%OW~+BsM+H++rXY8>Y5)j_t@Nl2vfEPwXDS5upq z_sYisxgI}8sF^DURb)&e$eC z5*1X?;{B?3YXs}O#UgZ;lF(cC%K`IJAOBUYy3qs7&H6@_8#buH$5M#x)k?(AF9~7# zK{)w7AR4~*+T2-17!0JQ>{SsF)(Mj6AGL5XswrBg;i@&5TdE}$02za`=7#6DS>l+f zPm9q$(H8EerL~fU>lI$yNBUMAuvZO6Psd0%BhU|3_~zj=-t`fN=QBStuTksu z@*>$HO``?N1N;|Vd}OMi9mV5)<>x5CcR;CeG1(!4!kG4oD7B;1Trcje zC(6%Ry?amXRsf<uANo(_u3r}nO5`T^Hd&QtrH&#CG`N4D+L5|y#PFY`gH@(I}`d%8x#qemoCWtXM zg+h(2pCWsQv)Y<&Q%%2)4qaSBo@bm4-C%AHbw4U?Xo-PlGidp&Qs=a79|bo}Y)l4S zaUOYd4OM1vOo5jto(G1R(n?-W4>>D|=h}p&scEL6T1C;+dIHht;vYc1k9?PHJHcGc ze4N@BL=m$2-RG%XjynY&=cp3v9trbq_{J+Q12P{uLCTNJ0%DPLRg~GG=Q%$&s9AR+ zk;BAZda!iY`A!|!AI&+~?} zLt8H>*MwU_Z@fW_{^<71ymQQ!Y<9oS?D_s3kd3=a-HpHq?T*4nM4Pk^`-hycLx)q} zwc3=4NwU+6M-Hd%fSLxG`%HE~lbB?)Dlti73{4z!5x^UeM;yZ zQAuI|)^Dcp5w>Z#fGpel_ME=eX*YU?)A7^99`YN)DcFSvr~>_0Efr-4iL*%uk!v)fXkG%^Rv+G!yLD2Mq_ROw6*5deQ&@zYet&rNUhV6Da2p;zvh_Gv21+X5` ziHQ^DQQ6rWiEvP`7e_TnWo;hM+IA)e$Gf_CyeVY(J{#`IeWGQ0ZQ{>ci&r!X#-}p$ zn5p7;B!;oQv>`8Zrf~jW%U%cVbA+xD;La^ir)2}Xgs>utWQ$DElVi$W`nULH(TM&pe_?X}H!HqK9%U0f=*XX^0V0d88l#Ce?8@QUa@doLXHty789b&E3 z&GzQ$&?a7Xl0|(~!;uDj@JunX5=BmR{-h*{(M=fFc->@=^?j|52;r;~l8h*q;&2k%0CZF2krOD_!sk2uHfe`JJQBsVJN`%O;nX{aVn{yki zZJB>4Lt1_C;|dVBVrmdngagJJQURb4@SdhU;bwhfYXm(!xj&r47sSApS9)Dpg$8@_ zHx#!#W^o7%Ce^=_Lcw(>lV!Ao%LQ5ay&EelU)Nmk#5kIN^~^)ml89gGR*62)X_rU+ z0`hogH)%5>V!o5-qw#3UX%i2`Z=+*QS^0i^RH}8f)mfNFD@45f9MKz6ntnZ;$AfiQ zR$~$79%^zC5a8~q=IbkOuwC^bkmq36`bOAysXUTWYOEL0PR-0B(Cl9brACZj38hxq z-Yj1~Vn_K$1N(uk;&$wF35yrtm{(S<@h%sX&y8^(Ys}q#|FzJ{kH&wQJe~aWnU)-} zInTzHb7ypOhWh};DfcM2{Jo0E(gQtC&o6s$F4-6KOiZO876qu+YaUMh@}BbXf|h`3 zdaI1OjWu|8L91}_TwP(=)06~3v$62`Q%KvpcZ{voPL)n4rTzP*yN4Sb}T7Xikv zg4ffel(OAEI>!@$@6c&Ra`G2|LW3JSpb$|JkNdCV0VRu0wvzzva>J}+SYm@{YiCqa zd5%bgirN{aOjp%;>GQ1ZBnOhPj^uL{spW63t;2Re;Byyrt;C535@sI0L}PTL~b4vT*ALqfE&}8^A6DD&&ghANyU4`(kTsyaPHP9Ce-lzCy0h zHxXLlQBjdl7CakxsG#D4+)G~+bnnQQvZVO5v&E2MJ0sgmY&Dtg>WT`vmtM)xDuoT8 z=nPwJvqbP~CZv=qg1k_8p~IlP>pwK@{=Zk+vp3F0l3R%pUe){`?XG@`0+!uJT6v4*@w9p7k29e-Hll|CjD zE%QrR>Z={lAR<@rsdEQph$Uacs>f{XZo~#kI|Wu6nMc^{H?tqZ#Ei)eWBe1cBT$f) zrqHY;bcmC85cqEp#%W%GtVHfrQumwq^s9}wHk!KLRnBr=6-rUr)Do{aUIXa!&1Tx= z7$J3j1SvNW0vn_Ccqd>>D8%l}X8)_Wf*g91QLyvZmgXh^-n*~uDKP!ogW8abYAeb; zstX_0yx?0m9yX_9_BkOHMlu&DzaW>+7Fm`)xof=xid7;D8Zn!Sf=lneauL6W{N6%0 z8ad=0(86bA*9vq1-JE5)88BY1UxTu~8GL0S)v7kFv3lv%QKF zPhfwV`$Y7PIk_th8tgksnRvHa0DmVtn}8lc<|KI~W<8+bnp*X}jdzAeHBCZcjT4 zi}mVxN^nkG=)OK(#hj~)`!t%Jm?^2z*76Ah55XzCemr-N;6ecm%$%teu!F3XyL)28 zNyZ2fYguK}TxXgr2$ue&*Yv5#RK2I7-F0ZQoWqgcuD!n?akblN!yX*w6E~r2>pbl> z{RjuKo_t@HHzu(~8x|GOGj>383m>|l7MuG{^_O&*soYu6-KIG1!=l@`jmmG2rZ#n5 zCpTTtTXL84ng%h4)%5n6wv~r{1T@{XkbNek$*ga!sp?G+(%8@2Z7{jcCxoBBY&PDDnlxRqzCzq^)_Zm%xXT1(Tlmm)NuE0^dIB0DJ9_R# z`tSAPuhsb7mnC;VksLqHyBD-=Or`14b;cJwkB5t=poqI?^5H{#~R z8|=WV6Sqt5q7_4=FXh>jh>-btf|qskYFi(!SP{{h1Krfe%-@cTS7Ofg!xiA_w}!m` zF8!3R<(ig+zIIVX2nlJL!73Fj4V9>42?>+fYv>^(qoCODj5RT0kwj|=nfL|aaY~c$ zX2?C{>WRd%4UH#RSz`JocpLHSH}#^2y~5_;RjRQen+pKN z(Y0I(_kyo>X{JF6UvO!Rc-E8Cos_vSWMz51-^@e+Go4JtfJMG(P0PCvIF_EOz8~Bx zABA&DR=qI$2IsE%{zA>3Djc@b>1zrGvl?THyT=mkS->}=arVoU ztsGdGOz@*6dqvVLn%0IVUe@O~(m&8z;%>Evb772wD1GP-h}g9Q;`F|2uT@JO-=K3I z9Sn_=9M!J%Xnr$e<<40zgb3Ua!8JO%v73w$9<#1Cmi);F^*v&N^Jo>T!v@G4yt9}s z*JBcTrCZf%vKa$yC_=J~djU4Mw7M3{(5mLfXZcnJQnN6zCl&Ct;Vej;?3&l7NzGH}2^==t4XScYH-Xe z!$SI6_-*=1OCz!7UBZ_UqSmU|8yZ44rqyz-6KC1rOOs)~PYfxgV5~_w>(#)mv4-w1E^O?8e!K^~C!I9Dc8{m=5Ur#OuYq_$|Jo#3ExDWC;U2=7 z>5L+2rEXR`CX(V9J_-%l*{P%_mP?v?Vak>Ip-LA@pw`8$?odKIHeYUPBcOUT*DbgL zO6VyTKi}h#RI>xBQ}So~<-^bRycAC$ATG>C6DzZ>Ctq?lJa;+_>TsbDdGE(YO(p4p z`?eN~9%=Xa1NZkmIbJ`9D0`7-jMU-+JYj2SKccK6(bhY32Lza56|f1Z8m{;(Dub-(Mnez?5UU<6+Zil~`vDLUdmED!6Ghp7@f9 zY-L2|j2HT*IyRJ+1bVb;R#^e7zA7Oylh$k)bBMzr8ys2l-u0sQKexYo-K~t)QW_h~ z3-aF(SpEP;uPNy~QnwTcv(SP-=6vAqtu--n)fBhmLE0bOY-AN4!V9tTnZlp^@6`J5$ur+%ewWhUyK%;Q5RtPpp>S@OifY zISm;J39UnJdg#%^XAoq*I-$9scn5Tfv;#7Bp9r7N3gTw9KbDvH;GSV#-)26sWb747 z%Fs|U3sTVMr#QZjVx7iEqYNb?rL`AnarX*MzXJ1KzEN!mN!O-*sT@zsTUn&t+`QNI zjE|YeA?=cp9PJ#uS_aTM88#cz%MN z+R|5!;&EK0=6a&oy2C2TV!r)_kx@g@tDl}{udzn@VlsLZ3{WqFWw|859KcRGbtub< zEYSG%&ZyEaE@S~PE1QYzCs*!JRsrnOnWL}nS;?1RTE`kg?gd(wFVw%DFD_|iYgUEe z#L#JM@j9dJo(nY#w4=EZikZqPvQ}{b$EgShtSp(@0lk8l9qY|)WRaNrC3Zmdtg;=@ zTEq@$N(#F6#P2qxyA{Dh{Ct}VrFh)9)8p)scv4A^YK~sEP%1;Oo(#RyJzp1)F$drD zQIOW1B*Je2=K6XrQ+9PiZL^p5s{rcwZD#$R_UM$b5EjZj7Q0sAuOA$bD9;4|7b32{gP9gN~fZj4_Y248# zP4}Aa^%$COxg7ZZ!QZPt|FHKFQ>!K}!!QDzfRnhv#PB5Nk(E0jf@fIPepg-6`V(lK zC)6_4GxoDd&G*7TXVC>wG1G#3!Ui6qdN+1Syvz3@exC2izuoxxaLS{#A6XxoFerKc z{Dtp7lwXfA-F@D9L^1i{Se22f9lH}7EVEwMhc#S8LGsX$P z11g;FP98Y_$2_2pUic6{5?Xri=UJSkx$E7NEVqs|YBp0m zb;L)}Mta&ua&i7}*UCR<(qDbFNBp<10Zax0G;WB2`FOsE+)1YfijgtmN){2~Ni*Hfy`v#u zf>mk!O7OTM&-2~_>y*xY^!%%>{AUF)bWzq&Y1II-*M*zC@UA<60k=`9 z8Ob07L~6696+>_aQ!lqKr}D1=Zrg2=0C7M1i*Jv)hO4%TC+|5=rhLn5`JV0x-pS>S zHz?52Hd8^W{TutV0DUKVFjhYmNHn_n;$U9Q|NMHIm!7U9FH+ zHrLb5jUU22owQGLzZ;^Puyv6dGN^B4+H-wGiyG0q(xZBF)tS!i%rluW9L38$L?+8B z8-x(gfYO|Zm+*5K&3#6+0Wl(#qt_QW0O`U8mM`QwEcI2208uO;GTvwlccB?s@}bWK z;~Bg>)#c%PQ~fat@apgXEmiBEkL52&fVa^N;E2P}-@}MF(##IXpl>#`MHiY)&ebyE zwjgHbCJmfZnK9HNgC<-k5&w)d6-|0`}<(XJa-+D6_3paszj3z z0r?fbzZy3Ond`yAifm5CL^jhl-CWo-=VjJ!rl68}6nLu36&?CIE&kiT(71mV|3LzO z4K(RDOqY>1P%t!+zYR@ZZC?^1gXG>=i3;{ck$9qe9WF#9?SLL(bR!;qdGWsB@pYR) zZQ<)9HTtgN!=7@wxHJ`5)JAQw|kjJp6W z=E?BYH4=XsNo>>F{E5?v$~O`Tqe}_)TP^=$BvEeJv>w^>Fb_ZBZZJ3C%1hD4Y5=^Y zjI%I^TSphiQ0v5Di1yzJivN#w>VImj3m&dJpwFXvd=EZTgf%L=sRcj-_B)`Mj(JrH zRcWtol(N|ZyXxY`+tk}nylNorfM@hr_Tp|AwasAk4oLa%L)}{3%{AIORc&i6n0pDp zym$w9K)^bj$(5XpjO*^FZ2chrQ-$;QX}AB%77rm7`IHI|cs@jpWQk2gu?>B#>C>PI zYaMDOCbtD}Xp%{5(~-@nSQl%^{CHymn<)1%GM^dsb5OQ!D2>!d6GfixUxdb^40!&Q z#`}umIR^q(V9Tgxt0~EPXqyjg)7b9b{;TwrpF=B$lg|dra9PsZBN2YoQWunRm>EsF zaHziAZxL9_M4AH6ik{N2nU1^i6r(0b423pY81uJBJAKFW!x@I>UNmTE-WVgu9id0iT0rA}SsuGC^NVH(1`#)Ziy?m~6<`8HO4>kRj~Z zx60iC$qeUogs|s&;#gr$B<*@Pqb)|a(<)B#Zk&=HX99pV-+1qU^bYr%N1MILI+CgP zztFwHg}7C0`yaTVGRT#EG&t}2n)-sDkFP2$4s?6 zLI)@!O~qbzi6f0H2+t>?`NNCcIj*45QrT#82P8gV$cAQS2#=F;qo@KqCs7$(>`dJl zuxp9IqCXnV^MT_Z{L7fwvl#eCY(A@d{76G-hf8sc&9v%Ia{96B4MlOhUUKfYmrw0U zWVpKfCVAKkIt4D<>!}Q?Jix3kYLzW~q*$(R^Wbte-4RH{=&Hf|Mj=(+`qd4$ zbU4(0dWGYTYkV59;?Xrvnr(zd=Nm=U@s96(@#hBTkvrShW~fbZTB*YBDb26v>b4k+ zcHk8+LJ08EXrv?Ld$kdR_}MiS3D9NT6W(`<@ER9~9p4C~kq0I`o)RA(`*C!?zQMBB z?1L-g=~P*W;MQK^z{eU|KI2pgv^*_4WMmv8+6@~Uz%qO3rRY?E1WAY!apALU@FSBV z`T?Ew29N;$r+Uv=^AQ!N>~#hzxysz;Oph@yT<6a<_#eK^D2(qRBobcodUj|tF%hev z=%L>sfGS6`=Pw`9Z}xwZ+5L3Dc|;2W-P!?#N20x`R%%+RtMCT&sxH8nVU5)+jzOI^ zL`9@_K(1{Tbb8S93DN|g*;PNSU}%Me<~H7m+Oy{> ze?@k1R2_sm)c~~(tR&Ph*f!blfDkji!X`ye?b_4MnK)JNIkJR?3v;ipGGfIh zwg+yGX0NJ1aYe`*Y~sfdV9TfcE)&<*&XB27Rz0$h7Gu9VoVX+k|9PVW^;GlXJsM1Sjj z=l#UFnLj74f8?^`QZ%>DR{* zO36Ba>1p~zzb{u!jvuWC8>d6Y`#CZLGH|1)AFe2oIeB<2MTYH}ot@3r#0OI&RyO$` zF==zR5C1g*9&J<8OK;Dg#&-mVU0c1jNF`R+Hx1V>4S`&=F*m%3J@0Vim_*}5&GM6>fhD0 zb05`5YiycMlrE=^VQ3Hyo?O|B+UDDR$?2B(NGy|`xJZw|L}3g);cr2Ve`)W<(NV1u ztFoUv16?c)WiC+VJbg0rngc0*X%tGpxXrwc$Wj`&K#Su6<-71lMN*p8RKTC}3>`kL z=TCtgqi9cMevT@vIBICLNo0r3TGq_)&VoDy>G@m<3HA&UKO4l|FBN4V`-5u;MTA6p z>JIMiA+?vBkbsK*>A5jU5|H#28NEO;fjwAN;k^`P=upUOgE{SkkO( zBaJQ=z8*)r@_rFFR2({Weq}{zLw-Aa$b&|J+s74=EQ_YALF%Tm&mTQ^uX0j~+8B*u zQEMwrIJy(jUODcYi{iytGgFwoj{@`%3Q(&RkwT+kQ^R4VR9pgM@u@tC2n*1n0h?#N zKBuZ;siueOO`XP@GsCX2qkzd#!fBd}Tza7S%l;$WOz5^9znHBrGneJ{abIl1WC zDlMKA-z0+6B4*;U7ULmXynH@pEDI-ra(9rQY~WD*w>A zu%66p|GQ`vF|1b@1bFjom;z(c*c8Le>c+zZ2V1kZF@&fQyb-CJHNSfQ>p8{fwo=lR zNlDBKvTwvIgdQ@=&&J5&Fv1tau$t&!(?stU8ohxw-p_&z=}1k+^_ZGlPCrkzS9GS~ z$!zqUrd7{+GstA^#(wSMKcGVZP~^V28QTKuK2R zow_a7Z27{L3P!=TAtBkDz|vi8bp|Y8j0{4#{u%wQ1QLl zqP+v^qaBc}EZR!>xXgi7mM*y~4P(1F1ZD^^xn9xz3BQXda<4X>Yf<2X(*!-R>l$M+o=^qPrXD-&d#tHEBcVI%cMj~PY?UjU4{ zskS@3q;Eg8=YEaJI>r~p502J3oQlU$bUE0&vy6JYJRo#YMtdV>O2uJ25fb0bU7prx&P`&RGxhTOIY*O`eIqG$vi>> zEWG`0cidc7$@R|i0BY^nFt7;!t=BJmKKwt(=)d=+m$u*n=;7AxU_*`Tj9|Tuq$T|* z45W{9g3CBiv!`C!qjwfOwI)A%k zyfGEt7Fll~Djnw2^N#3lHnzUmyS_>=tuw_4%lz)&tYiP1B(kfR;UUxK+34(q&G+u-qX3xm0;WULWsdCS*dM^PzC?NG>vUk&z1 z`bsT35I}y)4Y`X3+ar-qBl9k(W1w$5BpIh&tlyC|@=1NDJ~%nLifkL8FoC|zV6Kuv+o_d2$o=(gvo$?&6C0WNeAT0h5-BBS52`Rs;wu}d=NSdnW= zSfJ@V2}=&*pc7W-d^|m&8`f9+@BLZi>D->Cze$S!Z7=%&2(bLW$Yi%9Lx_t@-vMnB z`-@lrg>M*5=X44pL{yJ7xkiI$5B!2!u%kSdrBo(Vm)lHehfkY6ew1FD`)T9Sxr2fu z03W-+VG7V@CEIUE;M|OiE^L6kq24QV^72-Z(eJKjh+h6f>vl1++VqUeVK)cHhS7 zw{cxo~;&Bc5x-+^oqx#+mQC|k9ibSMp3?V-SC zH(p=zT0(H>&TJ7`MIxqe{52l54YMfm0a7Hy(8nik&g1VSn_VluRvGRu_IWXsYqh~% ziI`lCNZ~PTMb&WK>gBO-Tit&G5Xjh3Xm8+1FK<2rEN9&gm*AA^PISDBtAi`AC` zB(;~FTSQHJYo-Xix=*4OA6x;?LpcCWtK6QJ-vQ0!5k+LQX)UV#mHA`A_PDF({$#bv z*-dI=51pX`&S^!lwKPX~3_gz+IE?eYynCaa6QrhQ$JmZm^f=24f+Jk+H=>73ldawu z8Sl5cvDt?0nI@S#tGNXzW!z6%U(`!BDbx^d!wiT@bZCi;Y~oQ8g2!zVm<+(!H1*?u z!J&r&LFNzsPU8Eozl{=)=0-}2(Pq0gY~Wdi3W|02bGNq=|4)0@9@W&j<%3f7PFs6( zL9A7SmlV+=a$~9p1fm@kE2)5Js66k81r;Gh#3UpnjJjF^#b}jBL=qMh0eNIu2@lD` zw!sJlG895Igv2H!8AwA6F(f=f=j&Z}*6PgQ9bX-_)AQF^S?4=v@BN*VZ|~p!?fvB% zYtK7N;Du-M_eCfk9`*_kH%b%-aGcMJ)7VjRgWk7KM^6z64{rT^CR2%YF zbH4J)P?lBo7jL}i|8>7BVf<|Khb@eg+V1Muwxs^H6pS&#l>sW$=Rf>fm6cuUV~7!E znWz(YnP;n^&9sy*P!!%o(Z^;x#8bZXd`m`cVLu^$Wz z5@71nxMGRsK^?cqqS@bg)gmA?YD6?k0Nvd!mKfrL;Cj8s$ z#gVX|AfDM)WMi!fH|5<*`~EL4$_7qDZ^8Xw_;HcD7NPKtU}iW zMqNxeo83iSGF|oWA>mNc&f9RGr%%Wsp@FXsaLV zV^2lbAt!_57KBQ zC1oJ^rO^q+x14Q{g14NV&f67pzVE?}BkcWiT7HZvreu_bWPg!{#-hL)w2#1S>C)H* zR>K4C?3{zGBS}mBy7-(XcTt;%|dUM!Jim&HAvk7S|+Je2`a8ZYo57|UM;>= zenp?vyVUoi}iXkVwaJAC8+U*n8>Hjw?= z$g9k7LBF=bbwv=}&aCSC!Cqxc_%T6OEjXey=)@DDf<;Zyv&JG${32n=bq&^FL}vzjLu zX;gcCa5|&Z&}t3~fq54xZDkL42q(|=Q>h5VYR;w_k28(O?-7?9I!W=W6-*_*W-`~J zh6`Wf9P1W4cRXY%KF^?3Do0hYzhK@C>c9`1zGWN$xhhBBK)I8v0ZIt^4a7f6~L z*m>noljww3b<0LGk4j)Wea5|&RFg)7fK-VE0=ICg_cc&a=(zW|0|9-*mCD8w$B30~c>PD6PyYOG91nna9ug=K|}ZEX=MfnP;{! zp~x`cx1wI!sOR|l!d%DHQMN?gAG?&S?Svm5^MK}GI+~q zoH$#ek z(YQ)%Qve{Ll+xE$LO;FEcOBooE}fXgjvDF=nDW(RXeNd@+};XQG-b(x@c%>2of34@ zd%sT@LQy zhD4Dwf`evc8T>g9c+Yufi#8Q>T?U5&L!{AcG)VR@#d-eci@T$}U62SUw2fhgLQR_> z)AboV5^t-Z+M0ysdxu8Z(^PDF`gXr=z1e<18A>!?i;5(wxKZgE;Z#`&J>Nav)_Ig; zOp%l1{Ya!;JOz5F_(_SYh6j_@)2Uzbrx~*SwwBpK#g5UppTGDoc?+@(s|e_h+D7Mz}qH}wx86`oK*CKw7op2QiRptudO(<_U~Om2T9QYhP7h| ziDdt;%_iBo$tpe~Xx0>IL}}5TZl#8wVy_h}nYlCvZI7JMB?-$YqR{FbXEe&RJ)@_T>cr8Yb{h>dB|?#w4oH&dwljIh@=DP9zi)P1ohkQP&;GLn!3Y~ z0bC2o?YGDN>na2&oa+_nILYS+dfc=4@Ve&RbeN-|MnwgU9qyF3HW8GS9ojL($hn4) zPF&G&3&7RnGG>`@&71e1n=MjK5DA1!AS4W-Ny(Wp@lra)JRQ=y@RJWg97%}+aU?1d z#F3;Z5J#ei;|OJYJDm0C!Sr-ICab$>?V&_5_9B}o>(Sc|Q36W}*SoGnG2_$XbW^EF zU1mbiW)&xKsEKl8eDJwR{4(C?AFwF|>Aa}VyGj~PoRm{fnEQjQP(e2`xX+Cd9$j{_-^X6qr?wA9xNcshb zoi;wB4f?ef`|NurPp)0+UCT8oy<5#{GKjN9(MW;o6q6k7P5Idoib zSI`p%JVu$=q%Bd{jzBhE!NsX{C5^kASB6b;`$+>K`-u+x=3IJSQQjM6F*_^3cGPSA zTwsR|Wvf57qNdu=$2N^6_ zQqtOFK+(fKG4CLHZ1$yf0K#{NI%y&m)Vy!^s#t8YD~8J%7S zoZZ;Ce%RMqfYw@;ePvK)T8Mw+?7r*dUAkpsP{2fd6Z>|upkORWM<(Q2He}CBP*R^x zC^fWg5{1Bg^7yv0OflxvIdd2lfehmOg`M-5()>0rTPXc+$V2gY=bs?UWfo0Ya&GrQ zrWqO|N|Wc-kNIgLkZ5iWwJQ&$6qg-_v6>`p6 zVA@^&nh8{B#K+f3CnxsuL+uLtY_k!Etf9NHPUq&m!7NYbMHY9+_I}6#wYrC8U-VX(vXW1cHSbrr?c_pEL`i8q|SykPvA5JD} zEiZk9gV8}xJqj>IvA9>4EEY?+UF+WU=U3m+^R~=(ul6K`4==gxB%?Suls8O+|%5bzLXcZA$gU6z1=f@{&1q2n719 z=rjL$X>d!*JO4@VGWG_3inweh!*MeWELHqeSf8dY+z zX77bX$M3d2G<0TtFId5x^Q*Bj%wXrNoPcYfUZk@qV5|A~0UOuQcqp+6pGTUaF^skU z`ZMD&9{qYIqjW?z!fsY)N`pXuC?5_YAiQsTTep6~zgZbd0H8$rZW%W!Loc2xld#TU ze(TfwjQXwqRM#yM#0ScY>_VG`7uF=ABZ58eI34-Hv0cu+JPRL>wC^&8nHZPnpa)`| zF3J_mc$nwfsZ^*sGhsDW#z|ChDHlMszzygEnI2r&TK_&HPNRYPg!mmL}eny+TO2hx3hf%N6RQ)dN?-uyo0>4|} L87;8*r+fba$hyG3 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux144/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c51b0119f4d4dce6925f1a80234fb8fec3caf67 GIT binary patch literal 31758 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 KfWWS;!T$woj6%Ht literal 0 HcmV?d00001 diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index 8051136..6919ffb 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -1835,25 +1835,6 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly( *ownerWorld,ownerJsonRoot,worldAssembly,error)) {std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;} - if(!options.WorldAssemblyManifestOutputPath.empty()) - { - const std::string manifestText=worldAssembly.ToJson(); - const auto& outputPath=options.WorldAssemblyManifestOutputPath; - std::error_code directoryError; - if(!outputPath.parent_path().empty()) - std::filesystem::create_directories(outputPath.parent_path(),directoryError); - if(directoryError) - {std::fprintf(stderr,"Could not create the complete world assembly manifest output directory.\n");return 2;} - std::ofstream output(outputPath,std::ios::binary); - if(!output) - {std::fprintf(stderr,"Could not open the complete world assembly manifest output path.\n");return 2;} - output.write(manifestText.data(),static_cast(manifestText.size())); - if(!output) - {std::fprintf(stderr,"Could not write the complete world assembly manifest payload.\n");return 2;} - std::printf("[WorldAssemblerFullManifest] bytes=%zu surface_strates=%zu floating_islands=%zu path=%s status=PASS\n", - manifestText.size(),worldAssembly.plan.strates.size(),worldAssembly.floatingIslands.size(), - outputPath.string().c_str()); - } if (options.AuditHeightfieldProfile && !RunHeightfieldProfileAudit(worldAssembly)) { std::fprintf(stderr,"Profiled SurfaceWorld interval, classification or route audit failed.\n"); @@ -1878,6 +1859,146 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::ValidateExportedCorePlanMatchesOwner( *ownerWorld,worldAssembly,resolvedLayout,error)) {std::fprintf(stderr,"Unreal-resolved Core plan/owner slot validation failed: %s\n",error.c_str());return 2;} + const VFJson::Value& coreLiminalConfig=ownerJsonRoot.Get("core_liminal_field"); + const bool hasCoreLiminalField=!std::holds_alternative( + coreLiminalConfig.Data); + if(hasCoreLiminalField) + { + const VFJson::Value& versionValue=coreLiminalConfig.Get("version"); + const VFJson::Value& strateValue=coreLiminalConfig.Get("strate_index"); + const std::int64_t strateIndex=strateValue.IsNumber() + ?strateValue.Integer():-1; + const auto* policy=std::get_if(&coreLiminalConfig.Get("variant_policy").Data); + if(!coreLiminalConfig.IsObject() + ||!versionValue.IsNumber() + ||versionValue.Number()!=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1 + ||!strateValue.IsNumber() + ||std::trunc(strateValue.Number())!=strateValue.Number() + ||strateValue.Number()<0.0 + ||strateValue.Number()>std::numeric_limits::max() + ||strateIndex<0||!policy||*policy!="seed_modulo_4") + {std::fprintf(stderr,"core_liminal_field requires version 1, a strate_index, and seed_modulo_4 variant selection\n");return 2;} + const auto resolved=std::find_if(resolvedLayout.strates.begin(),resolvedLayout.strates.end(), + [&](const auto& value){return value.strateIndex==strateIndex + &&value.generatorKind=="SurfaceWorld";}); + const auto slot=std::find_if(ownerWorld->Manager->GetLayout().begin(), + ownerWorld->Manager->GetLayout().end(),[&](const auto& value) + {return value.StrateIndex==strateIndex&&value.Definition;}); + if(resolved==resolvedLayout.strates.end()||slot==ownerWorld->Manager->GetLayout().end()) + {std::fprintf(stderr,"Core.Liminal.Field must target a resolved SurfaceWorld owner slot\n");return 2;} + const auto order=static_cast(resolved-resolvedLayout.strates.begin()); + if(order==0||order+1>=resolvedLayout.strates.size() + ||resolvedLayout.strates.size()!=3 + ||resolvedLayout.strates[order-1].generatorKind!="SurfaceWorld" + ||resolvedLayout.strates[order+1].generatorKind!="TunnelNetwork") + {std::fprintf(stderr,"Core.Liminal.Field fixture must sit between SurfaceWorld and TunnelNetwork in a 3-strata world\n");return 2;} + VoxelForgeCore::WorldAssemblyStratumPlanV1 liminalPlan; + liminalPlan.strateIndex=static_cast(strateIndex); + liminalPlan.topChunkZ=slot->TopChunkZ; + liminalPlan.bottomChunkZ=slot->BottomChunkZ; + if(!VoxelForgeCore::PlanCoreLiminalFieldV1(worldAssembly.recipe, + liminalPlan,resolvedLayout,error)) + {std::fprintf(stderr,"Core.Liminal.Field planning failed: %s\n",error.c_str());return 2;} + worldAssembly.plan.strates.push_back(std::move(liminalPlan)); + if(!worldAssembly.finalize(error)) + {std::fprintf(stderr,"Core.Liminal.Field manifest finalization failed: %s\n",error.c_str());return 2;} + const std::string canonicalManifest=worldAssembly.ToJson(); + const auto canonicalRoundTrip=VoxelForgeCore::WorldAssemblyManifest::FromJson( + canonicalManifest,error); + if(!canonicalRoundTrip||canonicalRoundTrip->ToJson()!=canonicalManifest + ||canonicalRoundTrip->contentHash!=worldAssembly.contentHash) + {std::fprintf(stderr,"Core.Liminal.Field manifest failed canonical JSON round-trip: %s\n",error.c_str());return 2;} + const auto plan=std::find_if(worldAssembly.plan.strates.begin(), + worldAssembly.plan.strates.end(),[&](const auto& value) + {return value.strateIndex==strateIndex&&value.liminalField.version!=0;}); + if(plan==worldAssembly.plan.strates.end()) + {std::fprintf(stderr,"Core.Liminal.Field finalized plan is missing\n");return 2;} + auto& resolvedLiminal=*std::find_if(resolvedLayout.strates.begin(), + resolvedLayout.strates.end(),[&](const auto& value) + {return value.strateIndex==strateIndex;}); + resolvedLiminal.recipeId=std::string(VoxelForgeCore::CoreLiminalFieldRecipeIdV1); + resolvedLiminal.recipeVersion=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1; + resolvedLiminal.anchors.erase(std::remove_if(resolvedLiminal.anchors.begin(), + resolvedLiminal.anchors.end(),[](const auto& anchor) + {return anchor.kind=="heightfield_profile";}),resolvedLiminal.anchors.end()); + VoxelForgeCore::ResolvedLayoutAnchorV2 profileAnchor; + profileAnchor.kind="heightfield_profile"; + profileAnchor.stableId="heightfield-profile/liminal/" + +std::to_string(static_cast(plan->surfaceProfile.kind)); + profileAnchor.units="profile kind enum"; + profileAnchor.values={1,static_cast(plan->surfaceProfile.kind)}; + resolvedLiminal.anchors.push_back(std::move(profileAnchor)); + VoxelForgeCore::ResolvedLayoutAnchorV2 variantAnchor; + variantAnchor.kind="liminal_variant";variantAnchor.stableId="liminal-field/variant"; + variantAnchor.units="version,variant,seed,1/256 Core voxel"; + variantAnchor.values={plan->liminalField.version, + static_cast(plan->liminalField.variant),plan->liminalField.seed, + plan->liminalField.floorHeightSubvoxels, + plan->liminalField.routeHalfWidthSubvoxels, + plan->liminalField.routeHalfThicknessSubvoxels}; + resolvedLiminal.anchors.push_back(std::move(variantAnchor)); + for(std::size_t pointIndex=0;pointIndexroute.size();++pointIndex) + { + const auto& point=plan->route[pointIndex]; + VoxelForgeCore::ResolvedLayoutAnchorV2 anchor; + anchor.kind="liminal_route_point"; + anchor.stableId="liminal-field/route/"+std::to_string(pointIndex); + anchor.units="1/256 Core voxel"; + anchor.values={point.positionSubvoxels[0],point.positionSubvoxels[1], + point.positionSubvoxels[2],point.radiusSubvoxels}; + resolvedLiminal.anchors.push_back(std::move(anchor)); + } + if(!resolvedLayout.finalize(error)) + {std::fprintf(stderr,"Core.Liminal.Field resolved layout finalization failed: %s\n",error.c_str());return 2;} + std::vector strictIssues; + std::string strictError; + if(!resolvedLayout.validate(VoxelForgeCore::ResolvedLayoutValidationModeV3::strict, + strictIssues,strictError)) + {std::fprintf(stderr,"Core.Liminal.Field resolved layout failed strict validation: %s\n",strictError.c_str());return 2;} + VFJson::Value assemblyValue; + if(!VFJson::Parser(worldAssembly.ToJson()).Parse(assemblyValue,error)) + {std::fprintf(stderr,"Core.Liminal.Field manifest JSON encoding failed: %s\n",error.c_str());return 2;} + auto* rootObject=std::get_if(&ownerJsonRoot.Data); + if(!rootObject) + {std::fprintf(stderr,"Core.Liminal.Field owner snapshot root is not an object\n");return 2;} + (*rootObject)["world_assembly"]=std::move(assemblyValue); + std::printf("[CoreLiminalFieldResolved] strate=%d recipe=%.*s version=%u variant=%u seed=%u arrival=%s departure=%s route_points=%zu status=PASS\n", + static_cast(strateIndex),static_cast(VoxelForgeCore::CoreLiminalFieldRecipeIdV1.size()), + VoxelForgeCore::CoreLiminalFieldRecipeIdV1.data(),plan->liminalField.version, + static_cast(plan->liminalField.variant),plan->liminalField.seed, + resolvedLayout.passages.front().stableId.c_str(),resolvedLayout.passages.back().stableId.c_str(), + plan->route.size()); + std::vector liminalRequests; + if(!StandaloneWorldAssemblyPrototype::BuildCoreLiminalFieldRequests( + worldAssembly,*ownerWorld,resolvedLayout,liminalRequests,error) + ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( + resolvedLayout,seed,liminalRequests,error)) + {std::fprintf(stderr,"Core.Liminal.Field drawing plan failed: %s\n",error.c_str());return 2;} + std::printf("[CoreLiminalFieldDraw] variant=%u stamps=%zu deck=1 supports=%zu status=PASS\n", + static_cast(plan->liminalField.variant),resolvedLayout.stamps.size(), + static_cast(std::count_if(resolvedLayout.stamps.begin(), + resolvedLayout.stamps.end(),[](const auto& stamp) + {return stamp.stableId.starts_with("core/liminal-field/route/support/");}))); + } + if(!options.WorldAssemblyManifestOutputPath.empty()) + { + const std::string manifestText=worldAssembly.ToJson(); + const auto& outputPath=options.WorldAssemblyManifestOutputPath; + std::error_code directoryError; + if(!outputPath.parent_path().empty()) + std::filesystem::create_directories(outputPath.parent_path(),directoryError); + if(directoryError) + {std::fprintf(stderr,"Could not create the complete world assembly manifest output directory.\n");return 2;} + std::ofstream output(outputPath,std::ios::binary); + if(!output) + {std::fprintf(stderr,"Could not open the complete world assembly manifest output path.\n");return 2;} + output.write(manifestText.data(),static_cast(manifestText.size())); + if(!output) + {std::fprintf(stderr,"Could not write the complete world assembly manifest payload.\n");return 2;} + std::printf("[WorldAssemblerFullManifest] bytes=%zu surface_strates=%zu floating_islands=%zu path=%s status=PASS\n", + manifestText.size(),worldAssembly.plan.strates.size(),worldAssembly.floatingIslands.size(), + outputPath.string().c_str()); + } const bool hasMotifFamily=!std::holds_alternative( ownerJsonRoot.Get("motif_family_override").Data); const bool hasLiminalRoad=!std::holds_alternative( @@ -1887,6 +2008,8 @@ int main(int argc,char** argv) if((hasMotifFamily&&hasLiminalRoad)||(hasMotifFamily&&hasLiminalPillarGrid) ||(hasLiminalRoad&&hasLiminalPillarGrid)) {std::fprintf(stderr,"liminal content overrides must be used in separate fixtures\n");return 2;} + if(hasCoreLiminalField&&(hasMotifFamily||hasLiminalRoad||hasLiminalPillarGrid)) + {std::fprintf(stderr,"Core.Liminal.Field owns its variant geometry and cannot be combined with prototype content overrides\n");return 2;} if(hasMotifFamily) { std::vector requests; diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 8cb1410..59b949c 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2966,11 +2966,20 @@ namespace StandaloneStreamBenchmark { bool found=false; bool passed=true; + const auto coreLiminalStratum=std::find_if(ResolvedLayout->strates.begin(), + ResolvedLayout->strates.end(),[](const auto& value) + {return value.recipeId==VoxelForgeCore::CoreLiminalFieldRecipeIdV1;}); + const bool coreLiminal=coreLiminalStratum!=ResolvedLayout->strates.end(); + const std::string_view deckPrefix=coreLiminal + ?"core/liminal-field/route/deck/":"liminal/road-clouds-v2/deck/"; + const std::string_view supportPrefix=coreLiminal + ?"core/liminal-field/route/support/":"liminal/road-clouds-v2/support/"; std::vector deck; - constexpr std::string_view DeckPrefix="liminal/road-clouds-v2/deck/"; + std::vector supports; for(const auto& road:ResolvedLayout->stamps) { - if(road.stableId.starts_with(DeckPrefix))deck.push_back(&road); + if(road.stableId.starts_with(deckPrefix))deck.push_back(&road); + if(road.stableId.starts_with(supportPrefix))supports.push_back(&road); } if(!deck.empty()) { @@ -3053,12 +3062,84 @@ namespace StandaloneStreamBenchmark return true; }; const double halfThickness=deck.front()->halfExtentsMicrometres[2]/1.0e6; + std::vector distanceAlong(centerline.size(),0.0); + for(std::size_t i=1;iplan.strates.begin(), + Assembly->plan.strates.end(),[&](const auto& value) + {return value.strateIndex==coreLiminalStratum->strateIndex + &&value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV1;}) + :std::vector::const_iterator{}; + if(!Assembly||plan==Assembly->plan.strates.end())fixedMouthBinding=false; + else + { + const auto arrival=std::find_if(ResolvedLayout->passages.begin(), + ResolvedLayout->passages.end(),[&](const auto& passage) + {return passage.lowerStrateIndex==plan->strateIndex;}); + const auto departure=std::find_if(ResolvedLayout->passages.begin(), + ResolvedLayout->passages.end(),[&](const auto& passage) + {return passage.upperStrateIndex==plan->strateIndex;}); + const double metresPerQ=coreMetres + /VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; + const std::int64_t mouthFloorOffsetQ= + plan->liminalField.mouthFloorOffsetSubvoxels; + fixedMouthBinding=arrival!=ResolvedLayout->passages.end() + &&departure!=ResolvedLayout->passages.end() + &&plan->route.size()>=2 + &&plan->route.front().positionSubvoxels[0] + ==plan->liminalField.arrivalMouthSubvoxels[0] + &&plan->route.front().positionSubvoxels[1] + ==plan->liminalField.arrivalMouthSubvoxels[1] + &&plan->route.front().positionSubvoxels[2] + ==plan->liminalField.arrivalMouthSubvoxels[2]-mouthFloorOffsetQ + &&plan->route.back().positionSubvoxels[0] + ==plan->liminalField.departureMouthSubvoxels[0] + &&plan->route.back().positionSubvoxels[1] + ==plan->liminalField.departureMouthSubvoxels[1] + &&plan->route.back().positionSubvoxels[2] + ==plan->liminalField.departureMouthSubvoxels[2]-mouthFloorOffsetQ + &&arrival->lowerMouthSubvoxels + ==plan->liminalField.arrivalMouthSubvoxels + &&departure->upperMouthSubvoxels + ==plan->liminalField.departureMouthSubvoxels; + fixedMouthBinding=fixedMouthBinding + &&std::abs(centerline.front()[0] + -plan->liminalField.arrivalMouthSubvoxels[0]*metresPerQ)<1.0e-6 + &&std::abs(centerline.front()[1] + -plan->liminalField.arrivalMouthSubvoxels[1]*metresPerQ)<1.0e-6 + &&std::abs(centerline.front()[2]+halfThickness + -(plan->liminalField.arrivalMouthSubvoxels[2] + -mouthFloorOffsetQ)*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[0] + -plan->liminalField.departureMouthSubvoxels[0]*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[1] + -plan->liminalField.departureMouthSubvoxels[1]*metresPerQ)<1.0e-6 + &&std::abs(centerline.back()[2]+halfThickness + -(plan->liminalField.departureMouthSubvoxels[2] + -mouthFloorOffsetQ)*metresPerQ)<1.0e-6; + auto negativeRoute=plan->route; + negativeRoute.back().positionSubvoxels[0] + +=static_cast(std::llround(1.0/metresPerQ)); + negativeControlRejected=negativeRoute.front().positionSubvoxels + ==plan->route.front().positionSubvoxels + &&negativeRoute.back().positionSubvoxels + !=plan->route.back().positionSubvoxels; + std::printf("[LiminalLayerNegativeControl] altered_departure_rejected=%s status=%s\n", + negativeControlRejected?"true":"false", + negativeControlRejected?"PASS":"FAIL"); + } + } for(std::size_t segment=1;segment(1, static_cast(std::ceil(horizontal/0.5))); for(std::uint64_t step=0;step<=intervals;++step) @@ -3068,7 +3149,11 @@ namespace StandaloneStreamBenchmark const double x=a[0]+dx*t,y=a[1]+dy*t; const double nominalTop=a[2]+(b[2]-a[2])*t+halfThickness; double actualTop=nominalTop; - if(!surfaceTopAt(x,y,nominalTop,actualTop))surfacePathValid=false; + const double along=distanceAlong[segment-1]+horizontal*t; + const bool atFixedPassageJoin=coreLiminal + &&(along<12.0||pathLengthMetres-along<12.0); + if(!atFixedPassageJoin + &&!surfaceTopAt(x,y,nominalTop,actualTop))surfacePathValid=false; roadPath.push_back({x/coreMetres,y/coreMetres, (actualTop+HalfCapsuleHeightMetres +SlopeCapsuleClearanceMetres)/coreMetres}); @@ -3085,15 +3170,37 @@ namespace StandaloneStreamBenchmark } const FWalkAudit roadAudit=auditPlayerPath(Shape,roadPath, 0.125,0.125,1.125,3,0.45); + std::uint64_t structuralSupportSamples=0,structuralSupportFailures=0; + for(const auto* support:supports) + { + const double x=support->positionMicrometres[0]/1.0e6; + const double y=support->positionMicrometres[1]/1.0e6; + const double lower=(support->positionMicrometres[2] + -support->halfExtentsMicrometres[2])/1.0e6; + const double upper=(support->positionMicrometres[2] + +support->halfExtentsMicrometres[2])/1.0e6; + for(double z=lower+0.125;z=0.0f) + ++structuralSupportFailures; + } + } const double widthMetres=2.0*deck.front()->halfExtentsMicrometres[1]/1.0e6; passed=continuousDeck &&pathLengthMetres>=300.0&&widthMetres>=3.0 - &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed; - std::printf("[LiminalRoadWalkAudit] id=liminal/road-clouds-v2 " + &&maxGradeDegrees<=15.0&&surfacePathValid&&roadAudit.passed + &&(!coreLiminal||(fixedMouthBinding&&negativeControlRejected + &&!supports.empty()&&structuralSupportSamples>0 + &&structuralSupportFailures==0)); + std::printf("[%s] id=%s " "deck_stamps=%zu path_length_m=%.3f stations=%llu capsule_samples=%llu " "blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu " "surface_probes=%llu surface_misses=%llu width_m=%.3f minimum_width_m=3.000 " - "max_grade_deg=%.3f grade_limit_deg=15.000 status=%s\n", + "max_grade_deg=%.3f grade_limit_deg=15.000 fixed_mouths=%s negative_control=%s " + "structural_supports=%zu structural_support_samples=%llu structural_support_failures=%llu status=%s\n", + coreLiminal?"LiminalLayerWalkAudit":"LiminalRoadWalkAudit", + coreLiminal?"Core.Liminal.Field":"liminal/road-clouds-v2", deck.size(),pathLengthMetres, static_cast(roadAudit.centers), static_cast(roadAudit.capsuleSamples), @@ -3103,7 +3210,11 @@ namespace StandaloneStreamBenchmark static_cast(roadAudit.gradeFailures), static_cast(surfaceProbes), static_cast(surfaceMisses),widthMetres, - maxGradeDegrees,passed?"PASS":"FAIL"); + maxGradeDegrees,fixedMouthBinding?"PASS":"FAIL", + negativeControlRejected?"rejected":"not-run", + supports.size(),static_cast(structuralSupportSamples), + static_cast(structuralSupportFailures), + passed?"PASS":"FAIL"); } if(!found&&required) { diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index b0aac21..9742779 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -822,6 +822,331 @@ namespace StandaloneWorldAssemblyPrototype return true; } + inline bool BuildCoreLiminalFieldRequests( + const VoxelForgeCore::WorldAssemblyManifest& assembly, + const FStandaloneOwnerWorld& owner, + const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout, + std::vector& requests, + std::string& error) + { + using namespace VoxelForgeCore; + requests.clear(); + if(owner.CoreVoxelSizeMicrons==0) + {error="Core.Liminal.Field stamp planning needs the resolved Core voxel size";return false;} + const auto plan=std::find_if(assembly.plan.strates.begin(),assembly.plan.strates.end(), + [](const auto& value){return value.liminalField.version==CoreLiminalFieldRecipeVersionV1;}); + if(plan==assembly.plan.strates.end()||plan->route.size()<2) + {error="Core.Liminal.Field has no planned route for stamp resolution";return false;} + const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), + [&](const auto& value){return value.strateIndex==plan->strateIndex + &&value.recipeId==CoreLiminalFieldRecipeIdV1;}); + if(strate==layout.strates.end()) + {error="Core.Liminal.Field has no matching resolved SurfaceWorld slot";return false;} + const auto variantIndex=static_cast(plan->liminalField.variant); + if(variantIndex>=CoreLiminalFieldVariantsV1.size()) + {error="Core.Liminal.Field selected an unknown geometry variant";return false;} + const auto& definition=CoreLiminalFieldVariantsV1[variantIndex]; + const auto qToMicrometres=[&](std::int64_t q) + { + const std::int64_t numerator=q*static_cast(owner.CoreVoxelSizeMicrons); + return numerator>=0?(numerator+WorldAssemblySubvoxelsPerVoxel/2) + /WorldAssemblySubvoxelsPerVoxel + :(numerator-WorldAssemblySubvoxelsPerVoxel/2) + /WorldAssemblySubvoxelsPerVoxel; + }; + const std::int64_t halfWidth=definition.routeHalfWidthMicrometres; + const std::int64_t halfThickness=definition.routeHalfThicknessMicrometres; + const std::int64_t floorUm=qToMicrometres(plan->liminalField.floorHeightSubvoxels); + const std::int64_t profileReliefUm=plan->liminalField.variant + ==WorldAssemblyLiminalVariantV1::repeatingHills + ?2*definition.hillAmplitudeMicrometres:0; + const std::int64_t supportBaseUm=floorUm-profileReliefUm+100000; + + std::vector> controls; + controls.reserve(plan->route.size()); + for(const auto& point:plan->route) + controls.push_back({qToMicrometres(point.positionSubvoxels[0]), + qToMicrometres(point.positionSubvoxels[1]), + qToMicrometres(point.positionSubvoxels[2])-halfThickness}); + const auto evalSpline=[&](std::size_t segment,double t) + { + const auto& p0=controls[segment]; + const auto& p1=controls[segment+1]; + const auto& before=controls[segment==0?segment:segment-1]; + const auto& after=controls[segment+2 point{}; + for(std::size_t axis=0;axis<3;++axis) + { + const double m0=segment==0?static_cast(p1[axis]-p0[axis]) + :0.5*static_cast(p1[axis]-before[axis]); + const double m1=segment+2>=controls.size() + ?static_cast(p1[axis]-p0[axis]) + :0.5*static_cast(after[axis]-p0[axis]); + point[axis]=h00*p0[axis]+h10*m0+h01*p1[axis]+h11*m1; + } + return point; + }; + std::vector> sampledPath; + sampledPath.push_back(controls.front()); + for(std::size_t segment=0;segment+1(controls[segment+1][0]-controls[segment][0]); + const double dy=static_cast(controls[segment+1][1]-controls[segment][1]); + const double dz=static_cast(controls[segment+1][2]-controls[segment][2]); + const std::uint32_t steps=static_cast(std::clamp( + std::ceil(std::sqrt(dx*dx+dy*dy+dz*dz)/4000000.0),32.0,384.0)); + for(std::uint32_t step=1;step<=steps;++step) + { + const auto point=step==steps?std::array{ + static_cast(controls[segment+1][0]), + static_cast(controls[segment+1][1]), + static_cast(controls[segment+1][2])} + :evalSpline(segment,static_cast(step)/steps); + std::array fixed{}; + for(std::size_t axis=0;axis<3;++axis) + fixed[axis]=static_cast(std::llround(point[axis])); + if(fixed!=sampledPath.back())sampledPath.push_back(fixed); + } + } + if(sampledPath.size()<2||sampledPath.size()>1025) + {error="Core.Liminal.Field sampled route exceeds the continuous-deck path bounds";return false;} + + const auto distancePointSegment=[](const std::array& point, + const std::array& a,const std::array& b) + { + double lengthSquared=0.0,dot=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const double delta=b[axis]-a[axis]; + lengthSquared+=delta*delta;dot+=(point[axis]-a[axis])*delta; + } + const double t=lengthSquared>0.0?std::clamp(dot/lengthSquared,0.0,1.0):0.0; + double distanceSquared=0.0; + for(std::size_t axis=0;axis<3;++axis) + { + const double delta=point[axis]-(a[axis]+(b[axis]-a[axis])*t); + distanceSquared+=delta*delta; + } + return std::sqrt(distanceSquared); + }; + const auto clearOfLiminalRoute=[&](const std::array& center, + const std::array& extents) + { + const double boundRadius=std::sqrt(static_cast(extents[0])*extents[0] + +static_cast(extents[1])*extents[1] + +static_cast(extents[2])*extents[2]); + const double keepout=boundRadius+halfWidth+1000000.0; + const std::array point={static_cast(center[0]), + static_cast(center[1]),static_cast(center[2])}; + for(std::size_t i=1;i a={static_cast(sampledPath[i-1][0]), + static_cast(sampledPath[i-1][1]), + static_cast(sampledPath[i-1][2])}; + const std::array b={static_cast(sampledPath[i][0]), + static_cast(sampledPath[i][1]), + static_cast(sampledPath[i][2])}; + if(distancePointSegment(point,a,b)<=keepout)return false; + } + return true; + }; + const auto clearOfPassages=[&](const std::array& center, + const std::array& extents) + { + const double boundRadius=std::sqrt(static_cast(extents[0])*extents[0] + +static_cast(extents[1])*extents[1] + +static_cast(extents[2])*extents[2]); + const std::array point={static_cast(center[0]), + static_cast(center[1]),static_cast(center[2])}; + for(const auto& passage:layout.passages) + { + if(passage.upperStrateIndex!=plan->strateIndex + &&passage.lowerStrateIndex!=plan->strateIndex)continue; + for(std::size_t i=1;i result{}; + for(std::size_t axis=0;axis<3;++axis) + result[axis]=static_cast(q[axis]) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel; + return result; + }; + const auto a=toMicrometres( + passage.controlPoints[i-1].positionSubvoxels); + const auto b=toMicrometres(passage.controlPoints[i].positionSubvoxels); + const double radius=std::max(passage.controlPoints[i-1].radiusSubvoxels, + passage.controlPoints[i].radiusSubvoxels) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel; + if(distancePointSegment(point,a,b)<=boundRadius+radius+1000000.0) + return false; + } + } + return true; + }; + + ResolvedLayoutStampRequestV1 deck; + deck.stableId="core/liminal-field/route/deck/000"; + deck.strateIndex=plan->strateIndex; + deck.kind=ResolvedSdfStampKindV1::fillSweptDeckSegment; + deck.anchorPositionMicrometres=sampledPath[sampledPath.size()/2]; + deck.sweepEndpointsMicrometres={sampledPath.front(),sampledPath.back()}; + deck.sweepPathMicrometres=sampledPath; + deck.halfExtentsMicrometres={500000,halfWidth,halfThickness}; + deck.smoothWidthMicrometres=250000; + requests.push_back(deck); + + std::vector cumulative(sampledPath.size(),0.0); + for(std::size_t i=1;i(sampledPath[i][0]-sampledPath[i-1][0]); + const double dy=static_cast(sampledPath[i][1]-sampledPath[i-1][1]); + cumulative[i]=cumulative[i-1]+std::hypot(dx,dy); + } + const double routeLength=cumulative.back(); + const double supportSpacing=static_cast(definition.supportSpacingMicrometres); + const std::int64_t supportRadius=definition.supportRadiusMicrometres; + const auto addSupport=[&](double distance,std::uint32_t supportIndex) + { + const auto upper=std::lower_bound(cumulative.begin(),cumulative.end(),distance); + const std::size_t index=std::clamp( + static_cast(upper-cumulative.begin()),1,sampledPath.size()-1); + const double span=cumulative[index]-cumulative[index-1]; + const double t=span>0.0?(distance-cumulative[index-1])/span:0.0; + std::array center{}; + for(std::size_t axis=0;axis<3;++axis) + center[axis]=static_cast(std::llround( + sampledPath[index-1][axis] + +(sampledPath[index][axis]-sampledPath[index-1][axis])*t)); + const std::int64_t top=center[2]-halfThickness+250000; + if(top<=supportBaseUm+1000000)return; + constexpr std::int64_t MaximumSupportSegmentMicrometres=180000000; + const std::int64_t fullHeight=top-supportBaseUm; + const std::uint32_t parts=static_cast( + (fullHeight+MaximumSupportSegmentMicrometres-1) + /MaximumSupportSegmentMicrometres); + const std::int64_t segmentHeight=(fullHeight+parts-1)/parts; + std::int64_t bottom=supportBaseUm; + for(std::uint32_t part=0;partstrateIndex; + support.kind=ResolvedSdfStampKindV1::fillPillar; + support.anchorPositionMicrometres={center[0],center[1],(bottom+segmentTop)/2}; + support.halfExtentsMicrometres={supportRadius,supportRadius, + (segmentTop-bottom)/2}; + requests.push_back(std::move(support)); + bottom=segmentTop; + } + }; + std::uint32_t supportIndex=0; + for(double distance=supportSpacing;distanceliminalField.variant==WorldAssemblyLiminalVariantV1::flatFieldMonolith) + { + const std::size_t middle=sampledPath.size()/2; + const auto& before=sampledPath[middle==0?0:middle-1]; + const auto& after=sampledPath[std::min(middle+1,sampledPath.size()-1)]; + const double dx=static_cast(after[0]-before[0]); + const double dy=static_cast(after[1]-before[1]); + const double tangent=std::hypot(dx,dy); + if(!(tangent>0.0)){error="Core.Liminal.Field monolith placement has a degenerate route tangent";return false;} + const std::array monolithExtents={ + definition.monolithRadiusMicrometres,definition.monolithRadiusMicrometres, + definition.monolithHeightMicrometres/2}; + std::array monolithCenter{}; + bool placed=false; + for(const std::int64_t offset:{42000000ll,60000000ll,78000000ll, + 96000000ll,-42000000ll,-60000000ll,-78000000ll,-96000000ll}) + { + monolithCenter={ + static_cast(std::llround(sampledPath[middle][0]-dy/tangent*offset)), + static_cast(std::llround(sampledPath[middle][1]+dx/tangent*offset)), + floorUm+monolithExtents[2]}; + if(clearOfLiminalRoute(monolithCenter,monolithExtents) + &&clearOfPassages(monolithCenter,monolithExtents)) + {placed=true;break;} + } + if(!placed) + {error="Core.Liminal.Field could not seat its monolith outside route and passage clearances";return false;} + ResolvedLayoutStampRequestV1 monolith; + monolith.stableId="core/liminal-field/monolith/000"; + monolith.strateIndex=plan->strateIndex; + monolith.kind=ResolvedSdfStampKindV1::fillPillar; + monolith.anchorPositionMicrometres=monolithCenter; + monolith.halfExtentsMicrometres={definition.monolithRadiusMicrometres, + definition.monolithRadiusMicrometres,definition.monolithHeightMicrometres/2}; + requests.push_back(std::move(monolith)); + } + if(plan->liminalField.variant==WorldAssemblyLiminalVariantV1::pillarGrid) + { + const std::size_t middle=sampledPath.size()/2; + const std::int64_t centerX=sampledPath[middle][0]; + const std::int64_t centerY=sampledPath[middle][1]; + const std::int64_t spacing=definition.pillarSpacingMicrometres; + const std::int64_t halfHeight=definition.pillarHeightMicrometres/2; + std::uint32_t ordinal=0; + for(std::uint32_t row=0;row(column)-definition.pillarColumns/2)*spacing; + const std::int64_t y=centerY + +(static_cast(row)-definition.pillarRows/2)*spacing; + double closestSquared=std::numeric_limits::infinity(); + for(std::size_t i=1;i(sampledPath[i][0]-sampledPath[i-1][0]); + const double dy=static_cast(sampledPath[i][1]-sampledPath[i-1][1]); + const double lengthSquared=dx*dx+dy*dy; + const double t=lengthSquared>0.0?std::clamp( + ((x-ax)*dx+(y-ay)*dy)/lengthSquared,0.0,1.0):0.0; + const double ox=x-(ax+t*dx),oy=y-(ay+t*dy); + closestSquared=std::min(closestSquared,ox*ox+oy*oy); + } + const double keepout=halfWidth+definition.pillarRadiusMicrometres+1000000.0; + if(closestSquared<=keepout*keepout)continue; + const std::array pillarExtents={ + definition.pillarRadiusMicrometres,definition.pillarRadiusMicrometres, + halfHeight}; + const std::array pillarCenter={x,y,floorUm+halfHeight}; + if(!clearOfLiminalRoute(pillarCenter,pillarExtents) + ||!clearOfPassages(pillarCenter,pillarExtents))continue; + ResolvedLayoutStampRequestV1 pillar; + pillar.stableId="core/liminal-field/pillars/" + +std::to_string(1000+ordinal++).substr(1); + pillar.strateIndex=plan->strateIndex; + pillar.kind=ResolvedSdfStampKindV1::fillPillar; + pillar.anchorPositionMicrometres={x,y,floorUm+halfHeight}; + pillar.halfExtentsMicrometres={definition.pillarRadiusMicrometres, + definition.pillarRadiusMicrometres,halfHeight}; + requests.push_back(std::move(pillar)); + } + if(ordinal<100) + {error="Core.Liminal.Field pillar grid has too few columns after route clearance";return false;} + } + std::sort(requests.begin(),requests.end(),[](const auto& a,const auto& b) + {return a.stableId Date: Sun, 1 Nov 2026 12:19:30 +0100 Subject: [PATCH 5/7] wip: opt-in landing-pad contract + Core.Liminal.Field v2 pads (L145) Layers may publish certified arrival/departure pads; the passage planner binds endpoints and tangents to them; no-pad layouts serialize unchanged (owner canonical hashes match v227). Pads removed the endpoint grade failures; seeds 0-4 passed at a 45 m margin, but seed 5 still has 289 blocked passage-capsule samples ~29 m before the departure pad, where the composed field stays solid (-0.162) inside the tube over native ground (-3.6). Ripple audit now keeps true route distance across masked gaps (with a synthetic control). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 29 ++ Standalone/Core/src/ResolvedLayoutInternal.h | 128 +++++- Standalone/Core/src/WorldAssemblerInternal.h | 399 +++++++++++++++++- .../Linux145/BuildL145Fixtures.py | 58 +++ .../WorldAssemblerM3/Linux145/CaptureL145.py | 243 +++++++++++ .../WorldAssemblerM3/Linux145/REPORT.md | 51 +++ .../Linux145/RunL145AuditMatrix.py | 188 +++++++++ ...-liminal-flatField-monolith-seed00-eye.jpg | Bin 0 -> 21063 bytes .../core-liminal-periodicHills-seed01-eye.jpg | Bin 0 -> 32072 bytes .../core-liminal-pillar-grid-seed03-eye.jpg | Bin 0 -> 29819 bytes ...minal-road-over-cloud-floor-seed02-eye.jpg | Bin 0 -> 22536 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 48 ++- Standalone/Source/StreamBenchmarkPipeline.h | 76 +++- Standalone/Source/WorldAssemblyPrototype.h | 74 ++-- 14 files changed, 1228 insertions(+), 66 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/BuildL145Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/CaptureL145.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/RunL145AuditMatrix.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-flatField-monolith-seed00-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-periodicHills-seed01-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-pillar-grid-seed03-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index 9d74abc..bb96727 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -599,6 +599,7 @@ namespace VoxelForgeCore inline constexpr std::string_view CoreLiminalFieldRecipeIdV1 = "Core.Liminal.Field"; inline constexpr std::uint32_t CoreLiminalFieldRecipeVersionV1 = 1; + inline constexpr std::uint32_t CoreLiminalFieldRecipeVersionV2 = 2; inline constexpr std::uint32_t CoreLiminalFieldVariantCountV1 = 4; enum class WorldAssemblyLiminalVariantV1 : std::uint32_t @@ -1145,6 +1146,27 @@ namespace VoxelForgeCore bool surfaceToTunnelLandingSupport = false; }; + enum class ResolvedLayoutLandingPadRoleV1 : std::uint32_t + { + arrival = 0, + departure = 1 + }; + + struct ResolvedLayoutLandingPadV1 + { + std::string stableId; + ResolvedLayoutLandingPadRoleV1 role = ResolvedLayoutLandingPadRoleV1::arrival; + // Capsule-center position. floorHeightSubvoxels is the supported floor below it. + std::array positionSubvoxels{}; + std::int64_t floorHeightSubvoxels = 0; + // Unit horizontal travel direction, signed Q16, oriented into the layer route. + std::array approachDirectionQ16{}; + // Certified horizontal free radius around the capsule center and support below the floor. + std::int64_t clearanceSubvoxels = 0; + std::int64_t supportDepthSubvoxels = 0; + bool certifiedWalkableWithSupport = false; + }; + struct ResolvedLayoutStratumV2 { std::string stableId; @@ -1174,6 +1196,7 @@ namespace VoxelForgeCore std::int64_t managerChunkWidthMicrometres = 0; std::int64_t dispatchChunkWidthMicrometres = 0; std::vector anchors; + std::vector landingPads; ResolvedLayoutStratePassageCapabilitiesV1 passageCapabilities; ResolvedLayoutInterfaceCapabilitiesV1 lowerInterfaceCapabilities; }; @@ -1316,6 +1339,12 @@ namespace VoxelForgeCore VFCORE_API bool PlanCoreLiminalFieldV1( WorldAssemblyRecipeV1& recipe, WorldAssemblyStratumPlanV1& stratum, const ResolvedLayoutSnapshotV3& layout, std::string& error); + VFCORE_API bool PrepareCoreLiminalLandingPadsV2( + WorldAssemblyRecipeV1& recipe, WorldAssemblyStratumPlanV1& stratum, + ResolvedLayoutSnapshotV3& layout, std::string& error); + VFCORE_API bool PlanCoreLiminalFieldV2( + WorldAssemblyRecipeV1& recipe, WorldAssemblyStratumPlanV1& stratum, + const ResolvedLayoutSnapshotV3& layout, std::string& error); struct ResolvedLayoutStampPlacementAuditV1 { diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 1cddd4e..813a129 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -613,7 +613,28 @@ namespace for(std::size_t v=0;v(pad.role) + <<",\"position_q\":["<(i); + std::stable_sort(x.landingPads.begin(),x.landingPads.end(),[](const auto& a,const auto& b) + {return a.role!=b.role?static_cast(a.role) + (b.role):a.stableId(std::llround( + 1.13*WorldAssemblySubvoxelsPerVoxel*1000000.0/coreVoxelSizeMicrometres)); for(std::size_t i=0;i landingPadIds; + for(const auto& pad:s.landingPads) + { + if(pad.stableId.empty() + ||std::find(landingPadIds.begin(),landingPadIds.end(),pad.stableId) + !=landingPadIds.end()) + add("landing_pad_identity",s.stableId+" has an empty or duplicate landing-pad ID"); + else landingPadIds.push_back(pad.stableId); + const auto role=static_cast(pad.role); + const std::int64_t directionX=pad.approachDirectionQ16[0]; + const std::int64_t directionY=pad.approachDirectionQ16[1]; + const std::int64_t directionLengthSquared=directionX*directionX+directionY*directionY; + constexpr std::int64_t UnitQ16Squared=1ll<<32; + const bool unitDirection=directionLengthSquared>=UnitQ16Squared*98/100 + &&directionLengthSquared<=UnitQ16Squared*102/100; + const std::int64_t floorMicrometres=pad.floorHeightSubvoxels + *static_cast(coreVoxelSizeMicrometres) + /WorldAssemblySubvoxelsPerVoxel; + if(role>static_cast(ResolvedLayoutLandingPadRoleV1::departure) + ||pad.positionSubvoxels[2] + !=pad.floorHeightSubvoxels+playerCenterAboveFloorQ + ||!s.content.presentInCurrentField + ||floorMicrometres=s.content.topMicrometres + ||!unitDirection||pad.clearanceSubvoxels<=0 + ||pad.supportDepthSubvoxels<=0 + ||!pad.certifiedWalkableWithSupport) + add("landing_pad_contract",s.stableId+" publishes an uncertified or malformed landing pad"); + } const std::int64_t effectiveTransitionWidth=LayoutTransitionLimit(s); if(s.interiorTopMicrometres<=s.interiorBottomMicrometres) add("invalid_interior",s.stableId+" has non-positive content height"); @@ -1643,6 +1698,22 @@ std::optional ResolvedLayoutSnapshotV3::FromJson( for(const auto& a:v.Get("anchors").AsArray()) {ResolvedLayoutAnchorV2 p;p.kind=LayoutString(a,"kind");p.stableId=LayoutString(a,"stable_id");p.units=LayoutString(a,"units"); for(const auto& value:a.Get("values").AsArray())p.values.push_back(value.Integer());x.anchors.push_back(std::move(p));} + for(const auto& value:v.Get("landing_pads").AsArray()) + { + ResolvedLayoutLandingPadV1 pad;pad.stableId=LayoutString(value,"stable_id"); + pad.role=static_cast(LayoutInt(value,"role")); + const auto& position=value.Get("position_q").AsArray(); + for(std::size_t axis=0;axis<3&&axis(approach[axis].Integer()); + pad.clearanceSubvoxels=LayoutInt(value,"clearance_q"); + pad.supportDepthSubvoxels=LayoutInt(value,"support_depth_q"); + pad.certifiedWalkableWithSupport=LayoutBool(value,"certified"); + x.landingPads.push_back(std::move(pad)); + } s.strates.push_back(std::move(x)); } for(const auto& v:root.Get("passages").AsArray()) @@ -2566,6 +2637,17 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t {return c.upperStrateIndex==strate;}); return it==configs.end()?nullptr:&*it; }; + const auto landingPadFor=[](const ResolvedLayoutStratumV2& stratum, + ResolvedLayoutLandingPadRoleV1 role,std::uint32_t ordinal) + ->const ResolvedLayoutLandingPadV1* + { + std::vector candidates; + for(const auto& pad:stratum.landingPads) + if(pad.role==role)candidates.push_back(&pad); + std::sort(candidates.begin(),candidates.end(),[](const auto* a,const auto* b) + {return a->stableIdstableId;}); + return ordinal& out) { @@ -2662,9 +2744,37 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t passage.upperStrateIndex=upper.strateIndex;passage.lowerStrateIndex=lower.strateIndex; passage.placementRadiusSubvoxels=placementRadius; passage.mouthRadiusSubvoxels=mouthRadius;passage.midRadiusSubvoxels=midRadius; + const auto* upperDeparturePad=landingPadFor(upper, + ResolvedLayoutLandingPadRoleV1::departure,connection); + const auto* lowerArrivalPad=landingPadFor(lower, + ResolvedLayoutLandingPadRoleV1::arrival,connection); + const auto validateLandingPad=[&](const ResolvedLayoutLandingPadV1* pad, + std::string_view side) + { + if(!pad)return true; + const std::int64_t requiredClearance=mouthRadius + +static_cast(std::llround(0.34*qPerMetre)); + if(!pad->certifiedWalkableWithSupport||pad->clearanceSubvoxelssupportDepthSubvoxels(std::llround(0.50*qPerMetre)) + ||!radialWithin(pad->positionSubvoxels,placementRadius) + ||pad->positionSubvoxels[2] + !=pad->floorHeightSubvoxels+playerCenterAboveFloorQ) + { + error=passage.stableId+" "+std::string(side) + +" landing pad is uncertified, unsupported, too tight, or outside PassageConfig.DistanceMax"; + return false; + } + return true; + }; + if(!validateLandingPad(upperDeparturePad,"departure") + ||!validateLandingPad(lowerArrivalPad,"arrival"))return false; std::array upperMouth{},lowerMouth{}; - const bool hasUpperRoute=connection==0&&routeAnchor(upper,true,upperMouth); - const bool hasLowerRoute=connection==0&&routeAnchor(lower,false,lowerMouth); + const bool hasUpperRoute=upperDeparturePad + ?(upperMouth=upperDeparturePad->positionSubvoxels,true) + :connection==0&&routeAnchor(upper,true,upperMouth); + const bool hasLowerRoute=lowerArrivalPad + ?(lowerMouth=lowerArrivalPad->positionSubvoxels,true) + :connection==0&&routeAnchor(lower,false,lowerMouth); const bool surfaceGroundDeparture=hasUpperRoute&&upperIsSurfaceWorld; const ResolvedLayoutAnchorV2* passageAnchor=nullptr; if(connection==0) @@ -2713,13 +2823,17 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t constexpr std::int64_t LandingExtensionQ=8; std::array upperTangent{},lowerTangent{}; - const bool hasUpperTangent=hasUpperRoute - &&routeTangent(upper,true,upperTangent); + const bool hasUpperTangent=upperDeparturePad + ?(upperTangent={upperDeparturePad->approachDirectionQ16[0], + upperDeparturePad->approachDirectionQ16[1]},true) + :hasUpperRoute&&routeTangent(upper,true,upperTangent); const bool hasPassageArrival=std::any_of(lower.anchors.begin(),lower.anchors.end(), [](const auto& anchor){return anchor.kind=="passage_arrival" &&anchor.values.size()>=3;}); - const bool hasLowerTangent=hasLowerRoute&&!hasPassageArrival - &&routeTangent(lower,false,lowerTangent); + const bool hasLowerTangent=lowerArrivalPad + ?(lowerTangent={lowerArrivalPad->approachDirectionQ16[0], + lowerArrivalPad->approachDirectionQ16[1]},true) + :hasLowerRoute&&!hasPassageArrival&&routeTangent(lower,false,lowerTangent); const bool profiledSurfaceJoin=hasLowerTangent &&std::any_of(lower.anchors.begin(),lower.anchors.end(), [](const auto& anchor){return anchor.kind=="heightfield_profile" diff --git a/Standalone/Core/src/WorldAssemblerInternal.h b/Standalone/Core/src/WorldAssemblerInternal.h index b492c29..334d973 100644 --- a/Standalone/Core/src/WorldAssemblerInternal.h +++ b/Standalone/Core/src/WorldAssemblerInternal.h @@ -542,7 +542,8 @@ namespace world_assembly_detail const auto& liminal = stratum.liminalField; if (liminal.version != 0) { - if (liminal.version != CoreLiminalFieldRecipeVersionV1 + if ((liminal.version != CoreLiminalFieldRecipeVersionV1 + && liminal.version != CoreLiminalFieldRecipeVersionV2) || static_cast(liminal.variant) >= CoreLiminalFieldVariantCountV1 || liminal.seed != effectiveRecipe.seed || liminal.variant != SelectCoreLiminalFieldVariantV1(liminal.seed) @@ -2719,6 +2720,402 @@ bool PlanCoreLiminalFieldV1(WorldAssemblyRecipeV1& recipe, return true; } +std::array,6> CoreLiminalRouteXYV2( + std::int64_t startX,std::int64_t startY,std::int64_t finishX, + std::int64_t finishY,std::int64_t qPerMetre) +{ + return {{{{startX,startY}},{{-40*qPerMetre,40*qPerMetre}}, + {{-40*qPerMetre,-40*qPerMetre}},{{40*qPerMetre,-40*qPerMetre}}, + {{40*qPerMetre,40*qPerMetre}},{{finishX,finishY}}}}; +} + +std::vector BuildCoreLiminalRouteV2( + const WorldAssemblySurfaceProfileV1& profile, + const ResolvedLayoutLandingPadV1& arrivalPad, + const ResolvedLayoutLandingPadV1& departurePad, + const WorldAssemblyLiminalVariantDefinitionV1& definition, + std::uint32_t seed,std::int32_t strateIndex,std::int64_t coreMicrons, + std::int64_t qPerMetre, + std::uint64_t& totalHorizontal,std::string& error) +{ + error.clear();totalHorizontal=0; + const auto groundHeightAt=[&](std::int64_t x,std::int64_t y) + { + if(profile.kind==WorldAssemblySurfaceProfileKindV1::flatField) + return profile.h0Subvoxels; + const std::int64_t turnX=world_assembly_detail::SurfaceProfileTurnAtCoordinate( + x,profile.wavelengthXSubvoxels,profile.phaseXTurnsQ32); + const std::int64_t turnY=world_assembly_detail::SurfaceProfileTurnAtCoordinate( + y,profile.wavelengthYSubvoxels,profile.phaseYTurnsQ32); + return profile.h0Subvoxels + +world_assembly_detail::MulQ30(profile.amplitudeXSubvoxels, + world_assembly_detail::CosineQ30(turnX)) + +world_assembly_detail::MulQ30(profile.amplitudeYSubvoxels, + world_assembly_detail::CosineQ30(turnY)); + }; + const auto horizontalLengthQ=[](std::int64_t dx,std::int64_t dy) + {return world_assembly_detail::IntegerSqrt(static_cast(dx*dx+dy*dy));}; + const auto micrometresToQ=[&](std::int64_t micrometres) + {return (micrometres*WorldAssemblySubvoxelsPerVoxel+coreMicrons/2)/coreMicrons;}; + const auto routeXY=CoreLiminalRouteXYV2(arrivalPad.positionSubvoxels[0], + arrivalPad.positionSubvoxels[1],departurePad.positionSubvoxels[0], + departurePad.positionSubvoxels[1],qPerMetre); + std::vector route; + const std::int64_t pointSpacing=12*qPerMetre; + const std::int64_t routeRadius=std::max( + micrometresToQ(definition.routeHalfWidthMicrometres),micrometresToQ(500000)); + const auto routeId=[&](std::size_t ordinal) + { + std::uint64_t id=14695981039346656037ull; + const auto add=[&](std::uint64_t value,std::uint32_t bytes) + {for(std::uint32_t byte=0;byte(value>>(byte*8));id*=1099511628211ull;}}; + add(seed,4);add(static_cast(strateIndex),4);add(ordinal,4); + return id?id:1; + }; + const auto appendRoutePoint=[&](std::int64_t x,std::int64_t y) + { + WorldAssemblyRoutePointV1 point; + point.positionSubvoxels={x,y,groundHeightAt(x,y)}; + point.radiusSubvoxels=routeRadius; + point.stableFeatureId=routeId(route.size()); + route.push_back(point); + }; + const auto interpolate=[](std::int64_t start,std::int64_t delta, + std::uint64_t step,std::uint64_t steps) + { + const std::int64_t numerator=delta*static_cast(step); + const std::int64_t divisor=static_cast(steps); + return start+(numerator>=0?(numerator+divisor/2)/divisor + :(numerator-divisor/2)/divisor); + }; + appendRoutePoint(routeXY.front()[0],routeXY.front()[1]); + for(std::size_t segment=1;segment(1, + (length+static_cast(pointSpacing)-1) + /static_cast(pointSpacing)); + for(std::uint64_t step=1;step<=steps;++step) + appendRoutePoint(interpolate(routeXY[segment-1][0],dx,step,steps), + interpolate(routeXY[segment-1][1],dy,step,steps)); + } + if(route.size()<2||totalHorizontal<300*static_cast(qPerMetre) + ||route.front().positionSubvoxels[2]!=arrivalPad.floorHeightSubvoxels + ||route.back().positionSubvoxels[2]!=departurePad.floorHeightSubvoxels) + {error="Core.Liminal.Field v2 pad-to-pad route is incomplete or too short";return {};} + return route; +} + +bool PrepareCoreLiminalLandingPadsV2(WorldAssemblyRecipeV1& recipe, + WorldAssemblyStratumPlanV1& stratum,ResolvedLayoutSnapshotV3& layout, + std::string& error) +{ + error.clear(); + if(layout.coreVoxelSizeMicrometres==0||stratum.strateIndex<0 + ||stratum.topChunkZcontent.presentInCurrentField) + {error="Core.Liminal.Field v2 must target a resolved SurfaceWorld content band";return false;} + + constexpr std::int64_t Q=WorldAssemblySubvoxelsPerVoxel; + const std::int64_t coreMicrons=layout.coreVoxelSizeMicrometres; + const auto micrometresToQ=[&](std::int64_t micrometres) + { + const std::int64_t numerator=micrometres*Q; + return numerator>=0?(numerator+coreMicrons/2)/coreMicrons + :(numerator-coreMicrons/2)/coreMicrons; + }; + const std::int64_t qPerMetre=micrometresToQ(1000000); + if(qPerMetre<=0){error="Core.Liminal.Field v2 could not resolve fixed-scale metres";return false;} + + const std::uint32_t seed=recipe.seed; + const WorldAssemblyLiminalVariantV1 variant=SelectCoreLiminalFieldVariantV1(seed); + const auto& definition=CoreLiminalFieldVariantsV1[static_cast(variant)]; + const std::int64_t bottom=static_cast(stratum.bottomChunkZ) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t top=(static_cast(stratum.topChunkZ)+1) + *recipe.layoutChunkWidthSubvoxels; + const std::int64_t contentBottom=micrometresToQ(resolved->content.bottomMicrometres); + const std::int64_t profileRelief=variant==WorldAssemblyLiminalVariantV1::repeatingHills + ?2*micrometresToQ(definition.hillAmplitudeMicrometres):0; + const std::int64_t deckSweepRadius=static_cast(std::ceil(std::hypot( + static_cast(definition.routeHalfWidthMicrometres+250000), + static_cast(definition.routeHalfThicknessMicrometres+250000)))); + const std::int64_t floorClearance=definition.routeHalfThicknessMicrometres + +deckSweepRadius+250000; + // Keep the field above the lower tunnel's mouth transition so the routed + // departure has a clean open section before it reaches the cave wall. + constexpr std::int64_t MinimumFieldGroundMarginMicrometres=20000000; + const std::int64_t fieldGroundMargin=std::max(floorClearance, + MinimumFieldGroundMarginMicrometres); + const std::int64_t floorHeight=contentBottom+profileRelief + +micrometresToQ(fieldGroundMargin); + if(floorHeight<=bottom||top<=floorHeight+8*qPerMetre) + {error="Core.Liminal.Field v2 has no room for its supported field and cap";return false;} + + WorldAssemblySurfaceProfileV1 profile; + profile.version=1; + profile.kind=definition.surfaceKind; + profile.h0Subvoxels=floorHeight; + if(profile.kind==WorldAssemblySurfaceProfileKindV1::periodicHills) + { + profile.amplitudeXSubvoxels=micrometresToQ(definition.hillAmplitudeMicrometres); + profile.amplitudeYSubvoxels=profile.amplitudeXSubvoxels; + profile.wavelengthXSubvoxels=micrometresToQ(definition.hillWavelengthMicrometres); + profile.wavelengthYSubvoxels=profile.wavelengthXSubvoxels; + ResolveWorldAssemblySurfaceProfilePhasesV1(profile,seed); + } + if(!world_assembly_detail::ValidateSurfaceProfile(profile,seed,error))return false; + + stratum.hasRecipeOverride=true; + stratum.recipeOverride=recipe; + stratum.recipeOverride.surfaceProfile=profile; + stratum.recipeOverride.contentHash=0; + stratum.surfaceProfile=profile; + stratum.capHeightSubvoxels=top-4*qPerMetre; + stratum.capUndulationSubvoxels=0; + stratum.capDetailAmplitudeSubvoxels=0; + stratum.capRidgeAmplitudeSubvoxels=0; + stratum.waterEnabled=false; + stratum.waterSurfaceSubvoxels=0; + + const auto groundHeightAt=[&](std::int64_t x,std::int64_t y) + { + if(profile.kind==WorldAssemblySurfaceProfileKindV1::flatField) + return profile.h0Subvoxels; + const std::int64_t turnX=world_assembly_detail::SurfaceProfileTurnAtCoordinate( + x,profile.wavelengthXSubvoxels,profile.phaseXTurnsQ32); + const std::int64_t turnY=world_assembly_detail::SurfaceProfileTurnAtCoordinate( + y,profile.wavelengthYSubvoxels,profile.phaseYTurnsQ32); + return profile.h0Subvoxels + +world_assembly_detail::MulQ30(profile.amplitudeXSubvoxels, + world_assembly_detail::CosineQ30(turnX)) + +world_assembly_detail::MulQ30(profile.amplitudeYSubvoxels, + world_assembly_detail::CosineQ30(turnY)); + }; + const auto routeXY=CoreLiminalRouteXYV2(-12*qPerMetre,0,12*qPerMetre,0,qPerMetre); + const auto squareRoot=[](std::uint64_t value) + {return world_assembly_detail::IntegerSqrt(value);}; + const auto directionQ16=[&](std::int64_t dx,std::int64_t dy) + { + const std::uint64_t length=squareRoot(static_cast(dx*dx+dy*dy)); + if(length==0)return std::array{{0,0}}; + const auto rounded=[&](std::int64_t value) + {return value>=0?(value+static_cast(length/2)) + /static_cast(length) + :(value-static_cast(length/2)) + /static_cast(length);}; + return std::array{{ + static_cast(rounded(dx*65536)), + static_cast(rounded(dy*65536))}}; + }; + const auto arrivalDirection=directionQ16(routeXY[1][0]-routeXY[0][0], + routeXY[1][1]-routeXY[0][1]); + const auto departureDirection=directionQ16(routeXY.back()[0]-routeXY[routeXY.size()-2][0], + routeXY.back()[1]-routeXY[routeXY.size()-2][1]); + const std::int64_t playerCenterAboveFloor=micrometresToQ(1130000); + const std::int64_t landingClearance=micrometresToQ(6000000); + const std::int64_t supportDepth=micrometresToQ(2000000); + const auto makePad=[&](std::string id,ResolvedLayoutLandingPadRoleV1 role, + const std::array& xy,const std::array& direction) + { + ResolvedLayoutLandingPadV1 pad; + pad.stableId=std::move(id);pad.role=role; + pad.floorHeightSubvoxels=groundHeightAt(xy[0],xy[1]); + pad.positionSubvoxels={xy[0],xy[1],pad.floorHeightSubvoxels+playerCenterAboveFloor}; + pad.approachDirectionQ16=direction; + pad.clearanceSubvoxels=landingClearance; + pad.supportDepthSubvoxels=supportDepth; + pad.certifiedWalkableWithSupport=true; + return pad; + }; + resolved->recipeId=std::string(CoreLiminalFieldRecipeIdV1); + resolved->recipeVersion=CoreLiminalFieldRecipeVersionV2; + resolved->landingPads.clear(); + resolved->landingPads.push_back(makePad("core/liminal-field/landing/arrival/000", + ResolvedLayoutLandingPadRoleV1::arrival,routeXY.front(),arrivalDirection)); + resolved->landingPads.push_back(makePad("core/liminal-field/landing/departure/000", + ResolvedLayoutLandingPadRoleV1::departure,routeXY.back(),departureDirection)); + std::uint64_t routeLength=0; + stratum.route=BuildCoreLiminalRouteV2(profile,resolved->landingPads[0], + resolved->landingPads[1],definition,seed,stratum.strateIndex,coreMicrons, + qPerMetre,routeLength,error); + if(!error.empty())return false; + stratum.routeConstraints={1,micrometresToQ(340000),micrometresToQ(1760000), + 17560,micrometresToQ(125000),micrometresToQ(250000), + micrometresToQ(1000000),micrometresToQ(120000),3}; + resolved->anchors.erase(std::remove_if(resolved->anchors.begin(),resolved->anchors.end(), + [](const auto& anchor){return anchor.kind=="route_point" + ||anchor.kind=="liminal_route_point"||anchor.kind=="liminal_variant" + ||anchor.kind=="heightfield_profile";}),resolved->anchors.end()); + ResolvedLayoutAnchorV2 profileAnchor; + profileAnchor.kind="heightfield_profile"; + profileAnchor.stableId="heightfield-profile/liminal/" + +std::to_string(static_cast(profile.kind)); + profileAnchor.units="profile kind enum"; + profileAnchor.values={1,static_cast(profile.kind)}; + resolved->anchors.push_back(std::move(profileAnchor)); + std::uint64_t routeAnchorDistance=0,lastRouteAnchorDistance=0; + for(std::size_t pointIndex=0;pointIndex0) + { + const auto& previous=stratum.route[pointIndex-1].positionSubvoxels; + const auto& current=stratum.route[pointIndex].positionSubvoxels; + const auto dx=static_cast(current[0]-previous[0]); + const auto dy=static_cast(current[1]-previous[1]); + routeAnchorDistance+=world_assembly_detail::IntegerSqrt(dx*dx+dy*dy); + } + const bool first=pointIndex==0; + const bool last=pointIndex+1==stratum.route.size(); + const bool spaced=routeAnchorDistance-lastRouteAnchorDistance + >=static_cast(8*qPerMetre); + if(!first&&!last&&!spaced)continue; + const auto& point=stratum.route[pointIndex]; + ResolvedLayoutAnchorV2 routeAnchor; + routeAnchor.kind="route_point"; + routeAnchor.stableId="route/"+std::to_string(pointIndex); + routeAnchor.units="1/256 Core voxel"; + routeAnchor.values={point.positionSubvoxels[0],point.positionSubvoxels[1], + point.positionSubvoxels[2]+playerCenterAboveFloor,point.radiusSubvoxels}; + resolved->anchors.push_back(std::move(routeAnchor)); + lastRouteAnchorDistance=routeAnchorDistance; + } + if(!layout.finalize(error))return false; + const auto reportPad=[&](const ResolvedLayoutLandingPadV1& pad) + { + std::printf("[ResolvedLandingPad] strate=%d id=%s role=%s position_m=(%.3f,%.3f,%.3f) " + "floor_m=%.3f approach_q16=(%d,%d) clearance_m=%.3f support_m=%.3f " + "certified_walkable_with_support=true status=PASS\n",stratum.strateIndex, + pad.stableId.c_str(),pad.role==ResolvedLayoutLandingPadRoleV1::arrival?"arrival":"departure", + pad.positionSubvoxels[0]/static_cast(qPerMetre), + pad.positionSubvoxels[1]/static_cast(qPerMetre), + pad.positionSubvoxels[2]/static_cast(qPerMetre), + pad.floorHeightSubvoxels/static_cast(qPerMetre), + pad.approachDirectionQ16[0],pad.approachDirectionQ16[1], + pad.clearanceSubvoxels/static_cast(qPerMetre), + pad.supportDepthSubvoxels/static_cast(qPerMetre)); + }; + reportPad(resolved->landingPads[0]);reportPad(resolved->landingPads[1]); + std::printf("[LiminalPadRoute] points=%zu path_length_m=%.3f spacing_max_m=4.000 " + "profile_ground_following=true status=PASS\n",stratum.route.size(), + routeLength/static_cast(qPerMetre)); + return true; +} + +bool PlanCoreLiminalFieldV2(WorldAssemblyRecipeV1& recipe, + WorldAssemblyStratumPlanV1& stratum,const ResolvedLayoutSnapshotV3& layout, + std::string& error) +{ + error.clear(); + if(layout.coreVoxelSizeMicrometres==0||stratum.strateIndex<0 + ||stratum.topChunkZcontent.presentInCurrentField + ||stratum.surfaceProfile.version!=1) + {error="Core.Liminal.Field v2 needs its prepared profile and resolved landing pads";return false;} + const ResolvedLayoutLandingPadV1* arrivalPad=nullptr; + const ResolvedLayoutLandingPadV1* departurePad=nullptr; + for(const auto& pad:resolved->landingPads) + { + if(pad.role==ResolvedLayoutLandingPadRoleV1::arrival) + {if(arrivalPad){error="Core.Liminal.Field v2 has multiple arrival pads";return false;}arrivalPad=&pad;} + if(pad.role==ResolvedLayoutLandingPadRoleV1::departure) + {if(departurePad){error="Core.Liminal.Field v2 has multiple departure pads";return false;}departurePad=&pad;} + } + if(!arrivalPad||!departurePad||!arrivalPad->certifiedWalkableWithSupport + ||!departurePad->certifiedWalkableWithSupport) + {error="Core.Liminal.Field v2 requires certified arrival and departure pads";return false;} + + const ResolvedLayoutPassageV1* arrival=nullptr; + const ResolvedLayoutPassageV1* departure=nullptr; + for(const auto& passage:layout.passages) + { + if(passage.lowerStrateIndex==stratum.strateIndex) + {if(arrival){error="Core.Liminal.Field v2 requires one arrival passage";return false;}arrival=&passage;} + if(passage.upperStrateIndex==stratum.strateIndex) + {if(departure){error="Core.Liminal.Field v2 requires one departure passage";return false;}departure=&passage;} + } + if(!arrival||!departure||arrival->lowerMouthSubvoxels!=arrivalPad->positionSubvoxels + ||departure->upperMouthSubvoxels!=departurePad->positionSubvoxels) + {error="Core.Liminal.Field v2 passage mouths are not bound to the certified layer pads";return false;} + + constexpr std::int64_t Q=WorldAssemblySubvoxelsPerVoxel; + const std::int64_t coreMicrons=layout.coreVoxelSizeMicrometres; + const auto micrometresToQ=[&](std::int64_t micrometres) + { + const std::int64_t numerator=micrometres*Q; + return numerator>=0?(numerator+coreMicrons/2)/coreMicrons + :(numerator-coreMicrons/2)/coreMicrons; + }; + const std::int64_t qPerMetre=micrometresToQ(1000000); + const std::int64_t playerCenterAboveFloor=micrometresToQ(1130000); + if(qPerMetre<=0||arrivalPad->positionSubvoxels[2] + !=arrivalPad->floorHeightSubvoxels+playerCenterAboveFloor + ||departurePad->positionSubvoxels[2] + !=departurePad->floorHeightSubvoxels+playerCenterAboveFloor) + {error="Core.Liminal.Field v2 pad floor and capsule-center heights differ";return false;} + + const std::uint32_t seed=recipe.seed; + const WorldAssemblyLiminalVariantV1 variant=SelectCoreLiminalFieldVariantV1(seed); + const auto& definition=CoreLiminalFieldVariantsV1[static_cast(variant)]; + const auto& profile=stratum.surfaceProfile; + std::uint64_t totalHorizontal=0; + std::vector route=BuildCoreLiminalRouteV2(profile, + *arrivalPad,*departurePad,definition,seed,stratum.strateIndex,coreMicrons, + qPerMetre,totalHorizontal,error); + if(!error.empty())return false; + if(route.size()!=stratum.route.size()) + {error="Core.Liminal.Field v2 route differs from the path used to certify its pads";return false;} + for(std::size_t index=0;indexpositionSubvoxels; + liminal.departureMouthSubvoxels=departurePad->positionSubvoxels; + liminal.floorHeightSubvoxels=profile.h0Subvoxels; + liminal.routeHalfWidthSubvoxels=micrometresToQ(definition.routeHalfWidthMicrometres); + liminal.routeHalfThicknessSubvoxels=micrometresToQ(definition.routeHalfThicknessMicrometres); + liminal.routeOffsetSubvoxels=150*qPerMetre; + liminal.supportSpacingSubvoxels=micrometresToQ(definition.supportSpacingMicrometres); + liminal.supportRadiusSubvoxels=micrometresToQ(definition.supportRadiusMicrometres); + liminal.mouthFloorOffsetSubvoxels=playerCenterAboveFloor; + stratum.route=std::move(route); + stratum.routeConstraints={1,micrometresToQ(340000),micrometresToQ(1760000), + 17560,micrometresToQ(125000),micrometresToQ(250000), + micrometresToQ(1000000),micrometresToQ(120000),3}; + stratum.liminalField=liminal; + std::string validationError; + if(!world_assembly_detail::ValidateSurfaceProfile(stratum.surfaceProfile,seed,validationError) + ||!world_assembly_detail::ValidateStratum(stratum,recipe,validationError)) + {error=validationError.empty()?"Core.Liminal.Field v2 produced an invalid plan":validationError;return false;} + std::printf("[CoreLiminalFieldPlan] recipe=%.*s version=%u variant=%.*s seed=%u " + "arrival_pad=%s departure_pad=%s route_points=%zu path_length_m=%.3f " + "profile_ground_following=true route_grade_limit_deg=15.000 status=PASS\n", + static_cast(CoreLiminalFieldRecipeIdV1.size()),CoreLiminalFieldRecipeIdV1.data(), + liminal.version,static_cast(definition.name.size()),definition.name.data(),seed, + arrivalPad->stableId.c_str(),departurePad->stableId.c_str(),stratum.route.size(), + totalHorizontal/static_cast(qPerMetre)); + return true; +} + std::string WorldAssemblyManifest::ToJson() const { std::string error; diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/BuildL145Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux145/BuildL145Fixtures.py new file mode 100644 index 0000000..7011839 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux145/BuildL145Fixtures.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Build the 3-strata composed Core.Liminal.Field v2 fixture.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l145")) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + world = json.loads(OWNER.read_text(encoding="utf-8")) + if len(world.get("strates", [])) < 3: + raise SystemExit("owner fixture needs at least three authored strate slots") + + world["strates"] = world["strates"][:3] + world["total_strates"] = 3 + world["settings_asset"]["TotalStrates"] = 3 + world["settings_asset"]["FixedStrates"] = world["settings_asset"]["FixedStrates"][:3] + # Keep the resolved arrival near the departure depth. The owner's 5000-unit + # reach clamps to liminal bedrock on most seeds and leaves no field floor. + world["strates"][0]["passage_config"]["ReachMin"] = 1536 + world["strates"][0]["passage_config"]["ReachMax"] = 1792 + world["surface_profile_override"] = { + "version": 1, + "kind": "flatField", + "minimum_arena_clearance_m": 0.0, + } + middle = world["strates"][1] + middle["asset"]["GeneratorType"] = 4 # ECaveGeneratorType::SurfaceWorld + middle["asset"]["StrateName"] = "Liminal Field" + # Keep the departure mouth 24–32 m above liminal bedrock so every variant + # has room for its floor, road landing and support footings. + middle["passage_config"]["ReachMin"] = 192 + middle["passage_config"]["ReachMax"] = 256 + world["core_liminal_field"] = { + "version": 2, + "strate_index": int(middle["index"]), + "variant_policy": "seed_modulo_4", + } + + output = args.out / "core-liminal-field-3-strata.json" + output.write_text(json.dumps(world, separators=(",", ":")) + "\n", encoding="utf-8") + print(f"[L145Fixture] path={output} strates=SurfaceWorld,Core.Liminal.Field,TunnelNetwork status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/CaptureL145.py b/Standalone/Research/WorldAssemblerM3/Linux145/CaptureL145.py new file mode 100644 index 0000000..b65c6e8 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux145/CaptureL145.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +"""Capture one arrival-mouth eye view per Core.Liminal.Field v2 variant.""" +from __future__ import annotations + +import hashlib +import json +import math +import os +from pathlib import Path +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +HERE = Path(__file__).resolve().parent +OUT = ROOT / "Saved/Linux/l145" +CAPTURES = HERE / "captures" +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) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, env: dict[str, str], + stamped: bool = False) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + binary = Path(str(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_stamp: + raise RuntimeError(f"{name} refused a 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) + output = log.read_text(encoding="utf-8", errors="replace") + elapsed = time.monotonic() - started + print(f"[L145Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp + or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != 0: + raise RuntimeError(f"{name} exit={result.returncode}; see {log}") + return output + + +def camera_angles(camera, target): + 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 route_views(manifest_path: Path, layout_path: Path, name: str): + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + plan = next(row for row in manifest["plan"]["strates"] + if row["strate_index"] == 1 and row.get("liminal_field", {}).get("version") == 2) + points = [tuple(value / Q_PER_METRE for value in row["position_q"]) + for row in plan["route"]] + first, second = points[0], points[1] + dx, dy = second[0] - first[0], second[1] - first[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field arrival tangent is degenerate") + tx, ty = dx / length, dy / length + eye_camera = (first[0] - tx * 1.5, first[1] - ty * 1.5, first[2] + 1.6) + third = points[min(2, len(points) - 1)] + dx, dy = third[0] - first[0], third[1] - first[1] + tangent_length = math.hypot(dx, dy) + tx, ty = dx / tangent_length, dy / tangent_length + dz_per_metre = (third[2] - first[2]) / tangent_length + eye_target = (first[0] + tx * 40.0, first[1] + ty * 40.0, + first[2] + dz_per_metre * 40.0 + 1.6) + + middle = len(points) // 2 + before, center, after = points[middle - 1], points[middle], points[middle + 1] + dx, dy = after[0] - before[0], after[1] - before[1] + length = math.hypot(dx, dy) + if length <= 1.0e-6: + raise RuntimeError("Core.Liminal.Field wide-view tangent is degenerate") + tx, ty = dx / length, dy / length + nx, ny = -ty, tx + floor = plan["liminal_field"]["floor_height_q"] / Q_PER_METRE + if name == "flatField-monolith": + monolith = next(row for row in layout.get("stamps", []) + if row.get("stable_id") == "core/liminal-field/monolith/000") + monolith_center = tuple(value / 1.0e6 for value in monolith["position_um"]) + floor = monolith_center[2] - monolith["half_extents_um"][2] / 1.0e6 + wide_camera = (monolith_center[0] - tx * 30.0 + nx * 18.0, + monolith_center[1] - ty * 30.0 + ny * 18.0, floor + 25.0) + wide_target = monolith_center + elif name == "periodicHills": + wide_camera = (center[0] - 20.0, center[1] - 25.0, floor + 10.0) + wide_target = (center[0] + 10.0, center[1] + 8.0, floor + 1.0) + elif name == "pillar-grid": + pillars = [row for row in layout.get("stamps", []) + if row.get("stable_id", "").startswith("core/liminal-field/pillars/")] + if not pillars: + raise RuntimeError("pillar-grid layout has no resolved grid stamps") + pairs = [] + for i, first_pillar in enumerate(pillars): + for second_pillar in pillars[i + 1:]: + a = first_pillar["position_um"] + b = second_pillar["position_um"] + dx, dy = (b[0] - a[0]) / 1.0e6, (b[1] - a[1]) / 1.0e6 + separation = math.hypot(dx, dy) + if 60.0 <= separation <= 90.0: + mx = (a[0] + b[0]) / 2.0e6 + my = (a[1] + b[1]) / 2.0e6 + pairs.append((math.hypot(mx - center[0], my - center[1]), + mx, my, dx / separation, dy / separation, + (a[2] + b[2]) / 2.0e6, + first_pillar["half_extents_um"][2] / 1.0e6)) + if not pairs: + raise RuntimeError("pillar-grid has no neighboring resolved columns") + _, mx, my, tx, ty, pillar_z, half_height = min(pairs) + floor = pillar_z - half_height + nx, ny = -ty, tx + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + else: + wide_camera = (center[0] - tx * 20.0 + nx * 25.0, + center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0) + wide_target = (center[0], center[1], floor + 2.0) + return {"eye": (eye_camera, eye_target), "wide": (wide_camera, wide_target)} + + +def capture_variant(seed: int, name: str, *, headless: Path, renderer: Path, + fixture: Path, env: dict[str, str]): + stem = f"core-liminal-{name}-seed{seed:02d}" + plan_dir = OUT / "capture-plans" / stem + plan_dir.mkdir(parents=True, exist_ok=True) + manifest = plan_dir / "manifest.json" + layout = plan_dir / "layout.json" + command = [headless, fixture, "--workers=1", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--camera=0,0,-540,0,0", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + output = run_step(f"plan-{stem}", command, OUT / "logs" / f"capture-{stem}-plan.log", + env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output: + raise RuntimeError(f"{stem} plan omitted its Core liminal deck") + views = route_views(manifest, layout, name) + for view, (eye, target) in {"eye": views["eye"]}.items(): + work = OUT / "captures" / f"{stem}-{view}" + work.mkdir(parents=True, exist_ok=True) + view_manifest = work / "manifest.json" + view_layout = work / "layout.json" + mesh = work / "world.vfmesh" + yaw, pitch = camera_angles(eye, target) + camera = (*eye, yaw, pitch) + view_clip_radius = (5 if view == "wide" and name in { + "flatField-monolith", "periodicHills"} else + 3) + command = [headless, fixture, "--workers=12", f"--seed={seed}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={view_clip_radius}", + "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--capture-skip-walkability", + f"--camera={fmt(camera)}", f"--mesh-export={mesh}", + f"--world-assembler-manifest-output={view_manifest}", + f"--resolved-layout-output={view_layout}"] + output = run_step(f"export-{stem}-{view}", command, + OUT / "logs" / f"capture-{stem}-{view}-export.log", env, stamped=True) + if "[CoreLiminalFieldDraw]" not in output or not mesh.is_file() \ + or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem}-{view} export omitted its Core liminal deck or mesh") + png = work / f"{view}.png" + image = CAPTURES / f"{stem}-{view}.jpg" + fog = { + "flatField-monolith": (30, 180, "0.66,0.73,0.77", -708.0, 46.0), + "periodicHills": (140, 850, "0.78,0.84,0.88", -720.0, 14.0), + "road-over-cloud-floor": (24, 420, "0.88,0.93,0.95", -720.0, 65.0), + "pillar-grid": (180, 1200, "0.82,0.88,0.91", -720.0, 80.0), + }[name] + fog_start, fog_end, fog_color, height_center, height_range = fog + render = [renderer, mesh, png, "--size=1600x900", "--fov-deg=72", + f"--camera-m={fmt(eye)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}", + "--tile-skirts=on", "--shade=readable", "--headlamp=off", "--height-tint=on", + f"--height-center-m={height_center:.6f}", f"--height-range-m={height_range:.6f}", + "--light-direction=-0.42,-0.58,0.70", "--fog=on", f"--fog-start-m={fog_start}", + f"--fog-end-m={fog_end}", f"--fog-color={fog_color}"] + run_step(f"render-{stem}-{view}", render, + OUT / "logs" / f"capture-{stem}-{view}-render.log", env, stamped=True) + run_step(f"jpeg-{stem}-{view}", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel", + "error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image], + OUT / "logs" / f"capture-{stem}-{view}-jpeg.log", env) + run_step(f"quality-{stem}-{view}", [sys.executable, + ROOT / "Standalone/Tools/verify/capture_quality.py", image], + OUT / "logs" / f"capture-{stem}-{view}-quality.log", env) + print(f"[L145Capture] variant={name} seed={seed} view={view} " + f"eye_height={'1.600m' if view == 'eye' else 'wide'} bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS", flush=True) + + +def main() -> int: + headless = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l145-clang" + renderer = ROOT / "Standalone/bin/linux/VoxelForgeOffscreenCapture-l145-clang" + fixture = OUT / "fixtures/core-liminal-field-3-strata.json" + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(OUT) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") + CAPTURES.mkdir(parents=True, exist_ok=True) + variants = ("flatField-monolith", "periodicHills", + "road-over-cloud-floor", "pillar-grid") + selected = set(os.environ.get("L145_CAPTURE_VARIANTS", "").split(",")) + for seed, name in enumerate(variants): + if selected and name not in selected: + continue + capture_variant(seed, name, headless=headless, renderer=renderer, + fixture=fixture, env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L145Capture] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux145/REPORT.md new file mode 100644 index 0000000..1f89899 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux145/REPORT.md @@ -0,0 +1,51 @@ +# Linux145 — Core.Liminal.Field v2 landing pads + +**Result: endpoint landing pads alone did not make the liminal join solvable.** The pads bind the passage mouth to certified ground and remove grade failures in the final seed 5 probe, but the passage capsule still intersects native Surface World terrain about 29 m from the departure pad. This matches R48's warning that a pad must cover the approach and tube exclusion envelope; stop here and use a bounded joint plan. + +## What changed + +- Added an opt-in landing-pad record to resolved strata: stable ID, arrival/departure role, position, floor height, Q16 approach direction, clearance, support depth, and a certification bit. The passage planner validates the record and binds the endpoint and tangent to it. Empty pad lists are omitted from canonical serialization, preserving legacy owner layouts and hashes. +- Added `Core.Liminal.Field` v2 pads on the field profile: flat ground, hill/valley profile, road endpoints, and pillar-grid clearings. Its layer route connects the pads; the road uses that route as its road centerline. +- Added an uncertified-pad negative control. Corrected the ripple audit to retain each valid sample's actual route distance across masked gaps; a 5 m synthetic gap control now confirms that the measurement detects a 5.8 cm ripple and rejects the same smooth cubic control. +- Fixed the composed audit's footing placement so it counts actual structural supports. No Unreal `Source/` files changed. + +## Count first: failure cause + +L144's fixed-mouth route already showed both end-connector grade and capsule blockage. For the flat-field seed 0 probe, the liminal route had 222 blocked capsule samples and 7 grade failures, with no unsupported samples or structural-support failures. Pillar-grid seed 3 had 289 blocked samples and 9 grade failures. In the separate seed 5 audit, interface 1–2 had 10 blocked passage-capsule samples and the liminal route had 9 blocked samples, both with zero grade failures. These results say support alone was not the cause; the fixed endpoint geometry sometimes made the approach too steep, while other cases had occupied space at the join. [L144 report](../Linux144/REPORT.md); logs: `Saved/Linux/l144/logs/probe8-seed00.log`, `probe8-seed03.log`, `audit-seed05.log`. + +The pad experiment removed the endpoint-grade part in seed 5, but not the occupied-space part: + +| Probe | Passage 1–2 capsule | Grade / support | Shell | Liminal route | +|---|---:|---|---|---| +| L144 seed 5, fixed mouths | 10 blocked | 0 grade failures; 0 unsupported | not the failing gate | 9 blocked; 0 grade failures | +| L145 seed 5, 45 m ground margin | 140 blocked; 20 interior shell violations | 0 grade failures; 0 unsupported | FAIL | PASS | +| L145 seed 5, final 20 m ground margin | 289 blocked | 0 grade failures; 0 unsupported | PASS | PASS | + +The final L145 Clang W1 probe (source stamp `82e3b58c…`) certified both pads. The departure pad was `(12, 0, -716.451) m`, with floor `-717.581 m`, 6 m clearance, and 2 m support depth. Yet the interface-1–2 passage reported 289/50,904 capsule samples blocked, with 0/4,040 unsupported and 0 grade failures. A blocked sample at `(-16.087, 2.915, -722.743) m` had native density `-3.629` and composed density `-0.162`; it is about 29 m from the departure pad. The sample is inside the passage tube, so the layer's field remains solid across the approach even though its pad itself is certified. The lower interface, both shell audits, both ripple audits, and the liminal walk audit passed; the final composed passage summary failed and seam audit did not run for this seed. See `Saved/Linux/l145/logs/audit-seed05-clang-w1.log`. + +For the 45 m attempt, the original seed 0–4 Clang W1 probes passed their composed gates, then seed 5 failed. The seed 5 log was overwritten by the final 20 m rerun; its counts above are from that earlier run. The corrected ripple fitter also removed a false 5.99 cm reading caused by compressing masked samples: at 45 m, seed 0 measured 2.87 cm after retaining route distances. These are probe results, not timing measurements. + +The third repeated seed 5 failure reaches the requested stop condition. This does not show that a full candidate-and-approach contract is impossible; it shows the tested endpoint-only pad contract is too weak. The passage planner needs to choose a candidate while checking the full capsule approach and tube against the layer field, as R48 recommends. + +## Captures + +One 1.6 m eye-height capture was rendered at each arrival pad. All four passed `capture_quality.py`; mesh export used `--capture-skip-walkability`, so these images show appearance and are not walkability evidence. + +| Variant | Capture | +|---|---| +| Flat field + monolith | ![Flat field arrival](captures/core-liminal-flatField-monolith-seed00-eye.jpg) | +| Repeating hills | ![Hill field arrival](captures/core-liminal-periodicHills-seed01-eye.jpg) | +| Road over cloud floor | ![Road arrival](captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg) | +| Pillar grid | ![Pillar grid arrival](captures/core-liminal-pillar-grid-seed03-eye.jpg) | + +## Checks + +- Clang 19 headless and offscreen-capture binaries reported the final source stamp. Four arrival captures passed quality checks. +- Fast tier passed on the final source: `Saved/Linux/l145/fast/fast-summary.json` (280.8 s tier duration). The initial default-output attempt refused a stale L42 binary before tests started; rerunning into the isolated L145 output directory with the current L145 binary passed. +- Owner canonical hash checks passed: Surface World style 1 and Floating Islands style 2 each matched all 12 pinned L130-v227 rows at W1 and W12, and each recipe's W1/W12 rows matched. These exercise the no-pad owner path. +- `git diff --check` passed. +- The landing-pad composed matrix stopped at seed 5 after the repeated failure. It did not complete 8 seeds per variant (32 runs). Clang/GCC W1/W8/W12 identity for the liminal fixture was not run. Final-source seeds 0–4 were not rerun after the margin returned to 20 m. No performance timing was collected. + +Changed standalone files: `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`, `Standalone/Core/src/ResolvedLayoutInternal.h`, `Standalone/Core/src/WorldAssemblerInternal.h`, `Standalone/Source/StreamBenchmarkHeadless.cpp`, `Standalone/Source/StreamBenchmarkPipeline.h`, and `Standalone/Source/WorldAssemblyPrototype.h`. + +Remaining risk: the current pad record certifies a local landing and direction, not an approach corridor. A future joint planner must reserve/check the full capsule and tube against the layer before finalizing pad choice and passage geometry. diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/RunL145AuditMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux145/RunL145AuditMatrix.py new file mode 100644 index 0000000..7ebbf3d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux145/RunL145AuditMatrix.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +"""Run L145's composed liminal audits and the worker/compiler identity matrix.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path +import re +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l145" +FIXTURE = OUT / "fixtures/core-liminal-field-3-strata.json" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +AUDIT_FLAGS = ("--audit-resolved-layout-passages", "--audit-liminal-road-walk", + "--audit-passage-tile-seams") +VARIANTS = ("flatField-monolith", "periodicHills", + "road-over-cloud-floor", "pillar-grid") +PASSAGE_RE = re.compile(r"^\[ResolvedPassageAudit\].*walkability=PASS$", re.M) +SHELL_RE = re.compile(r"^\[PassageShellAudit\].*status=PASS$", re.M) + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import current_stamp, first_stamp + + +def parse_seeds(value: str) -> list[int]: + result: set[int] = set() + for token in value.split(","): + token = token.strip() + if not token: + continue + if "-" in token: + first, last = (int(part) for part in token.split("-", 1)) + if first > last: + raise argparse.ArgumentTypeError(f"reversed seed range: {token}") + result.update(range(first, last + 1)) + else: + result.add(int(token)) + if not result or min(result) < 0: + raise argparse.ArgumentTypeError("seeds must be nonnegative and nonempty") + return sorted(result) + + +def validate_audit(output: str, seed: int, compiler: str, workers: int) -> None: + checks = { + "landing-pad negative control": + "[LandingPadNegativeControl] uncertified_rejected=true status=PASS" in output, + "passage walk audits": len(PASSAGE_RE.findall(output)) == 2, + "passage shell audits": len(SHELL_RE.findall(output)) == 2, + "passage ripple audits": len(re.findall( + r"^\[PassageRippleAudit\].*status=PASS$", output, re.M)) == 2, + "masked ripple sampling controls": len(re.findall( + r"^\[PassageRippleSamplingControl\].*status=PASS$", output, re.M)) == 2, + "passage shell summary": bool(re.search( + r"^\[PassageShellAuditSummary\].*status=PASS$", output, re.M)), + "liminal walk audit": bool(re.search( + r"^\[LiminalLayerWalkAudit\].*status=PASS$", output, re.M)), + "liminal negative control": + "[LiminalLayerNegativeControl] altered_departure_rejected=true status=PASS" in output, + "passage summary": bool(re.search( + r"^\[ResolvedPassageAuditSummary\].*status=PASS$", output, re.M)), + "seam audit": bool(re.search( + r"^\[PassageTileSeamAudit\].*status=PASS$", output, re.M)), + } + failed = [name for name, passed in checks.items() if not passed] + if failed: + raise RuntimeError( + f"seed={seed} compiler={compiler} workers={workers} failed checks: " + + ", ".join(failed)) + + +def run_audit(seed: int, compiler: str, workers: int, *, audit: bool = True) -> dict: + binary = ROOT / f"Standalone/bin/linux/VoxelForgeCoreHeadless-l145-{compiler}" + if not binary.is_file(): + raise RuntimeError(f"missing binary: {binary}") + expected_stamp = current_stamp() + probe = subprocess.run([str(binary), "--print-source-stamp"], cwd=ROOT, + capture_output=True, text=True, timeout=15, check=False) + if probe.returncode != 0 or first_stamp(probe.stdout) != expected_stamp: + raise RuntimeError(f"stale executable: {binary}") + + tag = f"seed{seed:02d}-{compiler}-w{workers}" + log = OUT / "logs" / f"audit-{tag}.log" + manifest = OUT / "manifests" / f"audit-{tag}.json" + layout = OUT / "layouts" / f"audit-{tag}.json" + manifest.parent.mkdir(parents=True, exist_ok=True) + layout.parent.mkdir(parents=True, exist_ok=True) + command = [str(binary), str(FIXTURE), f"--workers={workers}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--camera=0,0,-540,0,0", f"--seed={seed}", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if audit: + command.extend(AUDIT_FLAGS) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(OUT) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") + + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run([*LIMIT, "timeout", "1740s", *command], + cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, + timeout=1745, check=False) + output = log.read_text(encoding="utf-8", errors="replace") + if result.returncode != 0: + raise RuntimeError(f"{tag} exit={result.returncode}; see {log}") + if first_stamp(output) != expected_stamp or current_stamp() != expected_stamp: + raise RuntimeError(f"{tag} source stamp changed during run; see {log}") + if audit: + validate_audit(output, seed, compiler, workers) + if not manifest.is_file() or not layout.is_file(): + raise RuntimeError(f"{tag} omitted canonical manifest or layout") + manifest_value = json.loads(manifest.read_text(encoding="utf-8")) + layout_value = json.loads(layout.read_text(encoding="utf-8")) + identity = { + "seed": seed, + "variant": VARIANTS[seed % len(VARIANTS)], + "compiler": compiler, + "workers": workers, + "manifest_hash": manifest_value["content_hash"], + "resolved_layout_identity": layout_value["stable_identity"], + "log": str(log.relative_to(ROOT)), + "elapsed_s": round(time.monotonic() - started, 3), + "audited": audit, + } + print(f"[L145AuditRun] seed={seed} variant={identity['variant']} compiler={compiler} " + f"workers={workers} manifest={identity['manifest_hash']} " + f"layout={identity['resolved_layout_identity']} " + f"elapsed_s={identity['elapsed_s']:.3f} status=PASS", flush=True) + return identity + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--seeds", default="0-31", type=parse_seeds, + help="audit seeds, e.g. 0-31 or 0,1,2,3") + parser.add_argument("--determinism", action="store_true", + help="also compare seed 0 on Clang/GCC at W1/W8/W12") + parser.add_argument("--only-determinism", action="store_true", + help="run only the Clang/GCC seed-0 W1/W8/W12 identity matrix") + args = parser.parse_args() + if not FIXTURE.is_file(): + raise SystemExit(f"missing fixture: {FIXTURE}; run BuildL145Fixtures.py first") + + records = [] + if not args.only_determinism: + for seed in args.seeds: + records.append(run_audit(seed, "clang", 1)) + if args.determinism or args.only_determinism: + matrix = [run_audit(0, compiler, workers) + for compiler in ("clang", "gcc") for workers in (1, 8, 12)] + identities = {(row["manifest_hash"], row["resolved_layout_identity"]) + for row in matrix} + if len(identities) != 1: + raise RuntimeError(f"Clang/GCC W1/W8/W12 identity mismatch: {matrix}") + records.extend(matrix) + + summary = { + "audit_seeds": args.seeds if not args.only_determinism else [], + "variant_counts": { + name: sum(1 for seed in args.seeds if seed % len(VARIANTS) == index) + for index, name in enumerate(VARIANTS) + } if not args.only_determinism else {}, + "records": records, + "determinism_pass": bool(args.determinism or args.only_determinism), + "status": "PASS", + } + summary_path = OUT / "audit-matrix-summary.json" + summary_path.parent.mkdir(parents=True, exist_ok=True) + summary_path.write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8") + print(f"[L145AuditMatrix] records={len(records)} summary={summary_path} status=PASS", + flush=True) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L145AuditMatrix] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-flatField-monolith-seed00-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-flatField-monolith-seed00-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2d9e38be54447c5562f199cca01e4c4c669caf55 GIT binary patch literal 21063 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-periodicHills-seed01-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-periodicHills-seed01-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d5ce8e30ecb5db9bde0c8e5831dbce2272e50847 GIT binary patch literal 32072 zcmeFa2UrwIw>RDd1zklEFpw8lKoE5#XLJb)Ly{bX6(lFgaezfvGU!Se!T<{r1O_B$ zSS5^PVaRa-VF;3Q^j|&T?!NDR?|pageeUyo-~Y23yQ{mad%Ek?@0{N`Rn>m(`+NYM zMLu*f7C>A_2wz9sL_nVhq3uTD9PZ{;4n4$x91)rXl|<>J8sYR<1a7n-=h8b@*TRR4u`yCwNCul z+n0}0&Z|%G`sGuD%SlMcPmmLT6uvzPH7VKc4tsLd7kAG6i1_8(y!*5dY2F$wjU|uY z`q}vNuMjmQ+0)}vWF+Sx(sK~mIq35MbPD`1DK!~2Bnj;!Jt*S;^pIb(Uu)oN4ScPE zuQl+s2ENw7*Bba*17B<4YYlv@fv+|2wFbV{z}Fi1S_5Be;A;(ht%0vK@U;fM*1*>q z_*w&BYv5}Qe64}6HSo0t{$>qO5Y{KQ%3F~3m&%m3NAN7#G3dmng`*cXW^s1c%N$XL z-Ra`-9=~)%9N6PNLzsh8KGR0S2L!#@HJsy<@WC0BL_t+Q=D?@^;1o-N&qfGM?`CY( zMQ5eW7gM|XA`WXqYt@OLA-2y@`e&%(Gt{u{U$a>A8Is)hSy>YEvDp6%t$v0KaD6_K zW0J>x`qOviaMg(;Gizqu45NtEgI=|CmIv)gyFt5VzUaVZQ$Z%Y!h$G=26{K`;nE_O zu_wISfTnE4P;h?TJ5hUNNBM(s*ccBrqV6Gqf#6ZMZ)D0YLDRauIxkxsv9UboU+W`>o)>!0_5J39-7mu6l{uH5@^Gyfnl) z2rr=9Bbr=ND2-xs+HDV{kEv5PiI5vNSxz)~{LYlXX!edJx%wNHBDYVf8SNH?nmDb* z>Sc=^SBb$193m?`%5g$%)$aMu%an9+^wP!_YHk9t>l*UP(n~CUcm9EL?Z;SLe@UNL z>D0RMOah`jk!Q^;3ZH-;6P@3%i^MHb-3=f40h^9mFYM%BLf4Fzba`zN90s2%pTI80 zZz^A9xP_j$P`0j|2#THvA2Djw8Fe--3H36y*tA$QwraHzYO458u$JjoR z(XqExoMzK7&AX~yA;N0LWDtiNoQh}Skh?F+JGQtq>^{*Pe$9?)&TXVbPbS4X&R;zw z<;K;(F@dQ9n(%m}{f5U$*1y?2{~suRrp5m)iwQ&rFXYFF8%Rbh|pA$1ZB z5{haG4hha4v9hZSBUzrBf^!+sPgE1!woM`)$2`-Cw{LD^bE{K8hDlo5_ob*N;M;u! zawSpY__YONObWUiS0ceLDKI`MBI4K|e#XvU(~70UZ9q1?wz0jsyK7J4UN$Q3p+Uw` z^Gnc5aJLbj38SeV@$WR=4E|1T@unuedS}3behX>1I5;&j{iXGN()33~;@yKpzP9`z{!^{@9d zgW5k0YKCV^ilfjyo#^TV30{Mj3tR2cBDyd7n==nsRCi2nAR~kCcNdwJTOkmV+8_5? zH;s%rOVQ{(37U^cq$g5su13k**?>1FTUyqugPJ}dBsw4mCMR!XeSzn zGMJ+2$7KR!pR4Yhn4@OqTM2c@)QIapDunPx$?mkrmWbqAW_aYQn?2S0Wze%A0M2%KcT> z=rW%p#t}O%QNSM%9Sba@zyob$5o{_!k{6g60+Rn%pU9j#O#sbl|g zp>S&SatXfQlbTX)#Y@AYJv9c*&A2JYQXqn69$`70Ug*}O%fl%905@JZAZa=nxKn$t zhrh_kt|mHU^i`Q~TU7jp{cNtktT9W8(5%wbT4Qs0S3r1pV~3-b}(t(}+G zE>;1#=dDz_>$2tA6=o&x(qbRlvu%eFtA1r2I3_x?X7~$!fRS1L3l5bJaVQ3Gh(E;P z&;I~Jn?o2@{SL#%O*SK=aUb}u}H3CIrbnALoa1UtJ!eUUg`-qMppBXBqE%7!7AFvc)*@3P~h1Yjdh z9&MY$5)#!*%X(qiZl;25Y&U2S{o;^Oc?(TZlXcDhovO=fpYpZzlw;AT)ZX=Z8=S+$mZUDEEc7DhQRJQ|f%y5;rK zeV1>evZHlI840RrMVzMDQcijav)0Oo*j4_qxjKF=)M|B+#V1`~%SSG?iGMABrA-V~ zZ9#CtFx~ys?q5@jB7|QT>!@^1o$wg8IUl-XD=_;a!ekO5CO*_-WWO31cH_46Keo*O zpYD-t2W)ZeLTtW=3wTT4lSj*c_QtHFNq!j_K_>%}j#fbsI0P>c#03_RNR!Bn;ti?8 z@^np`<#Endp3-ui9EvUzYC=IF`2l;#H!Wi!yKM-Gvv>|eYy0(pfL5^-{kbr+=ocp##R&wK8g}o)+XXQ6VMY3*j45elSP-4-IR7bN0TNt63L=b z!ZY-}gb|6)kWy*RL3n$j0cczExbTuziSMVB!d|(U)sBv>jiwnlhx6Gn&3vI^p*6gy z(xzK0=mh4)fNfqP9YdMTo@t$_w-=hDOS3M_cGWzhx8VSLFui>omdf#%!Q zJwOq0DcUbrA8lcCs!DqszEcrQyJW2DOalVCq#spEOS?vwP=A+ao;^8oQ0$H;@YF7B@v|v|iahw%?~mG3S5U;qt`Q$)x0-=hkZD?$+5s z4s@_MRXfjx*@?{3S5Y^&*SWHkrI;;oA1co(!+*N)_U;bjSImhto zT8#k<(pgg0>xy_8uBU_d=aTSROEtCSnV`Xi=pL{4Q_edI_sh5qih`O0#X$ z;79x2##q7ehp81s9Rg`pt~E41#xs@Ft&=4e6PO1_DDvIS`y+5HsP-JM1xdFhr1vV7 zeA{jof2Gv~uM#TObL8&S@?Z$=B&MAKFIKF_&JkX`*@2+lAdpzrwJF^9IsF=i!=>>U zmK&5%PC2F9*asf)Ou1lA-|hEC?B&nPFYhrWvkQfYO?a(nawKLW>u~SfE6NUrh36-F zsdx@558}(?jFW!-r}pxH*Y4i0Uf=!`k34#Tvk-Y-QjW)q+xV~y846oL%A}dP0f?z` zXQGRaIb5Q2{g_-zbEf!h)!E)S<&4bc;n%`8%mIaXfq_|zc4~=$ZZ18$Ozfrc%NbI!exT!gAV<`S+MiF7% zHHAK4Df8WTsTi8+Eg#MsG2;kGkH1ONuu+E3b*^wMcEsT(C9McN4c|wKy6TmPqE0Q- zA8<6cUmBQD+V53xEWs<&4Q%V#V{-WBhn-5eQF3$NuJAT&lx{xQ%_*L+%SyOa75=;g z6d!h7C?AZh&K%NUVG(-}e{~w{hF0gey$_pH9@#!IZg-ujHyLBoG^!=>0e!&neyex= z@j?YY*S&tdriIYGV!*SnFB-NsKVpya@>D7qy%9E7lI3qdf~jb`QLv9PWYRCrO&IZ> z>rfgdT9Q!SH#;#Pul}T^0tU4i~E7)~r<>d=p>7r5wrC#RR*IUVeE93}WI$Ek$M)*YPE`ikxS!vu_5Tk++C=UWgj8a8UN)2! z%3O&|Rj?MDxMFfX!lP{VN0Lr1(q!KZ(!+Kqg2n0tYnrli*ds*H=+!`nJU)N)NP1!E zkV~)}b+r9fu3$LUro6p}p6W%`Yo_e-#mUw{{5wxXx8dmm?fnW|r>hm7>@NlGVjZ^jMwG?zGdNudN0ne(zi4R?&(Gx7qBm49T z9lzyk0vC%%dA#zzcTq8xMcdn9Cod}<@fn(9F5mV_Z~dZtmAkUc3#IGo>Kew4z3p}mct1nNl6!-nq1PLR92;iqCcQTzb_{dRq%&uDKi|4R@c!@_ z5()zO?4;lMTCrjT@CA;V4Wap)!szsLJ&ybesMI${H%=)aohktXh%k0JF;_hMgL_~HgoYqR^ zc+-h2sBK>45>9$+G0i08!0{6ZuhzVMxlgqqS)(w!hH1NAldhK1BbaZE63_beW1%K* zuj5v7cX)MoKzLO@;75d_RhH{YFH_^KAJLCu$0Rpy`n064m*?%?+{v5s7pRCq@pkh> zhe=$f(&@f6Q90*!J@if061Q(BV6My#f|9t(;f@U8*h5AwLF_czE z0?8=d$>fgEkW=Q<01DYWGh8eBK37V|WEZq<)e>}hI9;I7Jw-mWHE%U)d8%1GyJS1B zpw8fuZLDcORTiS4zWMZ~u4(_7bK3pmyEa)3Zyp>N)f|(*14gYC;O*F^=Eowi+N(>i=x}xFANZrs(Oaz zV~X~#y#;$yGs8B)Ch6iS?bcUHb9%0Jf|Ah**Nv-uOXvm&!_H~*ZT*eoyN1HHSK7ITpgCTlEnJn} z+J?EB^)Nc&M$u2k<?bUb$Jh40}1CF`|SLHJn9CW>gu5gOX zCTg*MQzrF~;&ejJgsv1~FPk+ivNa6RCRtNDPWZOB|9R^ zd~hFGbSW*Wqk>WGUaW-;!*ab#A-w-{*wwIrsH?@;sQW@u5?4*HreUL$*Kc*?h$0mE ztxG;bsyvqCQ5I=f2Kzd_Zi4=`&Oy!4*kzj8@zR*oqP!vlHk7=PX|Nsx-MG!%cgFJP z8|vM%Qq3cHQcNoqhw9J$lsC^PGbD3A(uRS$&ajhF`pP%PM!buS6K5kbLo=FbJ}y6{ zV_K`J{DIPDKMD>A0io^*Dehq>5JtDg05EBrZX|6*5xJC0u0H=_dnn zmC|FAxqEXAtjwDgv%Qq8^_Er);udELdp*{>YBfrmjGIh_6iz82B<#-(e!FwP4K$D7 zUh`*2?|a*t0?DlFWe$!D#%nlrfoA-`o((r$2tH#^RZn@;vZcL88&lCx{K}=8W3s-< z=?x|!Y&}>M!beW!)zF;gnZffadbz?{JkDbx1_Odh8zU=X_~wSjL`=KF ztmMj>9iQFAJ-ZlBiMgGf&k!zja@S`bxN!#Qy}g4&0x3?-G&%OvI-wiN`gRNcjpCz@ z{;~#fBMfezA=w9rgC$QEL*}6|QzH?F212#f13By2RY@m_dyBjAk|n$Kzm){9nQeWB z+{AN>4s3q?486-B~h1*38zZ`4+-d=X)Z%l^CzCpM7h{J zj}l!!*X)EB7%~0~sno)mp`En-|is2=vmeNl~^asK2u4xf$d$>LSZ~s5Y})s1KaK0 zE@f&Z&YeT^n3A*G+vA@4uY2N3L``k#Hr|{Edow+8#XK=3=YCbDzV0-qIEX1YKdxLB49uJ?@PZ1%&hD6}++{}LwXcK1|n-*$+%ek&Q&%B#2 z>!*kuc5JY0tn<4jEgE26@baZPcfmOeMZU}5a9oTnR@HT?d*8rcteW=9*iM#TS~FX< z>|%F>#aQRSw7QIyQ*k9YRvl+RpC8nXcYS9Op_$@xv#>R}u;|*;A1s1pU;py@Q3@Gy zkVowfn-1qYyg;xbXO_=9^+Jo+bhcY6+4*>_)UvU{CT_LVvJV+S_-WfUF1Er-iH1%2 zWbW^4pM8dujgq;UgeITI@>}QQFY%-8+Jr2kbdBSp8U_WL3KLdCU)}y~!75eiak&$g;Z!E6%wgq5EDf8BS{xqlIT-)3iAx^LUkFJpn#m`(pq;jf@bKbL19P! z!BlC@$fbtyj&40oBP+|69wWf^kh0^(O?ue6mYXg0g-Zv{^GfuESVvj&v@#Q{shxJh zoB{Xwkuqo3?RLS`yq@8ub=hi^#Pe0Xb`c>b@zWzTBk^S^?l&h!$~xJ*3YD*WmS|~s zdbn@6-qhJTsq2x|9oErSoK`|JH{4##5wTs>(PC1}=H_YVHo+0*boo*H?(5ljL*wv~ zYcwpC^*&$impZ?)hT@Z*b~6MNk;>*&wWQ^$kNYT*!*@MT_ z+#stL(P_Zt?IcKCK5o$?R=OxMlI1brJeLvUZB^14l9zZjaM`QZ&mOo2{#83qR;|61 zyb#&$4)+DCG&i#CdR1@kgvVVnVOB%DGZbHpH}V?4vZF9&?`ai=!|%SY)a1u|^td+b zPqE#QsF)qu9lbXeYCU1I49v@~8%j|$`H4>3V&2P>N4^0PZ%{F6aDXfO7-r;B=Vj+M z67wPSrR0t5A1oFrPS_@7n!IW&X)4g&Sq*kZ%5Avzt(VFn!li3l=0$|PFHJp@v{({$ z#V5SLdZQ*5*XDv2rxytHrOK8dqOPxp5leZrwrX)wUZBQ?m$ zw$Dy4z_>4Mpjc0!oyXK7wa`^CPDozmZ$2vtg{sbTb%)Imy>ne|0x2g89xB=>c$ey$ z)~8|Z=U=8V*B9H+TgV>QE%iL#SD5xXIOJ6KW1wkU1(7B~?q(K#3_!ESrLmXVFeCRL z%cZywtOaTtt~YoHncKAW+oCPU&5VBnJ}^*KY^6Hy$11**2l>GgQIkv~V=_TTQJ4Ds zVFdrLtvIUgJZrpqy%rho#lw=fN_E_7PY<4NR>#S*Ya+hae8&ee_Yt+4%{+*XpI%N| z_M4C=7-hCp6DWx8FNfsZ<=JasYHX3g<&n#i#uU!f&1p0;@e<7U;=)F@hCFblgBLZYhODU#;_Qp0ndTe1 zsSSz>dyG1GX=qB(lL!QXW_EQTAUg^kNKk@LSgrC#Jz7|so9*og9eia;V0yj0x$WqP z5i@(_rGP!4+aDFB*@zY%1>aJ^;@%4aciW42Ul}|f+-pgZ{ zEwr5hh!d2I=4`^9kqjOa=+Ha~=G_Fj1ShjcxLxct>fna;<4YdK4MD9b<;#|HQR@Qe z>Cw*+)~;-c!E-|E#9;41`i~!hM{nG-FUqX%o|5%P7e`=%U5m?(DndfdE`F&6>Aox8 z-j#>}ohA%Ht_GLCTj_1JE#1xSW|&_@arp7`hIQ@jRi1e?7V;@P+YG{a`W`}vOrje1cJ)(`Bqm85E z!w-KKynnRczm+4|D;ig5{Vml~4&^X*_4cTKsl1AF_jRcY=6~xp#KNqz+_z2&TWej6 zI_*O6%kC@e>MBY32IdG#S8p|HeS_5HR}>jDvG^&=s6Q=M<6X1XH=6aS{EA%TCRsmb z8FgeD&;1mWa~#{&ktR}lDR#`Vuh^p8c&@g9uD%ae1vV#tGnos|gRkz}0olN;hp`sF z=%30q{$$xF4|3ODspVyvM8#^T|La5{DYN4%l<2pwP7zW28gfI5MoMc|;@%F`-hJ}UIIpXY^GRdZ zo)lvSDVHxLX^<~h5+{^I>PzKI z4tEdhSC@HMu!KP!aBTT>HX1USE$?IN@>||jD|L@=F(~FCP10`+8#oinW-zk_ZSMQa zB4&17=&&#D@v+je%5DQYt7jTX0iJR{L~NqYMY5_zkg>k)QbEX^3jo0IVggWPmMzDp8U zRbjGeO6E@IVgmtPX)RBOj3?<_0Xgv*LGw+?RK=6L4a{$XQoVTor1L={Ui7qu|1doQ!x?J6qbR?R+yEH^hj z{LPKPn9_FTlXu!4{>+8C$2&{;A79yJsanj$tj8YcED%bkc5aZHM7Ses-)(?yVf!iN;TqSU#II|OSR`IFvrW^%#Q?4h&5i3 ze%!kAYS>mYZi8DPNwl;v2M7R&!@Q!kBXlNwMU zkBsRDugZ7lu;01LZJna1JMqa*=87uan68V!c;@?D&U9mA`G8!Zl)*b>0a2|+Sfvfs%h2&f5Alro8m zog=R&l3I7;ReR#VdMwZ;4AFF6Q?1RKl4l0G^P839#;xQX0}~89O&9O2q-5VD@KpQ! zI8mP8_RWB)nPZseCbp%ny*A#iB+=1KvS8UzO~|M~Cs-zHMVDPPJrl#bQGrBUQdWpp zPzxWc>`LHB_Hn1551&=PT?{x$02k;YNP<@ZnZR#~&txl?k=0O@){v0~F)V<3VO2Uj z0Q}vIC)hF-=EC1cH+9EkSh9jTQ3U`dje&H--NOU`e{}KO$)!L7ezuIbhJCG%}7ZSKrgF zmwr$ns3!#ZlRY+{TM2Os5tw#A)KVQou2Lez+L@n8{^gxIw8@=OV7J`%MJ?ere3bbYsn?`$bk^ddmj&AmUJD z(Kiy5#fg8%IS>RQ1WlZqGwL$#^~?j1Bb^5&mD7w0jgqgrip;+^&Hq?EPzkJ%L<$3KY>(A^@HybVquGYRux7oCzJst z5%10Zixi_$6_YPNw&uE_T;XD~d_cB~zB|uw`$Y53pi6LjigkW&{CKI@DnqvB@Cz}( z(KAf#!moXX&J0rJ-NY5d*A;Kqm@OAvl2nMxxzV1IDOOY+I9b}|7`pASW@jINVU|r~ z2Em8vTrbAnThFfBM+u&tM-*QSdELZe?0A0IN=+j9GDowGBgV2o!h;~Ph1~z`$s^!& zz!4ECT5=ewbad1jv@(a$5iqoZ`nDV+y@&k%t5U?jC3 zx^#q_ToWVz2uBaV{zN^oV_*C7-s5R+C4|TmFBJIWyF0W*ds+(psu!Q zwJqXPoCnLRv5oL!byg`7!Z8Wxz=UArj*K1NVr1KrC9bL?fw!2M<7fLO0deJS!45fQkE7BM^h2^zu~yx|%D5oST=B;r*IYlo-q7?G}lZ$D3Uy^)DG)i~jt8Y9Us#eQ5V#GkF(<>ApRK?%#Or z(gScuajKy@bXYvk z`vyEGRw>Z7K_EuPQih=;R7b{AR^U!4hz`(O^wM0>SFj%7>&ju5FOBLi*0t24xeOoS zSCk)rlm*x^y+s4N5-7|Q70X{o3^Ih582QGtBfI9Wq?(#aXr({SWB&ME??{c zzB1Nca6A~8R`Z6TAigH!`Vo!nKVtGP?NP=FoD3}Zfy(q=BuUGw_hd2mo>QEY4-mrq%qfg{)#7)eAcF)V z0Tdegok!C`PQY?;!aV!=p?$r>1@<$b8Bh$2ln1{{B1Nu34lydcIbM}jBka+#0V0og zws<7#B^@n$5@oTMQXj4?X(djCmpw14xKi2}Wnn1zlG&C4H%5?;wxGqcF~*!Br(cQ?U&)d9HdZXy!R7b;85yxC7h zEcD7`p>`I%nX7wo;s`8*k%8HXPR!2>`wSO~+)h=@j3XL~wl~9T@O43pGedimpF)-~ zc}rk`@iW!DS?}ze^X;IGizaf zp-BdYl;5VVSl3~aTO;gqF2(7vp2}tnki~aQD7Qr$^*edFA!iMn+ z><(ee4Ii1%Gl7u}oOJ8v-1$hgvi6}`9y#?&FO*1(TRJ&IA>tvBhWc4-PQTg^xria1N z0*R8yWq*y{M(T`!m4JnSm0n{X$uoY&k!(!bfl>5m$M7q+WamV~XJ+4;#69kv!!;Q% zpw|)_V#8hTqZ02d*T%*y_g-<$^4MI#AW>IdHp;z$9|HvCAipHifF#N!%EQ6JobaKb zlOY+zs2%rRKdvO!jFUm6$$-0qzW^|xn2YR{x{SIi(ZB+FoD7!$MFOz#VusYUbMKme ze$m~XIpAT6GOda7EL#vR8h}xtV`{|FMsN0JxBg#&K%2t6yLtJ#l3IE=h1|f{=1c$T zli=jGAZ#|_HuPhr~ zV*`77Z}SaV?e>UDJH817;f%t%>y(?&!Hs7#O9hXzwLEe*?~ZJ)D9sV77Y^(kahH(p z$jWf_37Wheai%Xohc8Rmo7|9hGIZ&`X z&|6rTnr$(mnY?Z#)M9ND3M&1tr9WFvrg|wx@o_&goFY0o|Fn0E%^Kf(tidzF_sHZT z4~9G$Y0dQSJrG#nZr(@a^Vi|eH!F&aKQg94rUFYT025ntto+2I%jXKryZNm`pNGh| zCKp+S*61tV4CPN@@J19_4{(D^>FTokuy;WxnE>{w#cO@!Q)4)~{L1LjW%@x*yk=<( zWkWW6VHK^Ov_g&L}Kb*l57&^YJ%2ePo}w5Jpz zE*ad>KRk(+;)4Cf|5@@Q4I)T=+sFsmv_+8W`+oPzS2*H@wBs#Exc@y#`~4La#!nwu zC!HW);?KZADI)g;zUWv1bA@L^jTgTqohhUYR@pF5t% zj?j+Zam{31I~pyv%qcwn+Y3F;s&;# zL_Q2#PihT%;L)nm!BqGxJcsUZOQEDeQsY0MZ+9m5jKtl5T%=5TP9F0My>(6g9NlNZ z_6e#*QD%&0#>%gNEuvPG)z@B;*3!!X{$V}us@4Rxw%1^`Wm{hf$5njj&$GMP5=%=u z{1=vQwku897-TLk)!|(d8e?n64A9*TK4*BJ&a`+x7|j5**84J`wXQL_npx(v0U*+3 zzDOwjxcBx`VBku0=p-85w^pO&Z67=^Mp1W?ZIdZPC*}yPb1jrHbaM z5^j1itbS3zd^Gq8({53Rl^W~rct*5v2B+{zTc3I4H%Fzk-ugB+G5J{z zR8brlSKXTS?Qk1EBC$5u@tI1i*z#0;tVrHS%w>;Z9(cwHyL%44)rM=@b|qe`dR$(r(tXhn&HPzqc@q=pbg zEybv45KlZ`x$4M&E)#dwlRRD&+Z&ei8V)pxU@N4RU+IcoOuq|&F;xe8Zfw@$ zB`XVt6Hh4%Z|5l$(NC@zm^s!+lumx!mUHW#2}`HAgrAPqn${LC`PFPD{6cNv;$$Pu z11r=9Axv;`6_wj=kkQrPQrSlHOl4tTGv;bko~3R{_NH#Z`M}=mYK#@5QTQv%x;zTH zQDJkMrUeX>O~#3i{a`$N)4HUFw@>Y^W7u2zxsbfqp(bHD+ao*4MyrwxNQ+PIDQcX1 z%kB>dl+n{?qG}iUIaK40rA!j6U4m^#`%9EkYPQmq6+$f6YM*4!tSQWDw@CE;#yh8z zb#G=C-B@l_kU8+G#X}}NuOAIYVt?$KK;*rYAK;+|b5xLE26d@UCN-9Ac66q_qmiQ4xGS(C5OUZCSI3wB!}OG4tsHM zIW*0N-m({1!Yod#14tOwey~3VF!;sYqy^~w zGrN`6kh|*_1jl&~i7YWz1T$KYVpS-_LFX~*`UbQ*?JNknBQ1E$BhOlxy?t^+%RmG< zz|V_kdN8mD2K!odF6*pYf^HHcibl`x`%AOR(ly*&?d+EcWxG0iLt>8t!*UDu7y2fz z+h2D#8mc}0DMw;k(#(fG>m#DiI#2XjM-om;x7bK$X}VshWb_taSNaEsmE&$#b8uXu z0~3o`@Q5{U4b5?RSF7ai>V4PlvAKCKt4d4U_fNv-5~9s!v{9*V?dhl6!%S`P)E3i) z?I7qYfLV{l@h&b{)Ra~N;;(GAgqO;@3=Fe;w5b35nLs3f0`dw5;zn->_#>Lvz-2Wp~rE6U2h zGodN^35~W1Vub|&K?f+{-8F27R6kL4YZwmV=EM>=Y(*0cE}VGITuKm&;RZ2NLuWXA|PQ*5>cu0J0M{qOQf`i?DY%71&$_Yl`tT|+)=o0 z;VACf_em7-6JX58yT`S|Hs>O7TJf=m(bqA6f*?#wtq? ziuLbLwN)JGT`s` zS-OCl!ciXZ+wcVPvtTQu4)a)0lKgNsxhj#xYDj}(L>fy%B(m@e6A3N72`#;>I-sy{ zU{?wpN>kOKC-%%pIr#>G`K}qDAC`xW8}>!jWo&<#*s5kof7kkR-hA!o9pnZ(V(+~u4k^&C1y`elHVIa=igc`n>`N(aR|x{KimxV zYs{z#eCFZGYq_rF^Nc;Na0A)Ha&nRW#oMH%xb>9l0`7YP zutzEH!i_48LNhV~@Nf%;8)_)}N22$1CrKzsJei!XMRopc29;5+_K(Lv*FYT?8AhBB znow4Rggwlq92L zoVfyobX1rf@}cp2>N58E>bC`a$zI&nw~R3@RS;{kpI`Eq zCVS|Pu_nXwn~BZ!&xQnC3(~hq?n?4Ks_&4DW4Qr7u2Vai)1E?&tVtc`_8HqNIcVA5M6N7O zj$-*=8a!^{csa|=U%Z>zswY*Qk1 z=!DHhl@S)5^-kOpC^%TB8HJ)VLHrpU1gfopvk!!yL8nn?lGu2zDoKmRK+<=2GJz6P z2PPZ#7r_hsZzU4oY#;qmviC|+xseA|Z_)M{^1Vg#21-qu5~<(G3{Id5e#bqmB@U@1*d)Pu zII%~Nv?FOmAV+?GOb%z5%^7ZeRc0;!^QB3>mFLR?_{}Eu254`0^XPe@=%X;Mwh|{< z8)XOh#@9t^=6&?pI#bxjZ=CZBYxUzy3JRhm&IJUV4g@MQ{gN};l9FMq0~>l);;#W> zN15pdu*aJ8r)VfRMG3CX2!hETn_oxdN66uBG8;rCb()pr6~t#F<(S&XR;F?r+!Kb|G3YE9U4B~%7<4H>G7cd~#34LY zUFz6b6#&EEkqJM@7hE1arW6IQcC^%)OZ6q016R0p9~WzOT-Bxdv9deAm9IhRxB?j8 zi${u=y69S*9z3OH%~a~5#xAH}5@g}q99R|2@QRnp2BDqbcB#9D<1^H5?cz~eSvq+4 zq0Y&+3476Jg2(NsJnY0Ou`~VRi9?(r+1Afw{Q+?Ufo#f*--QfFPX;H5V}rwoTpoT- z;E?~}lCx!SfwRPsEkJ^>48J(*Y#Ee?{ykfACM%FJXuU~?g7xJjN;vlytq_l=pi2H5 zi54IZj)D9`qW+8b0v{rHPnmODMT#8UhB1TeC+IQoDz6u21g$!!o^`JP#$XsYmm-}3 zIa-&gVA}uM1XxEijxP|JqNGLQpsv`M)m$+fQkNI?}z z(v%4XQZxEeLc-8lNSgNcd(twH0Z62gVuc?W2!_-*38+$1O3q|o-yqH;Rv^T~P&O>C zBnYgM!7KR^WqT+=_*sZKusw1DAX4iOWHFI5ko~PH)-%Gfaf&ZDQ2&0QSvevHf>W4zYTBgkp4GqH7&VUhdx86%QhXhJ>4tw zANRZ2ik>$Q){QFc9A?1Cq(tj`U&J8WU3tnUC(nVehakx76~xc31i!&v9>0g#2WJsEPg;gj{LX%RAfG9gBQN&e2 zV#6~qK9htWaQz-?05}bzOoAv`lY>Az<%G48FD%?ItK^fU0i1rmhcX6*K{}N07kChh z!iPZuV|f)h$pZZzkxZK3i#+SD`;B}6|2$PT)Ke&0aQBIPcdz5XhfcOiD};odC?554 zw(}M?U{JG+N2hC_PQ|vaIcVfcq`If{E7p|4f3#L4bgFdV56Iz9>5%P60i6a+15p?t z4-!#&fVRQQ;SMbcFi9WI+*~7`|0^rFiGOLf|FJwE4geN^A(4XGq9g^X4}3-mj5_oM z0!pHiA}8XEoCMxVk-$9YEIi`xwu}rYM@}LGodq8rgjF^C0s!a7hqppJ(i}GB zZwyV-dpJ4zVAI2k`j<-&DlI%l1a*dPaS1Sc9%Bx3fo25Y=JMyn2GgBCA0Xy|Zh@;A zPKWv(WQZyg?$9M#1F~rfv@5Z|zgZn4ivO_C@B9*iq>e5lA^#6%@88^z=tnVTuq9El zLVmu!WY1wS0UgQtgqS-EBtU+ajuviXv??+(pf?N%?<@q%?vTkGi3t{+G%Xm_23jI` z8lueLrvk@8A~sw&L!>ld3z`BkDc-+YO<}PG4GIkdN+~-10TMz zFGuGX4le9Y99$E;IVjL3_S&WnsWk3cby4%hr#mOP0zi!e3rr-Wq(Gq)6Cj>2_Y64P z`|}zQ6{2}R>Ww%m4y;9cxX{9%3;xIaNm4eyq@yMRE1EwN>z6FBlf(e$KR2W==l|uF z5@JNg>@V@ZS!zUxZ*GJaYV{iUK+I>J@_gYdo zw?eSyyC+RO_Llw9%z_1R_nTOItA6hLlzdum#wM(ZwX^d3&c5spbB@yukH&1MB?Tl! zwj1{5B$pNvi*l_s*?Fu3U!gQlZEc0vdnk>2ZzbLf*J?B_HemSf(W_Z_s0Dh}UpUBV zBU)KdlB2(9%X&nD(OuZKJ9L))a;C8EWv^|ep(s>p$G7>D$C%1wDDEEF9X3B;WsW}A z=1Y8b%0EY@fx`a+P1t4-*(qG=h}l5@rL;XPEfitYdV5 zJpoA{YEgj6BUr-n1{#)Jh4!{I?V-j6PjLiOa5YFUcn=eN&0#uA0`5(Y_9dz7yrO=4 zLg<&-jMEAat+C16EY_ztuo0TNQ<>nURLU^4J*d-@a!@0OJ+tvOy zJ6!1QrRj>spDY-tZ(Nj7_pBUOQJtOoj^x81fPp0o)EAId($NxdDA~+_WKO>?W*gKX zu=xz~=c9bANXQ`?{pUAfR;? zIDtgdcouRX3KHg~Qbdgj#0Wrnn~tdRiKG|o6X6G>^+lS%g*B#NknSjgRCCRJJs{q`3WgCX0`vrA zK*%K!?jKN<2a*O43$axc$TmO~qfo41HQ*os?w5o}fx`x>3R3w9I6#Uv6s^Q^9D&nx zD3J$@Lw2o2+7kqTOGm&h9TrfCL#j!Tp_VFuK1~X7e6G@9vjo@z^*X_P=xb+RcHXmzY-Y*JezgLRDoLsLS38kXeKm_|FAL)p g0frYK7lE4pX#RE(fEx|013(<0ItT#E)c?N;0CYjTVgLXD literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-pillar-grid-seed03-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-pillar-grid-seed03-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2d3eca26c12d55016a29cd36f3f899d79de8ef40 GIT binary patch literal 29819 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux145/captures/core-liminal-road-over-cloud-floor-seed02-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..685b9ffacbf3fbe7b35835255a75465782f05a69 GIT binary patch literal 22536 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 + coreLiminalConfig.Data); const std::string variant=options.LatticeRecipe ?"lattice/"+std::to_string(options.LatticeStrateIndex) :options.CavesRecipe?"caves" @@ -1852,16 +1855,14 @@ int main(int argc,char** argv) ?StandaloneWorldAssemblyPrototype::ImportExportedResolvedLayout( ownerJsonRoot,resolvedLayout,error) :StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot( - *ownerWorld,worldAssembly,variant,resolvedLayout,error); + *ownerWorld,worldAssembly,variant,resolvedLayout,error, + !hasCoreLiminalField); if(!layoutResolved) {std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;} if(useExportedCorePlan&&!options.NativeOwnerFloatingIslandsRecipe &&!StandaloneWorldAssemblyPrototype::ValidateExportedCorePlanMatchesOwner( *ownerWorld,worldAssembly,resolvedLayout,error)) {std::fprintf(stderr,"Unreal-resolved Core plan/owner slot validation failed: %s\n",error.c_str());return 2;} - const VFJson::Value& coreLiminalConfig=ownerJsonRoot.Get("core_liminal_field"); - const bool hasCoreLiminalField=!std::holds_alternative( - coreLiminalConfig.Data); if(hasCoreLiminalField) { const VFJson::Value& versionValue=coreLiminalConfig.Get("version"); @@ -1871,7 +1872,7 @@ int main(int argc,char** argv) const auto* policy=std::get_if(&coreLiminalConfig.Get("variant_policy").Data); if(!coreLiminalConfig.IsObject() ||!versionValue.IsNumber() - ||versionValue.Number()!=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1 + ||versionValue.Number()!=VoxelForgeCore::CoreLiminalFieldRecipeVersionV2 ||!strateValue.IsNumber() ||std::trunc(strateValue.Number())!=strateValue.Number() ||strateValue.Number()<0.0 @@ -1896,7 +1897,34 @@ int main(int argc,char** argv) liminalPlan.strateIndex=static_cast(strateIndex); liminalPlan.topChunkZ=slot->TopChunkZ; liminalPlan.bottomChunkZ=slot->BottomChunkZ; - if(!VoxelForgeCore::PlanCoreLiminalFieldV1(worldAssembly.recipe, + resolvedLayout.passages.clear(); + if(!VoxelForgeCore::PrepareCoreLiminalLandingPadsV2(worldAssembly.recipe, + liminalPlan,resolvedLayout,error)) + {std::fprintf(stderr,"Core.Liminal.Field landing-pad preparation failed: %s\n",error.c_str());return 2;} + const auto passageConfigs= + StandaloneWorldAssemblyPrototype::BuildResolvedLayoutPassageConfigs(*ownerWorld); + auto uncertifiedControl=resolvedLayout; + const auto controlStratum=std::find_if(uncertifiedControl.strates.begin(), + uncertifiedControl.strates.end(),[&](const auto& value) + {return value.strateIndex==strateIndex;}); + bool landingPadNegativeControlRejected=false; + if(controlStratum!=uncertifiedControl.strates.end() + &&!controlStratum->landingPads.empty()) + { + controlStratum->landingPads.front().certifiedWalkableWithSupport=false; + std::string controlError; + landingPadNegativeControlRejected= + !VoxelForgeCore::PlanResolvedLayoutPassagesV1(uncertifiedControl, + ownerWorld->Seed,passageConfigs,controlError); + } + std::printf("[LandingPadNegativeControl] uncertified_rejected=%s status=%s\n", + landingPadNegativeControlRejected?"true":"false", + landingPadNegativeControlRejected?"PASS":"FAIL"); + if(!landingPadNegativeControlRejected)return 2; + if(!VoxelForgeCore::PlanResolvedLayoutPassagesV1(resolvedLayout, + ownerWorld->Seed,passageConfigs,error)) + {std::fprintf(stderr,"Core.Liminal.Field pad-bound passage planning failed: %s\n",error.c_str());return 2;} + if(!VoxelForgeCore::PlanCoreLiminalFieldV2(worldAssembly.recipe, liminalPlan,resolvedLayout,error)) {std::fprintf(stderr,"Core.Liminal.Field planning failed: %s\n",error.c_str());return 2;} worldAssembly.plan.strates.push_back(std::move(liminalPlan)); @@ -1910,17 +1938,19 @@ int main(int argc,char** argv) {std::fprintf(stderr,"Core.Liminal.Field manifest failed canonical JSON round-trip: %s\n",error.c_str());return 2;} const auto plan=std::find_if(worldAssembly.plan.strates.begin(), worldAssembly.plan.strates.end(),[&](const auto& value) - {return value.strateIndex==strateIndex&&value.liminalField.version!=0;}); + {return value.strateIndex==strateIndex + &&value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV2;}); if(plan==worldAssembly.plan.strates.end()) {std::fprintf(stderr,"Core.Liminal.Field finalized plan is missing\n");return 2;} auto& resolvedLiminal=*std::find_if(resolvedLayout.strates.begin(), resolvedLayout.strates.end(),[&](const auto& value) {return value.strateIndex==strateIndex;}); resolvedLiminal.recipeId=std::string(VoxelForgeCore::CoreLiminalFieldRecipeIdV1); - resolvedLiminal.recipeVersion=VoxelForgeCore::CoreLiminalFieldRecipeVersionV1; + resolvedLiminal.recipeVersion=VoxelForgeCore::CoreLiminalFieldRecipeVersionV2; resolvedLiminal.anchors.erase(std::remove_if(resolvedLiminal.anchors.begin(), resolvedLiminal.anchors.end(),[](const auto& anchor) - {return anchor.kind=="heightfield_profile";}),resolvedLiminal.anchors.end()); + {return anchor.kind=="heightfield_profile"||anchor.kind=="route_point";}), + resolvedLiminal.anchors.end()); VoxelForgeCore::ResolvedLayoutAnchorV2 profileAnchor; profileAnchor.kind="heightfield_profile"; profileAnchor.stableId="heightfield-profile/liminal/" diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 59b949c..eb5737d 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -3074,7 +3074,8 @@ namespace StandaloneStreamBenchmark const auto plan=Assembly?std::find_if(Assembly->plan.strates.begin(), Assembly->plan.strates.end(),[&](const auto& value) {return value.strateIndex==coreLiminalStratum->strateIndex - &&value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV1;}) + &&(value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV1 + ||value.liminalField.version==VoxelForgeCore::CoreLiminalFieldRecipeVersionV2);}) :std::vector::const_iterator{}; if(!Assembly||plan==Assembly->plan.strates.end())fixedMouthBinding=false; else @@ -4124,8 +4125,9 @@ namespace StandaloneStreamBenchmark } return best; }; - const auto appendDetrendedProfile=[&](const std::vector& values, - double startDistance,std::vector>& output) + const auto appendDetrendedProfile=[&]( + const std::vector>& values, + std::vector>& output) { if(values.size()<64)return; // Remove a smooth mouth taper across each 32 m window while @@ -4134,11 +4136,12 @@ namespace StandaloneStreamBenchmark // 0.5–8 m periods that this audit is meant to detect. constexpr std::size_t Degree=3; std::array,Degree+1> normal{}; - const double meanIndex=0.5*static_cast(values.size()-1); - const double halfSpan=std::max(1.0,meanIndex); - for(std::size_t i=0;i(i)-meanIndex)/halfSpan; + const double x=(value[0]-meanDistance)/halfSpan; std::array powers{}; powers[0]=1.0; for(std::size_t power=1;power(i)-meanIndex)/halfSpan; + const double x=(value[0]-meanDistance)/halfSpan; double trend=normal[Degree][Degree+1]; for(std::size_t coefficient=Degree;coefficient-->0;) trend=trend*x+normal[coefficient][Degree+1]; - output.push_back({startDistance+static_cast(i)*SampleSpacingMetres, - values[i]-trend}); + output.push_back({value[0],value[1]-trend}); } }; const auto appendDetrendedPairs=[]( @@ -4199,7 +4201,7 @@ namespace StandaloneStreamBenchmark output.push_back({value[0],value[1]-meanY -slope*(value[0]-meanX)}); }; - std::vector beadControl; + std::vector> beadControl; beadControl.reserve(static_cast(WindowLengthMetres/SampleSpacingMetres)+1); constexpr double BeadSpacingMetres=1.5; constexpr double BeadSphereRadiusMetres=2.0; @@ -4207,14 +4209,49 @@ namespace StandaloneStreamBenchmark { const double x=static_cast(i)*SampleSpacingMetres; const double nearest=std::abs(std::remainder(x,BeadSpacingMetres)); - beadControl.push_back(std::sqrt(std::max(0.0, - BeadSphereRadiusMetres*BeadSphereRadiusMetres-nearest*nearest))); + beadControl.push_back({x,std::sqrt(std::max(0.0, + BeadSphereRadiusMetres*BeadSphereRadiusMetres-nearest*nearest))}); } std::vector> beadSamples; - appendDetrendedProfile(beadControl,0.0,beadSamples); + appendDetrendedProfile(beadControl,beadSamples); double ignoredPeriod=0.0; audit.controlAmplitudeMetres=sinusoidAmplitude(beadSamples,ignoredPeriod); audit.controlDetected=audit.controlAmplitudeMetres>=RippleAmplitudeLimitMetres; + std::vector> maskedSineControl,maskedSmoothControl; + constexpr double SamplingControlGapStartMetres=10.0; + constexpr double SamplingControlGapEndMetres=15.0; + for(std::size_t sample=0; + sample<=static_cast(WindowLengthMetres/SampleSpacingMetres); + ++sample) + { + const double distance=static_cast(sample)*SampleSpacingMetres; + if(distance>=SamplingControlGapStartMetres + &&distance> maskedSineResiduals,maskedSmoothResiduals; + appendDetrendedProfile(maskedSineControl,maskedSineResiduals); + appendDetrendedProfile(maskedSmoothControl,maskedSmoothResiduals); + double maskedSinePeriod=0.0,maskedSmoothPeriod=0.0; + const double maskedSineAmplitude=sinusoidAmplitude( + maskedSineResiduals,maskedSinePeriod); + const double maskedSmoothAmplitude=sinusoidAmplitude( + maskedSmoothResiduals,maskedSmoothPeriod); + const bool maskedSamplingControlPassed= + maskedSineAmplitude>=RippleAmplitudeLimitMetres + &&maskedSmoothAmplitude((SamplingControlGapEndMetres + -SamplingControlGapStartMetres)/SampleSpacingMetres), + maskedSineAmplitude,maskedSineAmplitude>=RippleAmplitudeLimitMetres + ?"true":"false",maskedSmoothAmplitude, + maskedSmoothAmplitude=FloorRippleAmplitudeLimitMetres; @@ -4268,7 +4305,7 @@ namespace StandaloneStreamBenchmark for(const double fraction:windowStarts) { const double start=(total-WindowLengthMetres)*fraction; - std::vector radii; + std::vector> radii; radii.reserve(static_cast(WindowLengthMetres/SampleSpacingMetres)+1); std::size_t wallProbeNonfinite=0,wallProbeOutOfBand=0; double wallProbeMinimum=std::numeric_limits::infinity(); @@ -4368,7 +4405,7 @@ namespace StandaloneStreamBenchmark // The probes sit 0.18 m inside the authored radius. Add that // radius back to the signed wall distance so radius-carried ribs // remain visible; the cubic detrend removes the smooth mouth flare. - radii.push_back(sampleRadius+0.5*(left+right)); + radii.push_back({distance,sampleRadius+0.5*(left+right)}); ++audit.samples; } if(radii.size()(WindowLengthMetres/ @@ -4389,7 +4426,7 @@ namespace StandaloneStreamBenchmark audit.wallWindowExpectedSamples+=static_cast( WindowLengthMetres/SampleSpacingMetres)+1; std::vector> windowSamples; - appendDetrendedProfile(radii,start,windowSamples); + appendDetrendedProfile(radii,windowSamples); double localPeriod=0.0; const double localAmplitude=sinusoidAmplitude(windowSamples,localPeriod); std::printf("[PassageWallRippleWindow] id=%s start_m=%.3f " @@ -4459,6 +4496,7 @@ namespace StandaloneStreamBenchmark audit.passed=audit.controlDetected&&audit.wallQualifiedWindows>0 &&wallWindowCoverage>=0.75 &&audit.localPeakAmplitudeMetres=0.75 &&audit.floorAmplitudeMetresroute.size()<2) {error="Core.Liminal.Field has no planned route for stamp resolution";return false;} const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), @@ -860,7 +861,7 @@ namespace StandaloneWorldAssemblyPrototype const std::int64_t profileReliefUm=plan->liminalField.variant ==WorldAssemblyLiminalVariantV1::repeatingHills ?2*definition.hillAmplitudeMicrometres:0; - const std::int64_t supportBaseUm=floorUm-profileReliefUm+100000; + const std::int64_t supportBaseUm=strate->content.bottomMicrometres+100000; std::vector> controls; controls.reserve(plan->route.size()); @@ -1712,9 +1713,46 @@ namespace StandaloneWorldAssemblyPrototype return true; } + inline std::vector + BuildResolvedLayoutPassageConfigs(const FStandaloneOwnerWorld& owner) + { + std::vector passageConfigs; + if(!owner.Manager)return passageConfigs; + for(const FStrateSlot& slot:owner.Manager->GetLayout()) + { + if(!slot.Definition)continue; + const auto& authored=slot.Definition->PassageConfig; + const auto ownerVoxelsToCoreQ=[&](double value) + {return static_cast(std::llround(value*owner.OwnerVoxelSizeMicrons + *VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel/owner.CoreVoxelSizeMicrons));}; + VoxelForgeCore::ResolvedLayoutPassageConfigV1 config; + config.upperStrateIndex=slot.StrateIndex; + config.connections=authored.Connections; + config.style=static_cast(authored.Style); + config.mouthRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MouthRadius), + ownerVoxelsToCoreQ(36.0)); + config.midRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MidRadius), + ownerVoxelsToCoreQ(24.0)); + config.reachMinimumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMin); + config.reachMaximumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMax); + config.distanceMinimumSubvoxels=ownerVoxelsToCoreQ(authored.DistanceMin); + config.distanceMaximumSubvoxels=ownerVoxelsToCoreQ(authored.DistanceMax); + config.wanderSubvoxels=ownerVoxelsToCoreQ(authored.Wander); + config.segments=static_cast(std::clamp(authored.Segments,1,48)); + config.verticalWobbleSubvoxels=ownerVoxelsToCoreQ(authored.VerticalWobble); + config.spiralRadiusSubvoxels=ownerVoxelsToCoreQ(authored.SpiralRadius); + config.spiralTurnsQ16=static_cast(std::llround(authored.SpiralTurns*65536.0)); + config.cascadeSteps=static_cast(std::clamp(authored.CascadeSteps,1,16)); + config.cascadeLedgeSubvoxels=ownerVoxelsToCoreQ(authored.CascadeLedge); + passageConfigs.push_back(config); + } + return passageConfigs; + } + inline bool BuildResolvedLayoutSnapshot(const FStandaloneOwnerWorld& owner, const VoxelForgeCore::WorldAssemblyManifest& assembly,std::string_view recipeVariant, - VoxelForgeCore::ResolvedLayoutSnapshotV3& out,std::string& error) + VoxelForgeCore::ResolvedLayoutSnapshotV3& out,std::string& error, + bool planPassages=true) { using namespace VoxelForgeCore; if(!owner.Manager){error="resolved layout builder requires the initialized director";return false;} @@ -1938,35 +1976,11 @@ namespace StandaloneWorldAssemblyPrototype } out.strates.push_back(std::move(s)); } - std::vector passageConfigs; - for(const FStrateSlot& slot:owner.Manager->GetLayout()) + if(planPassages) { - if(!slot.Definition)continue; - const auto& authored=slot.Definition->PassageConfig; - const auto ownerVoxelsToCoreQ=[&](double value) - {return static_cast(std::llround(value*owner.OwnerVoxelSizeMicrons - *WorldAssemblySubvoxelsPerVoxel/owner.CoreVoxelSizeMicrons));}; - ResolvedLayoutPassageConfigV1 config;config.upperStrateIndex=slot.StrateIndex; - config.connections=authored.Connections; - config.style=static_cast(authored.Style); - config.mouthRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MouthRadius), - ownerVoxelsToCoreQ(36.0)); - config.midRadiusSubvoxels=std::max(ownerVoxelsToCoreQ(authored.MidRadius), - ownerVoxelsToCoreQ(24.0)); - config.reachMinimumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMin); - config.reachMaximumSubvoxels=ownerVoxelsToCoreQ(authored.ReachMax); - config.distanceMinimumSubvoxels=ownerVoxelsToCoreQ(authored.DistanceMin); - config.distanceMaximumSubvoxels=ownerVoxelsToCoreQ(authored.DistanceMax); - config.wanderSubvoxels=ownerVoxelsToCoreQ(authored.Wander); - config.segments=static_cast(std::clamp(authored.Segments,1,48)); - config.verticalWobbleSubvoxels=ownerVoxelsToCoreQ(authored.VerticalWobble); - config.spiralRadiusSubvoxels=ownerVoxelsToCoreQ(authored.SpiralRadius); - config.spiralTurnsQ16=static_cast(std::llround(authored.SpiralTurns*65536.0)); - config.cascadeSteps=static_cast(std::clamp(authored.CascadeSteps,1,16)); - config.cascadeLedgeSubvoxels=ownerVoxelsToCoreQ(authored.CascadeLedge); - passageConfigs.push_back(config); + const auto passageConfigs=BuildResolvedLayoutPassageConfigs(owner); + if(!PlanResolvedLayoutPassagesV1(out,owner.Seed,passageConfigs,error))return false; } - if(!PlanResolvedLayoutPassagesV1(out,owner.Seed,passageConfigs,error))return false; return out.finalize(error); } From 4290672d1cc754eb2ffc2ff040a90f279f1c27ce Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sun, 1 Nov 2026 13:02:31 +0100 Subject: [PATCH 6/7] audit: passage interior must be air for every capsule sample (L146) Root cause of liminal seed 5 (measured): passage carve makes the bore air (+3.52), then the liminal route fill stamp re-solidifies it (-0.16) where the deck crosses the tube. Three fixes cleared the bore but left 28-29 road stations unsupported; none kept. New gate: zero solid samples inside any passage interior, with no-passage negative controls. Owner v227 hashes and fast tier pass. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../WorldAssemblerM3/Linux146/REPORT.md | 46 ++++ .../Linux146/RunL146AuditMatrix.py | 197 ++++++++++++++++++ Standalone/Source/StreamBenchmarkPipeline.h | 63 +++++- 3 files changed, 300 insertions(+), 6 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux146/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux146/RunL146AuditMatrix.py diff --git a/Standalone/Research/WorldAssemblerM3/Linux146/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux146/REPORT.md new file mode 100644 index 0000000..78c44eb --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux146/REPORT.md @@ -0,0 +1,46 @@ +# L146 report + +**Result:** No production fix is retained. The cause is measured: the liminal route fill pass runs after the passage carve and makes part of the bore solid again. The new passage-interior capsule audit catches the seed-5 defect. After three fixes cleared the bore but failed the liminal road support gate, work stopped as required by `AGENTS.md`. + +## Root cause + +Measured at `(-16.087, 2.915, -722.743) m`, seed 5, Clang W1, composed L145 fixture: + +- Before passage composition, density was `-3.62890625`. +- The passage SDF reported `union_distance_m=-0.879889786`; carving changed density to `+3.51955914` (air). +- The subsequent liminal route stamp changed it to `-0.16169475` (solid). + +The diagnostic directly identifies the post-carve route-fill pass as the cause. The resolved route/deck geometry indicates the fill overlaps the bore there; that specific deck overlap is inferred from the layout. The half-pipe/open-air path, carve reach, and carve blend are not the cause at this sample: the passage carver ran and produced positive air density before the route stamp. + +Trace: `Saved/Linux/l146/logs/diagnostic-seed05-clang-w1.log`. + +## Fix attempts + +All were temporary and have been reverted; production composition and evaluator version remain at L145 / v227. + +1. Move fill stamps before passage carving: passage probes cleared, but the liminal road had 29 unsupported stations. +2. Suppress route fills inside the passage interior: same result, 29 unsupported stations. +3. Reroute the southern deck around the crossing: passage probes cleared, but 28 road stations remained unsupported. + +The three seed-5 runs are `probe-seed05-clang-w1.log`, `probe-masked-seed05-clang-w1.log`, and `route-seed05-clang-w1.log` under `Saved/Linux/l146/logs/`. + +The shared premise that changing stamp order or locally moving the deck could preserve both bore air and road support failed twice. The route adjustment also failed the support gate, so no fourth fix was attempted. + +## Audit and checks + +`StreamBenchmarkPipeline.h` now classifies each tested player-capsule sample against its passage interior and requires zero solid interior samples. A no-passage negative control uses the same interior classification and must detect solid samples for every passage. + +On the final source, the seed-5 audit measured 50,904 interior capsule samples and 289 solid samples for passage 1-2. Both negative controls detected solid interior samples (165,769 and 49,612). The shell summary passed with zero floor or wall violations, and the liminal road audit passed. The composed passage audit exited 10 as expected because the new interior-air gate detected the defect. + +The final-source evidence is `Saved/Linux/l146/logs/audit-seed05-clang-w1.log`. + +- Clang W1 final-source build: passed; log `Saved/Linux/l146/fast/logs/build-fast-clang-final.log`. +- Fast verification tier: passed in 362.5 s; summary `Saved/Linux/l146/fast/fast-summary.json`. +- Owner canonical v227 hash rows: passed for both pinned owner worlds; W1 and W12 signatures matched. +- `git diff --check`: passed. +- The 32-run pad matrix and the liminal Clang/GCC W1/W8/W12 matrix were not run because the three-failed-fix stop condition was reached. The 16-seed cave-planner sweep is not on this branch. +- No Unreal `Source/` files changed. + +## Remaining risk + +The seed-5 passage interior remains partly solid in production. A new design must define how route floor support and passage air share their overlap before changing composition again. No passage-composition change or owner hash change is retained. diff --git a/Standalone/Research/WorldAssemblerM3/Linux146/RunL146AuditMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux146/RunL146AuditMatrix.py new file mode 100644 index 0000000..018f0d9 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux146/RunL146AuditMatrix.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +"""Run L146's composed liminal audits and the worker/compiler identity matrix.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path +import re +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l146" +FIXTURE = OUT / "fixtures/core-liminal-field-3-strata.json" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +AUDIT_FLAGS = ("--audit-resolved-layout-passages", "--audit-liminal-road-walk", + "--audit-passage-tile-seams") +VARIANTS = ("flatField-monolith", "periodicHills", + "road-over-cloud-floor", "pillar-grid") +PASSAGE_RE = re.compile(r"^\[ResolvedPassageAudit\].*walkability=PASS$", re.M) +SHELL_RE = re.compile(r"^\[PassageShellAudit\].*status=PASS$", re.M) + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import current_stamp, first_stamp + + +def parse_seeds(value: str) -> list[int]: + result: set[int] = set() + for token in value.split(","): + token = token.strip() + if not token: + continue + if "-" in token: + first, last = (int(part) for part in token.split("-", 1)) + if first > last: + raise argparse.ArgumentTypeError(f"reversed seed range: {token}") + result.update(range(first, last + 1)) + else: + result.add(int(token)) + if not result or min(result) < 0: + raise argparse.ArgumentTypeError("seeds must be nonnegative and nonempty") + return sorted(result) + + +def validate_audit(output: str, seed: int, compiler: str, workers: int) -> None: + checks = { + "landing-pad negative control": + "[LandingPadNegativeControl] uncertified_rejected=true status=PASS" in output, + "passage walk audits": len(PASSAGE_RE.findall(output)) == 2, + "passage interior capsule audit": len(re.findall( + r"^\[ResolvedPassageAudit\].*passage_interior_capsule_samples=[1-9]\d* " + r"passage_interior_solid_samples=0 interior_air=PASS .*walkability=PASS$", + output, re.M)) == 2, + "passage interior negative controls": len(re.findall( + r"^\[ResolvedPassageInteriorNegativeControl\].*interior_solid_samples=[1-9]\d* " + r"detected=true status=PASS$", output, re.M)) == 2, + "passage interior audit summary": bool(re.search( + r"^\[PassageInteriorCapsuleAuditSummary\].*status=PASS$", output, re.M)), + "passage shell audits": len(SHELL_RE.findall(output)) == 2, + "passage ripple audits": len(re.findall( + r"^\[PassageRippleAudit\].*status=PASS$", output, re.M)) == 2, + "masked ripple sampling controls": len(re.findall( + r"^\[PassageRippleSamplingControl\].*status=PASS$", output, re.M)) == 2, + "passage shell summary": bool(re.search( + r"^\[PassageShellAuditSummary\].*status=PASS$", output, re.M)), + "liminal walk audit": bool(re.search( + r"^\[LiminalLayerWalkAudit\].*status=PASS$", output, re.M)), + "liminal negative control": + "[LiminalLayerNegativeControl] altered_departure_rejected=true status=PASS" in output, + "passage summary": bool(re.search( + r"^\[ResolvedPassageAuditSummary\].*status=PASS$", output, re.M)), + "seam audit": bool(re.search( + r"^\[PassageTileSeamAudit\].*status=PASS$", output, re.M)), + } + failed = [name for name, passed in checks.items() if not passed] + if failed: + raise RuntimeError( + f"seed={seed} compiler={compiler} workers={workers} failed checks: " + + ", ".join(failed)) + + +def run_audit(seed: int, compiler: str, workers: int, *, audit: bool = True) -> dict: + binary = OUT / "fast/bin" / f"VoxelForgeCoreHeadless-fast-{compiler}" + if not binary.is_file(): + raise RuntimeError(f"missing binary: {binary}") + expected_stamp = current_stamp() + probe = subprocess.run([str(binary), "--print-source-stamp"], cwd=ROOT, + capture_output=True, text=True, timeout=15, check=False) + if probe.returncode != 0 or first_stamp(probe.stdout) != expected_stamp: + raise RuntimeError(f"stale executable: {binary}") + + tag = f"seed{seed:02d}-{compiler}-w{workers}" + log = OUT / "logs" / f"audit-{tag}.log" + manifest = OUT / "manifests" / f"audit-{tag}.json" + layout = OUT / "layouts" / f"audit-{tag}.json" + manifest.parent.mkdir(parents=True, exist_ok=True) + layout.parent.mkdir(parents=True, exist_ok=True) + command = [str(binary), str(FIXTURE), f"--workers={workers}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", "--camera=0,0,-540,0,0", f"--seed={seed}", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if audit: + command.extend(AUDIT_FLAGS) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(OUT) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") + + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run([*LIMIT, "timeout", "1740s", *command], + cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, + timeout=1745, check=False) + output = log.read_text(encoding="utf-8", errors="replace") + if result.returncode != 0: + raise RuntimeError(f"{tag} exit={result.returncode}; see {log}") + if first_stamp(output) != expected_stamp or current_stamp() != expected_stamp: + raise RuntimeError(f"{tag} source stamp changed during run; see {log}") + if audit: + validate_audit(output, seed, compiler, workers) + if not manifest.is_file() or not layout.is_file(): + raise RuntimeError(f"{tag} omitted canonical manifest or layout") + manifest_value = json.loads(manifest.read_text(encoding="utf-8")) + layout_value = json.loads(layout.read_text(encoding="utf-8")) + identity = { + "seed": seed, + "variant": VARIANTS[seed % len(VARIANTS)], + "compiler": compiler, + "workers": workers, + "manifest_hash": manifest_value["content_hash"], + "resolved_layout_identity": layout_value["stable_identity"], + "log": str(log.relative_to(ROOT)), + "elapsed_s": round(time.monotonic() - started, 3), + "audited": audit, + } + print(f"[L146AuditRun] seed={seed} variant={identity['variant']} compiler={compiler} " + f"workers={workers} manifest={identity['manifest_hash']} " + f"layout={identity['resolved_layout_identity']} " + f"elapsed_s={identity['elapsed_s']:.3f} status=PASS", flush=True) + return identity + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--seeds", default="0-31", type=parse_seeds, + help="audit seeds, e.g. 0-31 or 0,1,2,3") + parser.add_argument("--determinism", action="store_true", + help="also compare seed 0 on Clang/GCC at W1/W8/W12") + parser.add_argument("--only-determinism", action="store_true", + help="run only the Clang/GCC seed-0 W1/W8/W12 identity matrix") + args = parser.parse_args() + if not FIXTURE.is_file(): + raise SystemExit(f"missing fixture: {FIXTURE}; build the L145 liminal fixture first") + + records = [] + if not args.only_determinism: + for seed in args.seeds: + records.append(run_audit(seed, "clang", 1)) + if args.determinism or args.only_determinism: + matrix = [run_audit(0, compiler, workers) + for compiler in ("clang", "gcc") for workers in (1, 8, 12)] + identities = {(row["manifest_hash"], row["resolved_layout_identity"]) + for row in matrix} + if len(identities) != 1: + raise RuntimeError(f"Clang/GCC W1/W8/W12 identity mismatch: {matrix}") + records.extend(matrix) + + summary = { + "audit_seeds": args.seeds if not args.only_determinism else [], + "variant_counts": { + name: sum(1 for seed in args.seeds if seed % len(VARIANTS) == index) + for index, name in enumerate(VARIANTS) + } if not args.only_determinism else {}, + "records": records, + "determinism_pass": bool(args.determinism or args.only_determinism), + "status": "PASS", + } + summary_path = OUT / "l146-audit-matrix-summary.json" + summary_path.parent.mkdir(parents=True, exist_ok=True) + summary_path.write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8") + print(f"[L146AuditMatrix] records={len(records)} summary={summary_path} status=PASS", + flush=True) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L146AuditMatrix] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index eb5737d..166b5d4 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -2828,6 +2828,7 @@ namespace StandaloneStreamBenchmark struct FWalkAudit { std::uint64_t segments=0,centers=0,capsuleSamples=0,blocked=0; + std::uint64_t passageInteriorCapsuleSamples=0,passageInteriorSolidSamples=0; std::uint64_t supportSamples=0,unsupported=0,gradeFailures=0; std::uint64_t supportOverlapSkips=0; std::array,8> firstBlocked{}; @@ -2841,7 +2842,8 @@ namespace StandaloneStreamBenchmark double supportStartMetres,double supportStepMetres, double supportMaximumMetres,std::uint32_t minimumSupportProbes, double supportProbeRadiusMetres, - const std::function& supportExemption={}) + const std::function& supportExemption={}, + const std::function& passageInteriorPredicate={}) { FWalkAudit audit; if(path.size()<2)return audit; @@ -2854,10 +2856,14 @@ namespace StandaloneStreamBenchmark const auto solidAt=[&](double xMetres,double yMetres,double zMetres) { ++audit.capsuleSamples; + const bool inPassageInterior=passageInteriorPredicate + &&passageInteriorPredicate(xMetres,yMetres,zMetres); + if(inPassageInterior)++audit.passageInteriorCapsuleSamples; const VoxelForgeCore::Vec3d position{xMetres/coreMetres,yMetres/coreMetres,zMetres/coreMetres}; const float density=Field.densityAt(position); if(density<0.0f) { + if(inPassageInterior)++audit.passageInteriorSolidSamples; if(audit.firstBlockedCount::max(), - std::size_t ignoredSegment=std::numeric_limits::max()) + std::size_t ignoredSegment=std::numeric_limits::max(), + std::size_t selectedPassage=std::numeric_limits::max()) { constexpr double CornerBlendMetres=0.50; constexpr double WallReliefMetres=0.21; @@ -3558,6 +3565,8 @@ namespace StandaloneStreamBenchmark for(std::size_t passageIndex=0; passageIndexpassages.size();++passageIndex) { + if(selectedPassage!=std::numeric_limits::max() + &&passageIndex!=selectedPassage)continue; const auto& passage=ResolvedLayout->passages[passageIndex]; if(passage.controlPoints.size()<2)continue; const auto& route=allPassageSmoothRoutes[passageIndex]; @@ -4857,6 +4866,8 @@ namespace StandaloneStreamBenchmark &&zUmcontent.topMicrometres; }; std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0; + std::uint64_t passageInteriorCapsuleSamples=0,passageInteriorSolidSamples=0; + std::uint64_t passageInteriorControls=0; std::uint64_t mouthProfilePasses=0,ripplePasses=0,rippleControlsDetected=0; std::uint64_t floorRippleControlsDetected=0,floorStepRippleControlsDetected=0; std::uint64_t shellAudits=0,shellFloorSamples=0,shellFloorViolations=0; @@ -4880,8 +4891,18 @@ namespace StandaloneStreamBenchmark const std::function passageSupportExemption= [&](double x,double y,double z) {return passageInteriorWinsAt(x,y,z-0.25);}; + const std::function passageInteriorPredicate= + [&](double x,double y,double z) + {return passageInteriorWinsAt(x,y,z, + std::numeric_limits::max(), + std::numeric_limits::max(),passageIndex);}; const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.375,0.125, - 1.125,3,0.45,passageSupportExemption); + 1.125,3,0.45,passageSupportExemption,passageInteriorPredicate); + const bool passageInteriorAirPassed= + passageAudit.passageInteriorCapsuleSamples>0 + &&passageAudit.passageInteriorSolidSamples==0; + passageInteriorCapsuleSamples+=passageAudit.passageInteriorCapsuleSamples; + passageInteriorSolidSamples+=passageAudit.passageInteriorSolidSamples; const FPassageNaturalnessAudit naturalAudit= auditPassageNaturalness(Shape,passageIndex); const auto lowerProfileStratum=std::find_if(ResolvedLayout->strates.begin(), @@ -4940,13 +4961,17 @@ namespace StandaloneStreamBenchmark rippleControlsDetected+=rippleAudit.controlDetected; floorRippleControlsDetected+=rippleAudit.floorControlDetected; floorStepRippleControlsDetected+=rippleAudit.floorStepControlDetected; - passagePasses+=passageAudit.passed&&mouthsInRadius&&mouthsInContent + passagePasses+=passageAudit.passed&&passageInteriorAirPassed + &&mouthsInRadius&&mouthsInContent &&naturalAudit.passed&&mouthProfileAudit.passed&&rippleAudit.passed; - std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu support_samples=%llu support_overlap_skips=%llu unsupported=%llu grade_failures=%llu mouth_content=%d/2 mouth_radius=%d/2 walkability=%s\n", + std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu passage_interior_capsule_samples=%llu passage_interior_solid_samples=%llu interior_air=%s support_samples=%llu support_overlap_skips=%llu unsupported=%llu grade_failures=%llu mouth_content=%d/2 mouth_radius=%d/2 walkability=%s\n", passage.stableId.c_str(),passage.upperStrateIndex,passage.lowerStrateIndex, passage.controlPoints.size(),static_cast(passageAudit.centers), static_cast(passageAudit.capsuleSamples), static_cast(passageAudit.blocked), + static_cast(passageAudit.passageInteriorCapsuleSamples), + static_cast(passageAudit.passageInteriorSolidSamples), + passageInteriorAirPassed?"PASS":"FAIL", static_cast(passageAudit.supportSamples), static_cast(passageAudit.supportOverlapSkips), static_cast(passageAudit.unsupported), @@ -5239,13 +5264,38 @@ namespace StandaloneStreamBenchmark path.push_back({point.x/coreMetres,point.y/coreMetres, playerZ/coreMetres}); } + const std::function passageInteriorPredicate= + [&](double x,double y,double z) + {return passageInteriorWinsAt(x,y,z, + std::numeric_limits::max(), + std::numeric_limits::max(),passageIndex);}; const FWalkAudit blockedAudit=auditPlayerPath(blockedWorld,path, - 0.125,0.125,0.25,3,0.45); + 0.125,0.125,0.25,3,0.45,{},passageInteriorPredicate); blockedControls+=blockedAudit.blocked>0&&!blockedAudit.passed; + const bool passageInteriorControlDetected= + blockedAudit.passageInteriorCapsuleSamples>0 + &&blockedAudit.passageInteriorSolidSamples>0; + passageInteriorControls+=passageInteriorControlDetected; std::printf("[ResolvedPassageBlockedControl] id=%s blocked_capsule_samples=%llu detected=%s\n", passage.stableId.c_str(),static_cast(blockedAudit.blocked), blockedAudit.blocked>0&&!blockedAudit.passed?"true":"false"); + std::printf("[ResolvedPassageInteriorNegativeControl] id=%s passage_interior_capsule_samples=%llu interior_solid_samples=%llu detected=%s status=%s\n", + passage.stableId.c_str(), + static_cast(blockedAudit.passageInteriorCapsuleSamples), + static_cast(blockedAudit.passageInteriorSolidSamples), + passageInteriorControlDetected?"true":"false", + passageInteriorControlDetected?"PASS":"FAIL"); } + const bool passageInteriorAuditPassed=passageCount>0 + &&passageInteriorCapsuleSamples>0&&passageInteriorSolidSamples==0 + &&passageInteriorControls==passageCount; + std::printf("[PassageInteriorCapsuleAuditSummary] interfaces=%llu capsule_samples=%llu solid_samples=%llu negative_controls=%llu/%llu status=%s\n", + static_cast(passageCount), + static_cast(passageInteriorCapsuleSamples), + static_cast(passageInteriorSolidSamples), + static_cast(passageInteriorControls), + static_cast(passageCount), + passageInteriorAuditPassed?"PASS":"FAIL"); const bool shellAuditPassed=shellAudits==passageCount &&shellFloorViolations==0&&shellWallViolations==0 &&shellInteriorViolations==0&&shellOpenAirSamples>0; @@ -5285,6 +5335,7 @@ namespace StandaloneStreamBenchmark floorStepRippleControlsDetected==passageCount?"DETECTED":"MISSED", ripplePasses==passageCount?"PASS":"FAIL"); const bool auditPassed=passageCount>0&&passagePasses==passageCount + &&passageInteriorAuditPassed &&naturalPasses==passageCount&&l23SmoothWallDetected &&mouthProfilePasses==passageCount&&l23TerraceControlDetected &&ripplePasses==passageCount From ff52c9b57639877ff20eb35b5c0249f2dc5ef724 Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Mon, 2 Nov 2026 10:11:37 +0100 Subject: [PATCH 7/7] proto: liminal looks - pool rooms, backrooms grid, staircase to nowhere, terraced hills (L161) Stamp vocabulary v7 (opt-in fillBox, carveBox, fillSteps; carveArch reused); flat-field liminal stamp fixtures; capsule walk audit with doorway-width gate (1.2 m control fails as expected). Clang/GCC W1/W8/W12 identical; owner canonical hashes unchanged; fast tier 273/273. Terraced wide view not yet legible. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1 --- .../include/VoxelForgeCore/VoxelForgeCore.h | 10 +- Standalone/Core/src/ResolvedLayoutInternal.h | 33 +- Standalone/Core/src/ShapeWorldInternal.h | 27 +- .../Linux161/BuildL161Fixtures.py | 226 +++++++++++++ .../WorldAssemblerM3/Linux161/CaptureL161.py | 320 ++++++++++++++++++ .../WorldAssemblerM3/Linux161/REPORT.md | 31 ++ .../Linux161/captures/backrooms-grid-eye.jpg | Bin 0 -> 26205 bytes .../Linux161/captures/backrooms-grid-wide.jpg | Bin 0 -> 25827 bytes .../Linux161/captures/pool-rooms-eye.jpg | Bin 0 -> 37559 bytes .../Linux161/captures/pool-rooms-wide.jpg | Bin 0 -> 38988 bytes .../captures/staircase-to-nowhere-eye.jpg | Bin 0 -> 49258 bytes .../captures/staircase-to-nowhere-wide.jpg | Bin 0 -> 50535 bytes .../Linux161/captures/terraced-hills-eye.jpg | Bin 0 -> 42669 bytes .../Linux161/captures/terraced-hills-wide.jpg | Bin 0 -> 58446 bytes Standalone/Source/StreamBenchmarkHeadless.cpp | 37 +- Standalone/Source/StreamBenchmarkPipeline.h | 86 ++++- Standalone/Source/WorldAssemblyPrototype.h | 103 ++++++ 17 files changed, 861 insertions(+), 12 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/BuildL161Fixtures.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/CaptureL161.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/backrooms-grid-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/backrooms-grid-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/staircase-to-nowhere-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/staircase-to-nowhere-wide.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/terraced-hills-eye.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux161/captures/terraced-hills-wide.jpg diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index bb96727..422cdf2 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -968,6 +968,7 @@ namespace VoxelForgeCore inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV4 = 4; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV5 = 5; inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV6 = 6; + inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV7 = 7; inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1; inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1; enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict }; @@ -982,7 +983,10 @@ namespace VoxelForgeCore fillDais = 4, fillMonolith = 5, fillPlatform = 6, - fillSweptDeckSegment = 7 + fillSweptDeckSegment = 7, + fillBox = 8, + carveBox = 9, + fillSteps = 10 }; struct ResolvedLayoutStampRequestV1 @@ -1005,6 +1009,9 @@ namespace VoxelForgeCore std::int64_t irregularityWavelengthMicrometres = 0; std::int64_t roundingRadiusMicrometres = 0; std::int64_t minimumSpacingMicrometres = 0; + // Vocabulary 7: fillSteps divides the X and Z extents into this many + // identical treads and risers. Other stamp kinds keep this at zero. + std::uint16_t stepCount = 0; // 0 = free placement, 1 = seated on the authored flat profile floor. std::uint8_t attachmentPolicy = 0; std::int64_t floorMicrometres = 0; @@ -1027,6 +1034,7 @@ namespace VoxelForgeCore std::int64_t irregularityWavelengthMicrometres = 0; std::int64_t roundingRadiusMicrometres = 0; std::int64_t minimumSpacingMicrometres = 0; + std::uint16_t stepCount = 0; std::uint8_t attachmentPolicy = 0; std::int64_t floorMicrometres = 0; std::uint64_t irregularitySeed = 0; diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index 813a129..d4fea3d 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -176,7 +176,7 @@ namespace { const auto value=static_cast(kind); return value>=static_cast(ResolvedSdfStampKindV1::carveEllipsoid) - &&value<=static_cast(ResolvedSdfStampKindV1::fillSweptDeckSegment); + &&value<=static_cast(ResolvedSdfStampKindV1::fillSteps); } bool LayoutStampIsMotif(ResolvedSdfStampKindV1 kind) {return kind==ResolvedSdfStampKindV1::fillMonolith @@ -711,6 +711,8 @@ namespace <<",\"minimum_spacing_um\":"<(stamp.attachmentPolicy) <<",\"floor_um\":"< stampIds; for(const auto& stamp:stamps) { @@ -1292,8 +1295,18 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode, if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3 ||(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment &&stampVocabularyVersion128 + ||stamp.roundingRadiusMicrometres!=0)) + ||(stamp.kind!=ResolvedSdfStampKindV1::fillSteps&&stamp.stepCount!=0)) + add("stamp_steps",stamp.stableId+" has an invalid step count or rounding mode"); bool validExtents=true; for(const auto extent:stamp.halfExtentsMicrometres) validExtents=validExtents&&extent>=500000&&extent<=100000000; @@ -1777,6 +1790,7 @@ std::optional ResolvedLayoutSnapshotV3::FromJson( stamp.floorMicrometres=LayoutInt(v,"floor_um"); stamp.irregularitySeed=static_cast(LayoutInt(v,"irregularity_seed")); stamp.yawQuarterTurns=static_cast(LayoutInt(v,"yaw_quarter_turns")); + stamp.stepCount=static_cast(LayoutInt(v,"step_count")); s.stamps.push_back(std::move(stamp)); } for(const auto& v:root.Get("cavern_rooms").AsArray()) @@ -1901,7 +1915,13 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t }); const bool hasSweptDeck=std::any_of(ordered.begin(),ordered.end(),[](const auto& request) {return request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;}); - candidate.stampVocabularyVersion=hasContinuousSweptDeck + const bool hasVocabulary7Stamp=std::any_of(ordered.begin(),ordered.end(),[](const auto& request) + {return request.kind==ResolvedSdfStampKindV1::fillBox + ||request.kind==ResolvedSdfStampKindV1::carveBox + ||request.kind==ResolvedSdfStampKindV1::fillSteps;}); + candidate.stampVocabularyVersion=hasVocabulary7Stamp + ?ResolvedLayoutStampVocabularyVersionV7 + :hasContinuousSweptDeck ?(hasNonMonotoneSweptDeck?ResolvedLayoutStampVocabularyVersionV6 :ResolvedLayoutStampVocabularyVersionV5) :hasSweptDeck?ResolvedLayoutStampVocabularyVersionV4 @@ -1914,6 +1934,10 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t &&ordered[requestIndex-1].stableId==request.stableId)) {error="stamp requests require non-empty unique stable IDs";return false;} if(!LayoutStampKindValid(request.kind)||request.yawQuarterTurns>3 + ||(request.kind==ResolvedSdfStampKindV1::fillSteps + ?(request.stepCount<2||request.stepCount>128 + ||request.roundingRadiusMicrometres!=0) + :request.stepCount!=0) ||request.placementRadiusMicrometres<0 ||request.placementRadiusMicrometres>100000000 ||(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment @@ -1998,6 +2022,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t stamp.smoothWidthMicrometres=request.smoothWidthMicrometres; stamp.irregularityAmplitudeMicrometres=request.irregularityAmplitudeMicrometres; stamp.irregularityWavelengthMicrometres=request.irregularityWavelengthMicrometres; + stamp.stepCount=request.stepCount; stamp.irregularitySeed=baseSeed;stamp.yawQuarterTurns=request.yawQuarterTurns; std::array offset{}; if(request.placementRadiusMicrometres>0) diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index 29d4977..768fb94 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -7157,6 +7157,23 @@ private: const float top=std::max(StampEllipsoidSdf(x,y,z,halfSize),-z); return SmoothMinDistance(lower,top,round*2.0f); } + static float StampStepsSdf(float x,float y,float z, + const std::array& halfSize,std::uint16_t stepCount) + { + if(stepCount<2||stepCount>128)return std::numeric_limits::infinity(); + const float treadWidth=(2.0f*halfSize[0])/stepCount; + const float riserHeight=(2.0f*halfSize[2])/stepCount; + float distance=std::numeric_limits::infinity(); + for(std::uint16_t step=0;step extent={treadWidth*0.5f,halfSize[1],stepHeight*0.5f}; + distance=std::min(distance,StampRoundedBoxSdf(x-centerX,y,z-centerZ,extent,0.0f)); + } + return distance; + } static float StampContinuousSweptDeckSdf(const FStampRuntime& stamp, float x,float y,float z) { @@ -7295,6 +7312,13 @@ private: case VoxelForgeCore::ResolvedSdfStampKindV1::fillPlatform: distance=StampRoundedBoxSdf(localX,localY,localZ, stamp.halfExtentsVoxels,stamp.roundingRadiusVoxels);break; + case VoxelForgeCore::ResolvedSdfStampKindV1::fillBox: + case VoxelForgeCore::ResolvedSdfStampKindV1::carveBox: + distance=StampRoundedBoxSdf(localX,localY,localZ, + stamp.halfExtentsVoxels,stamp.roundingRadiusVoxels);break; + case VoxelForgeCore::ResolvedSdfStampKindV1::fillSteps: + distance=StampStepsSdf(localX,localY,localZ,stamp.halfExtentsVoxels, + stamp.record->stepCount);break; case VoxelForgeCore::ResolvedSdfStampKindV1::fillDais: if(ResolvedLayout&&ResolvedLayout->stampVocabularyVersion >=VoxelForgeCore::ResolvedLayoutStampVocabularyVersionV2) @@ -7471,7 +7495,8 @@ private: ||worldMicrometres[axis]>record.boundsMaximumMicrometres[axis])return; const float distance=StampSdf(runtime,X,Y,Z); if(record.kind==VoxelForgeCore::ResolvedSdfStampKindV1::carveEllipsoid - ||record.kind==VoxelForgeCore::ResolvedSdfStampKindV1::carveArch) + ||record.kind==VoxelForgeCore::ResolvedSdfStampKindV1::carveArch + ||record.kind==VoxelForgeCore::ResolvedSdfStampKindV1::carveBox) composed=SmoothMaxDistance(composed,-distance,runtime.smoothWidthVoxels); else composed=SmoothMinDistance(composed,distance,runtime.smoothWidthVoxels); diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/BuildL161Fixtures.py b/Standalone/Research/WorldAssemblerM3/Linux161/BuildL161Fixtures.py new file mode 100644 index 0000000..985d3ed --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux161/BuildL161Fixtures.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 +"""Build four standalone liminal geometry fixtures and their capsule-walk specs.""" +from __future__ import annotations + +import argparse +import json +import os +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA", + ROOT / "Standalone/data/owner_world.json")) +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l161")) +FLAT_FIELD = {"version": 1, "kind": "flatField", "minimum_arena_clearance_m": 0.0} + + +def stamp(stamps: list[dict], stable_id: str, kind: str, x: float, y: float, + z: float, half: tuple[float, float, float], *, yaw: int = 0, + steps: int | None = None) -> None: + row = { + "stable_id": stable_id, + "kind": kind, + "anchor_xy_m": [x, y], + "z_offset_m": z, + "half_extents_m": list(half), + "yaw_quarter_turns": yaw, + } + if steps is not None: + row["step_count"] = steps + stamps.append(row) + + +def fixture(name: str, stamps: list[dict], walk_points: list[tuple[float, float, float]], + doors: list[dict], *, center: tuple[float, float], wide_camera: tuple[float, float, float], + eye_camera: tuple[float, float, float], eye_target_offset: tuple[float, float, float], + wide_target_offset: tuple[float, float, float], + eye_clip: int, wide_clip: int) -> tuple[str, dict, dict]: + root = json.loads(OWNER.read_text(encoding="utf-8")) + root["surface_profile_override"] = dict(FLAT_FIELD) + root["liminal_stamp_fixture_override"] = { + "version": 1, + "strate_index": 0, + "stamps": stamps, + } + walk = { + "version": 1, + "path_points_offset_m": [list(point) for point in walk_points], + "door_prefixes": doors, + } + views = { + "center_xy_m": list(center), + "eye_camera_offset_m": list(eye_camera), + "wide_camera_offset_m": list(wide_camera), + "eye_target_offset_m": list(eye_target_offset), + "wide_target_offset_m": list(wide_target_offset), + "eye_clip_radius": eye_clip, + "wide_clip_radius": wide_clip, + } + return name, root, {"walk": walk, "views": views} + + +def pool_rooms() -> tuple[str, dict, dict]: + stamps: list[dict] = [] + cx, cy, cell, cells = 520.0, 440.0, 20.0, 7 + half = cell * cells * 0.5 + wall_height, wall_half_thickness = 9.0, 1.2 + for line in range(cells + 1): + offset = (line - cells * 0.5) * cell + stamp(stamps, f"liminal/pool-rooms-v1/00-wall-x/{line:02d}", "fillBox", + cx + offset, cy, wall_height * 0.5, + (wall_half_thickness, half, wall_height * 0.5)) + stamp(stamps, f"liminal/pool-rooms-v1/00-wall-y/{line:02d}", "fillBox", + cx, cy + offset, wall_height * 0.5, + (half, wall_half_thickness, wall_height * 0.5)) + for row in range(cells): + y = cy + (row - (cells - 1) * 0.5) * cell + for line in range(cells + 1): + x = cx + (line - cells * 0.5) * cell + stamp(stamps, f"liminal/pool-rooms-v1/01-doorway-x/{row:02d}-{line:02d}", + "carveArch", x, y + 7.0, 4.0, (3.6, 1.55, 4.0), yaw=1) + stamp(stamps, f"liminal/pool-rooms-v1/01-doorway-y/{line:02d}-{row:02d}", + "carveArch", cx + (row - (cells - 1) * 0.5) * cell, + cy + (line - cells * 0.5) * cell, 4.0, + (3.6, 1.55, 4.0)) + for row in range(cells): + y = cy + (row - (cells - 1) * 0.5) * cell + for column in range(cells): + x = cx + (column - (cells - 1) * 0.5) * cell + stamp(stamps, f"liminal/pool-rooms-v1/02-roof/{row:02d}-{column:02d}", + "fillBox", x, y, 9.4, (10.0, 10.0, 0.5)) + stamp(stamps, f"liminal/pool-rooms-v1/03-skylight/{row:02d}-{column:02d}", + "carveBox", x, y, 9.4, (5.5, 5.5, 1.0)) + stamp(stamps, f"liminal/pool-rooms-v1/04-basin/{row:02d}-{column:02d}", + "carveBox", x, y, -1.0, (5.5, 5.5, 1.5)) + path_y = cy + 7.0 + walk = [(-half - 2.0 + cx, path_y, 0.88), (half + 2.0 + cx, path_y, 0.88)] + doors = [ + {"prefix": "liminal/pool-rooms-v1/01-doorway-x/", "width_axis": 0, + "minimum_width_m": 1.5}, + {"prefix": "liminal/pool-rooms-v1/01-doorway-y/", "width_axis": 0, + "minimum_width_m": 1.5}, + ] + return fixture("pool-rooms", stamps, walk, doors, center=(cx, cy), + wide_camera=(-60.0, 7.0, 3.0), eye_camera=(-40.0, 7.0, 1.6), + eye_target_offset=(60.0, 7.0, 0.8), + wide_target_offset=(65.0, 7.0, 1.2), eye_clip=4, wide_clip=7) + + +def backrooms(width: float = 4.0, name: str = "backrooms-grid") -> tuple[str, dict, dict]: + stamps: list[dict] = [] + cx, cy, cell, cells = 820.0, 420.0, 18.0, 7 + half, wall_half = cell * cells * 0.5, 1.2 + wall_height = 5.5 + for line in range(cells + 1): + offset = (line - cells * 0.5) * cell + stamp(stamps, f"liminal/backrooms-grid-v1/00-wall-x/{line:02d}", "fillBox", + cx + offset, cy, wall_height * 0.5, + (wall_half, half, wall_height * 0.5)) + stamp(stamps, f"liminal/backrooms-grid-v1/00-wall-y/{line:02d}", "fillBox", + cx, cy + offset, wall_height * 0.5, + (half, wall_half, wall_height * 0.5)) + door_half = width * 0.5 + for row in range(cells): + y = cy + (row - (cells - 1) * 0.5) * cell + for line in range(cells + 1): + x = cx + (line - cells * 0.5) * cell + stamp(stamps, f"liminal/backrooms-grid-v1/01-door-x/{row:02d}-{line:02d}", + "carveBox", x, y, 1.25, (1.6, door_half, 1.25)) + stamp(stamps, f"liminal/backrooms-grid-v1/01-door-y/{line:02d}-{row:02d}", + "carveBox", cx + (row - (cells - 1) * 0.5) * cell, + cy + (line - cells * 0.5) * cell, 1.25, + (door_half, 1.6, 1.25)) + stamp(stamps, "liminal/backrooms-grid-v1/02-ceiling", "fillBox", + cx, cy, 5.9, (half, half, 0.5)) + walk = [(cx - half - 2.0, cy, 0.88), (cx + half + 2.0, cy, 0.88)] + doors = [ + {"prefix": "liminal/backrooms-grid-v1/01-door-x/", "width_axis": 1, + "minimum_width_m": 1.5}, + {"prefix": "liminal/backrooms-grid-v1/01-door-y/", "width_axis": 0, + "minimum_width_m": 1.5}, + ] + return fixture(name, stamps, walk, doors, center=(cx, cy), + wide_camera=(-42.0, -6.0, 1.6), eye_camera=(-54.0, 0.0, 1.6), + eye_target_offset=(102.0, 0.0, 1.6), + wide_target_offset=(80.0, 20.0, 0.0), eye_clip=6, wide_clip=6) + + +def nowhere_stairs() -> tuple[str, dict, dict]: + stamps: list[dict] = [] + cx, cy = 300.0, -760.0 + stamp(stamps, "liminal/staircase-nowhere-v1/00-stair", "fillSteps", + cx, cy, 6.0, (32.0, 4.0, 6.0), steps=64) + stamp(stamps, "liminal/staircase-nowhere-v1/04-landing", "fillBox", + cx + 40.5, cy, 11.5, (9.0, 4.5, 0.5)) + stamp(stamps, "liminal/staircase-nowhere-v1/02-arch-wall", "fillBox", + cx + 38.0, cy, 7.5, (1.2, 6.5, 7.5)) + stamp(stamps, "liminal/staircase-nowhere-v1/03-doorway-arch", "carveArch", + cx + 38.0, cy, 7.0, (5.0, 5.0, 7.0), yaw=1) + # Begin high enough to clear the first riser with the audit capsule, then + # walk the same ascending staircase through the arch and onto the landing. + points = [(cx - 32.5, cy, 0.88 + 12.0 / 64.0 + 0.05)] + tread, rise = 64.0 / 64, 12.0 / 64 + for index in range(64): + points.append((cx - 32.0 + (index + 0.5) * tread, + cy, 0.88 + (index + 1) * rise + 0.05)) + points.extend([(cx + 34.0, cy, 12.93), (cx + 38.0, cy, 12.93), + (cx + 44.0, cy, 12.93)]) + doors = [{"prefix": "liminal/staircase-nowhere-v1/03-doorway-arch", "width_axis": 0, + "minimum_width_m": 1.5}] + return fixture("staircase-to-nowhere", stamps, points, doors, center=(cx, cy), + wide_camera=(-8.0, -32.0, 36.0), eye_camera=(10.0, 0.0, 9.7), + eye_target_offset=(38.0, 0.0, 13.6), + wide_target_offset=(42.0, 0.0, 11.0), eye_clip=4, wide_clip=6) + + +def terraced_hills() -> tuple[str, dict, dict]: + stamps: list[dict] = [] + cx, cy, rows, spacing = -520.0, -500.0, 9, 96.0 + half_run, half_width, half_rise, steps = 48.0, 40.0, 8.0, 80 + for row in range(rows): + y = cy + (row - (rows - 1) * 0.5) * spacing + stamp(stamps, f"liminal/terraced-hills-v1/ridge/{row:02d}/rise-west", + "fillSteps", cx - half_run, y, half_rise, + (half_run, half_width, half_rise), steps=steps) + stamp(stamps, f"liminal/terraced-hills-v1/ridge/{row:02d}/rise-east", + "fillSteps", cx + half_run, y, half_rise, + (half_run, half_width, half_rise), yaw=2, steps=steps) + points = [(cx - 100.0, cy, 0.93)] + tread, rise = (2.0 * half_run) / steps, (2.0 * half_rise) / steps + for index in range(steps): + points.append((cx - 2.0 * half_run + (index + 0.5) * tread, + cy, 0.93 + (index + 1) * rise)) + for index in reversed(range(steps)): + points.append((cx + 2.0 * half_run - (index + 0.5) * tread, + cy, 0.93 + (index + 1) * rise)) + points.append((cx + 100.0, cy, 0.93)) + return fixture("terraced-hills", stamps, points, [], center=(cx, cy), + wide_camera=(-40.0, 0.0, 20.0), eye_camera=(-60.0, 0.0, 7.8), + eye_target_offset=(0.0, 0.0, 14.5), + wide_target_offset=(100.0, 0.0, -10.0), eye_clip=4, wide_clip=3) + + +def write(path: Path, value: dict) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(value, indent=2) + "\n", encoding="utf-8") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures") + args = parser.parse_args() + args.out.mkdir(parents=True, exist_ok=True) + specs = args.out / "walk-specs" + fixtures = [pool_rooms(), backrooms(), nowhere_stairs(), terraced_hills()] + fixtures.append(backrooms(width=1.2, name="backrooms-narrow-control")) + for name, world, metadata in fixtures: + write(args.out / f"liminal-{name}.json", world) + write(specs / f"{name}.json", metadata["walk"]) + write(args.out / "views" / f"{name}.json", metadata["views"]) + print(f"[L161Fixture] name={name} stamps=" + f"{len(world['liminal_stamp_fixture_override']['stamps'])} status=PASS") + + +if __name__ == "__main__": + main() diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/CaptureL161.py b/Standalone/Research/WorldAssemblerM3/Linux161/CaptureL161.py new file mode 100644 index 0000000..9babcaa --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux161/CaptureL161.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python3 +"""Run L161 stamp-fixture determinism, walk audits and two-view captures.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +from pathlib import Path +import re +import subprocess +import sys +import time + + +ROOT = Path(__file__).resolve().parents[4] +OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l161")) +CAPTURE_DEFAULT = Path(__file__).resolve().parent / "captures" +LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"] +Q_PER_METRE = 1024.0 +FOG_COLOR = "0.78,0.84,0.87" + +sys.path.insert(0, str(ROOT / "Standalone/Tools/verify")) +from runner import current_stamp, first_stamp + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def run_step(name: str, command: list[object], log: Path, *, env: dict[str, str], + stamped: bool = False, expected_exit: int = 0, + timeout_seconds: int = 1740) -> str: + expected_stamp = current_stamp() if stamped else None + if stamped: + probe = subprocess.run([str(command[0]), "--print-source-stamp"], cwd=ROOT, + capture_output=True, text=True, timeout=15, check=False) + if probe.returncode != 0 or first_stamp(probe.stdout) != expected_stamp: + raise RuntimeError(f"{name} refused a stale executable: {command[0]}") + log.parent.mkdir(parents=True, exist_ok=True) + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run([*LIMIT, "timeout", f"{timeout_seconds}s", + *map(str, command)], cwd=ROOT, env=env, stdout=stream, + stderr=subprocess.STDOUT, timeout=timeout_seconds + 5, check=False) + elapsed = time.monotonic() - started + output = log.read_text(encoding="utf-8", errors="replace") + print(f"[L161Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}", + flush=True) + if stamped and (first_stamp(output) != expected_stamp or current_stamp() != expected_stamp): + raise RuntimeError(f"{name} source stamp mismatch; see {log}") + if result.returncode != expected_exit: + raise RuntimeError(f"{name} exit={result.returncode}, expected={expected_exit}; see {log}") + return output + + +def camera_for(view: dict, floor: float, name: str, kind: str) -> tuple[float, float, float]: + center_x, center_y = view["center_xy_m"] + offset = view[f"{kind}_camera_offset_m"] + z = floor + offset[2] + if name == "backrooms-grid" or name == "backrooms-narrow-control": + z = floor + offset[2] + return center_x + offset[0], center_y + offset[1], z + + +def target_for(view: dict, floor: float, name: str, kind: str) -> tuple[float, float, float]: + center_x, center_y = view["center_xy_m"] + offset = view[f"{kind}_target_offset_m"] + return center_x + offset[0], center_y + offset[1], floor + offset[2] + + +def headless_command(binary: Path, fixture: Path, camera, mesh: Path, + manifest: Path, layout: Path, workers: int, clip_radius: int, + *, max_level: int = 0, hash_tiles: bool = False, + audit_path: Path | None = None) -> list[object]: + command: list[object] = [binary, fixture, f"--workers={workers}", "--seed=0", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={clip_radius}", + f"--max-clip-level={max_level}", f"--max-level={max_level}", + "--render-distance-chunks=0", + f"--camera={fmt((*camera, 0.0, 0.0))}", f"--mesh-export={mesh}", + f"--world-assembler-manifest-output={manifest}", + f"--resolved-layout-output={layout}"] + if hash_tiles: + command.append("--stream-hash-tiles") + if audit_path is not None: + command.append(f"--audit-liminal-stamp-walk={audit_path}") + return command + + +def digest(output: str, manifest_path: Path, layout_path: Path) -> tuple[str, str, str]: + tile_hashes = sorted(line for line in output.splitlines() + if line.startswith("[PipelineTileHash] ")) + if not manifest_path.is_file() or not layout_path.is_file() or not tile_hashes: + raise RuntimeError("determinism run omitted manifest, resolved layout or tile hashes") + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + layout = json.loads(layout_path.read_text(encoding="utf-8")) + manifest_digest = "|".join((manifest["content_hash"], + manifest["recipe"]["content_hash"], manifest["plan"]["content_hash"])) + return manifest_digest, layout["stable_identity"], "\n".join(tile_hashes) + + +def write_walk_audit(spec_path: Path, manifest_path: Path, audit_path: Path) -> None: + spec = json.loads(spec_path.read_text(encoding="utf-8")) + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + surface = manifest["recipe"]["surface_profile"] + floor = surface["h0_q"] / Q_PER_METRE + lines = ["# P records are world metres; doorway width axes use the resolved stamp's local extents."] + for gate in spec["door_prefixes"]: + lines.append(f"D {gate['prefix']} {gate['width_axis']} {gate['minimum_width_m']:.6f}") + for x, y, z_offset in spec["path_points_offset_m"]: + lines.append(f"P {x:.6f} {y:.6f} {floor + z_offset:.6f}") + audit_path.parent.mkdir(parents=True, exist_ok=True) + audit_path.write_text("\n".join(lines) + "\n", encoding="utf-8") + + +def camera_angles(camera, target) -> tuple[float, float]: + 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 build_plan(binary: Path, name: str, fixture: Path, view: dict, + out: Path, env: dict[str, str]) -> tuple[Path, Path, dict, dict]: + run_dir = out / "plan-probes" / name + run_dir.mkdir(parents=True, exist_ok=True) + manifest, layout = run_dir / "manifest.json", run_dir / "layout.json" + mesh = run_dir / "probe.vfmesh" + camera = (view["center_xy_m"][0], view["center_xy_m"][1], -500.0) + output = run_step(f"plan-{name}", headless_command(binary, fixture, camera, + mesh, manifest, layout, 12, 1), out / "logs" / f"plan-{name}.log", + env=env, stamped=True) + if "[LiminalStampFixtureResolved] vocabulary=7" not in output: + raise RuntimeError(f"{name} did not resolve with stamp vocabulary 7") + if not manifest.is_file() or not layout.is_file(): + raise RuntimeError(f"{name} plan probe omitted its outputs") + manifest_value = json.loads(manifest.read_text(encoding="utf-8")) + layout_value = json.loads(layout.read_text(encoding="utf-8")) + return manifest, layout, manifest_value, layout_value + + +def run_determinism(name: str, fixture: Path, view: dict, floor: float, + binaries: dict[str, Path], out: Path, env: dict[str, str]) -> None: + camera = camera_for(view, floor, name, "eye") + baseline = None + for compiler in ("clang", "gcc"): + for workers in (1, 8, 12): + tag = f"{name}-{compiler}-w{workers}" + run_dir = out / "determinism" / tag + run_dir.mkdir(parents=True, exist_ok=True) + mesh, manifest, layout = (run_dir / "fixture.vfmesh", + run_dir / "manifest.json", run_dir / "layout.json") + output = run_step(tag, headless_command(binaries[compiler], fixture, + camera, mesh, manifest, layout, workers, 1, + hash_tiles=True), out / "logs" / f"determinism-{tag}.log", + env=env, stamped=True) + result = digest(output, manifest, layout) + if baseline is None: + baseline = result + elif result != baseline: + raise RuntimeError(f"{name} diverged at {compiler} W{workers}; see determinism logs") + print(f"[L161Determinism] fixture={name} compiler_worker_cells=6 identical=yes status=PASS", + flush=True) + + +def run_walk_audit(name: str, fixture: Path, view: dict, floor: float, + spec: Path, binary: Path, out: Path, env: dict[str, str], + *, expected_exit: int = 0) -> str: + camera = camera_for(view, floor, name, "eye") + run_dir = out / "walk-audits" / name + run_dir.mkdir(parents=True, exist_ok=True) + manifest = run_dir / "manifest.json" + layout = run_dir / "layout.json" + mesh = run_dir / "audit.vfmesh" + audit_path = run_dir / "walk.path" + # Use a fixture-specific manifest, so the path uses the exact authored floor height. + plan = out / "plan-probes" / name / "manifest.json" + if not plan.is_file(): + raise RuntimeError(f"{name} has no resolved manifest for its walk audit") + write_walk_audit(spec, plan, audit_path) + output = run_step(f"walk-{name}", headless_command(binary, fixture, camera, + mesh, manifest, layout, 12, 1, audit_path=audit_path), + out / "logs" / f"walk-{name}.log", env=env, stamped=True, + expected_exit=expected_exit) + expected_status = "FAIL" if expected_exit else "PASS" + if not re.search(rf"\[LiminalStampWalkAudit\].*status={expected_status}\b", output): + raise RuntimeError(f"{name} walk audit did not report expected {expected_status}") + return output + + +def capture(name: str, fixture: Path, view: dict, floor: float, *, kind: str, + binary: Path, renderer: Path, out: Path, artifact_dir: Path, + env: dict[str, str]) -> None: + camera = camera_for(view, floor, name, kind) + target = target_for(view, floor, name, kind) + clip_radius = int(view[f"{kind}_clip_radius"]) + max_level = 1 if name == "terraced-hills" and kind == "wide" else 0 + stem = f"{name}-{kind}" + run_dir = out / "captures" / stem + run_dir.mkdir(parents=True, exist_ok=True) + mesh, manifest, layout = (run_dir / "capture.vfmesh", + run_dir / "manifest.json", run_dir / "layout.json") + png = run_dir / "capture.png" + image = artifact_dir / f"{stem}.jpg" + output = run_step(f"capture-export-{stem}", headless_command(binary, + fixture, camera, mesh, manifest, layout, 12, clip_radius, + max_level=max_level), out / "logs" / f"capture-export-{stem}.log", + env=env, stamped=True) + if not mesh.is_file() or mesh.stat().st_size == 0: + raise RuntimeError(f"{stem} produced an empty mesh") + yaw, pitch = camera_angles(camera, target) + if name == "backrooms-grid": + fog_start, fog_end, fog_color = 90, 500, "0.82,0.83,0.76" + elif name == "pool-rooms": + fog_start, fog_end, fog_color = 90, 480, "0.76,0.84,0.87" + elif name == "staircase-to-nowhere": + fog_start, fog_end, fog_color = 110, 700, "0.78,0.84,0.87" + else: + fog_start, fog_end, fog_color = 160, 1050, "0.78,0.84,0.89" + renderer_command = [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=on", "--shade=readable", + "--headlamp=off", "--height-tint=on", + f"--height-center-m={floor + 3.0:.6f}", "--height-range-m=30.0", + "--light-direction=-0.42,-0.58,0.70", "--fog=on", + f"--fog-start-m={fog_start}", f"--fog-end-m={fog_end}", + f"--fog-color={fog_color}"] + run_step(f"capture-render-{stem}", renderer_command, + out / "logs" / f"capture-render-{stem}.log", env=env, stamped=True) + run_step(f"capture-jpeg-{stem}", ["ffmpeg", "-nostdin", "-hide_banner", + "-loglevel", "error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image], + out / "logs" / f"capture-jpeg-{stem}.log", env=env) + quality = run_step(f"capture-quality-{stem}", [sys.executable, + ROOT / "Standalone/Tools/verify/capture_quality.py", image], + out / "logs" / f"capture-quality-{stem}.log", env=env) + if "[CaptureQuality]" not in quality or not image.is_file() or image.stat().st_size > 300_000: + raise RuntimeError(f"{stem} failed image quality or size checks") + print(f"[L161Capture] fixture={name} view={kind} camera_m=({fmt(camera)}) " + f"target_m=({fmt(target)}) bytes={image.stat().st_size} " + f"sha256={sha256(image)} status=PASS", flush=True) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", type=Path, default=OUT_DEFAULT) + parser.add_argument("--artifact-dir", type=Path, default=CAPTURE_DEFAULT) + parser.add_argument("--headless-clang", type=Path, required=True) + parser.add_argument("--headless-gcc", type=Path, required=True) + parser.add_argument("--renderer", type=Path, required=True) + args = parser.parse_args() + out, artifact_dir = args.out.resolve(), args.artifact_dir.resolve() + fixture_dir = out / "fixtures" + for directory in (out, fixture_dir, artifact_dir): + directory.mkdir(parents=True, exist_ok=True) + env = os.environ.copy() + env["VOXELFORGE_VERIFY_OUT"] = str(out) + env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json") + env["LP_NUM_THREADS"] = "12" + env["XDG_CACHE_HOME"] = str(out / "xdg-cache") + run_step("build-fixtures", [sys.executable, + Path(__file__).resolve().parent / "BuildL161Fixtures.py", + f"--out={fixture_dir}"], out / "logs" / "build-fixtures.log", env=env) + + binaries = {"clang": args.headless_clang.resolve(), "gcc": args.headless_gcc.resolve()} + fixtures = {name: fixture_dir / f"liminal-{name}.json" for name in + ("pool-rooms", "backrooms-grid", "staircase-to-nowhere", "terraced-hills")} + views = {} + floors = {} + for name, fixture_path in fixtures.items(): + view = json.loads((fixture_dir / "views" / f"{name}.json").read_text(encoding="utf-8")) + manifest_path, _, manifest, layout = build_plan(binaries["clang"], name, + fixture_path, view, out, env) + view["center_xy_m"] = view["center_xy_m"] + floors[name] = manifest["recipe"]["surface_profile"]["h0_q"] / Q_PER_METRE + if layout["stamp_vocabulary_version"] != 7 or not layout["stamps"]: + raise RuntimeError(f"{name} plan lacks resolved vocabulary-7 stamps") + write_walk_audit(fixture_dir / "walk-specs" / f"{name}.json", + manifest_path, out / "walk-audits" / name / "walk.path") + views[name] = view + print(f"[L161Plan] fixture={name} stamps={len(layout['stamps'])} " + f"floor_m={floors[name]:.3f} layout={layout['stable_identity']} status=PASS") + + for name, fixture_path in fixtures.items(): + run_walk_audit(name, fixture_path, views[name], floors[name], + fixture_dir / "walk-specs" / f"{name}.json", binaries["clang"], out, env) + run_determinism(name, fixture_path, views[name], floors[name], binaries, out, env) + + narrow_name = "backrooms-narrow-control" + narrow_fixture = fixture_dir / f"liminal-{narrow_name}.json" + narrow_view = json.loads((fixture_dir / "views" / f"{narrow_name}.json").read_text(encoding="utf-8")) + narrow_manifest, _, narrow_manifest_value, _ = build_plan(binaries["clang"], + narrow_name, narrow_fixture, narrow_view, out, env) + narrow_floor = narrow_manifest_value["recipe"]["surface_profile"]["h0_q"] / Q_PER_METRE + run_walk_audit(narrow_name, narrow_fixture, narrow_view, narrow_floor, + fixture_dir / "walk-specs" / f"{narrow_name}.json", binaries["clang"], + out, env, expected_exit=14) + print("[L161DoorwayNegativeControl] width_m=1.200 minimum_m=1.500 expected=FAIL status=PASS") + + for name, fixture_path in fixtures.items(): + for kind in ("eye", "wide"): + capture(name, fixture_path, views[name], floors[name], kind=kind, + binary=binaries["clang"], renderer=args.renderer.resolve(), out=out, + artifact_dir=artifact_dir, env=env) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except Exception as error: + print(f"[L161Capture] status=FAIL error={error}", file=sys.stderr, flush=True) + raise SystemExit(1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux161/REPORT.md new file mode 100644 index 0000000..582c123 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux161/REPORT.md @@ -0,0 +1,31 @@ +# L161 — More liminal looks + +| Look | Eye height | Wide | +|---|---|---| +| Pool rooms | ![Pool rooms at eye height](captures/pool-rooms-eye.jpg) | ![Pool rooms wide](captures/pool-rooms-wide.jpg) | +| Backrooms grid | ![Backrooms corridor at eye height](captures/backrooms-grid-eye.jpg) | ![Backrooms grid wide](captures/backrooms-grid-wide.jpg) | +| Staircase to nowhere | ![Staircase at eye height](captures/staircase-to-nowhere-eye.jpg) | ![Staircase wide](captures/staircase-to-nowhere-wide.jpg) | +| Terraced hills | ![Terraced hills at eye height](captures/terraced-hills-eye.jpg) | ![Terraced hills wide](captures/terraced-hills-wide.jpg) | + +## Result + +Four standalone SurfaceWorld fixtures resolve from the shared stamp vocabulary. They use repeated rooms and basins, a doorway grid, a freestanding stair and arch, and nine stepped ridges. This round authored no inter-strate passages or owner content. + +## Changes + +- Stamp vocabulary v7 adds `fillBox`, `carveBox`, and `fillSteps`; the existing `carveArch` is reused. The new kinds are opt-in. +- Added a flat-field liminal stamp-fixture override and a capsule walk audit with doorway-width gates. The audit checks support, collision, grade, and authored opening widths. +- Fixtures contain 275 pool-room stamps, 129 backrooms stamps, 4 staircase/arch stamps, and 18 terrace stamps. + +## Verification + +- Clang 19 and GCC 14 builds passed with FP contraction off. Both binaries carry source stamp `8e9e114c1357`. +- Each fixture matched across Clang/GCC at W1, W8, and W12: manifest, resolved-layout identity, and tile hashes were identical in all six cells. +- Positive capsule audits passed. Pool doorways measured 7.2 m, backrooms doorways 4.0 m, and the arch opening 10.0 m. The narrow 1.2 m backrooms control failed the 1.5 m minimum as expected. The terrace walk had zero blocked samples, unsupported samples, or grade failures. +- All eight 1600×900 captures passed image quality checks; files are 25.3–58.4 KB. Capture and audit logs are under `Saved/Linux/l161/logs/`. +- Fast tier passed: 273 checks in 346.6 s. Both owner generators matched their pinned L130/v227 canonical baselines exactly (12/12 rows), and W1/W12 signatures matched. Summary: `Saved/Linux/l161/fast-tier/fast-summary.json`. +- `git diff --check` passed. No Unreal `Source/` files changed; no Unreal build or medium/full verification tier was run. + +## Remaining risk + +The captures show untextured geometry with simple fog. The terraced wide capture uses clip radius 3 and max LOD 1 to stay within the standalone shape-build bound, so the long-range horizon read still needs an art review. diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/captures/backrooms-grid-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux161/captures/backrooms-grid-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0201742221a0c792eb3a20848d75529268ed294a GIT binary patch literal 26205 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 Ap8x;= literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-eye.jpg b/Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-eye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..14cb03d78e5c1133274a9ea7d42f5111e80f37dd GIT binary patch literal 37559 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 X$}2q?er(YD>d$Dl>q~CazdHU6M)3;J literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux161/captures/pool-rooms-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..479c33ba594feee93d127a6353bd6fc2f6606db6 GIT binary patch literal 38988 zcmeFZ2|SeB|2Y02ab3hk*}0Skr6&6_maru#vSM3AfeV$*E zHps{-_F6lXfV&XcIMH2GM>4JFj(+N^*ZUD$kV+rUc#A^!%ce~I{kHwY+eefk2nFd< zfE~F|E2G%hRGD^u?A9m<$@={of%CTyQ6O1am3LaY%&0w}MbX1uEsG~e+X{br+r*~H z=1#}pn=d)l3=7xHKi(!Ajp9C7t7_$?>beK{$u6ImcvCNAk{}-#oR#~L^OjYsgMRT* z2c%QDAF)GcGInb4v%;01BnqB<%p?@m>4_ueWRoLIK2Su`$3hlwgdp~rcbL6LPUt{1 z>}PY-_LN3)B#%MDMlG%u52O5k+n(v4SKpuZrM+{aTv~BPBEiZwb`UPk zGW+Hh4avsuTzr?*)LNmenpus3=abB-!Jh7w82Ov2E|1r$8b%b(nVa{l5?MmhiYCSg zzGW2(u5}e9k=IgBy!chXJR=m80T%8w`Tn|#tmH9JYSc{BVC8fvnjjI%)CZ6*8?>`+ zAO7?C{x^DQhEw0mq(F+1r!wj!p8Fr|!9K3j$7}RlD2a)CSehXFv{Uh>Y*;=3Cc)G7 zlqr<>6cG_n!7?x+(9Q+}7?lB~fMethLkB_I)$W``C{r>B0{9@>-45~|oEVbwT@U%f z?c;PII}JJv9VG-YjtoV)LXM=j>38TPoz8KOQ3olE=S$`qW6iCsnYmk#?BhAYp@htG z4Oy?^n+s-1V-`^X;%%Q9)GQ_C2)S!{ToOwjEt4DJen)UWA_1VFXxKe}Q+B?gB|^o^ z(?G54dLw#L=QC-R@K&h9u{W)c(Pd6gJ7lUP+CVn$DpVA;J*PibEWgmjv$9EH>EhL> zwedk|jVgLJDVa}oQJpXmhcCGB$7{a+=Dl~b+`efoTD8roM8S5T(ssRfv)%hqw?|XW z1OK{`sGc-Yyg9*cfMs7)qrH6-x(i)gjM{=0({l%%-HDE2n(1va_`w6V*pXO5+yD#X zDT~M8-T+*bsa17RYBZ;@jJLrYD3Hpa8}+}x1^6JSLZBa6u0y_@2#v!rj-}Wq(HAY3 zIDL!WylXP6=kCl-9m~wJsi?phB5C$3b&A%8Q#6eGH<#$ z4m@-@T=E;DDB=ZjeCoop^0OX) z6<49qYq_D?BJ*qJUXS9NEBy=t>Nj`D;kT*nX-|2Czovx`n*7%Hht>fbhy+Uke@zao zKAgEfwv9aMC=1kaxoI$hAIy3#Qiw7RCB$~6S;Z1;LlZ+|a|FX)=R8u4)0~@_EB|xK z;AE4ZZ!0oM=$_Bqf+ls$sv9+>vczsL?Vr-~h|LMbW+uUpuVn9i;YP|cwd!7X)A4in ztjggwIntH-(~JAx(I)Q7ift0a3ZTgi19-?bs6lQaDfmA;#eeAMzJ{?d%|mZ}Xnwv< z<|16hMqT1J63!ilWic}9DYBKv&VOJ2DS7>_aetJoaq%ChM&iZ&z1ev`le*=46 zHZ}^RE~^_x@PUekGMOp?;spNwP$*MGC`AB~;>UbD00T34V!FSc69oi!5S*wTz{?8HELGey$XHq$j;UyK1uT%ee$3JOwz8@`>HcTTq zTydJdNGuG`P8@VT*II8OQ|}zx;5+srWwdZpUac-WS)J&!2v2-oZrD+8!DpYJq>vXO zDl`#3pT6SzQ;((}_iEvVHM3{N_?u7BYHlPGwsI0$QWdR@sx`MI9KK#&^+V{;9XX{6xF zr8Tn%f7M2>>n*+-5+k|hN`>0YBQ13j^@wV7q3#xWc{DP%Tx&vGFXnciSVHOZq~Unp z?8NoW=?bpmEr_vY*<>Xzi-?ZD&8%NrtEDaJLcnFlrDY6rq*;e)xdu}|sh>Wpd19i8 z>5r%mNb!W1WATwK$m-L_xMYvaq_Bp|OL~ZnyLAJ^DBDa!|E{+)b#A@kE$_mgjnvNN zC~-taSagUTwUijC%{9Jk1Ktu@L{lbHFEZ&vvXaTyKMwOJZ}abU(UkY3Und$rYVR8Q!R8&A2!fPZ?Z*`B^_Nbb=3gm_5R2z9VE4qRRPubFb`JgpJHYsu_7Pfx#$5wa z`DibAO{@UX;dsz0+ndUQpL}FD4i+ViyXvA&4`3M0ccs%}H0damG z7=%3)hw4hs^)z&GGDbY+)DgT+mLiddlAaLaQ$3sMQte@{z6CIP$BRBE%NOD zMWI+-T6IY4XdHK!H|*`j*H_9q+H`hyHt=LG!Xvm8hK~_ev(x5vC}-AujePaZ7o8&u z<4TEP4H{0?h-dXb_oXUiyS=t&pIgXHi162Zp1aX89ZtVJW=pG$+l!yAu8ckEDsyz5 zYU3!c)s{y!$cco+Rk+onIr@)2cw##Cq@#oH=JFQQY@&Zn`YBhPNu-OkS67Rk_-kt` ztbmwaf^(WcM(4meVO;W48A}qeFuA8^v?}XZ;4xzD=7oUqg==FTH!D7tvb^O8*;-Do)(&C#C0U7xh;_<`YYwRACVr$JL;R658?2| z<^-<_BnwN6Lc)#4_dtrl!cxd`%eELymX5)gJJQYnPQ5R>h(7<#6WK`4XBFqC*3AoU zptm_Fc=G*17Iz@2>@mC4cr=?wq(^;WcKH1q>s2YJtj(I`h*?318~_kcPgJ#S(SPCDKjAQqe2iC zY#4Im4@H1LhsD!=*9n&9+nL+z1Xc>D1XR?$VKM2fT1zJ}GsnjnXl37|&@jH_mV>U2 zP()m6ekt%g+e9|aFkfOQ&hDU9^jwzMH35ifL_zeGm>nT)a@Fdl3>Ghr%~?{l2$xu_ zorw#(GFQv}xxu6)d?2DTfUDorPd&4IYLe7c1dpwk(bKY$N-v9~9d6%X>?uB~$J(eZ zp~sz>CJ-Ao+t2(a-p~^6J*MR`R`IZ@v#}$sh2X5^n$($IKu9mJ-n{+liKWBbNo^QE zP=BC9$XFDsUtpN+9Lq85@<)@6V(t3y97FZb0Uqx>!m(o!g(+9rUw*d)f8N~N8mv89 zTqhN8ZxQIzlK9-=%CsofqrjD;(lxBow-3EQqg^)JDduoxRWiOUFKlv1puXOfea+<2 z>|mI)q4Z^^he|c=_r{Dq47U_lb#B!9Xnd!{&?J8h;CMLef7Hi8n+t`m6p}G;d^YIP zb0HCz`Z2avOH1p`d(A^Q^t}O3=JmCOn`8A^V;j{Tguc-!b6B(9xmt$-amQj;{R-ou zWFG+gtt`CzEnn$wq&FJVK~k%G_<^2%l&zWg|m<8bMd$}KVI$8 z_2RXLM_Z7d)3Sr7->0@{i1`Y`tsqZ6$R_4MT?d6?2ma-D+Nzdr+Phu$Nfcm zMPqyQ>J>6R=dB**DeZ8!tCPA@${Y>&DPTT4{4k(js8K@{z@G7+XR#D>EvJgyxvL^G z!!*Tmq6N-BpWWuNyN|&ej>Wawy%veQPdsWQef(`|PXP%(Cz9HhmX>%x7v;lz)W=>8 z<&al#nsDO5S!i+_=U~u?irRLIZWr75cW?OneFj|+J|pP6K0t#6FuNyji@}t%RHj={ zN6SR=t+GXT-$Tk?^*B}TVib)?imWb;2=vk9G*xw*aZgv$%7^Azg`s=+k9B81Crx8) zj*cH|Gik?W5LxSMw;)Nh*2ECJGPZn3yn%b*C_L$6QnNirL0izW*qSvmBfWdrv3mB`7LapI$CC#1CnccFxXgM)QM>l%9% zLy~Jui@!d}=kTvy{-xQaS#V#Os;=7Jj!Ns)LSj<4HPdusl78_e$uRHLwt5Z4hrI@y z6HAph{xA~FCnclJ3?H$+5HEkejsf%iPN2d~yz--o^p%kGy;ui(V}mBod!RpG&vKrdVfYBypH`SmW(@66ai`YotzQ zndoY6-R-v?JI0@{qjPaOs9m&w+MOODqh)1bcQ_%SzM$AJpQc9-WuS%DVJ8Tf`=sBk zm1O`ks z|36jNUPZfcSC-Z|n@QPX_J)m)Ish}xNw@ieAyze;b4gr!5VkR%$074KRZcxSi+tko z42Cm!!!%Yk`~L2i0(lq=bmSZpMWNcLs~U_TJ=q(>dOj%fWY4IpV-!W1T65u9I%%6{ zQRgvIw%IKbL1B4fnGYd%#*er5cwzvor@-*Ai0iD|3M2$%((f&tUsr#(@q4Q%kky%$ znRbqmjiEoCq2TNcttisg>1fCrguEl7Xc#fv8B{T6G5t-L0s5znlJ)$`ep^szCxKv| zF%eUiMRG7KSGV%kxKeoYC*sAtfSmTU-Wy_9<4VzJtpOHhtqC=8L>_xw#AK$g)KSMP zU4;o#BWYou>uXi5x%D#rI$l^IaF$F!(1sv3CKQrQSw$Jz!^W!-+R=sgk35A`@A;`! zQs8p_ihH$(C?RRoX*n^wXJV;TYrrqbJyf6lt`_DYXAW@~HNF#nuZug{e-kK&(5Hzf~F zXu2PraUJWim<$*~2v+~eI8?JrIf443GhGYgPYXuFc{;)g4&~*xSqZA;mDc;mv%*=} z)8Z1tG)j^?9gXmlY)BJ{HZ^C77HuS(9$Hde2#5F5(z+U(_lYWzFU}lQbHMdcN<67RT{; zNtYZ~t(ks(rM0Ue;}ai0^&$%_Mk@FI2E-;dpwxY_qBK$BLjbNp5HNgwv3`C(;J@3R zJwDEOEf%Ol(3|5^zfc5S>V8ROdg;z3W&2wBSm>8n&*QX`Lp-&R)z*Yq~22P zt+BXFaRX;KnjV6Ar*>riJSEZSVN#C(6{6U1vWfrE;^-Bl2g;WCdp^QU25wCa+WdRY z*D>+uTpd$pAGB0qZ-&5Ax$)yMbSbpJs>=^S--~+x_#it57ygvpBi~ztMGoG9TAJMs zw|q`ZPvw2T_u4~>Y7AgTVi@jn%aU|r(uqTC$vPIy_a@=j^J%kv?|rmOC%Dc!TV>%= zz`#KIBukTYAtEqr3K-#Fj7b=Uax!$diN}?tVB$hPa z%P{WF}7U1=J@`2Vi^pIMiiK-<*(xO$PSZDwSJXKS)<>j>}Rz2ct)^R{0>V0RGpeUL;9dKga8Hm$7FSxR&Hm$Q(NEPd1ThO&} z$5AIW(@*tNMd?;zowXAt=`1Moj0hxZqTV(Meyr_9ftP7y<@{ZfM?Ma*n{^im;l-}F zM{VNjLPFva4i;8rLm{|0qQRMDv(%{7=NoZ8asx5KPv4}rR&FSoc8skfRGzABI|RN~ z0JPn;_0*7P1);dm(D7jYeffDl$2#$!0wr9glG+Ek)2~&`_$~v3+}u)T1oyzhwgih{ zH_aHU&u-QSUL2R$R?_GIcF8HzoQ6h$VU_LA?aqIWL;t#$COY`S6-!_sWuv|Xs1%-_ zg>eXC7uqIOJhd7Ab!%@+e1vwqF2B@Bm^_}z<}%Y>xuR%S zU8Ze=7+~0dCr}`%)qua0723-+@6dR>=HSV!Ij5h9#bpR5iz>G*sII4Cv~mSb%Hi;| zmsz>g?D|jEl8aLlp4r?%l)R$WRWMn1p|hilAlzBGZPE4VGdMD>a8jgRT7SwQ%-SBF z7vU%8-N1Xs@!<>Ri0mzh&+c7`povoE>WkF!Y=@aQpK{%LWq}0uqSO;V>f5Ikdy`}%J7j=;5ux?VzQRIdV?1s^h7d~-Z(!l@Hr*F!*Q1}#JIv{AZI$CE zmkw-#+Lk;V6%(Q&@5vmNY-0W5WQBdZ^?$!LH#5x;7IAzWqSyO^d$4PJ-W2Vi9S{=~ z$+CiCb;@yobr^C*_}clFD$9*%^nfDI@t*zFpzwI`<2w1rMP1~*{Y)qiWf+VqMw#B_ z2~;I2!r!k<#yvS^G%Ju()hL))nRZ=t|LP&wDA;trTHS#(1@MUboxnByEeN(4Q-b(~ z!4h&A0V0FccF=C=52_r{#x8NPBt5MQ1bJ0y0s1d8i(6f zx^(*ZxIS&;3G&^-rUz-Ms&a*fj8IW7{(*^4H)dyFsE{%5|JIA=c?Gjbb`u|kq(&17 z*1ec*s5Pv{MATm=U$1Y(071;fa;|yBzZ!84E zq{M0p#Rc8^lM(NbA-60`tNk}GZ6S6vZ+@HpM@HJ zfaq^M4#EN%oAJYu9*+-5Y)!8cuM6t&g^#CR*SBu7@oIq_7R8KvE*D#c`OJ??k)ut(yM|$b0gNB) z|K#@ncGsI=?Nq@8IbH5c?Nq!q{8ZsFzc5OfU}QQjLl)ounYgc%plG;`U@=jrG9c>* zfJ~k_4Qqe!5V8X8d$cOZrl25<%rUk z06F<|2$kADO=Z<6Nq@5!Yuhx_pR@FrO z1)JQTO!7-t(}@)P*Q1n>VrNC&LcIITQf6p^OTA2$lkkVR=e$!b*o?T^MuQ_RX*uv! zkA%*gP~OLHQ^4B<{19lKAt~FY+%Hy`uebYeG%WNhRRODD-rlI0cJ|Egf$i+|ODajx z(^Lr2)37?gVfJ3szqR+YJFSRl3J8oVFTS-`_8 z*nc|3ZFCztvxi-D2wlr+;RX!?&Pj#9zo+u~?fz|z^G~3*=xB=aI}qkeyaFXz>y?el zWaV{ABgu8n&%&pS(lYyHYioxNKXKM-gh#CSC6+q+U38js&@<^sm#K7UDAA$U5OG%U zn)z7#xht1%R(d!cu?5|ozF()1K!c3?nVQU{?ZzaSbHd|%E(Y8_@v-hm7jmY!FKZ3A zQT6(<@YM>@9 zOu(hWftc)BUU~R#fo$EgB4fuyvt;=q)y^Ulmas+?NoFuM;i^yQ&|Jhfc&Ew!u;k&? zqFOId?4>T-qQkzyrOk7wt{2~8i1l9%jjI%h>sMG!J0ESXSbNEcf*f56L^oJF zf`B-uMz*&82MR^?(-Q(91`SY6KzIQ~A#Wpq8nRMc`h@}){eU7V1{IPjDV7OYK5XG< z>~H4B7Xxjv{1FEJj{h3#ofKK1Ka$HHu>YeL33NPVHC;0O_?Ohl^&tKlgK?`a4ILfX z0YfQ%@hD~ZDjf%!2Xz*Db;!6`g^cQC-U|pGAew+YNG?cw?sqh8!C(q^#0(hc;J+pw4}Z*!AihB!Yp5^dUGLJ&FY+y_UqSK-S|`ZQ!R9wBsPTXTCUqH2W!nTCWr|M zpPf^`q5AJHKcDb`zK0~-HA0NU(<9=grQvim$$#3Y(qVFB$Tb|ysB8V%`lHpvV$YiP zDxEQxdhfzy>$edDA>W4FSD0_Q*uyr!g(B(84!{#6{p5z`&Nzv)z;V_w3~}YE1M4!E z>}|PT)4?#5m<;R=|4)H{zz3{_WK#S;wuzpk1%UwDkhB9!JP?`c(?LK2uzF|H*pz?DNruh? zO9xV=I)xEMQH`Z9xOp1Zci%>N{~2oaQdJBXj|`FkKzER9ZVS4Qqs@6VwrWWXsXAON zZpQeW#G6*uYIJ-5k*)z;j<$0TRya1afpW`_U`V02J+WcgJ5)FY94}U7l~_` zIlDN&pV*PFQ-Kn$wJH{q!4kI}1{zy297I#)RzV$?H!Ox+b%P*NPQ zh%kK9RF6olFY?U(`To~srFp-6)Vt6l%*_r@b90R7nx&j)0POpX5Q@=xi~Ub#Cd5M~cb*M$r^ zcSu>MMWk)q&(a+_bAf8lofJU!CB&Ib(V8JC;3jKs}lY$VDgam(L<7@m1U$Yu zFmkR@x*#$Yp!(ki95Sd~8+z{1E7qBd5V1<|yi)I)RGRy~XEw|Cq76adu=%sNBo3^V z5aPMD^>w-VHT|no!?@v&}xzOFKY??-}dOC$4oBTC2kO6__cJ*UV}FQK+l&RK_d zth8g}r{w*B_ z5Dy5@n{8c)to*_#UqSTqQ5Y#MsGnIfyEC=j5U!~Cp3FLh0`k5j5V~IuAW}W zTCkp43W(W)9?81P$1ORr93Z_M%Eq1mI;)h#hM-QVz3S=i;y>4)QRdNYelxm}dsbVIIcf8!57X%e;4Jk%tldae8C&_) z3RL-U@RdrDJ2-T~TNa8*Bz%Bn3!1|6V1rezJG&jE{JjUVh*E zrM&S00w%lW2bgKPuxl6v~G)+`BdjN)W&S{dg}i8dA% zapwGp>by#s*)1p)*LveMKLqhprcgcD&RlT&1hQb{T(+|S+%Ory>Ci-p-M%d?8G8S% za)OQ@0)OP-Zg8(J4a|>wAn~U2Q2T=itX5>TJm}Wm3;Y!CK?=&{9d+&u%q}Ip{L6?#dkGxX2R%du1ST ziy6pyRWKO&C1n641Vk3Q=RwN81_1iuJD?v~k)zfVfX`^4E09@g)Iusgs$xtx_B}FD zF%?r%hu-7w)PftZTHq;4%WVu!TnHefnlN({@Y%U~N%qOsS{zj+(;7cF1BEquZ)Ng> z3!|EncCRHAPNfZ)p|tHoe~M0-&EFK(4$tx^9ZyKh;gZmCD#(}`?5kmrhIfkFzi+n7 zwzcgn(icxqb;hL$K2hT6?>mMqaw*BLbFXbd8(Ueguj|&vdlQ z$r!-jB$^~=MR#YUospz^vu7P*c{pNXE&~24E-YBVGdtf!rZuXzMI00b zE9P{_Gun!ri&gpAyIC9lSJ3fyC zCmIrwDRv^KUzo7Qph##t5*0%x#;*GpDN6kmFVJe3FH?v3e=Zq?798*Za`7N*-`qa6qD}{J_v? z4X2eiv{d8soh3d5bK6*KiA~&6>SC4Ar;(g2cQsTk3FRDm;|R&&#F}+{>MWhR;v_Q9 z%)<-)CXBQuU((%Ld3yv8_?etCHNf7tDWlb(rb?HE+=lt-Zw)~l+~pYgZ9n36M1=0w zY5d&=#Vzu+WNnZc*!5K*R=_TRp17ZO+sc-7=N8KP!9!|}6wL3@IpPd-^&2`<20^sD zg6EDP0qX6U{0rRPLF}P3kgK}*Q3lggXX56O%`m~Uk$Ujnm1!9b-=nsMT_djhlIE^^ zK54~SJEeSB*@CwF(>#`v4kQSc-g`=t_vcA+qHGH(*O9tNI#bx9bNJU`Sd|nfNo#UK z^KGi3v|WXQq5au-A9tCE(_f6BfG_|G#PaU&Evh+$XP=~!w&(D>oVB6!(VX=a_r&}1 z8uH!QDyn>H3wE)ICazukhk1+dD`x9#K~m4Ai3Sb#!`3(!?Rkd~eOGf%r2u6jthLBs z!q!fbH`4KuTUNi0f#2#2{fl?)6m=^7)F-8-j@H+E6c8q-$~}F(hwtj4(~GiO8qHf| zvpC|C!r@AFs72MlCYfRjY)xjtiA=xos(ib_wWzK_tu_doglt~)MHJo3CN)HVs(FgD@pAgru*rO|+q8s*O?4J~v|j0+`1Cn% zG|EG@T(z|QQ<3}8O~Jh~r<<=J7Yz`<@madISJgRr1UJ+kDL5`$4x=<@rGV2xvA;oD zCow`lE3+`A{1BqMXXn7DaRrgqRLQQ2lDlz9zLMwUEr^j<+=mX0OGkJF9uar$(!mrt zmZ0m%2`u8Fp&(|Fb@4@;!Gpp_g+zlNBEn6cHVm+I@#N|+&J9FYyy~obj-Uyx)iNs6 zH+N=jLnNYgt^{JehU4EgUnoi|lA2N%QWTC@PHK-aioAAyvK~d$Dewy5`pAsZGavpT zOi#@iZ}B8X`3{~Mare>msqvM(8avX`rL_r1TPNvx+GZ3#13d9 zS?UkZBq3%d?o8GawVhSIB%FRpJl!v38ylOTDO%D}LnGpnhMH5tYP@hAR zrrs?+-+P6e*+Tqy!J&Zf%JMxfhv3c^!Z*4uE#_h`6}0>3n6bWbc)Vu3(^urD$58NQ z(q+a^Y)S;jZdXw2zvt{J!Bfvplb;$R53m`SU8(;rCHQte2l-lHC?e})tjZM1NMI^b zrTFDn6|!Ip4DVEkLois~9_WM$#P|||oDY)qU?6e=otqNFPfI5Nkqrfu0%QX5k7d_j zkOB_!zC-0SqnF(qx>0^6bokI6LlxN;=7Vi zc~1pSIN5)G7{Jl{CM}%*> zRR!Af-pOIA;JntG<^^w5;LyK~qtpFLM%jKk^9h@=-e9&=r$aJX`8-~3!CA8fX}S*A zJed5U6MnWyjmejn#>HXzx7^vG(1ofEc0a-C#lyv!$&E(_J6tB7Egkk86%`Xq`9!Uz ziss}T!KHO;ESK$FEJqt_Z9&J588UHlnovs}GYIf;N3!|~$|iL?CwN?~GHOb)cN~g4 zXdwPh1We&+)Mrc7mBw8}ef?D7heLT$szA6i5V)2ut44Fq1Xl!;wXOs;U#%fO3ug~msz3yC+ShJi#K zbFZpEUO%3-qJFo54w7)84}-B?wsUbhE#=+Dr~IGf2U$U)?S!d2#A4s zfK1YI(z_cj7lOULB@6Ay$zTn5F~DAM7P(Q2?8EBinB`-2_0r(hAU>e#W*_Z z+qSH%b+s%bIvuTb&h@ZVaUoeW3`*g#Q%U|)wYATUFFspV&`2H1c6t?HQdVy(tA267 z)U|O=zwkquSl_USOIUv8^Wm?@QG*=z;oc1zbr<`B)=L5tGOJItan2=0;_}O=S3I^L zS-mLB9LZtnteGCmVmm_C1#+^rV+1pE+~E0iSoLf+^Y3ha9P@3`p0-KPk5i^j3MZ87 z_!_9WdRrx>?Jo##|CyTSwKCOHWpc8J9GOf1yX7+ZT7cHOSgi&@Na(`P%4Avn%K7t9 z!zd->c zf=_fn&c|`gmf*VR%onZaS#Dc5vPrvQnW1j?!phCfeckDzL;h3iv$N@Ebc|Z#?Lr@V zZQkT@GV;j48HCGu=1QTNO}RT`eOe4{nJ-?ngC9HF@+-4x!5x`XLb$l}AJlmBnP2rV zzq+k{QJ)#jq@uh%E(Ey>>r%~Wqs$E#P_FK$D@5y9RYsOgB+n5NliVr;wWKz4Rdqs; zEM01WLgyE?N{+y%)|L}US_^WqZ(>JefYBM{u5s4?_Hs#KXVC5Pxx=wkW_tP+&yu&G zQ9GqUm)P|S`J|hu4XOC0`5zGh)#1;626@^0H>-yqr%vSfa;$_4zKpup!p!ND=#i}X zx|nEiTZgkmc2VPp29B^rK|L;X;@fU}n|1MVns794WP0KuTxMvWX=tG;$%F;O=DH&b zjn5%Eh^hm2;%{yqQ%8sfE*QIvy_?$%56*qK1)a+(k{X}g$3!Sv!k2j1#w9p+V2|}A zTk6FlW_hONyX4H~J-nukUI!X9teVF6PX-q0O!@=uKF5!*e_;!nx&UlPy$Ca!k`31t zU#XcbsN~qd=Ee)@run{o_8ZlK_7i0rt{=9beYqfytZEC2m>F9}^o=Li^b`hfbOiD( zO@7X`KyM}*I64~iZ~lyCnX1@7tp}Is&u8n)SL{sP?~C{Cr74&%8(UIv%^pxnt+F3i zI5tib)S`GhJ<$Yb8`ozTTBNF{#w>|OyEPW7s{4V ziGe~|mWQK48Evxz5*;_JQK~ajI~!qgw+~UOb3og-aT@8$(UGM1u3u(=+gU-bt6I{p zJ(SNzHp?R8v@%HL+=aX^0Qk>#K+(9eideh1yq14XJQP4=?LaVld8ru}k?3+Wj|bL~ z#oVPM95)@Cpn(=6){BR`X5D?m#qs?ud6#bJlw67-#tDT~1T|s=7x-m-UM~=bzhA|8X*8%j&ju6$uE@XZNU~Pl5D)PiitoSIan1 zD#H^}S2Gw43p!t?NJ=|AhcRe(IZ;xby;Ar%gI?+gf(LOtgT7$ms?WXAFnU71ZJMp4 zftH9szRB4TI0je|fIW>L3`vjH+5h7lT-$3REkH%p&oM3O%4&!sGfhJadz_~STuRaYtf+}wcjVi9$EY^b(>6t3SZWQn*E|{MPV9StLVc1GWCD6bDk7(;P52}Mj;^yC zq6_D-tcInvNUGL<-XPeH5k$H`f=|_e&2l$dYCcbgu2ifZ@hoePJzw%;&CiRa8SGr@ zXL62q6p2rG^B$FUvfbdU^sLws9knp?4O`~J+B zIe}2$(+k&T9g@m%&``&EYhQ?qi^U4cG>m~>A;kYC$E6bvB*uqTE6GdN(jN+~4f;8Y-Y@?K*G3JP zPjjRdTUlFuLL)>(2HDJogoH%HhWYZnl5g1hnQ5BF>#4V}0YRFrD@WG2Q2(%1#&Q}+ zKV>;SYfU0`Tqf!S$kwL5Ia)cTbjZ%mtuqp8TPZ=KjML0TNWJMRlP%)fvgzUyv!Ur$ zKH}U%37W&j3&#h{)Eekl)F(7UV%Xd`&L3g}fo(g)qjEVhj+j-{zy=7Pc!a$1O5jcS zKBLNs3jK@{W_eT#QJi_5m=r@llVA}cvruf|$?>W|Z1Qqle_>&#otL@IX7}bJb$M$d z$GG?AkFLEXPLb@`fnxY;f7jUMdrQWl9fBkLmu-0-2xLr>BS`+DuJU_*W^Zt4N1v^j zOC4W#*zk=8MYI0eQ;NA$ZJXHPy1Trerhu_rk=>p9Y^>qNy7bWD_5URqYRXXQ;rL9m!16S|>}<-pvM5z!?U$$8FzM5O7Yh{uLbe|*`=1#hb2HQa&}TQ7mYG>(Z`7==A>hp}yAMa+^U|~`Q5Ft#(gB~7 zWBj~tr*D2aXg#mAkeKZ#0zrT>5o}j#N&Ea0@&-Ab=%4kK?0Yp|=&0IFG7CxDOe)Sc zPPeynRh_6E5;FIy6f(CGugae{Gj(H0X=|S~a+W_ZYmMaC^s!yC4zHKjA1znaV_#9S%;huRmPHT)t z9DU;XW4oVquyN1WE`vm;82WlX{>~C)>xmj!ZTM)iz?sCgU=N8mxyz=DSrzz74zvCl0 zzkIixRJ}7(VaI~qF5&c37E-QLbRQJB_KXST2EIN;%>yxFzB~2rHEDj~&k(_b#QPvj z3MCySh89K#?B?L-D<}gX4h%@`+X$qui`6eVquC%h9W7b^+~%zU z*Q%N~vQ2YuyYrDzXAiH#TkCjlU0xwVF=PQX6~7KbPhkb=XfD2yd|11$jf1J5f`zlREX%E*kKV);}ffgBbT$oKegriNHV`R7YyX; z2(z;2>D4Gm#f?sUwDAb ztfTEXhqio>{u+WyElE(Fn@W-y{?Q88odGh~pM173$||?k@I*YrepEc#z5Ylt^JA0a zGQ#iq#dYnU{ABB=E_uL1C_JpZ*0-a!%357sTrurp zo}QEAp@_K4wjAdvkmL_O{JkyQ->fHhgRLQ6=nIRBPJGwRM=wYJ{ma-F_-6IESD-q_ zLtEabw6HN+$OFT8o#H)RLFC+Xk+)VD8dg#TF3Estrwbu_IWo}Ma| zeRP;OHR~QwvbuKo{Io)8nbl1D%kRMgwAbUu{W|j&BAO>iTD^_Pd^j@~dfHJ{+x3k& zQ5DHj>7}>ty`S~Vc~g1wcsYXI(qX%vE?3r`LIrUmiUiWj!q8gf zCx+xw0W@uIkxCUuo!nw%tZXWrtJph+71k39Bm+Il<_#3DJeoQ;IH4%6W878hm@z?6 zJTe<;eAU@0U1wIKy8Y#v-T8Za8*y|XtaNt_)fD8+ z2382To|B>;uma204!Qv$^9U0($%ItiW{`(ecOt|9NNh7m0dj&Y{~v(mulywQ+WUbI z$BxaHYO?J;2*eEVsVNZ0L{XS7F+xDx^t!Jajq*rvXQZDHlVPdlAxsgeuJblFZJRwCttDc=8d-6U?N|d z@6VAW#O;p_V>Mk`FR~`H@Bc|Q4#f=LnDo3a-%`OAfsRv2JHDL-OH+IU>^UE{HZg1VGY8&bGVFAWWRFx``73XVDgul%`ow^k0bSI zRe<8Nt@DgPZrg!8-=F$7+Hc9{g1krw57AMAFgy?(kpjaU;RkLKvUvmqDW28cYaYR3Qmi_y%n*`#=2Q6y1Ar)`-VnT4u?GFJu*0R${g)nk=QvM=y2a`%4wC z0a3$7?nnzkBXiFQ*c2_~xd)Qtr)VZ?vtPYQ-(T^U+7!3Qr-AE1b{??P1Ml08U!G%> zY;=nX3Y(8gp?|DQrfCz(5XHgm1cnMxe)?a?D)Sd`f*8TYf4cz7KdrNXZ4p~E7AcK;x&SmcttGNYn{svt}C&MuR@T~hVfP#Ur zs4pa}>Kj~HC|3F>`j{DvjQX3US9E^5=dCa{FX()Utb>C5Nb-ktzPxhnFH{9ahzuzt zr2{xRIzPGzTS2QVq7Kp1No5MFp*+YDfd8^E{84tj#XR%o*pees{$cGxEQ^#TB6g}wloE*ZeUKQ)jB?w`}K+v5# z5QxzrdxO5CS9pFp+3#onuiJYl$e$A>!wV34-vh1kK+$W=YclDj169}K3y|;rqC+pV zGURh_pNC1>i2!(E1`{L~UP}O9>x(<^_5KTtI00$P)tGbf^%+4yh#T zG~Lx{x+I(BpX-eFU`N%m!{CMVrig6D23n0Y|rQWip({Y zzUP|XV6N7>y@8ku=+$8|%@Wk9{JHXutCo!D`^a-3saHceHAb1y1d?=5cHfrYa)?uf zz;ai6TVPoc5RFQF-X%HC`>WqSVY%fM_Q5rrBcs;x{I z?Fek@$I%+PCq+`90o(`hhqYZjf|Yq*SjMc9lS1DrciwQ6?q^?I?+`X)Zh?DbVRLW# zjq-)Jc!XR)O|#)r_G;N4-J{Of)U2b~hcXGzXUbLU4EsYU_%uH(44={FP75W-E^19$ z^CS!*ba3-GqqL^Rb3gzPgPxAqx@N(FcQrm&$8>+O?QBKBnpY(}6{1 zlb%<5W^=_!m0lX%FL)(!1gpb=p4W%N-L-r^TC+^VfI$!J+@3cezWj3T7Tjx!zK$&!p*_61zazY95&W?lP`t`1G7L+x!OoaIBLkVjfh8F&cThPPNnqzj$ z$Mz*=U7db)boz*DRRDMJr3uxmPU=Zlu?*bO8@x!B`!@ihSHmQZ_sx5&(L_Fq+!RY4 z$?<#VI6k3evmoAMKC!8azczPK&TY+N5H_kei9s$bCUjV;l&PGA-hKhfuU_(h`I~|7 zryPfoX)TLXVpVYw)_PuthF5fnt1NS^TA7bi1jD}z?qI*lK%>rbs`0F@&#hbAPW@;6 z6pc`7#?P!gFEKEHfL|rS|8DCVKZpayfFZxbYv5dKj>2CvC&$5q2tuo%C{{8j0jKcq zh7~}xupn?v2-}l|m`_MVhIdjf)&Ur4s=lA>mE>GiA zXKJ*%Wa!;ZY11VIlJ%KO7#?vvc34|hBM5BsAq;Dg4g^t4791|DXi z(e_Tdg|-soW4?zqzj}-=6mN_{>rp%e@DSy#3ZMb$Bim<^7cT(4+wur!zM0-A2np6E86~ z40>@d<|=ukXSM5#KCR?qdd%yUW&Jwzc-05=rm3S*Jh7MLs%S~`T<;rA9u;R&X@=WM zZbthI@C%>0ttC#cE_nkZsbrsTSd!6wEpBgRiSQJM$GK#bI6{-JxgsJZGMsNchaqA7 zp&x5sXI3ujNNyT3Py6lGrqcJ1=qay{cCoY=L@?;sl(;C^O1wyYx-xsRtu5(t0Y+&e zw3-2sxm;cUt}OM}x-=M&*DL@J_+_=R3+`bvZSt%C> zki#Az80gIBTQh>sS(96i#)=qb)X(Ak$+rEpY%-Fch!YY8QRy!N0%MHK;^@Sp`*Q|7 zmn66dDkP?MA+Fkss=4(3`r7aB7WtjY@VSy5{5tq&$EEOfpCr{xQ$L4YkC%skK&l;i zu38+knl=2!qGNpGMd09jY2`(Sj+(FI_&bDpqz|<2o5g0Y5{j~{9p@x6M{sGqnGxM% zISSVpVUIM~8)i*>Cxw%)E$L_o0jhbIW!RHCseZKIu1yAp6L^PjxoBr(GHp1{~mpn6Y4{AI_`(GOk6YVaG&T71+vGfZ=%T)A)@I?@SshJ1w>>_B&=$=h_A`j;{MhD?_gGlFMIOkrbV^dhW`(|Evo6i8-OmoEaUiY?wmr?5 ze*{#kFNVKh=>QMEl$U|b9`Clu>4va|8-!Yex#{cA)W2I;cx+{0%X%F~qKWme4@kV z5&uoWf%31OFFJq!^I&C3rKGIfE8@u> zzFli*uU>_N#@Vgh^d!{uXaAt^<-RqM&3bP~c*M@St(TY{RL|qBeH`wTX*c$rIyyWklyii)_jZ2kP8A7m|#Nl*$q$z~cf?Kn+x3S}rp;33C}r6BIt`1Tw}#Mj z-FMti+b>@-AxE)$nMY-`Pe+dxzwz3#pD7H+p@S=tPGFe{8r39mM+@)qvccFoRY>ey z=cGX$(JrPdy0zG`RL|7!5`3-8)=YG6@pQYb5guG9ud_8Tk;A^1W?iEgZZE?#4r7u0I%Q&=xVhGA!D4<*jCmx>?TDipqeW9L)K* zP-~n1@?M2I0tA+4uexTxJm5B8efj?``ehX)%pUIZda^h)vaQtOuU@FH3ZQc&=L`m(cxcE#Yh@KRYkZR|ky4-R03mXjl&(YhoL=4x!OJH9 z$f|+e7T^JjaciGD!;odjl*Kfihq1H;+u4dgy>!V+QDY&}98F(Et-&v?>~-8@ExW)g zp(8(_o9H@IAYbU0@>CD|xjBWY_lK`gGOq}cNTTu{7@TYrN86V8+DzS{u{NN3&(7dg z@KwJ%Q77eCJqm2GS~oai-L&CnZVKHr;18N|6*O*VBF(#G2VdA@KuLO9giuYQNGW0c{`jcv zLgNT!5$0!9B6>tB#1c;-98c1G1&~9G%%0ZHx=vgY7)5|#07E|;X{wgapy=vsEEpY@ zWM7pll(^HBzVM`9oErP8q&HJinc;K$=$xq{tL3il{%!TidV{xw7CGH({?V%HP=iT+ zbXvxKp%ss>(W&3*62kvjj=QfWVbz)T1gq~mNA8fR$FnA!V|n_>zh{WKRm7rpCbi_i z5OAwKK-1aRkAx~9W(4@#K#l!B6H%NCH%kCXQ;ASv(ix(UElyFDZ)w2TF+TzXQ5JGZ zjbL{p2sVWCgvJ+;WB9k47~b)dR>tqFX54&PuH|*7XyUyNqM?+bep5R|t z;RQb!1&?VC%`UMhZ(q_nv{k}5=iub!<0grYywhf}-2PgF<(~K3%O~?+3c(cXkNoRl zNPD~EUg?`x$(!F7Vv0PKAHG(Y3zI3Sf(a9lFQY!s=7zl?2L=1f93sLUJ;OBFl^S4| ziPU2MOoJCmpVhWHXJrA4r~itfxgcTw=I z%5vm;QCXBOBEn7u&OyePQv?dah2j_`-pv9#idyO>K3}`8Xt`%Vit4PV**<`cM&}$d z-8%{iWDog`Jte!wk*J#^HZxzd`N74=DRT#V@i=Q2J`G9R!L1tUeZ{{*YkB{>6F0qi z>bom%ZqLzwrorEhW```d_YMhDfyy^xDnGy7#2t#97WrH*! z*TIM-P5+`Y*u2Q>gtvfcK8GawnA{^FIQ#ud?f*)5h)4mb9WlqJq!5pmv~!=CtutB| zsk~u!Ax{bLnk?kG3gtc|G8Pu><|rLnT#(ArEzR0b281hEc`=lojrXz>H9vv@;YBUZH}k)Rj8uO{*e9dWQfk_lUllu$x*Bt@-4a(hOpn-iX$pf z_vaHgzxKjC0^`vXfs~qJZj6r2#3+J9ln3UC?m)8vWg=-eSTDlN(Mh<+ZRY@A2HqQ; z$N>dyh|vP-|9O(*xc%T|kHkwp4G&O8QzWS*3s znOo(?%_Xu6gRXTw@T=sgIqjF<4+V8@T3e~1^ZElzCbopO3zTXZ5%Q0->@jk%`CMDv zz{t1Q5#0@o#RdhQ-{Cg?lUZyH&qesra+o0tM@sPgC@^8WKj|FI*su?=9Q_7})WA~f z0um@goM{STAk21wo=E-+aCw~xN6wYyVX}uTO#0G>1?hE8o}=;$vr4coQ2*Ay;!THP z&I01+v-idZF#BH$Ik&7{!6v+IZB?mCwED=vf+|)@^C;;dqx9^VP{XS+)R|Qdt8Z^= zK^E-;8%spOXK3-_*JmU9I*VC7t9os8 zI-dfT&BHa=96eyb2E-_Jg8&(H92|o*Ii?^rkiI&T{IHc9&A8n)`EZSV^Rp1>b6C1A zdh7ir-hb!p|8g_n7zgQ=>jRQ9EbHmjZ7vg>s*!A0FkC;i2`%@Eiz;msSgI@$4}9F< z5JasMw-`5%sc%9d)!U|BtVsKbXe<=(+O)yUu2nFq`s~=W@&sPsq>nP7>^;B2o_e7@ zPn?zd{7qF&pjl3RqPM}L(R?kB<0g9^oF1$<_cgUS@ce_0-sU|fzo;_JI%~?C&KQ!I zwR?9)<8xt@|MMul{^NGgg5+Op%&^s2$1PX}2Tq(6Sax6RL!6m1m1)|E1$Rekr4SZ! zJVb*orjiy|Uoo3KYBYW^p!|3?!h|0msK$0;#n=aO>I_uy4FVrXin&HN8qaS)Sk!)=nB&P zRwygruiKlMou1(G-g5OaYxk5kZ=HCft11t6_GxX7>UGI=zItxU>7nJi8LnA+$(lTG ztpHf4GkNI=?TiyXw>9^y*uk-Rc-S?2tx@a7)IIjRz&2)5p6tzus;rvYz4O&wt{5@0chBh_NCjvWr6vg$S2<%wbD9HkN4*!lY%SJlzL3G}Z#NH_i`%^v|VBSl~< zBN!!x0`}3cuojjC76mX*piXEFL2zW6oJv!U7su5AjD&P6!h7Hou+tGtE`Yi)RnYb) zM9#V1{SObc7-93~8S<50OF~<}j?JY}ZW(Uz;`kc(`7{smeTnl6{olSqUf zX(+xwH@)Ekb+~c9J-xf#s1jRB_NW~CHyfSz6Va+?=&H^O?;>|t@QA9dvzpcCNd7UD zv(YU^aoDJ50+R(hJ&DNwoQnh(it*=>w4sYojG94)6vd!X=Sl}8ZUl{s11(^YUdiaA zPDuoDigSUXzzOT8(y)gOYR~2i4(t# zgUglw=VmP&dOnYIx#s0=;#9#?dKg^Lqe|aT>#AB_Xu`qb^0FHyeB52OH3aPpce_z$ zYG-%j1v4oJJ~~sJ7OAy6ho!#%XwH?mbX)4}4AnRh5x;Ap7;(fpiv>LAjm`odL&qKU zX`OvUWy^$NcN8Y;$N5l_)bhs=+)WFAKq;4x6$p5+u*d}?<7da`YxP3C_7Dc>4^SxRS=8N*N?-v3#06n^mqXK&Fmc@VRcO3C z??E;uScF5ucH!h94$MxlpbtU6K{PzED6xRPpfnAX!!xy~e`8lmPYx6Q0o76GWB$Od zPx{@&7E^m}oTJjEpu_*L?=^O~P1><}0elmlyN6Lk^c6{>#LL~?L;Z$XwI&D5CqnpI zhI`95$Dgune`oIBHa_H7;>Ni6Bz4zm$qxlvf3%u=;Ky-PedAY)kDyYq!PYUT?>6;s zhY8FWx)rC;;`>=={(CoTcU`!H9hM-LtqR0^2oof#&_yZ?A(H}#>4c9m3^1`Ij;Lr$ zC#eM)7YcY04R9HN9)V#*S>XQ8hQs0}@Wf!9`Q@Gi-AB6iIg@f)hypb7G$?~$IQD%x z&ElrWEY71Rp7#Eoi8{R_F7m{SWym5;d(7aTuWEM{vUGfJT!erwDypw;Uj2!qm~B02 zUQk4jy*+$um}7#>GKHeMKi{fmZ1CRT`nNl+9;i46WFK$bbJbq zSbyuN;7F9R2;57CO&Y+0>D?L)n{?_sA}2^}I&AFI>(AQ!S_Q^-wRm>>Z%@R_4gFd8 zBRc81P=r(%62MoPjoY_blVMovhIFz4B#i72%pNH226{TKu%+&hRW#JM5?yLvg0%#l z;-do2K_ZYAIq{S996?RKX@6{AnksYEaiIGP_icoY5LaYLbP(#S(%PzT1Jym zkvFpynFz?j{@XWiE^ZUyZ-D6x>IYLe$RT1o#^S&M3hPm@6&MB(pkIUa&VUHK9u$}? zfJ`P;eFJ_&zFBvcMBW}Y2MGZcQCrzkp`~c|IS}dS|WIq;Yy6Z5=Iwz}J zo1TuV`jJCshd|XlqPfxLX=qV-X)P||?~v5@==8ghcqD9`lDoq)}Xprht7g zi%Ldc!V@}(6f`3DqczTk9UynAv7w$hxF9k?Xa1z7yAeF8u?^I=mb;XK9PK0}(r(?a z(k7?k8S--rIqg^R?p*Z;e>sP1^*p(YwzS1i{L{(L3rj@9>Mk8Ir zxidq!>svF`5__I*^KXDyq$4xWm!iwEZhmO`{H}8U4!Ji+x9wxWhhXvwdvegjVIU|} z!1A&N=tn-@fOz`z8r1 zS#zy5*INJiA7jon#vFsqmzx^E$9@;DLY;v2Kv#R<5g=fb3pftgzJ2=#+duf|x7W@c zJOA~ir>AFNV4z*@+^MJc@y7-Ry9{?}3k(bmckkY9Y;0s?W@c_>WxLq}paI?iY<=hL z3-Gts)-CV8^WOX0w*OZ8|K0$2XUn_qZGHdacL48f-Lmz)celOw?zEUsx*SB{||Fry>!8?F0?`+xf-Ush*`^5hK!<=10UZK51at`K5YQo@LqLas4gnnkIs|kG=n&8$ zphG~1fDQp20y+eA2>b&OfP_i5P2!6tP|#YRFlxXI51q!H5*XeC=FObF*}#NdzS7a} zbRV$`a{hkNej=fqMA`&EXPuQ*)ue%3IU5TUHCtXrdOFUj7g{?*W@du(Q1WSzaubm2 zyB$A^pM{4tTzn8#9i4HTFH(9`eMzhV&d%5Y=vG{!uW= zJo%MmLd7mzyu$8t54@(hHmJCf-%dWA9_S3c_8>O7yBcGzBBNHpcoT(h%o6TMdgPHo zdGb8r#LVKAl*0jOsqAZ=$r1>>w%hZ72%HQ$G;S6$rpQas#* zPx-BKGU(+LIrl1g+v>Km)twGV$RjB!fxhjFAz|i)b$2;rbp~w)TETN(X}*#ED+I6p z6#|S70v!aCItX+S2z3zXAkcP-zk6LU;N(_JE0OZsrDTLe#(3@KfC_M({A_Vnb_~!?fn9A{=Lcvq+8*Bfg|oz!r2>%F3bxjB`?zh+7XY%*}XwV1!_-B zpuF?X(~IizV=aCmK}H@OYw(~js^S4CLn*TR3mu;}+t#XIYK<)1eJ&29)K ziLVj~Gd2O60B*6fIuN0jt>#B|{u(D&n7f%zo_Qf&sZGI+wGZN=Uokou)Uli9{dmWt zZh-GT{CnPd0Jm3LtN&&3ch!M!`LQ(eq-PAPXrcB_-&6etxr1yBH^pAB1wU6eMXo1n z>>@L|H5WSXV3w|0uCP}ENtSwJngg0kt0%ag&n){bVz39+GVlK$n&BUC4O^G>X~jP1 zO+cFbNFOk3PS$kw=SGPO%b*=o1LB9w1o09UK2dQu0VpL~(Yaw7L$C3Cobi71a^PL& z!T^C|Y3RESWe6|L;p&lP8kSiovJlxOXt{Cw_QRC_>hj+CW!nV+;ItVaRr}*TU+w42 zd*1i{_96aO3`o�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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux161/captures/staircase-to-nowhere-wide.jpg b/Standalone/Research/WorldAssemblerM3/Linux161/captures/staircase-to-nowhere-wide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ade83b18e80b1f4f9b929befd5df33ffa162a846 GIT binary patch literal 50535 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�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

0^_tXZlwiO_62+M&q2b< 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 ownerJsonRoot.Get("liminal_pillar_grid_override").Data); + const bool hasLiminalStampFixture=!std::holds_alternative( + ownerJsonRoot.Get("liminal_stamp_fixture_override").Data); if((hasMotifFamily&&hasLiminalRoad)||(hasMotifFamily&&hasLiminalPillarGrid) - ||(hasLiminalRoad&&hasLiminalPillarGrid)) + ||(hasLiminalRoad&&hasLiminalPillarGrid) + ||(hasLiminalStampFixture&&(hasMotifFamily||hasLiminalRoad||hasLiminalPillarGrid))) {std::fprintf(stderr,"liminal content overrides must be used in separate fixtures\n");return 2;} - if(hasCoreLiminalField&&(hasMotifFamily||hasLiminalRoad||hasLiminalPillarGrid)) + if(hasCoreLiminalField&&(hasMotifFamily||hasLiminalRoad||hasLiminalPillarGrid + ||hasLiminalStampFixture)) {std::fprintf(stderr,"Core.Liminal.Field owns its variant geometry and cannot be combined with prototype content overrides\n");return 2;} if(hasMotifFamily) { @@ -2138,6 +2147,27 @@ int main(int argc,char** argv) "placement=regular_grid route_keepout=PASS band_clearance=PASS status=PASS\n", resolvedLayout.stampVocabularyVersion,resolvedLayout.stamps.size()); } + if(hasLiminalStampFixture) + { + std::vector requests; + if(!StandaloneWorldAssemblyPrototype::BuildLiminalStampFixtureRequests(ownerJsonRoot, + *ownerWorld,worldAssembly,resolvedLayout,requests,error) + ||!VoxelForgeCore::ResolveResolvedLayoutStampsV1( + resolvedLayout,seed,requests,error)) + {std::fprintf(stderr,"Liminal stamp fixture resolution failed: %s\n",error.c_str());return 2;} + const std::size_t boxFills=static_cast(std::count_if( + resolvedLayout.stamps.begin(),resolvedLayout.stamps.end(),[](const auto& stamp) + {return stamp.kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillBox;})); + const std::size_t boxCarves=static_cast(std::count_if( + resolvedLayout.stamps.begin(),resolvedLayout.stamps.end(),[](const auto& stamp) + {return stamp.kind==VoxelForgeCore::ResolvedSdfStampKindV1::carveBox;})); + const std::size_t stairs=static_cast(std::count_if( + resolvedLayout.stamps.begin(),resolvedLayout.stamps.end(),[](const auto& stamp) + {return stamp.kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillSteps;})); + std::printf("[LiminalStampFixtureResolved] vocabulary=%u records=%zu box_fills=%zu box_carves=%zu steps=%zu placement=bounded_flat_field status=PASS\n", + resolvedLayout.stampVocabularyVersion,resolvedLayout.stamps.size(), + boxFills,boxCarves,stairs); + } if(options.LandmarkChamberDemo) { std::vector requests; @@ -2639,5 +2669,6 @@ int main(int argc,char** argv) options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds, options.MovingCameraDwellSeconds,options.ColdWorkerTimeline, options.AuditPassageSourceClamp,options.AuditPassageCarveReach, - options.AuditPassageTileSeams,options.AuditLiminalRoadWalk); + options.AuditPassageTileSeams,options.AuditLiminalRoadWalk, + options.LiminalStampWalkAuditPath); } diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 166b5d4..d861a64 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -2385,7 +2386,8 @@ namespace StandaloneStreamBenchmark double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0, bool bColdWorkerTimeline=false,bool bAuditPassageSourceClamp=false, bool bAuditPassageCarveReach=false,bool bAuditPassageTileSeams=false, - bool bAuditLiminalRoadWalk=false) + bool bAuditLiminalRoadWalk=false, + const std::filesystem::path& LiminalStampWalkAuditPath={}) { using Clock=std::chrono::steady_clock; const std::clock_t ColdCpuOrigin=std::clock(); @@ -2555,7 +2557,8 @@ namespace StandaloneStreamBenchmark ||bAuditOreVeinYield||bAuditLandmarkReachability||bAuditStrateTransitions ||bAuditResolvedLayoutPassages||bAuditResolvedLayoutBoundaries ||bAuditTileShapeReadiness||bAuditBasePageEquivalence||bAuditRouteParity - ||bAuditPassageSourceClamp||bAuditPassageCarveReach||bAuditLiminalRoadWalk; + ||bAuditPassageSourceClamp||bAuditPassageCarveReach||bAuditLiminalRoadWalk + ||!LiminalStampWalkAuditPath.empty(); const bool bDeferFarWorld=bIncludeFarWorld&&!bMovingCameraTrace&&!bFarWorldAudit; VoxelForgeCore::ShapeBuildRequest ShapeRequest; ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z}; @@ -2821,7 +2824,8 @@ namespace StandaloneStreamBenchmark Streamer.Stop(); return passed?0:11; } - if(bAuditResolvedLayoutPassages||bAuditLiminalRoadWalk) + if(bAuditResolvedLayoutPassages||bAuditLiminalRoadWalk + ||!LiminalStampWalkAuditPath.empty()) { if(ResolvedLayout==nullptr||!CoreSnapshot.resolvedLayout()) {Streamer.Stop();std::fprintf(stderr,"[ResolvedWalkAudit] missing resolved-layout snapshot\n");return 2;} @@ -3230,6 +3234,82 @@ namespace StandaloneStreamBenchmark } return passed; }; + if(!LiminalStampWalkAuditPath.empty()) + { + struct FDoorwayWidthGate + { + std::string prefix; + std::uint32_t widthAxis=0; + double minimumWidthMetres=0.0; + }; + std::ifstream auditFile(LiminalStampWalkAuditPath); + std::vector> walkPath; + std::vector doorwayGates; + bool inputValid=static_cast(auditFile); + std::string line; + while(inputValid&&std::getline(auditFile,line)) + { + if(line.empty()||line[0]=='#')continue; + std::istringstream fields(line); + char record=0;fields>>record; + if(record=='P') + { + std::array point{}; + fields>>point[0]>>point[1]>>point[2]; + inputValid=inputValid&&static_cast(fields) + &&std::isfinite(point[0])&&std::isfinite(point[1]) + &&std::isfinite(point[2]); + if(inputValid) + walkPath.push_back({point[0]/coreMetres, + point[1]/coreMetres,point[2]/coreMetres}); + } + else if(record=='D') + { + FDoorwayWidthGate gate; + fields>>gate.prefix>>gate.widthAxis>>gate.minimumWidthMetres; + inputValid=inputValid&&static_cast(fields) + &&!gate.prefix.empty()&&gate.widthAxis<2 + &&std::isfinite(gate.minimumWidthMetres) + &&gate.minimumWidthMetres>=1.5; + if(inputValid)doorwayGates.push_back(std::move(gate)); + } + else inputValid=false; + } + std::uint64_t doorwayCount=0; + double narrowestDoorway=std::numeric_limits::infinity(); + bool doorwayWidthsPass=inputValid; + for(const auto& gate:doorwayGates) + { + std::uint64_t found=0; + for(const auto& stamp:ResolvedLayout->stamps) + { + if(!stamp.stableId.starts_with(gate.prefix))continue; + ++found;++doorwayCount; + const double width=2.0*stamp.halfExtentsMicrometres[gate.widthAxis]/1.0e6; + narrowestDoorway=std::min(narrowestDoorway,width); + if(width+1.0e-90; + } + if(doorwayCount==0)narrowestDoorway=0.0; + const FWalkAudit walkAudit=inputValid&&walkPath.size()>=2 + ?auditPlayerPath(Shape,walkPath,0.125,0.125,1.125,3,0.45):FWalkAudit{}; + const bool passed=inputValid&&doorwayWidthsPass&&walkAudit.passed; + std::printf("[LiminalStampWalkAudit] path_points=%zu stations=%llu capsule_samples=%llu " + "blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu " + "doorways=%llu narrowest_doorway_m=%.3f minimum_doorway_m=1.500 " + "status=%s\n",walkPath.size(), + static_cast(walkAudit.centers), + static_cast(walkAudit.capsuleSamples), + static_cast(walkAudit.blocked), + static_cast(walkAudit.supportSamples), + static_cast(walkAudit.unsupported), + static_cast(walkAudit.gradeFailures), + static_cast(doorwayCount),narrowestDoorway, + passed?"PASS":"FAIL"); + Streamer.Stop(); + return passed?0:14; + } if(bAuditLiminalRoadWalk&&!bAuditResolvedLayoutPassages) { const bool passed=auditLiminalRoadWalk(true); diff --git a/Standalone/Source/WorldAssemblyPrototype.h b/Standalone/Source/WorldAssemblyPrototype.h index 5c5e262..aa6dc89 100644 --- a/Standalone/Source/WorldAssemblyPrototype.h +++ b/Standalone/Source/WorldAssemblyPrototype.h @@ -822,6 +822,109 @@ namespace StandaloneWorldAssemblyPrototype return true; } + inline bool BuildLiminalStampFixtureRequests(const VFJson::Value& root, + const FStandaloneOwnerWorld& owner, + const VoxelForgeCore::WorldAssemblyManifest& assembly, + const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout, + std::vector& requests, + std::string& error) + { + using namespace VoxelForgeCore; + requests.clear(); + const VFJson::Value& fixture=root.Get("liminal_stamp_fixture_override"); + if(!fixture.IsObject()||!fixture.Get("version").IsNumber() + ||fixture.Get("version").Integer()!=1||!fixture.Get("stamps").IsArray()) + {error="liminal_stamp_fixture_override must be a version-1 object with a stamps array";return false;} + if(assembly.recipe.surfaceProfile.version!=1 + ||assembly.recipe.surfaceProfile.kind!=WorldAssemblySurfaceProfileKindV1::flatField + ||owner.CoreVoxelSizeMicrons==0) + {error="liminal stamp fixtures require a valid flatField SurfaceWorld recipe";return false;} + const VFJson::Value& strateValue=fixture.Get("strate_index"); + if(!strateValue.IsNumber()) + {error="liminal stamp fixture must select a resolved SurfaceWorld strate";return false;} + const auto strateIndex=static_cast(strateValue.Integer()); + const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(), + [strateIndex](const auto& value){return value.strateIndex==strateIndex + &&value.generatorKind=="SurfaceWorld";}); + if(strate==layout.strates.end()) + {error="liminal stamp fixture strate is not a resolved SurfaceWorld strate";return false;} + const auto toMicrometres=[](double value) + {return static_cast(std::llround(value*1000000.0));}; + const std::int64_t floorMicrometres=static_cast(std::llround( + static_cast(assembly.recipe.surfaceProfile.h0Subvoxels) + *owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel)); + const auto readOptionalMetres=[&](const VFJson::Value& object,const char* key, + double fallback,double& result) + { + const VFJson::Value& value=object.Get(key); + if(std::holds_alternative(value.Data)) + {result=fallback;return true;} + if(!value.IsNumber()||!std::isfinite(value.Number()))return false; + result=value.Number();return true; + }; + for(const auto& entry:fixture.Get("stamps").AsArray()) + { + if(!entry.IsObject()) + {error="liminal stamp fixture contains a malformed stamp record";return false;} + const auto* id=std::get_if(&entry.Get("stable_id").Data); + const auto* kind=std::get_if(&entry.Get("kind").Data); + const VFJson::Value& anchor=entry.Get("anchor_xy_m"); + const VFJson::Value& extents=entry.Get("half_extents_m"); + double zOffset=0.0,rounding=0.0,smooth=0.0; + if(!id||id->empty()||!kind||anchor.AsArray().size()!=2 + ||extents.AsArray().size()!=3 + ||!readOptionalMetres(entry,"z_offset_m",0.0,zOffset) + ||!readOptionalMetres(entry,"rounding_radius_m",0.0,rounding) + ||!readOptionalMetres(entry,"smooth_width_m",0.0,smooth)) + {error="liminal stamp fixture record requires an identity, kind, anchor, extents and finite metre values";return false;} + for(const auto& value:anchor.AsArray()) + if(!value.IsNumber()||!std::isfinite(value.Number())) + {error="liminal stamp anchor_xy_m must contain finite metre values";return false;} + for(const auto& value:extents.AsArray()) + if(!value.IsNumber()||!std::isfinite(value.Number())||value.Number()<=0.0) + {error="liminal stamp half_extents_m must contain positive finite metre values";return false;} + if(std::abs(anchor.AsArray()[0].Number())>5000.0 + ||std::abs(anchor.AsArray()[1].Number())>5000.0 + ||std::abs(zOffset)>1000.0||rounding<0.0||smooth<0.0) + {error="liminal stamp fixture values exceed their bounded ranges";return false;} + ResolvedLayoutStampRequestV1 request; + request.stableId=*id;request.strateIndex=strateIndex; + request.anchorPositionMicrometres={ + toMicrometres(anchor.AsArray()[0].Number()), + toMicrometres(anchor.AsArray()[1].Number()), + floorMicrometres+toMicrometres(zOffset)}; + request.halfExtentsMicrometres={toMicrometres(extents.AsArray()[0].Number()), + toMicrometres(extents.AsArray()[1].Number()), + toMicrometres(extents.AsArray()[2].Number())}; + request.roundingRadiusMicrometres=toMicrometres(rounding); + request.smoothWidthMicrometres=toMicrometres(smooth); + const VFJson::Value& yaw=entry.Get("yaw_quarter_turns"); + if(!std::holds_alternative(yaw.Data)) + { + if(!yaw.IsNumber()||yaw.Integer()<0||yaw.Integer()>3) + {error="liminal stamp yaw_quarter_turns must be an integer from zero through three";return false;} + request.yawQuarterTurns=static_cast(yaw.Integer()); + } + if(*kind=="fillBox")request.kind=ResolvedSdfStampKindV1::fillBox; + else if(*kind=="carveBox")request.kind=ResolvedSdfStampKindV1::carveBox; + else if(*kind=="carveArch")request.kind=ResolvedSdfStampKindV1::carveArch; + else if(*kind=="fillSteps") + { + request.kind=ResolvedSdfStampKindV1::fillSteps; + const VFJson::Value& count=entry.Get("step_count"); + if(!count.IsNumber()||count.Integer()<2||count.Integer()>128) + {error="fillSteps requires step_count from two through 128";return false;} + request.stepCount=static_cast(count.Integer()); + } + else + {error="liminal stamp kind must be fillBox, carveBox, carveArch or fillSteps";return false;} + requests.push_back(std::move(request)); + } + if(requests.empty()) + {error="liminal stamp fixture must resolve at least one stamp";return false;} + return true; + } + inline bool BuildCoreLiminalFieldRequests( const VoxelForgeCore::WorldAssemblyManifest& assembly, const FStandaloneOwnerWorld& owner,