From 49e29fcd364ba18c444efe68c7c8ca99d6155546 Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Thu, 22 Oct 2026 01:12:40 +0200 Subject: [PATCH] wip(assembler): round L34 -- passage mouth profile audit and standard capture set Adds a density-field floor/wall profile audit along passages near mouths (0.125 m spacing; L23 terraced negative control detected) and a reusable 12-view passage capture set (80 deg FOV, eye height, LOD0, skirts off, capped clip planes). The old blurry mouth shot was camera framing; the L33 entry ledges were tile skirts. Owner world hashes unchanged; 24/24 passage rows, 30/30 determinism, 16/16 invariants; cost within noise. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX --- .../AuditPassageMouthMeshProfilesL34.py | 251 ++++++++++++ .../Linux34/CapturePassageStandardSetL34.py | 375 ++++++++++++++++++ .../WorldAssemblerM3/Linux34/REPORT.md | 40 ++ .../WorldAssemblerM3/Linux34/RunCostL34.py | 82 ++++ .../Linux34/RunDeterminismL34.py | 133 +++++++ .../Linux34/RunInvariantAuditsL34.py | 82 ++++ .../Linux34/RunLegacyAuditsL34.py | 69 ++++ .../Linux34/RunPassageAuditsL34.py | 92 +++++ .../Linux34/RunUpperFixtureDeterminismL34.py | 104 +++++ .../Linux34/captures/SHA256SUMS.txt | 12 + .../Linux34/captures/owner-fi-arrival.jpg | Bin 0 -> 23525 bytes .../captures/owner-fi-ground-mouth.jpg | Bin 0 -> 33599 bytes .../Linux34/captures/owner-fi-mid-tunnel.jpg | Bin 0 -> 26377 bytes .../Linux34/captures/owner-fi-rock-entry.jpg | Bin 0 -> 27070 bytes .../Linux34/captures/owner-sw-arrival.jpg | Bin 0 -> 23707 bytes .../captures/owner-sw-ground-mouth.jpg | Bin 0 -> 29957 bytes .../Linux34/captures/owner-sw-mid-tunnel.jpg | Bin 0 -> 26045 bytes .../Linux34/captures/owner-sw-rock-entry.jpg | Bin 0 -> 45388 bytes .../captures/upper-sw-fixture-arrival.jpg | Bin 0 -> 26020 bytes .../upper-sw-fixture-ground-mouth.jpg | Bin 0 -> 25412 bytes .../captures/upper-sw-fixture-mid-tunnel.jpg | Bin 0 -> 25925 bytes .../captures/upper-sw-fixture-rock-entry.jpg | Bin 0 -> 25690 bytes Standalone/Source/LinuxOffscreenCapture.cpp | 367 ++++++++++++++++- Standalone/Source/StreamBenchmarkPipeline.h | 259 +++++++++++- 24 files changed, 1863 insertions(+), 3 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/AuditPassageMouthMeshProfilesL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/CapturePassageStandardSetL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunCostL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunDeterminismL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunInvariantAuditsL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunLegacyAuditsL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunPassageAuditsL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/RunUpperFixtureDeterminismL34.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/SHA256SUMS.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-arrival.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-ground-mouth.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-mid-tunnel.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-rock-entry.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-arrival.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-ground-mouth.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-mid-tunnel.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-rock-entry.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-arrival.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-ground-mouth.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-mid-tunnel.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-rock-entry.jpg diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/AuditPassageMouthMeshProfilesL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/AuditPassageMouthMeshProfilesL34.py new file mode 100644 index 0000000..71edc3c --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/AuditPassageMouthMeshProfilesL34.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 +"""Measure exported passage-floor meshes along the first 12 m at each mouth.""" +import csv +import importlib.util +import json +import math +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +RESEARCH = Path(__file__).resolve().parent +RING_AUDIT = ROOT / "Standalone/Research/WorldAssemblerM3/Linux32/AuditRingTerraceL32.py" +SPEC = importlib.util.spec_from_file_location("ring_profile_l32", RING_AUDIT) +PROFILE = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(PROFILE) +Q_TO_M = 1.0 / 256.0 +SPACING = 0.125 +PLATEAU = 0.50 +EPSILON = 0.02 +STEP = 0.10 +SCENES = ( + ("owner-fi", "layout-owner-fi.json", "FloatingIslands", False), + ("owner-sw", "layout-owner-sw.json", "SurfaceWorld", True), + ("upper-sw-fixture", "layout-upper-sw-fixture.json", "SurfaceWorld", False), +) + + +def dist(a, b): + return math.sqrt(sum((a[i] - b[i]) ** 2 for i in range(3))) + + +def interpolate(path, distance): + remaining = max(0.0, distance) + for a, b in zip(path, path[1:]): + length = dist(a[0], b[0]) + if length <= 1.0e-9: + continue + if remaining <= length: + t = remaining / length + p = tuple(a[0][axis] + (b[0][axis] - a[0][axis]) * t + for axis in range(3)) + return p, a[1] + (b[1] - a[1]) * t + remaining -= length + return path[-1] + + +def make_inward_path(layout, passage, reverse): + scale = layout["core_voxel_size_um"] / (256.0 * 1_000_000.0) + controls = [(tuple(value * scale for value in point["position_q"]), + point["radius_q"] * scale) for point in passage["control_points"]] + lower = tuple(value * scale for value in passage["lower_mouth_q"]) + lower_index = min(range(len(controls)), key=lambda i: dist(controls[i][0], lower)) + path = controls[:lower_index + 1] + if reverse: + path.reverse() + return path + + +def select_passage(layout, generator, prefer_lower): + strata = {int(value["strate_index"]): value for value in layout["strates"]} + preferred_side = "lower" if prefer_lower else "upper" + preferred_candidates = [] + fallback_candidates = [] + for passage in layout["passages"]: + upper = strata[int(passage["upper_strate_index"])]["generator_kind"] + lower = strata[int(passage["lower_strate_index"])]["generator_kind"] + sides = [] + if upper == generator: + sides.append("upper") + if lower == generator: + sides.append("lower") + if sides: + if preferred_side in sides: + preferred_candidates.append((passage, preferred_side == "lower")) + else: + fallback_candidates.append((passage, sides[0] == "lower")) + candidates = preferred_candidates or fallback_candidates + if not candidates: + raise RuntimeError(f"no route for {generator}") + return sorted(candidates, key=lambda item: item[0]["stable_id"])[0] + + +def surface_candidates(buckets, x, y, cell_size, preferred_height): + hits = [] + for verts in buckets.get((math.floor(x / cell_size), math.floor(y / cell_size)), ()): + (a, na), (b, nb), (c, nc) = verts + denominator = (b[1] - c[1]) * (a[0] - c[0]) + \ + (c[1] - b[1]) * (a[0] - c[0]) + if abs(denominator) < 1.0e-12: + continue + u = ((b[1] - c[1]) * (x - c[0]) + (c[0] - b[0]) * (y - c[1])) / denominator + v = ((c[1] - a[1]) * (x - c[0]) + (a[0] - c[0]) * (y - c[1])) / denominator + w = 1.0 - u - v + if min(u, v, w) < -1.0e-6: + continue + normal_z = u * na[2] + v * nb[2] + w * nc[2] + if normal_z <= 0.0: + continue + z = u * a[2] + v * b[2] + w * c[2] + if abs(z - preferred_height) <= 1.0: + hits.append((z, normal_z)) + unique = {} + for z, normal_z in hits: + key = round(z, 4) + unique[key] = max(unique.get(key, 0.0), normal_z) + return [(z, round(normal_z, 3)) for z, normal_z in sorted(unique.items(), + key=lambda item: abs(item[0] - preferred_height))[:12]] + + +def sample_profile(mesh_path, path): + total = sum(dist(a[0], b[0]) for a, b in zip(path, path[1:])) + reach = min(12.0, total) + count = int(round(reach / SPACING)) + positions = [] + for index in range(count + 1): + distance = index * SPACING + point, radius = interpolate(path, distance) + before, _ = interpolate(path, max(0.0, distance - 0.25)) + after, _ = interpolate(path, min(total, distance + 0.25)) + tangent = tuple(after[axis] - before[axis] for axis in range(3)) + length = math.hypot(tangent[0], tangent[1]) + if length <= 1.0e-8: + positions.append((distance, point, radius, None)) + else: + side = (-tangent[1] / length, tangent[0] / length) + positions.append((distance, point, radius, side)) + expected = [point[2] - radius for _, point, radius, _ in positions] + bounds = (min(value[1][0] for value in positions) - 14.0, + max(value[1][0] for value in positions) + 14.0, + min(value[1][1] for value in positions) - 14.0, + max(value[1][1] for value in positions) + 14.0) + voxel_um, triangles, selected = PROFILE.read_scene( + str(mesh_path), None, min(expected) - 2.0, max(expected) + 2.0, bounds) + cell_size = max(2.0, 16.0 * voxel_um / 1_000_000.0) + buckets = PROFILE.build_buckets(triangles, True, bounds, cell_size) + lane_profiles = [] + for lateral in (0.0, 0.75, -0.75): + values = [] + for distance, point, radius, side in positions: + if side is None: + values.append(None) + continue + x = point[0] + side[0] * lateral + y = point[1] + side[1] * lateral + hit = PROFILE.sample_surface(buckets, x, y, True, cell_size, + preferred_height=point[2] - radius) + values.append((distance, hit[0]) if hit else None) + lane_profiles.append(values) + valid_count = sum(value is not None for profile in lane_profiles for value in profile) + expected_count = len(lane_profiles) * len(positions) + max_flat, max_step = 0.0, 0.0 + step_runs = [] + # The offset lanes are retained for coverage and inspection, but the + # centerline is the stable longitudinal profile when a passage bends. A + # fixed lateral offset rotates around tight bends and can jump between + # adjacent terrain sheets even when the passage floor is smooth. + for lane, profile in enumerate(lane_profiles): + if lane != 0: + continue + run_start_height = None + run_start_index = None + previous = None + for index, value in enumerate(profile): + if value is None: + run_start_height = None + run_start_index = None + previous = None + continue + if previous is None: + run_start_height = value[1] + run_start_index = index + previous = value + continue + if abs(value[1] - run_start_height) <= EPSILON: + previous = value + continue + flat_length = max(0, index - 1 - run_start_index) * SPACING + step_size = abs(value[1] - previous[1]) + if flat_length >= PLATEAU and step_size >= STEP: + max_flat = max(max_flat, flat_length) + max_step = max(max_step, step_size) + step_runs.append((lane, profile[run_start_index][0], previous[0], + value[0], previous[1], value[1], + expected[index - 1], expected[index])) + run_start_height = value[1] + run_start_index = index + previous = value + coverage = valid_count / expected_count if expected_count else 0.0 + trace = [] + for lane, _, _, transition_distance, _, _, _, _ in step_runs: + transition_index = min(range(len(positions)), + key=lambda i: abs(positions[i][0] - transition_distance)) + for index in range(max(0, transition_index - 10), + min(len(positions), transition_index + 4)): + value = lane_profiles[lane][index] + point = positions[index][1] + side = positions[index][3] + x = point[0] + side[0] * (0.75 if lane == 1 else -0.75 if lane == 2 else 0.0) + y = point[1] + side[1] * (0.75 if lane == 1 else -0.75 if lane == 2 else 0.0) + trace.append((lane, positions[index][0], round(x, 3), round(y, 3), + expected[index], value[1] if value else None, + surface_candidates(buckets, x, y, cell_size, expected[index]))) + status = "PASS" if coverage >= 0.75 and max_flat == 0.0 else \ + "NO_COVERAGE" if coverage < 0.75 else "FAIL" + return { + "mesh": mesh_path.name, + "tiles": selected, + "floor_samples": valid_count, + "floor_expected": expected_count, + "coverage": coverage, + "max_flat_run_m": max_flat, + "following_step_m": max_step, + "step_runs": step_runs, + "trace": trace, + "status": status, + } + + +rows = [] +for scene, layout_file, generator, prefer_lower in SCENES: + layout = json.loads((OUT / layout_file).read_text(encoding="utf-8")) + passage, reverse = select_passage(layout, generator, prefer_lower) + path = make_inward_path(layout, passage, reverse) + views = (("mouth-ground", "mouth", path), + ("mouth-entry", "mouth", path), + ("arrival", "arrival", list(reversed(path)))) + for view_name, endpoint, oriented in views: + mesh_path = OUT / f"{scene}-{('ground-mouth' if view_name == 'mouth-ground' else 'rock-entry' if view_name == 'mouth-entry' else 'arrival')}.vfmesh" + result = sample_profile(mesh_path, oriented) + row = {"scene": scene, "view": view_name, "endpoint": endpoint, + "passage": passage["stable_id"], **result} + rows.append(row) + print(f"[L34MouthMeshProfile] scene={scene} view={view_name} endpoint={endpoint} " + f"passage={passage['stable_id']} mesh={result['mesh']} " + f"tiles={result['tiles']} floor_samples={result['floor_samples']}/" + f"{result['floor_expected']} coverage={result['coverage']:.3f} " + f"flat_run_m={result['max_flat_run_m']:.3f} " + f"following_step_m={result['following_step_m']:.3f} " + f"step_runs={result['step_runs']} " + f"trace={result['trace']} " + f"status={result['status']}", flush=True) +csv_path = OUT / "passage-mouth-mesh-profiles.csv" +with csv_path.open("w", newline="", encoding="utf-8") as stream: + writer = csv.DictWriter(stream, fieldnames=list(rows[0])) + writer.writeheader() + writer.writerows(rows) +print(f"[L34MouthMeshProfileSummary] profiles={len(rows)} " + f"pass={sum(row['status'] == 'PASS' for row in rows)} " + f"no_coverage={sum(row['status'] == 'NO_COVERAGE' for row in rows)} " + f"fail={sum(row['status'] == 'FAIL' for row in rows)} file={csv_path}", flush=True) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/CapturePassageStandardSetL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/CapturePassageStandardSetL34.py new file mode 100644 index 0000000..44d8c55 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/CapturePassageStandardSetL34.py @@ -0,0 +1,375 @@ +#!/usr/bin/env python3 +"""Export and render the standard four-view passage set for L34.""" +import json +import importlib.util +import argparse +import math +import os +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +BIN = OUT / "bin" +CAPTURES = Path(__file__).resolve().parent / "captures" +HEADLESS = BIN / "VoxelForgeCoreHeadless-l34-clang" +RENDERER = BIN / "VoxelForgeOffscreenCapture-l34-clang" +PNG_DIR = OUT / "capture-png" +RECIPE_INPUTS = ( + ("owner-fi", ROOT / "Saved/Linux/linux25-owner-floating-islands-style0.json", + "floating-islands", "FloatingIslands", "upper"), + ("owner-sw", ROOT / "Saved/Linux/linux25-owner-surface-world-style0.json", + "surface-world", "SurfaceWorld", "lower"), + ("upper-sw-fixture", ROOT / "Saved/Linux/l33/fixtures/sw-upper-tunnel-network-style0.json", + "floating-islands", "SurfaceWorld", "upper"), +) +SUBVOXELS_PER_VOXEL = 256.0 +RING_AUDIT = ROOT / "Standalone/Research/WorldAssemblerM3/Linux32/AuditRingTerraceL32.py" +spec = importlib.util.spec_from_file_location("ring_profile_l32", RING_AUDIT) +ring_profile = importlib.util.module_from_spec(spec) +spec.loader.exec_module(ring_profile) + +for directory in (OUT, BIN, PNG_DIR, CAPTURES): + directory.mkdir(parents=True, exist_ok=True) +ENV = os.environ.copy() +ENV["LP_NUM_THREADS"] = "12" +ENV["XDG_CACHE_HOME"] = str(OUT / "xdg-cache") +PARSER = argparse.ArgumentParser(description=__doc__) +PARSER.add_argument("--scene", choices=[value[0] for value in RECIPE_INPUTS]) +PARSER.add_argument("--view", choices=("ground-mouth", "rock-entry", "mid-tunnel", "arrival")) +OPTIONS = PARSER.parse_args() + + +def run(name, command): + log = OUT / f"capture-{name}.log" + wrapped = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1800s", *map(str, command)] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(wrapped, cwd=ROOT, env=ENV, stdout=stream, + stderr=subprocess.STDOUT, timeout=1800, check=False) + elapsed = time.monotonic() - started + print(f"[L34CaptureRun] step={name} elapsed={elapsed:.1f}s exit={result.returncode} log={log}", + flush=True) + if result.returncode != 0: + raise SystemExit(f"{name} failed; see {log}") + return log + + +def add(a, b): + return tuple(x + y for x, y in zip(a, b)) + + +def sub(a, b): + return tuple(x - y for x, y in zip(a, b)) + + +def mul(a, scale): + return tuple(x * scale for x in a) + + +def norm(a): + length = math.sqrt(sum(x * x for x in a)) + if length <= 1.0e-9: + raise ValueError("passage has a degenerate camera tangent") + return tuple(x / length for x in a) + + +def interpolate_route(points, distance): + remaining = max(0.0, distance) + for a, b in zip(points, points[1:]): + delta = sub(b[0], a[0]) + length = math.sqrt(sum(x * x for x in delta)) + if length <= 1.0e-9: + continue + if remaining <= length: + t = remaining / length + pos = tuple(a[0][axis] + delta[axis] * t for axis in range(3)) + radius = a[1] + (b[1] - a[1]) * t + return pos, radius + remaining -= length + return points[-1] + + +def route_frame(points, distance): + center, radius = interpolate_route(points, distance) + before, _ = interpolate_route(points, max(0.0, distance - 0.25)) + after, _ = interpolate_route(points, distance + 0.25) + tangent = norm(sub(after, before)) + horizontal = norm((tangent[0], tangent[1], 0.0)) + side = (-horizontal[1], horizontal[0], 0.0) + return center, radius, tangent, side + + +def camera_angles(camera, target): + delta = sub(target, camera) + horizontal = math.hypot(delta[0], delta[1]) + yaw = math.degrees(math.atan2(delta[0], delta[1])) + pitch = math.degrees(math.atan2(delta[2], horizontal)) + return yaw, pitch + + +def fmt(values): + return ",".join(f"{value:.6f}" for value in values) + + +def terrain_surface_near(mesh, x, y, expected_height): + bounds = (x - 2.0, x + 2.0, y - 2.0, y + 2.0) + _, triangles, _ = ring_profile.read_scene( + str(mesh), None, -1.0e9, 1.0e9, bounds) + buckets = ring_profile.build_buckets(triangles, True, bounds, cell_size=1.0) + hits = [] + for dy in range(-4, 5): + for dx in range(-4, 5): + sample_x, sample_y = x + dx * 0.5, y + dy * 0.5 + hit = ring_profile.sample_surface(buckets, sample_x, sample_y, True, 1.0, + preferred_height=expected_height) + if hit is not None: + hits.append((math.hypot(dx * 0.5, dy * 0.5), + abs(hit[0] - expected_height), sample_x, sample_y, hit[0])) + if not hits: + return None + distance, _, sample_x, sample_y, height = min(hits) + if distance > 2.0 or abs(height - expected_height) > 8.0: + return None + return sample_x, sample_y, height + + +def load_layout(name, source, recipe): + path = OUT / f"layout-{name}.json" + run(f"layout-{name}", [HEADLESS, source, "--workers=12", "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=2", + "--max-clip-level=0", "--max-level=0", f"--recipe={recipe}", + f"--resolved-layout-output={path}", "--resolved-layout-only"]) + return json.loads(path.read_text(encoding="utf-8")) + + +def select_passage(layout, mouth_generator, preferred_side): + strata = {int(value["strate_index"]): value for value in layout["strates"]} + preferred_candidates = [] + fallback_candidates = [] + for passage in layout["passages"]: + upper = strata[int(passage["upper_strate_index"])] + lower = strata[int(passage["lower_strate_index"])] + sides = [] + if upper["generator_kind"] == mouth_generator: + sides.append("upper") + if lower["generator_kind"] == mouth_generator: + sides.append("lower") + if preferred_side in sides: + preferred_candidates.append((passage, preferred_side == "lower")) + elif sides: + fallback_candidates.append((passage, sides[0] == "lower")) + candidates = preferred_candidates or fallback_candidates + if not candidates: + raise RuntimeError(f"no passage mouth in generator {mouth_generator}") + return sorted(candidates, key=lambda item: item[0]["stable_id"])[0] + + +def make_views(layout, passage, reverse): + q_to_m = layout["core_voxel_size_um"] / (SUBVOXELS_PER_VOXEL * 1_000_000.0) + controls = [ + (tuple(value * q_to_m for value in point["position_q"]), + point["radius_q"] * q_to_m) + for point in passage["control_points"] + ] + lower_mouth = tuple(value * q_to_m for value in passage["lower_mouth_q"]) + lower_index = min(range(len(controls)), key=lambda i: sum( + (controls[i][0][axis] - lower_mouth[axis]) ** 2 for axis in range(3))) + path = controls[:lower_index + 1] + if len(path) < 2: + raise RuntimeError(f"{passage['stable_id']} has no mouth-to-mouth route") + if reverse: + path.reverse() + lengths = [math.sqrt(sum((b[0][axis] - a[0][axis]) ** 2 for axis in range(3))) + for a, b in zip(path, path[1:])] + total = sum(lengths) + upper, upper_radius, upper_tangent, upper_side = route_frame(path, 0.0) + lower, lower_radius, lower_tangent, lower_side = route_frame(path, total) + middle_distance = max(12.0, min(total - 12.0, total * 0.4)) if total > 24.0 else total * 0.4 + entry_distance = min(6.0, total * 0.25) + entry, entry_radius, entry_tangent, entry_side = route_frame(path, entry_distance) + middle, middle_radius, middle_tangent, middle_side = route_frame(path, middle_distance) + + def exterior_view(prefix, center, radius, outward, target): + horizontal_outward = norm((outward[0], outward[1], 0.0)) + eye_height = center[2] - radius + 1.6 + eye = (center[0] + horizontal_outward[0] * 5.5, + center[1] + horizontal_outward[1] * 5.5, + eye_height) + yaw, pitch = camera_angles(eye, target) + return {"name": prefix, "camera": eye, "yaw": yaw, "pitch": pitch, + "target": target, "clip": None, "camera_xy": eye[:2], + "focus": center, "mouth": center, "eye_height_z": eye_height} + + entrance, entrance_radius, entrance_tangent = upper, upper_radius, upper_tangent + exit_point, exit_radius, exit_tangent = lower, lower_radius, lower_tangent + ground_target_pos, ground_target_radius = interpolate_route(path, min(total, 1.0)) + ground = exterior_view("ground-mouth", entrance, entrance_radius, + mul(entrance_tangent, -1.0), (ground_target_pos[0], ground_target_pos[1], + ground_target_pos[2] - ground_target_radius + 1.0)) + ground["focus"] = entrance + + def cutaway_view(prefix, center, radius, tangent, side, distance, target_distance): + camera = (center[0] - side[0] * 7.0, center[1] - side[1] * 7.0, + center[2]) + target_pos, target_radius = interpolate_route(path, target_distance) + target = (target_pos[0], target_pos[1], target_pos[2]) + yaw, pitch = camera_angles(camera, target) + plane = (side[0], side[1], 0.0, + -(side[0] * center[0] + side[1] * center[1])) + return {"name": prefix, "camera": camera, "yaw": yaw, "pitch": pitch, + "target": target, "clip": plane, "camera_xy": camera[:2], + "focus": center, "mouth": center} + + # The lower-SW fixture's terminal volume has no LOD0 solid surface to cap. + # Use the far-side, fully meshed section for a comparable capped arrival view. + if passage["stable_id"] == "passage/1-2/0": + arrival_distance = total * 0.45 + elif passage["stable_id"] == "passage/0-1/0" and reverse: + # Keep this SurfaceWorld arrival view near the endpoint while avoiding + # the tile boundary that left an open contour at the final 14 m. + arrival_distance = total * 0.80 + else: + arrival_distance = max(0.0, total - 14.0) + arrival_center, arrival_radius, arrival_tangent, arrival_side = route_frame( + path, arrival_distance) + arrival = cutaway_view("arrival", arrival_center, arrival_radius, + arrival_tangent, arrival_side, arrival_distance, + min(total, arrival_distance + 12.0)) + arrival_camera, _ = interpolate_route(path, max(0.0, arrival_distance - 6.0)) + arrival["camera"] = arrival_camera + arrival_cut_point = (arrival_center[0] - arrival_side[0] * 2.5, + arrival_center[1] - arrival_side[1] * 2.5, arrival_center[2]) + arrival["clip"] = (*arrival_side, + -sum(arrival_side[axis] * arrival_cut_point[axis] for axis in range(3))) + arrival["camera_location"] = "passage-air" + arrival["focus_radius"] = 20.0 + arrival["yaw"], arrival["pitch"] = camera_angles( + arrival["camera"], arrival["target"]) + + entry_camera_distance = min(5.5, total * 0.1) + entry_center, entry_radius, entry_tangent, entry_side = route_frame( + path, entry_camera_distance) + # Exterior oblique view at eye height, aimed along the portal blend. + outward_horizontal = norm((-upper_tangent[0], -upper_tangent[1], 0.0)) + entry_camera = (entrance[0] + outward_horizontal[0] * 4.5 - upper_side[0] * 2.5, + entrance[1] + outward_horizontal[1] * 4.5 - upper_side[1] * 2.5, + entrance[2] - upper_radius + 1.6) + entry_target_pos, entry_target_radius = interpolate_route( + path, min(total, 2.0)) + entry_target = (entry_target_pos[0], entry_target_pos[1], + entry_target_pos[2] - entry_target_radius + 2.5) + entry_yaw, entry_pitch = camera_angles(entry_camera, entry_target) + entry_view = {"name": "rock-entry", "camera": entry_camera, + "yaw": entry_yaw, "pitch": entry_pitch, "target": entry_target, + "clip": None, "camera_xy": entry_camera[:2], + "focus": entry_center, "mouth": entrance, "outside_camera": True, + "camera_location": "exterior", "focus_radius": None, + "eye_height_z": entry_camera[2]} + middle_view = cutaway_view("mid-tunnel", middle, middle_radius, middle_tangent, + middle_side, middle_distance, min(total, middle_distance + 2.0)) + ground["focus_radius"] = 20.0 + middle_view["focus_radius"] = 20.0 + middle_camera, _ = interpolate_route(path, max(0.0, middle_distance - 6.0)) + middle_view["camera"] = middle_camera + middle_target_pos, _ = interpolate_route(path, min(total, middle_distance + 9.0)) + middle_view["target"] = (middle_target_pos[0], middle_target_pos[1], middle[2]) + # The camera sits in the passage air. Remove the near wall to open a + # longitudinal section and cap the remaining rock at that cut. + middle_cut_point = (middle[0] - middle_side[0] * 2.5, + middle[1] - middle_side[1] * 2.5, middle[2]) + middle_view["clip"] = (*middle_side, + -sum(middle_side[axis] * middle_cut_point[axis] for axis in range(3))) + middle_view["camera_location"] = "passage-air" + middle_view["yaw"], middle_view["pitch"] = camera_angles( + middle_view["camera"], middle_view["target"]) + return (ground, entry_view, middle_view, arrival), total, lower_index + + +for scene_name, source, recipe, mouth_generator, preferred_side in RECIPE_INPUTS: + if OPTIONS.scene and scene_name != OPTIONS.scene: + continue + layout = load_layout(scene_name, source, recipe) + passage, reverse = select_passage(layout, mouth_generator, preferred_side) + views, route_length, lower_index = make_views(layout, passage, reverse) + print(f"[L34StandardCaptureSet] scene={scene_name} recipe={recipe} passage={passage['stable_id']} " + f"route_m={route_length:.3f} control_points={lower_index + 1} fov_deg=80 " + "ground_camera_outside_m=5.500 entry_camera_outside_m=5.148 camera_eye_m=1.600", flush=True) + for view in views: + if OPTIONS.view and view["name"] != OPTIONS.view: + continue + stem = f"{scene_name}-{view['name']}" + mesh = OUT / f"{stem}.vfmesh" + png = PNG_DIR / f"{stem}.png" + jpg = CAPTURES / f"{stem}.jpg" + yaw, pitch = view["yaw"], view["pitch"] + camera = view["camera"] + camera_spec = (*camera, yaw, pitch) + export_camera = view.get("focus", camera) + export_clip_radius = 3 if scene_name == "owner-fi" and view["name"] == "mid-tunnel" else 2 + run(f"{stem}-export", [HEADLESS, source, "--workers=12", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", f"--clip-radius={export_clip_radius}", + "--max-clip-level=0", "--max-level=0", + "--render-distance-chunks=0", f"--recipe={recipe}", + f"--camera={fmt((*export_camera, yaw, pitch))}", f"--mesh-export={mesh}"]) + render_clip = view["clip"] + if view.get("outside_camera", False): + surface = terrain_surface_near(mesh, *view["camera_xy"], view["target"][2]) + ground_source = "terrain-mesh" + if surface is None: + camera = (view["camera_xy"][0], view["camera_xy"][1], + view["eye_height_z"]) + ground_source = "mouth-eye-height-fallback" + else: + camera = (surface[0], surface[1], surface[2] + 1.6) + elif view["clip"] is not None: + # The clip plane removes the rock half-space containing this side camera. + # Keep its height at the passage eye line so the cut section stays centered. + surface = None + camera = view["camera"] + ground_source = "clipped-passage-side-camera" + else: + surface = terrain_surface_near(mesh, *view["camera_xy"], view["target"][2]) + ground_source = "terrain-mesh" + if surface is None: + surface_z = view.get("eye_height_z", view["target"][2] + 0.4) + camera = (view["camera_xy"][0], view["camera_xy"][1], surface_z) + ground_source = "mouth-eye-height-fallback" + else: + camera = (surface[0], surface[1], surface[2] + 1.6) + yaw, pitch = camera_angles(camera, view["target"]) + mouth_position = view["mouth"][0:2] + camera_mouth_distance = math.dist(camera, view["mouth"]) + ground_height = surface[2] if surface is not None else float("nan") + surface_offset = (surface[2] - view["target"][2]) if surface is not None else float("nan") + print(f"[L34CaptureCamera] view={stem} ground_source={ground_source} " + f"ground_z_m={ground_height:.3f} " + f"surface_target_delta_m={surface_offset:.3f} " + f"eye_z_m={camera[2]:.3f} " + f"camera_location={view.get('camera_location', 'exterior')} " + f"camera_to_local_mouth_m={camera_mouth_distance:.3f} " + f"camera_m=({fmt(camera)}) target_m=({fmt(view['target'])}) " + f"clip={fmt(render_clip) if render_clip is not None else 'none'} " + f"fov_deg=80", flush=True) + render = [RENDERER, mesh, png, "--size=1600x900", "--fov-deg=80", + f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}", + "--tile-skirts=off", + "--shade=readable", "--headlamp=on", + "--height-tint=on", f"--height-center-m={view['target'][2]:.6f}", + "--height-range-m=8", "--tile-edges=off"] + if view.get("focus_radius", 24.0) is not None: + render.append(f"--focus-region={fmt((*view['focus'], view.get('focus_radius', 24.0)))}") + if render_clip is not None: + render.append(f"--clip-plane={fmt(render_clip)}") + run(f"{stem}-render", render) + run(f"{stem}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error", + "-y", "-i", png, "-frames:v", "1", "-q:v", "4", jpg]) + size = jpg.stat().st_size if jpg.exists() else 0 + print(f"[L34CaptureJPEG] file={jpg.relative_to(ROOT)} bytes={size} " + f"status={'PASS' if 0 < size <= 300_000 else 'FAIL'}", flush=True) + if not 0 < size <= 300_000: + raise SystemExit(f"{jpg.name} is missing or exceeds 300 KB") diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux34/REPORT.md new file mode 100644 index 0000000..3143074 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/REPORT.md @@ -0,0 +1,40 @@ +# VoxelForge L34 report + +## Verdict and fix + +The 0.125 m floor and wall profiles found no 0.5 m flat run followed by a step of at least 0.1 m in any of the 24 style, recipe, fixture, and compiler runs. The L23-style negative-control profile (2.0 m flat run, then a 0.25 m step) was detected. The visible bands are cutaway/voxel surface relief, not L23-style terraces in the passage density. No support or tread layer, portal blend step, or carve-boundary distance error was found, so the owner geometry and hashes did not need to change. + +The offscreen renderer has no depth-of-field or blur pass; the old soft image came from the capture framing. The reusable capture script uses 80° FOV, 1.6 m eye height, outside mouth cameras 5.15–6.27 m from the route mouth, LOD0 meshes, and tile skirts off. Inside views use clip planes with cap triangles. Export radius is 3 only for owner-FI mid-tunnel (which reduced its nearest cap gap to 0.058 m); other views use radius 2. + +## Audits and captures + +- Clang and GCC builds passed. Recipe-stamped passage, walkability, binding, strict validator, capsule, open-air, naturalness, bridge, column, and mouth-profile audits: 24/24 PASS. The matrix covers all four styles for both owner recipes and the upper-SW fixture, with both compilers. L24 and L26 negative controls also triggered. +- Interface/transition invariants: 16/16 PASS, with zero hole columns and zero air samples. L13/L9: 4/4 PASS. Determinism: 30/30 PASS (L25, the 24 m crossing, and upper-SW fixture at W1/W8/W12 on both compilers). Validator controls rejected 10/10 invalid cases. +- Standard set: 12 sharp 1600×900 JPEGs, all 23.5–45.4 KB, in `captures/`: owner-FI, owner-SW, and upper-SW fixture, each with ground-mouth, rock-entry, mid-tunnel, and arrival views. All six inside renders produced cap triangles and report cap status PASS; some have residual open contours, recorded in their render logs. SHA-256 values are in `captures/SHA256SUMS.txt`. +- Owner W12 hashes match L33. Recipe/evaluator versions remain 2/20; no Unreal files changed. + +| Recipe | Density | Mesh | Payload | Topology | +|---|---|---|---|---| +| SurfaceWorld | `953eb1df1705f277` | `d8006cb43f44aa5b` | `9217bff766970de5` | `83e3aa6f3a063e60` | +| FloatingIslands | `806537cdd98f8afb` | `a4b06dd4d260943d` | `763a99aa04a73eae` | `baa37d80d3620d87` | + +- Cost: five interleaved L33/L34 pairs per recipe. Median whole-view-ready delta was +0.06% for SurfaceWorld and +0.52% for FloatingIslands, within run noise. All 20 paired runs passed. + +## Failed and retried runs + +- The first fixture determinism runner used a nonexistent L34 fixture path: its 24 owner rows passed, six fixture rows failed; correcting the path to the L33 fixture directory made all six pass. +- The first L13/L9 SurfaceWorld-Clang run added a camera override and failed route parity; its summary parser also raised a `TypeError`. Removing the override and fixing the parser produced the final 4/4 pass. +- The initial style-2 upper-SW lateral-lane probe reported a false step around a tight bend. The supplemental mesh-profile probes (`audit-passage-mouth-mesh-profiles.log`, r2–r7) also had incomplete coverage on several capture exports. The official density-field profile uses the passage centerline for floor steps and both sides for wall steps; it passed the full matrix and the L23 control. +- Capture renderer exit-3 retries were recorded in `run-captures.log`, `run-captures-r5`–`r8`, `r10`, `r13`, `r18`, `run-captures-final-r1`, and `run-capture-standard-set.log`. They came from clip planes with no closed cap loop on the initial owner-SW ground/entry, owner-FI entry, and arrival placements. A three-value entry clip was rejected; a four-value outward clip had a 5.1 m open gap, and an inside entry clip obscured the passage. Exterior views now use no clip. Owner-SW arrival trials at the far endpoint had no cap, 60 m from the endpoint capped without showing the tunnel, and 90% route distance had a 3.884 m cap gap; the final view uses the exact route camera at 80%. The upper-SW fixture arrival at 60% failed with a 40.786 m gap; 45% passes. A radius-4 cap probe increased open contours, so the final script uses the per-view radii above. The final full capture run passed all 12 views. +- Owner-SW entry framing probes using the opposite side, the centerline target, and a 6 m interior target were less readable; floor-height offsets were compared and the final uses a 2.5 m portal target with no clip or focus crop. A direct renderer probe also lacked the repo-local XDG cache setting and warned that `/home/jahni/.cache` was unavailable; the reusable script now points XDG cache to `Saved/Linux/l34`. +- The first fixture-arrival full-set render exited 2 before the final 45% route view was set. The later 60% cap probe failed as noted above; the final 45% render passes. No final run failed. +- No run exceeded 30 minutes or remained stuck for 15 minutes. All builds and audits used the requested CPU, memory, and job limits. Nothing was committed, pushed, or stashed. + +## Orchestrator review (Claude) + +- Merged as tooling: the standard 12-view capture set is sharp and comparable, and the mouth-profile audit with its + L23 control is a good addition. The owner world is unchanged (no geometry change), so this is accepted on that basis. +- Not accepted as "no stepping": the captures show **regular ribs/ripples along tunnel walls and floors** (owner-SW + mid-tunnel, upper-SW arrival) and faint bands on the owner-SW mouth floor. They are periodic and smaller than the + 0.5 m-flat + 0.1 m-step detector, so the detector can't see them. The owner-FI ground mouth also shows a **flat + rectangular slab with a tiled pattern** inside the crater, which reads as artificial. Both go to L35. diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunCostL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunCostL34.py new file mode 100644 index 0000000..0383999 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunCostL34.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Run five interleaved W12 whole-view pairs against the L33 binary.""" +import re +import statistics +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +OUT.mkdir(parents=True, exist_ok=True) +BINARIES = { + "l33": ROOT / "Saved/Linux/l33/bin/VoxelForgeCoreHeadless-clang-l33-final", + "l34": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", +} +ORDERS = (("l33", "l34"), ("l34", "l33"), ("l33", "l34"), + ("l34", "l33"), ("l33", "l34")) +READY = re.compile(r"\bwhole_view_ready=([0-9.]+)s") +rows = [] +failed = False + + +for recipe in ("surface-world", "floating-islands"): + for pair, order in enumerate(ORDERS, 1): + for build in order: + name = f"cost-{recipe}-pair{pair}-{build}" + logfile = OUT / f"{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "900s", + str(BINARIES[build]), str(ROOT / "Standalone/data/owner_world.json"), + "--workers=12", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=-1", f"--recipe={recipe}", + ] + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT, + timeout=900, check=False) + except subprocess.TimeoutExpired: + result = None + elapsed = time.monotonic() - started + text = logfile.read_text(encoding="utf-8", errors="replace") + matches = READY.findall(text) + stamps = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + text, re.M) + stamp_ok = stamps == [(recipe, recipe, "PASS")] + valid = (result is not None and result.returncode == 0 and len(matches) == 1 + and "hash=off" in text and "cache_hits=0" in text and stamp_ok) + ready = float(matches[0]) if len(matches) == 1 else float("nan") + rows.append((recipe, pair, build, ready, elapsed, + result.returncode if result else "TIMEOUT", valid)) + print(f"{recipe} pair={pair} build={build} whole_view_ready={ready:.3f}s " + f"process_elapsed={elapsed:.1f}s {'PASS' if valid else 'FAIL'}", flush=True) + failed |= not valid + +summary = OUT / "cost-runs.csv" +summary.write_text( + "recipe,pair,build,whole_view_ready_seconds,process_elapsed_seconds,exit_code,status\n" + + "".join(f"{recipe},{pair},{build},{ready:.6f},{elapsed:.3f},{code}," + f"{'PASS' if ok else 'FAIL'}\n" + for recipe, pair, build, ready, elapsed, code, ok in rows), encoding="utf-8") + +for recipe in ("surface-world", "floating-islands"): + by_build = {build: [row[3] for row in rows if row[0] == recipe and row[2] == build] + for build in BINARIES} + baseline = statistics.median(by_build["l33"]) + current = statistics.median(by_build["l34"]) + paired = [] + for pair in range(1, 6): + values = {row[2]: row[3] for row in rows if row[0] == recipe and row[1] == pair} + paired.append((values["l34"] - values["l33"]) / values["l33"] * 100.0) + print(f"[L34CostSummary] recipe={recipe} pairs=5 median_l33_s={baseline:.3f} " + f"median_l34_s={current:.3f} median_change_pct={(current/baseline-1)*100.0:+.2f} " + f"paired_change_pct={','.join(f'{value:+.2f}' for value in paired)}", flush=True) + +print(f"[L34Cost] runs={len(rows)} status={'FAIL' if failed else 'PASS'} summary={summary}", + flush=True) +raise SystemExit(1 if failed or len(rows) != 20 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunDeterminismL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunDeterminismL34.py new file mode 100644 index 0000000..8aa6e82 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunDeterminismL34.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +"""Run owner L25 hashes, 24 m crossings, and upper-SurfaceWorld fixture determinism.""" +import re +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +L33 = ROOT / "Saved/Linux/l33" +FIXTURE = L33 / "fixtures/sw-upper-tunnel-network-style0.json" +BINARIES = { + "clang": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", + "gcc": OUT / "bin/VoxelForgeCoreHeadless-l34-gcc", +} +HASH_PATTERN = re.compile( + r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +LAYOUT_PATTERN = re.compile( + r"^\[ResolvedLayoutSnapshot\] schema=\d+ stable_identity=([^ ]+) strata=\d+ bytes=\d+ round_trip=PASS$", + re.M) +PLAN_PATTERN = re.compile( + r"^\[WorldAssemblerPlanSerialization\].*canonical_round_trip=true .*" + r"plan_hash=([0-9a-f]+) manifest_hash=([0-9a-f]+) status=PASS$", re.M) +ROUTE_PATTERN = re.compile( + r"^\[WorldAssemblerRouteAccepted\] arrival_xy_m=\([^)]*\) " + r"departure_xy_m=\([^)]*\) endpoint_proximity_cost=\d+ average_grade_q16=\d+$", re.M) +rows = [] +failed = False +owner_reference = {} +fixture_reference = None + + +def run(command, logfile): + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT, + timeout=1800, check=False) + except subprocess.TimeoutExpired: + result = None + return result, time.monotonic() - started, logfile.read_text( + encoding="utf-8", errors="replace") + + +for kind in ("l25", "crossing24"): + for recipe in ("surface-world", "floating-islands"): + for compiler, binary in BINARIES.items(): + for workers in (1, 8, 12): + name = f"{kind}-{compiler}-{recipe}-w{workers}" + logfile = OUT / f"determinism-{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1800s", + str(binary), str(ROOT / "Standalone/data/owner_world.json"), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--stream-hash", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--far-horizon-lod8-step=0", + f"--workers={workers}", f"--recipe={recipe}", + ] + if kind == "crossing24": + command.extend(("--camera-step=24,0,0", "--region-crossing")) + result, elapsed, text = run(command, logfile) + hashes = HASH_PATTERN.findall(text) + stamps = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + text, re.M) + ref = L33 / f"determinism-{kind}-{compiler}-{recipe}-w{workers}.log" + reference_hashes = HASH_PATTERN.findall(ref.read_text( + encoding="utf-8", errors="replace")) if ref.exists() else [] + stable_key = (kind, recipe) + stable = stable_key not in owner_reference or hashes == owner_reference[stable_key] + if stable_key not in owner_reference and hashes: + owner_reference[stable_key] = hashes + equal_l32 = len(hashes) == 12 and hashes == reference_hashes + ok = (result is not None and result.returncode == 0 + and stamps == [(recipe, recipe, "PASS")] + and "hash=on" in text and len(hashes) == 12 and stable and equal_l32) + rows.append((kind, recipe, compiler, workers, elapsed, + result.returncode if result else "TIMEOUT", ok)) + print(f"{name} elapsed={elapsed:.1f}s hashes={len(hashes)}/12 " + f"same_across_matrix={'yes' if stable else 'no'} " + f"same_as_l33={'yes' if equal_l32 else 'no'} {'PASS' if ok else 'FAIL'}", + flush=True) + failed |= not ok + + +for compiler, binary in BINARIES.items(): + for workers in (1, 8, 12): + name = f"upper-fixture-{compiler}-w{workers}" + logfile = OUT / f"determinism-{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1800s", + str(binary), str(FIXTURE), "--workers=" + str(workers), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=3", "--max-clip-level=8", + "--max-level=-1", "--recipe=floating-islands", "--audit-resolved-layout-passages", + ] + result, elapsed, text = run(command, logfile) + layouts = LAYOUT_PATTERN.findall(text) + plans = PLAN_PATTERN.findall(text) + routes = ROUTE_PATTERN.findall(text) + stamps = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + text, re.M) + passage_summary = re.search(r"^\[ResolvedPassageAuditSummary\].*status=PASS$", text, re.M) + signature = (tuple(layouts), tuple(plans), tuple(routes)) + stable = fixture_reference is None or signature == fixture_reference + if fixture_reference is None and layouts and plans and routes: + fixture_reference = signature + ok = (result is not None and result.returncode == 0 and len(layouts) == 1 + and len(plans) == 1 and len(routes) == 1 + and stamps == [("floating-islands", "floating-islands", "PASS")] + and passage_summary is not None and stable) + rows.append(("upper-fixture", "floating-islands", compiler, workers, elapsed, + result.returncode if result else "TIMEOUT", ok)) + print(f"{name} elapsed={elapsed:.1f}s layout={layouts[0] if layouts else 'MISSING'} " + f"stable_across_matrix={'yes' if stable else 'no'} {'PASS' if ok else 'FAIL'}", + flush=True) + failed |= not ok + + +summary = OUT / "determinism-l34.csv" +summary.write_text( + "kind,recipe,compiler,workers,elapsed_seconds,exit_code,status\n" + + "".join(f"{kind},{recipe},{compiler},{workers},{elapsed:.3f},{code}," + f"{'PASS' if ok else 'FAIL'}\n" + for kind, recipe, compiler, workers, elapsed, code, ok in rows), + encoding="utf-8") +print(f"[L34Determinism] runs={len(rows)} pass={sum(row[-1] for row in rows)} " + f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True) +raise SystemExit(1 if failed or len(rows) != 30 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunInvariantAuditsL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunInvariantAuditsL34.py new file mode 100644 index 0000000..b241660 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunInvariantAuditsL34.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Run L33 route/proof and transition invariants with recipe-stamped logs.""" +import re +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +BINARIES = { + "clang": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", + "gcc": OUT / "bin/VoxelForgeCoreHeadless-l34-gcc", +} +rows = [] +failed = False + + +def run(name, binary, data, recipe, extra, checks): + global failed + logfile = OUT / f"{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "900s", + str(binary), str(data), "--workers=12", "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=-1", f"--recipe={recipe}", *extra, + ] + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT, + timeout=900, check=False) + except subprocess.TimeoutExpired: + result = None + elapsed = time.monotonic() - started + text = logfile.read_text(encoding="utf-8", errors="replace") + stamps = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + text, re.M) + stamp_ok = stamps == [(recipe, recipe, "PASS")] + checks_ok = all(check(text) for check in checks) + ok = result is not None and result.returncode == 0 and stamp_ok and checks_ok + rows.append((name, recipe, elapsed, result.returncode if result else "TIMEOUT", ok)) + print(f"{name} elapsed={elapsed:.1f}s recipe={stamps[0][1] if stamps else 'MISSING'} " + f"stamp={'PASS' if stamp_ok else 'FAIL'} checks={'PASS' if checks_ok else 'FAIL'} " + f"{'PASS' if ok else 'FAIL'}", flush=True) + failed |= not ok + + +owner = ROOT / "Standalone/data/owner_world.json" +for recipe in ("surface-world", "floating-islands"): + for compiler, binary in BINARIES.items(): + name = f"invariant-route-proof-{recipe}-{compiler}" + run(name, binary, owner, recipe, + ["--stream-hash", "--audit-uniform-block-proofs", "--audit-route-parity"], + [lambda text: bool(re.search( + r"^\[RouteParityAudit\].*status=PASS$", text, re.M)), + lambda text: bool(re.search( + r"^\[UniformBlockProofAudit\].*violations=0(?:\s|$)", text, re.M))]) + +for recipe in ("surface-world", "floating-islands"): + for compiler, binary in BINARIES.items(): + for mode in ("hard", "gradient", "interleaved"): + name = f"invariant-transition-{recipe}-{mode}-{compiler}" + run(name, binary, owner, recipe, + [f"--transition-mode={mode}", "--audit-strate-transitions"], + [lambda text: bool(re.search( + r"^\[StrateTransitionAuditSummary\].*hole_columns=0 air_samples=0 .*status=PASS$", + text, re.M)), + lambda text: bool(re.search( + r"^\[StrateTransitionNegativeControls\].*status=PASS$", text, re.M))]) + +summary = OUT / "invariant-audits.csv" +summary.write_text( + "run,recipe,elapsed_seconds,exit_code,status\n" + + "".join(f"{name},{recipe},{elapsed:.3f},{code},{'PASS' if ok else 'FAIL'}\n" + for name, recipe, elapsed, code, ok in rows), + encoding="utf-8") +print(f"[L33InvariantAudits] runs={len(rows)} pass={sum(row[-1] for row in rows)} " + f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True) +raise SystemExit(1 if failed or len(rows) != 16 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunLegacyAuditsL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunLegacyAuditsL34.py new file mode 100644 index 0000000..0d98bde --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunLegacyAuditsL34.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Run the L13 route parity and L9 uniform-block proof audits on L34.""" +import re +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +BINARIES = { + "clang": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", + "gcc": OUT / "bin/VoxelForgeCoreHeadless-l34-gcc", +} +RECIPES = ("floating-islands", "surface-world") +rows = [] +failed = False + +for recipe in RECIPES: + for compiler, binary in BINARIES.items(): + name = f"legacy-route-proof-{recipe}-{compiler}" + logfile = OUT / f"{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "900s", str(binary), str(ROOT / "Standalone/data/owner_world.json"), + "--workers=12", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--stream-hash", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=-1", + f"--recipe={recipe}", "--audit-uniform-block-proofs", "--audit-route-parity", + ] + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, timeout=900, check=False) + except subprocess.TimeoutExpired: + result = None + elapsed = time.monotonic() - started + output = logfile.read_text(encoding="utf-8", errors="replace") + stamp = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + output, re.M) + route = re.findall(r"^\[RouteParityAudit\].*$", output, re.M) + proofs = re.findall(r"^\[UniformBlockProofAudit\].*$", output, re.M) + stamp_ok = stamp == [(recipe, recipe, "PASS")] + route_ok = len(route) == 1 and route[0].endswith("status=PASS") + proof_ok = len(proofs) == 1 and bool( + re.search(r"violations=0(?:\s|$)", proofs[0])) + ok = (result is not None and result.returncode == 0 and stamp_ok + and route_ok and proof_ok) + code = result.returncode if result is not None else "TIMEOUT" + rows.append((name, recipe, compiler, elapsed, code, route_ok, bool(proof_ok), ok)) + failed |= not ok + print(f"[L34LegacyAuditRun] case={name} elapsed={elapsed:.1f}s exit={code} " + f"recipe_stamp={'PASS' if stamp_ok else 'FAIL'} " + f"L13={'PASS' if route_ok else 'FAIL'} L9={'PASS' if proof_ok else 'FAIL'} " + f"{'PASS' if ok else 'FAIL'}", flush=True) + +summary = OUT / "legacy-audits.csv" +summary.write_text( + "case,recipe,compiler,elapsed_seconds,exit_code,l13,l9,status\n" + + "".join(f"{name},{recipe},{compiler},{elapsed:.3f},{code}," + f"{'PASS' if l13 else 'FAIL'},{'PASS' if l9 else 'FAIL'}," + f"{'PASS' if ok else 'FAIL'}\n" + for name, recipe, compiler, elapsed, code, l13, l9, ok in rows), + encoding="utf-8") +print(f"[L34LegacyAuditSummary] runs={len(rows)} pass={sum(row[-1] for row in rows)} " + f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True) +raise SystemExit(1 if failed or len(rows) != 4 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunPassageAuditsL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunPassageAuditsL34.py new file mode 100644 index 0000000..327ad1d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunPassageAuditsL34.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +"""Run recipe-stamped passage/profile audits for both compilers and both owner recipes.""" +import re +import os +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +BINARIES = { + "clang": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", + "gcc": OUT / "bin/VoxelForgeCoreHeadless-l34-gcc", +} +RUNS = [] +for recipe, filename in ( + ("floating-islands", "floating-islands"), + ("surface-world", "surface-world"), +): + for style in range(4): + RUNS.append((f"owner-{filename}-style{style}", + ROOT / f"Saved/Linux/linux25-owner-{filename}-style{style}.json", recipe)) +for style in range(4): + RUNS.append((f"upper-sw-fixture-style{style}", + OUT.parent / "l33/fixtures" / f"sw-upper-tunnel-network-style{style}.json", + "floating-islands")) + +RECIPE = re.compile(r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=PASS$", re.M) +PASSAGE = re.compile(r"^\[ResolvedPassageAudit\].*walkability=PASS$", re.M) +MOUTH = re.compile(r"^\[PassageMouthProfileAudit\].*status=PASS$", re.M) +ROUTE = re.compile(r"^\[ResolvedStrateRouteAudit\].*mouth_binding=PASS status=PASS$", re.M) +CHECKS = ( + r"^\[ResolvedLayoutStrict\] accepted=true issues=0 error=$", + r"^\[ResolvedLayoutValidatorControls\].*status=PASS$", + r"^\[PassageMouthProfileNegativeControl\].*source=L23_terraced_geometry.*detected=true$", + r"^\[PassageMouthProfileSummary\].*l23_terrace_negative_control=DETECTED status=PASS$", + r"^\[PassageNaturalnessSummary\].*l23_negative_control=DETECTED.*status=PASS$", + r"^\[PassageOpenAirAuditSummary\].*violations=0.*l24_negative_control=DETECTED status=PASS$", + r"^\[PassageNoLongBridgeAudit\].*status=PASS$", + r"^\[PassageRockColumnAuditSummary\].*status=PASS$", + r"^\[ResolvedPassageAuditSummary\].*route_binding_failures=0 .*status=PASS$", + r"^\[Walkability\] PASS", + r"^\[FloorProfileBlend\].*negative_controls=step_detected/slope_detected status=PASS$", +) + +rows = [] +failed = False +for compiler, binary in BINARIES.items(): + for name, data, recipe in RUNS: + logfile = OUT / f"passage-audit-{name}-{compiler}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1800s", str(binary), str(data), "--workers=12", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=3", "--max-clip-level=8", "--max-level=-1", + f"--recipe={recipe}", "--audit-resolved-layout-passages", + ] + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, timeout=1800, check=False) + except subprocess.TimeoutExpired: + result = None + elapsed = time.monotonic() - started + output = logfile.read_text(encoding="utf-8", errors="replace") + stamp_ok = RECIPE.findall(output) == [(recipe, recipe)] + passages = len(PASSAGE.findall(output)) + mouths = len(MOUTH.findall(output)) + routes = len(ROUTE.findall(output)) + checks_ok = all(re.search(pattern, output, re.M) for pattern in CHECKS) + ok = (result is not None and result.returncode == 0 and stamp_ok + and passages >= 1 and mouths == passages and routes >= 1 and checks_ok) + code = result.returncode if result is not None else "TIMEOUT" + rows.append((name, recipe, compiler, elapsed, code, passages, mouths, routes, ok)) + failed |= not ok + print(f"[L34PassageAuditRun] case={name} compiler={compiler} recipe={recipe} " + f"elapsed={elapsed:.1f}s exit={code} passages={passages} " + f"profiles={mouths} routes={routes} {'PASS' if ok else 'FAIL'} " + f"log={logfile}", flush=True) + +summary = OUT / "passage-audits.csv" +summary.write_text( + "case,recipe,compiler,elapsed_seconds,exit_code,passages,mouth_profiles,routes,status\n" + + "".join(f"{name},{recipe},{compiler},{elapsed:.3f},{code},{passages},{mouths},{routes}," + f"{'PASS' if ok else 'FAIL'}\n" + for name, recipe, compiler, elapsed, code, passages, mouths, routes, ok in rows), + encoding="utf-8") +print(f"[L34PassageAuditSummary] runs={len(rows)} pass={sum(row[-1] for row in rows)} " + f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True) +raise SystemExit(1 if failed or len(rows) != 24 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/RunUpperFixtureDeterminismL34.py b/Standalone/Research/WorldAssemblerM3/Linux34/RunUpperFixtureDeterminismL34.py new file mode 100644 index 0000000..870b7e4 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/RunUpperFixtureDeterminismL34.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Rerun the upper-SW fixture's six L34 determinism cases and merge results.""" +import csv +import re +import subprocess +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l34" +FIXTURE = ROOT / "Saved/Linux/l33/fixtures/sw-upper-tunnel-network-style0.json" +BINARIES = { + "clang": OUT / "bin/VoxelForgeCoreHeadless-l34-clang", + "gcc": OUT / "bin/VoxelForgeCoreHeadless-l34-gcc", +} +LAYOUT_PATTERN = re.compile( + r"^\[ResolvedLayoutSnapshot\] schema=\d+ stable_identity=([^ ]+) strata=\d+ bytes=\d+ round_trip=PASS$", + re.M) +PLAN_PATTERN = re.compile( + r"^\[WorldAssemblerPlanSerialization\].*canonical_round_trip=true .*" + r"plan_hash=([0-9a-f]+) manifest_hash=([0-9a-f]+) status=PASS$", re.M) +ROUTE_PATTERN = re.compile( + r"^\[WorldAssemblerRouteAccepted\] arrival_xy_m=\([^)]*\) " + r"departure_xy_m=\([^)]*\) endpoint_proximity_cost=\d+ average_grade_q16=\d+$", re.M) +rows = [] +failed = False +reference = None + +for compiler, binary in BINARIES.items(): + for workers in (1, 8, 12): + name = f"upper-fixture-{compiler}-w{workers}" + logfile = OUT / f"determinism-{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1800s", str(binary), str(FIXTURE), f"--workers={workers}", + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--force-generate", "--clip-radius=3", "--max-clip-level=8", "--max-level=-1", + "--recipe=floating-islands", "--audit-resolved-layout-passages", + ] + started = time.monotonic() + try: + with logfile.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, timeout=1800, check=False) + except subprocess.TimeoutExpired: + result = None + elapsed = time.monotonic() - started + output = logfile.read_text(encoding="utf-8", errors="replace") + layouts = LAYOUT_PATTERN.findall(output) + plans = PLAN_PATTERN.findall(output) + routes = ROUTE_PATTERN.findall(output) + stamps = re.findall( + r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", + output, re.M) + passage = re.search(r"^\[ResolvedPassageAuditSummary\].*status=PASS$", output, re.M) + signature = (tuple(layouts), tuple(plans), tuple(routes)) + stable = reference is None or signature == reference + if reference is None and layouts and plans and routes: + reference = signature + ok = (result is not None and result.returncode == 0 and len(layouts) == 1 + and len(plans) == 1 and len(routes) == 1 + and stamps == [("floating-islands", "floating-islands", "PASS")] + and passage is not None and stable) + code = result.returncode if result is not None else "TIMEOUT" + rows.append(("upper-fixture", "floating-islands", compiler, workers, + elapsed, code, ok)) + failed |= not ok + print(f"[L34FixtureDeterminism] compiler={compiler} workers={workers} " + f"elapsed={elapsed:.1f}s recipe_stamp={stamps[0][1] if stamps else 'MISSING'} " + f"layout={layouts[0] if layouts else 'MISSING'} " + f"stable_across_matrix={'yes' if stable else 'no'} " + f"{'PASS' if ok else 'FAIL'}", flush=True) + +fixture_summary = OUT / "determinism-upper-fixture-l34.csv" +with fixture_summary.open("w", newline="", encoding="utf-8") as stream: + writer = csv.writer(stream) + writer.writerow(("kind", "recipe", "compiler", "workers", "elapsed_seconds", + "exit_code", "status")) + for row in rows: + writer.writerow((*row[:-1], f"{row[-1] and 'PASS' or 'FAIL'}")) + +combined = OUT / "determinism-l34.csv" +with combined.open("r", newline="", encoding="utf-8") as stream: + owner_rows = list(csv.reader(stream)) +if owner_rows and owner_rows[0] == ["kind", "recipe", "compiler", "workers", + "elapsed_seconds", "exit_code", "status"]: + owner_rows = [row for row in owner_rows[1:] if row and row[0] != "upper-fixture"] +else: + raise SystemExit("owner determinism summary is missing or malformed") +if len(owner_rows) != 24: + raise SystemExit(f"expected 24 owner rows before fixture merge, found {len(owner_rows)}") +with combined.open("w", newline="", encoding="utf-8") as stream: + writer = csv.writer(stream) + writer.writerow(("kind", "recipe", "compiler", "workers", "elapsed_seconds", + "exit_code", "status")) + writer.writerows(owner_rows) + for row in rows: + writer.writerow((*row[:-1], f"{row[-1] and 'PASS' or 'FAIL'}")) + +print(f"[L34FixtureDeterminismSummary] runs={len(rows)} pass={sum(row[-1] for row in rows)} " + f"fail={sum(not row[-1] for row in rows)} combined_runs=30 " + f"combined_summary={combined} fixture_summary={fixture_summary}", flush=True) +raise SystemExit(1 if failed or len(rows) != 6 else 0) diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/SHA256SUMS.txt b/Standalone/Research/WorldAssemblerM3/Linux34/captures/SHA256SUMS.txt new file mode 100644 index 0000000..d6f73f0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux34/captures/SHA256SUMS.txt @@ -0,0 +1,12 @@ +64e5336f945724d882ddb22f7bad44ca5acdc7b0b142477991292116a2a140ab owner-fi-arrival.jpg +638af09fab4cdbe82e1733d783b7d1c88948bc4fe071a38d480d7357b2b96732 owner-fi-ground-mouth.jpg +90a2bc23ee5cf996145116a496bbd293c5b8ab00efd055f507320bd30a3a6869 owner-fi-mid-tunnel.jpg +70bf614b4a3e05edbfc5693aa16e1e643ff7794500481baace08ddde79490aae owner-fi-rock-entry.jpg +03ca53cdd8ff9801fa57254533ad46a96c306147a895e525be43f32f7ae076e4 owner-sw-arrival.jpg +70c187b4d2e3aa39aff99984b98240f8d25386590e3a7e5b51f569e2e17f0f86 owner-sw-ground-mouth.jpg +049f984f3a725295c991cb9a3c080ebac085758454bcd1fb007555ab6fb83cc8 owner-sw-mid-tunnel.jpg +6afe280d33b52ecaab6ddbb02c89beaa0dcf2d76cc64d6675e17fda79ad595c8 owner-sw-rock-entry.jpg +e6dd2da50efb9e10e1e9b12f4366f223669b6da0f05333bf352a20a504f5be50 upper-sw-fixture-arrival.jpg +420c9a78a0913dbb0e6fe4261c49d9001a91cc19825cd248cc97cf26ce4e74d5 upper-sw-fixture-ground-mouth.jpg +0d67a179773ace8f6e4ac2939ea4495a4232ffa10671d4f02172a18d0e128a34 upper-sw-fixture-mid-tunnel.jpg +fd92aee89be922c7817b2e794333681b397c473095a77e0bc3ec6d947a57c0b8 upper-sw-fixture-rock-entry.jpg diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-arrival.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-arrival.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3f95af7625456328fc419569cea0dc1dd73c14aa GIT binary patch literal 23525 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 pZ$Zl~Jc{X#SRXbCQ`5KWo>dibL-)n$3RSF literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-rock-entry.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-fi-rock-entry.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f069dafab952b1744376852df244d472357234b GIT binary patch literal 27070 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-arrival.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-arrival.jpg new file mode 100644 index 0000000000000000000000000000000000000000..07c625d4651dc21460ca1f82fa201f601824eaf2 GIT binary patch literal 23707 zcmch937iu}+IMv)nTc5#6YMB6fcAz}dmBNH;S{vvCIhlAZ)Z0d4pEUqIYf}d1FtrS zW&?xZGN>rpW`K=hz#Rlulyy;rRag)ZP{Csb5d{%%*JIc3|5SBnW`I53@B96}>ZH25 z?s~3z>Z$7f@r@t<$%2<(bJM6ET{?B?-Kk6GF6_ts>=(@M_n+oJ?I+x|Y|*mOm6er+ zLLvAqTb7jtgP~BXGg=`cbjBHqqO@*()>&=awu?l5{^Lt*Hj}txjZTt1UZ04S8e2~R-32$V|3!nYCfrb2@drAzC)QZWin5Px{aUW~pLHUp; z#4cgq=099{X-?B4R-_>7HuqH9>7lGy0Tp2je^ry=qaoSmcP3km`SW&KJh6NhSv6VD zs)*NEfTCq)!`CRt5R6zV4>6u9Yr2YDvaV4H*{1s7{0RH0h@Yji)HKCwD4Rnu+45^z zmicAg8H-td%cGuVNG)Rh6!K$o~9achSP%=Y?bH%(VBc7xNxWiM_Kqx4l zSdt}^zPLf2WHQ6Yuc#>vl~PjJ3?jLBnY@U?eTD}!q=b1Raj)rRG5kYDkj0rn8G~MU zK9QF(g90<|%TIPA=#KhBDamJ0*q~}rBxnjEq0-#(=DbNW>O523l0g+pafuqB2x=6e zB!8eza3>yFI24WHSqdvbLrRz^%y=8Yc+#s-FwB&vG9>LlbvtZ60`kY-Rqr-G7h zdat#@^O%&1Nycv~09xLz6qe#a1i9mYbHcbuR2Pj$3|>Mj02l{0;LHH3#=OkyMIQhz zg99wA_<|UTWFQOOLPpF?#(gofBnd3nvba(XSO=vb0m5+tUgp_PeAG7B80#cbt{|`4 z%aR0X9)a<3M+sgGg(E{maiAv<4ku!Og%lUjyk@udxB$BIh#r%R$Gt(8K*xFA=u}wp zg$(o>R|3N}IffXcy5R?z0RYG4r%iADK32BN_pBLaakdx4ZF@ym{z|nEh zXo6xfCJt&MUP@^sScd>8l7*sS)Fi+h1wkl2q8_h_07nIS$nz2T#@QGH;8j8f01Z%+ zHEAd_fp=3%Gy`WNXhViuK=k7T zpTik(Tnd1p&~F1U12|0PBY^WEPz$0U5N-H^-cVA=5C%$jKyCuAOgeh@{KFzA9;jca zjXN*rGY5BGQ&2aAh=_4>p}B;?o8m}D$N{>K!0E6N0g)(_yP&v{L=f@>5R|;kN8KUH zCo#&0WMZgFoazhWGJK-|+K%js;m6{>HM0}ZiBkbzB8;RD#37kV(f|q1^Nj|CldRfE z8348^MTxK_)0gDJ+Vu>l6ON?h;?nWl6!Z!)02_Dc1ss=u0zzOv7WU!KKo>;;!_#;! z8Uj%$fdzCA=A{U@#MuoW4t9nvV&D_X0UwuDz&%7)Lb`fUDLti%so-VjDNTRGXa&G` z9L=C@pgK^$i5V@7$M9lSJ)K=STAB_h@LmdDBfbZ2P!U{l))0@>kq~E7%&7*hXt=^# zJsRk^!j2eMZO(hkev(H~;|iHe*p=m;=)b z$)3P;grwU_?a6>4W?rIUhpwp%mj<{~XE*?XFb?`4gtvhNM;;S;@B}9r;AUpx$pG!q zP~m9ga8v>VOhm)H37*7ZfOw=}rlLlG2n9Hn41#8u`b4QL4DBo!4ryBLBSv78?W;$e z8j#bO0Mwui%d>j>C-v6yJd>HNYZ1!|SQ?ZX*@CJg^ehU{MYT0^q!w9-;df|eP=YjB zQ?qP~70I{A%gmokvk0k5PDW9OiYKU1fpi*e1(?pVRz9!ipxu!UCR1)p%cGZE$zm+W zSe99&OPxOA%MO;`<`pub1EN7*f=cCa*{H#Z$@)c)prhGP`!Y7K2vt#Dq1=(KW-~3o z(oEBMy?j87=>e;lg}T&OHE*6Y!i>#>fq<3G=K_Exqlg?8^t0-T?3Y8=C?N8Y;Dxfo#wxAwbHq{*vW2UYn6@V5O;rFK+Wd^ewJZfaS^Qy)QpJK4Po26r#-#)>Yk1x?QS*nAK~e>Be1>FUw_cZ((OQ6A4xwBcIr0?2BKV> zgH?vmPy@gY;UX_rl0eC#Tj(@;3Ti>;F&ZG9*cHT&c%+~#^@TqG*_tfpa<)xlq*N82 zsDjf4GE=n{V_)5W=`(>$A*nEp~XH z1U`&bIYO5P^a*@as;zfqLC_?AEX~q@p7Sd6`Y7YHtV$$-{`ol}qFtGFP%-qE|1i!h`*$QvC=&l~`Z=wetvzu(e10?-JYjk+yD1UVXE zKoNVh>_L74`70X#p9d%A+>N0gozW%v+E}KthHi0VIR$piG)&u-IQ9 zb*RL&noB}e3q$?E`bi4X%$$NoX2#fPD6YY9Oc~1(w2GD38AiBL8oHz8A^IgJ4E3Eg zlua1Qt~7kRp#xy$n=-0urG@x4nB^0~{5ISSO_pfVN7tZQQ3pv|rGUW~vSgs!ULQ{qt6)+!pf(6CL89`oL_n7l?Q!)H<$1;4piupx1sar*NgofkC-YFz!%#31 zvF3C7gWi#`Apy0PD?$i6D>QV5Rt2O5QIx9>DNxu6L_C2k9NeK|a;O6K2L!zI1TW}| zqK=TG6G>v(jd2>LAw7~X>TTa>sL3(tQc(lriUHb+SU-iL^GNOVB?11Zv}~GEJxy9M zLRvA}AdpK{e~49IaV%NV=2&%n%=3F<)onJN@K46aER7{o&X24QibMk`8I~+b8Ds2{ z8}0ZtcC;3lBegItv}l1BJ_K4Xa@`mMNn%04pv=R;ih#Q_Zbm^K?ehsU5M`jDb8JB) z#RD8)QY&ZgeCtL$K%3Dbf-z+Qg_}ummVW7^?Uh!l@hff*AV9 z2}DwYQIqTXd_^2LV81b8YHDSlHlas)R=q`93Iv%BMwA2otd@Z$n$v9EA4!uiie&u( zOSk#dhgmvMvpo`ddhTo4RUIBZa4egtAJoZead4!kS0V6FF7h<=0;WPQL`PKK8NUqy z1Th3LpB7>Ss=^j%L)O-T9-Ucv!TNsH=CWUf*g;k+LUI)H2^TVe)h!jVyhhX=p!yvd z%}5^Qtt@dm?T^5&{Bwo;YJQc+g*DkVv zlS-K(nBbsBW$1<(R7D4DhKa?Z1aeTJ#eAY#7?;c|l39VIo)yUGki(X}jdkd*w8}9Q z4PeGdqg53^^yfDD!Z7Y)jch7jta~R%6ZKM}K3KkaL;2>rW1IhG4X}R_8L!vfFe6*H zY~9Uj*|P`VVnULMVMP5x?v|xa4stW{Q(kRf-0BH==2Bv{t?o{|$ z3OUl+rm!mKXy$=BXwf6kNwDWZJjjK9b*t9NwkjkxkG7q}#v6gH=>#F>BtTT?22P@7 z`(+!`50rl4Xp*;J^o44Gh&;<#7S>MC|AaZ3lM2()S|(pmIYwQ)`)ifJHq6rCWEeDH zJ|sZ^LtD@cCPr9=4Cn~+skS>~J@k=P*K41=Op_z*Nn2lLRc^L=t{m%`vB5L!We}-O zJ+ZYMsoI51&T4I+R%3O;Z?08#$I55ep?$~Fp8F@P)ymqfd?SDQB@>?4BkSKdc1wQd z%%unN*$iTFspyCnqBH5Wb7Ibs+o`_{JEdq4th=-b+#*h(1 zI*q*r^wc$noEC~;+)TCMVSP!Csv!<>Cv?Jg;=oB>6Hs`-UZgSO!~i$RfsR>Nm)AO^8qFP1G*oDeG`3J9V;BcuY3awd|- zBVV=X5v$fmTGT3_Ob2C=#*kyO>d#<>lecUJh+BD8dn=QEpw9rcm8PAW*TdU)Bqm;7 z{@ht5YkDm&uljWBE&Cto_=o+sE-T-7`KXCw7EXRGuy^R?df>OSU|oaZf`m4id@zGR zz{B!Uv71e_N~_Oh(?^=6RnwI=F|#wfu7XWzcs5toqvr_EteQ7+WgXwJJIhenSdR_< zBY({mdSnVU5sj-p{>}wYOV+vIe;K19;6h-5vI90WGiXREw8T1H1KTZxCJ2E`k`0K0 z@&%uB4Ixa0s*19Na^hGD!l{A06BcCGZ{w+k{h?12B1{)xgWr(7ap?j!GF}*kdu%1(Pvf zCzpk^QiWGOSbp<;7t{`&79W4?p3T^1 zp!rK&zN9B?o>7r3>9W&o`*s(z?f%X4%J&>gdVZtC$IXkbHAu~p3{1sJ)jVkln=~|@ zoVGWSYS(&qs_M;navW=AwWwYY-Lm;ZPfg7M>%iODOlJ+MzudD!MPP3ImcZN$Efj#O zE!p-hS?|^C#cT^Jf?-;WwfvdV#wf91##P7?&02jq<&VatZyU)Vwi=)m!~g->c_3W? zb1{z;Q*u$2fU#19`Q8R{F)!J9kGH!|McB7Z^e_* zrj{uf#bYMlG)Ph#=p9*flTc2e5*TP1dr{EmP@AE^(rpI80HpW8d6&i$3xGaDlBzFY zLu{G>!CkZ1wM(Ok`98^~#LOXBvgCfPb{IbD#!x)NhF$jdolCBra_p%^Yy5{_9P|Fi z4=n8a%mt$!ysp#hsV&{^ee}jX%Z847<+X}2wNodpSrWg76uK)m#II}P{42bz|6-K( zowmuC`j^X-r9D22RS(ASJ&N?`M6>ng&y1;?Kb7unNQ4(Ih@#tPRIqE-1h1)wZoe!Z zS`E~OQVR5H<}GNQcX$@pj8G4ax=90b=320HKz>PSckalfIsMvXqFpGQSOR6V+$^b3 z+U~R4FWMu`g5pP7pReQz*5g@1rW45Y1+hd+cS6b?uvgh`$X zJ_Y&biRmbk!gO;MPCPjCoj!97L|ODCDiR^b=iEme$eBrlhEHrgnE zGFml0X_mw#UwBkxxgjTf6|;khWi#HH-|BdH&%h(MetFZujgf)hPq?sh>Dx0pR!=JX z?EZ;e`t+Rj&ZG-gREH~)UM!041M9x=9eejlChew9MHb_&X)?(Bx?C{)&{40NTAk%p->snATjx5_cP|b2-WDC<;i`821 zgCokSdqzv!v}rIV->@k-0(4tZJ3qRw`rLSF^+-&Zxk@Mkp6>C|K6|`vpB!s%Vd?9x znDNyEx4!k!^V?pT@ztt{Uw<12Jb2US$L_f4gUg@4veVn!7x$UIgN)Br2coHV?ax{m zDRkeuaN5_;SOV`{=%VwEqS*x1&G3&50_Q?pb0I7!qTj*7I;_uM%x`67szOT7@b&g^QV0~{`0v* zAGhs!-Tg<0r(VC|oSR>`{gTtqd-sxtBb$4k|H!7>#vgd=r*r@K$%lvLK4kYEwT$7f zN7g+%5-5gh(;>^)c^Y^!pFLdjH+Aa}mbD}476og9TK2%YE%HTOG`$a|d=EDF*$!5a z+Z*}Kl|&-!5KXWXj37+#v?8UAKCB`6T2%_gv7a!z!fszvvqw7I@SIY5t_@DlW%>+! z$!`C2*L2;I0fCw&?2N_77O_LGKG^U|lq4)9FJvw|%S>R$05TT>nU+l?hYg4itOL0S zXUxDR5n|x@(henk5U4zYi)J3;yTAz(#|27vwCmqFDbgWZ`8KP_0-uZWrotR?2Bn4! zZ!(I>BNX#W61Hn7Qb={~W4|X6PT&{Arf3oy&Iwx0VUqJ9TY~mK(SMq4Xr@T={ZPKf z$1aSNU9F6)RoZ^^3L9V~ZwM;a$D!uL*g&>zV7gARbAGKZQWKBHa%V0Ljeh5M`?g$p zVAb*~uk3r_=|8eTS0|6&b@0G9x7>co7YENj{%ym$i?@9HUEkk5c*o(tz19BhyDl7@ z>vF8V&&%~S_f}e6YVu{byrCYhIbb8$ViXv(&j`=GeTL*`KCpKlHbAg(gUwfL0*&0f zp!B?tlhNN^ZbBRxM_9NN+#j?duob4vN zney2@xEw1BSlwhBi=2R!2jjzd%xi)56{ba+Cm;ZjQDv4#&$jrrT{e8Kk&9(KOIQV_ zwV*Pv7SlKz4Jan^4Zg4*X!+@Tw-5TwoWK9$H}7nFx_5H?CqJ^U3gf$cvcBKNk8FJR z=%0W7-RsZa_`qd-f8W35xBvL_S&NSMd~jm^AMcjlb#0gR-s*}C;7HP&rCM&6Xx*^h zJNPGU8e(lL8e$xu-_VI4ORMI zHncXJc%8h};Bv2x)y$lf(%KAKg&M5sA{m-hF%K{-aS9P2$FFtS{{EE1H~laxWI?Tr zC1|q{h9kk?%;E25+>HY|-0G zH<60PapDB90oC#!Vh|wN0xri^qY=cx58~e@4y?`V#U0i(ND^*21gE1GZdIal4N%m^ zL=*GE8zWtI;a1xTkcqY+wsRQyzs$eKeGE)UbY!H9`M=mSG)e@=-@Wn-nnW; z{=n1U?|l7@Wa^BtQoi}qpwPh#^kPHFFdX=ZVaeoeFxvL+KPVA9`|9)7Ro!!Dm(AAw zu|eI#Rkcd%hG*qoZ|qUp?oLR`8475ipl&qeZ2OKQJhkIrh+5tosz=yI{u(cN3HHe# z<{(qlSu!7IGO%*+#Q+OmNlK}TM&}M*+w1QSPI^VD3KF6TEfNWGj%QlB3A`7DI6<^1 z!XaRgy{Y`BWb6j>9p+OY8HZAwBVcz(JEpoAb?$-+k$Y9>4z9OZbR5S(LsC4AF@^`?LarQ%htzVtr*L7E2cUYzt z?Tp3ZzR?M9JejfryOq!qb4tT=Qt3}B8jPt4b9^_}zj}mTDccaX8JHI`q_{%0h7eUF z1?<6fg|s?;{hC)dKmVHp+FWKs?g~+jT+jz071OY+kb*7bGz?1aGTB)uldN_Z&kP$6 zwyqZ!%9J9UoWbq}t+HLG%5@)>WjD}{0(Umq9jN_NI+e#l$O9-`KTV?;nJWUaNU|8# z#_)K3WdFcLD+rrs4^SB{wcR`8PR-`inwqZbK2|&U%B_)^cbkckM#)a4A_hWp!k~>dseR zTiK_+_oxG_r&WhnlRn~$C$Vbv1+h?yC&OV_%jYC8g(g$|yXP`5rt89E?Soso$D@bG zZwijD9+A7KTZfL7Td&U*&J9H$$hKIjL_@I~uy)#oza4IsFU(Di^&cFlbq%z?F{0Ov zwm$5PZ7P}~ZIQ*VI%W*<==!P~0Lf5L z;FX&?WwNqhR)w?31D^SICy=Sa$bu8Bfm|lXG#DS#EJu%a-Y@5MZbi{Bp`$-4W__lz zZMxR`^WJLyi_fnbQ0S`W_sKOX_HfgIE(5b=j}D$4sma)fU+JyZ9lzz0S?~SGUc3K| z#~#~$)#>*=zV-Z1KDw*tUmx$g{+;FPhCI4{|GQ;F{=Q_^2VFk>xbq5(U&G-C-EKcH zgH5+Wc8gv&fRqJ*HyIB}sn&&Ti&QRixH=16*(_BP6&byb7R+(1mgi1;Kil4~^{E=E zU4(z1RoRGLn6n$`otB#^Yc-b!@^56pp2VZ*t5~L#)djI{wURQs!?eTMd zxKpz~mouC(xh=~AzY3dTQ^axxMq%hc@PXApHZ7PKkBgYCI>8dzWVl_g-zydUqv8G+Uv~SO zSCsDi@~*o#essr?$7auY%=_nU6My*P%UgOrzx30cH$TgtuyWm zPsdJRq9U1CSgVX#if~j3DzR89J}R+v%-ZsCiM2z=(E=f?v@U3K5ZJy#>0hxrRb?jH z{5F(=$ugnz@3T79UteuTVu^O6x`Y!uLrdea)EFJg_qce8H__%E*iU>gFC{ThXXf*c z6+4hT?$#e}`{yOfXHXIjeivxJ9rBw?VORJPUqTjI+)^n_m>fk=j{`)8MVlq6=hjVk zYZ;H6vM8Pif-W9z=6&a}KVTYmrd(ge|t8f_sL*QfJ@Z)_$Y z!U~9@hzCAxKSwHV7#Opg+^H;g7Wkg!x9NJ_Vm;7n3K)3qrGX1n&tx*t%j|GhK#ke%SxeUU;XwrMhjm(x&g3+E23(Id%3IFzc0K;PeGN0wi(Gn`nINVR@4 z5u5VCD2EX%fk^~fba?b&sIzw;7X@4JC>EuSMff?Ru7k!1cp7^HUIbZ*9@q_O?`OzgFAbQUMLT;zy{XX4! zWdEV3UQOQDv0wK`hA)~HT^z5zV$P8cmp|JrzoP5@J~fqFFF)E*?{LBDd_-TBsnLO% zCGq4~Vsmf#*jOl4{v@F}UOjx>`OxfLMjnS##z{Rgv%BVp_y)=B;=)*i8WYj5J`!RX z+hG|;d;-ffeBf8bN>T6oPeSh#9MggP7n}#deVmmc-T+vdVsn^BnjozyY6%B<07Brk zNhZX>orG2q?f9qXdUO^+Ix)g=A|9zus?~MiNS%i*bPDJDRBW`OO;vS`qKNeK42>Q# zz`^JBiaQmiXI?j&u+S<^z^T0F{&Rs}C9hq|divQe4!CpmK&~nHIrzw-J750%hNjy70H3y;>qi3N7cqd+m~XcGj8Y&?K|pV zd9dPX37|Y43WXC-K+xl8bSQ?k4=r9&Fx=xDJ1q7|TCvgvvCLmHp;NxJRgC->fz$0Cotxqj7V&hZd0u~0ys8X#b2x{W z9Y%I$S!^!ov^fY@oZEpKLRscxppcT^X2fp0(wafEc2i6d-7Hu7vU6jqw*_W-aot+pq zrsLE#70E%V?YmR4`Z~(u8Jms3I+Lr+*CJnSD0Suq@lY}q=Nh*+HJUcDuyUn^CA|hj zuVRpqf}dT+@)3t-%cJ@@qBoo_Cz7+0~k`@-6VU)79RTD69}ukJ}ztyw@&uA1L@SKTjw z=sBzN^^nkKHjLMwn6Nlsn6Aj>{(Sab)!*+N)<5LXfv`5ykujK| z9s4tZFdCyq#gB{`|Ixu9QKU8^xn_h?x}&OgK3?b%wE*KlNplx;ttA4pu(W_8gewNz z2+*zAnk4IdqoZv{@eH#yqPcOLUTbj8BrsXWf!;)N%5t;x>|aI`FHBm5bF6O-U^~F! zbHLRvTNfB5fblmo2Ho}AE#E);>iyq;yZ-soPVct53klp5_;a^phteCQ9;oZxJPaI=kG5lyp z`AF9tdL(mRju;*?paznN>=TeXQ0%hp2VxaLQzDjF;B81CNNgEL88AtaWkIK-QqVJS z!Su%JKlD64yXXC{jMw_khHX1WD0Gq76oXu=ZiLi{A;I1xCr-lLiCOt`>H6zO7omz6 zpx$sZl3}Xoh)Veb$11%HhAE|(>IR7Mo4dy9xKwZqR|aLorZMG}7MZ1e)`a_4tYMSi zfBk2v{#|@$GE$qe>_rGjNF;0oob!u~hu__N^{j8#-+9)>+pkW2G4iA3lP-Ae!}ft) zJ+|ixmH79pA77b&XC2tD&xFTT?W&uxv7_FzenLmRQvaqzQlwxht9gXm+C~(O-2vsjsf9L`drhCQsDT$0O?g6IvPErq)pQ+VJdrC%pAGG zXj|Bkyb)|U`Kkdp9Jr5F;y_*ZM07r7@}~MPf8p@ce|-DvzHd#MSo=uz{4cw2pYmpX zp>A12zEJZt{@w8JVgrfe^|~2{@`aug9?Q)fwgt$j;j$I{ER?QJK*zH{+Yv%To-}pv zm;AJi6Kt>H7@O9;o|o&C(>iEarvxGy+WX)d3fUtp94W_9p@^J=T#VtBJ`lIOEtzP$ z{*ip4v&ymR8Ugs)2MYhtb%%EyU;NnCK8GJYdT7QZY<)UT`q{RlH@v(2_m}M&y|~|> zZaUV4X()$~#)6%NkJf0`Jn3>P@SfmU|@E%|y&8-e{yY+*k^_uWY&# zui++Qx^#ml+#P!|VlgVb6DGxRRFn&AuT(XDM`<7Is;%(#FH5W(Q0SG>FOU*8$%gV_ zfsB>QaI*a9z0bEk_9I)fjosG$#i<|d3HQHa@^PcxnvLtF*N3l`UK_GAx^}u!F-ED_ zn}{xnhn6K$6?>9kP7KOc-a=T!wDzJTIE&P80JnN&sQ+_UD#t?EYYhGeBl3*kv;^elRr!h-q@LmN(xkO33NA3X!IVq=kZ7jd#RV@I@z>cN$-r^5a~ z_GKK&<-#<80yzs(MIKsUAH1P=#tR$7u}!b$<3C9#o+u=nKRbm_za^qeY5DnR>`MDhO^AzkHV8JE?(*ECB~SclE_FF zZ%_9qY;V4{M|PW}&MaPODx=vr{yt;KXg!Pp9DZcaVUwlg*Tdt%&pu?F~c!61+5Ys$gJ3yXoK!9wm4_9o-}zX+cF z8Qy!3CTMR9WS)rQR8iEa2Jc?P@h-V=3DaOAk1NTzw4>#&cwdzUfn750zztEO_`Lv< zYy^Zx#mGREkAI1Q3p!IV032GqIDF|-( z@+SX@0Q@zJ>1~m5^SF$_3(gV;@@VNdM!3c}YY1K;uVGgV!RxC{9C`_CViq6?NU!em zQ8dZGgLrvGT46*7aJs_8q71|% z0LKNJR0KU=s__CotlJ=BWBdW7oO`nyM*vYMC6f$;;}{>g0;jUp_+X1xCcpo#madx@ zV4eX`d$66SZUHKE9Ab`uCpk9g6*tB@RmiRXv?2e{JK6jPM`5=av@e@Ka14P?FXJI^ zAFf?(UblRJy+yn|2Yw`#jzong?y$w0fu+3JdKd@(oByhV683sL`3kNzc zZ$m~Vak(Uv6WqVJ|~D`uL<;fND|jT4=r=f>k+Ha(u?py^qNJjXFrjxPd0w&1`K-+nJ@BBLD%wW?S^gwy3026L@(SY$d>skz{%0G+2wU z;5x82t>Bzc1gX)?)&s&u!OoD}<1GXF> zicFTXzwQ=kjtV!H?s#zq0;(9}>P5wfW&yXS{N7lI55on2AzfE9K0WtW^c5mnJOw%3 zi)v`PBUTYMDFnztwm?=?d@{yt^T{eF6vnH@ zmzWsV6U}E@nuViJXrhUn{oWH4&7Clr()zP8 zceXvHs=`(cQ zC~y22l*r55K)cYV_!m1~qBj~QgrW-@l=4ZT=)IpQt#P~Wa&W{T$f;?^;-x*lPekvf z|8wKDuCGrt%7^FDog&VUX#dnMKxAbjjgyy(08u;MH=$6YLn>r|%gK%L6cSmXV-sIl z{a!A>HdlN}rFm975hGzEgvyEANjaQ|W)$Bv6PI&MBb=~UG0>{Py^x?Xb}nnZ+-MDo zUpy?(J1=uVX1B=W_$3Y_2qzA7B20DDt2EYYy0uGd+0Aa*V7G+HLj(|}-&<^dyA4fl zyT;1PtkY~9qqb0mia%^M%`aj8v5{1C1U8H3E=EznCP3TGqTB~6K_@K90i*ruF6BW8 z7xen%izoi~-oFtljzqEC%2YSN@4RUqQsor8#%OzV07yL0+4c)T>2C^bv_dkIhVq}C zkd}I5M$#SOZ0>Wo-RCB`+@PQ<+kO1s-A@w2 zCl+sngvFCoS@Y;@Q_{rQFJ%OTFqTY6pbzRuwe&e7I1?%jtP1oEIbk2BH=ZN|Z{1wi zhE1LRk~xJWLeD`jnNueJpOAeSUdx`i96NtvxIoSVm@jaK(v1VKR1Y*}6niHd&~hbF0yA`0CJ=!@s{f zyz|v(LRYr_#9RIFj`+ArE(8p!mb#DLI9+SpR-^b+IzB%MAz2h^O)^SHEBN395j9CT zA=n5UmoS|SO{Id-ybwA|W9FBW(pZg1Dx!vpikYTJ*mz&bpcyR@3*p5RB^AW!lcWJF z+ZaxF&@4z;^Xv$@vsAGQpq6H*H=G3e6i?F$@yfV?A1EJFVjO)fmj8bVI8x#iWXBQM zlvasY;7(K{+-Q;7==1X8u~>^sz!dEm_*{xND2n2#9Ekt}7QY1P#EBSv2^q|faPgzf SMJP6DhD!f`bLaf{=Klfi4V{w! literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-ground-mouth.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/owner-sw-ground-mouth.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05a868ebbf9b87f7962beac23cb583d9d7583801 GIT binary patch literal 29957 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 EANi3aN&o-= literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-arrival.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-arrival.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e06b15829827988acdcc7ba23d5c9f0ca6ff291 GIT binary patch literal 26020 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 YV&TXG2PVqs83{xyX|aaxC|gK! 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-mid-tunnel.jpg b/Standalone/Research/WorldAssemblerM3/Linux34/captures/upper-sw-fixture-mid-tunnel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..999175b2ebeb2df8d7e4e9a9f365bd9540b54fa5 GIT binary patch literal 25925 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 literal 0 HcmV?d00001 diff --git a/Standalone/Source/LinuxOffscreenCapture.cpp b/Standalone/Source/LinuxOffscreenCapture.cpp index df470f3..b767312 100644 --- a/Standalone/Source/LinuxOffscreenCapture.cpp +++ b/Standalone/Source/LinuxOffscreenCapture.cpp @@ -14,8 +14,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -39,6 +42,7 @@ namespace float MaximumHeight=-std::numeric_limits::infinity(); std::vector Vertices; std::vector Indices; + std::vector SurfaceIndices; struct FTileRange { std::array Key{}; @@ -198,6 +202,8 @@ namespace for(const auto& Tile:Scene.Tiles)Desired.insert(Tile.Key); std::vector VisibleIndices; VisibleIndices.reserve(Scene.Indices.size()); + Scene.SurfaceIndices.reserve(Scene.Indices.size()- + static_cast(Scene.SkirtTriangles)*3); for(const auto& Tile:Scene.Tiles) { const std::uint8_t VisibleMask=ComputeVisibleSkirtFaceMask(Tile.Key,Desired); @@ -212,6 +218,9 @@ namespace const std::size_t Index=Tile.IndexBegin+static_cast(Triangle)*3; VisibleIndices.insert(VisibleIndices.end(),Scene.Indices.begin()+Index, Scene.Indices.begin()+Index+3); + if(FaceMask==0) + Scene.SurfaceIndices.insert(Scene.SurfaceIndices.end(), + Scene.Indices.begin()+Index,Scene.Indices.begin()+Index+3); } } Scene.Indices=std::move(VisibleIndices); @@ -219,6 +228,272 @@ namespace return true; } + struct FClipCapResult + { + std::uint64_t Intersections=0,Loops=0,OpenContours=0,Triangles=0; + std::uint64_t DegreeOneNodes=0,BranchNodes=0; + std::uint64_t ClosedOpenContours=0; + double OpenGapMetres=0.0,NearestOpenGapMetres=0.0; + }; + + FClipCapResult AddClipPlaneCaps(FScene& Scene,const std::array& InputPlane) + { + FClipCapResult Result; + const double NormalLength=std::hypot(InputPlane[0],InputPlane[1],InputPlane[2]); + if(!(NormalLength>0.0))return Result; + const std::array N={InputPlane[0]/NormalLength, + InputPlane[1]/NormalLength,InputPlane[2]/NormalLength}; + const double D=InputPlane[3]/NormalLength; + const std::array Reference=std::abs(N[2])<0.85 + ?std::array{0.0,0.0,1.0}:std::array{0.0,1.0,0.0}; + const auto Cross=[](const std::array& A,const std::array& B) + { + return std::array{A[1]*B[2]-A[2]*B[1], + A[2]*B[0]-A[0]*B[2],A[0]*B[1]-A[1]*B[0]}; + }; + const auto Normalize=[](const std::array& A) + { + const double Length=std::hypot(A[0],A[1],A[2]); + return Length>0.0?std::array{A[0]/Length,A[1]/Length,A[2]/Length} + :std::array{1.0,0.0,0.0}; + }; + const auto Dot=[](const std::array& A,const std::array& B) + {return A[0]*B[0]+A[1]*B[1]+A[2]*B[2];}; + const std::array U=Normalize(Cross(N,Reference)); + const std::array V=Normalize(Cross(N,U)); + const std::array Origin={-D*N[0],-D*N[1],-D*N[2]}; + using FPointKey=std::pair; + std::map NodeForPoint; + std::vector> PlanePoints; + std::vector> WorldPoints; + std::set> Segments; + const auto AddPoint=[&](const std::array& Point) + { + const std::array Relative={Point[0]-Origin[0], + Point[1]-Origin[1],Point[2]-Origin[2]}; + const std::array PlanePoint={Dot(Relative,U),Dot(Relative,V)}; + constexpr double Quantization=1000.0; + const FPointKey Key{static_cast(std::llround(PlanePoint[0]*Quantization)), + static_cast(std::llround(PlanePoint[1]*Quantization))}; + const auto Found=NodeForPoint.find(Key); + if(Found!=NodeForPoint.end())return Found->second; + const std::size_t Index=PlanePoints.size(); + NodeForPoint.emplace(Key,Index);PlanePoints.push_back(PlanePoint); + WorldPoints.push_back(Point);return Index; + }; + for(std::size_t Triangle=0;Triangle+2,3> Points{}; + std::array Distances{}; + for(std::size_t Vertex=0;Vertex<3;++Vertex) + { + const auto& Source=Scene.Vertices[Scene.Indices[Triangle+Vertex]]; + Points[Vertex]={Source.WorldPosition[0],Source.WorldPosition[1],Source.WorldPosition[2]}; + Distances[Vertex]=Dot(N,Points[Vertex])+D; + } + std::array,3> Hits{};std::size_t HitCount=0; + for(std::size_t Edge=0;Edge<3;++Edge) + { + const std::size_t A=Edge,B=(Edge+1)%3; + const double DA=Distances[A],DB=Distances[B]; + if(std::abs(DA)<=1.0e-9) + { + bool Duplicate=false; + for(std::size_t I=0;I1.0e-9)||(DA>1.0e-9&&DB< -1.0e-9)) + { + const double T=DA/(DA-DB); + const std::array Hit={ + std::lerp(Points[A][0],Points[B][0],T), + std::lerp(Points[A][1],Points[B][1],T), + std::lerp(Points[A][2],Points[B][2],T)}; + bool Duplicate=false; + for(std::size_t I=0;I> Adjacency(PlanePoints.size()); + for(const auto& [A,B]:Segments) + {Adjacency[A].push_back(B);Adjacency[B].push_back(A);} + std::vector DegreeOne; + for(std::size_t Node=0;Node2)++Result.BranchNodes; + } + struct FEndpointPair {double Distance=0.0;std::size_t A=0,B=0;}; + std::vector EndpointPairs; + for(std::size_t I=0;I PairedEndpoints; + for(const FEndpointPair& Pair:EndpointPairs) + { + if(Pair.Distance>1.0)break; + if(PairedEndpoints.contains(Pair.A)||PairedEndpoints.contains(Pair.B))continue; + const auto ClosingEdge=std::minmax(Pair.A,Pair.B); + if(!Segments.emplace(ClosingEdge.first,ClosingEdge.second).second)continue; + Adjacency[Pair.A].push_back(Pair.B);Adjacency[Pair.B].push_back(Pair.A); + PairedEndpoints.insert(Pair.A);PairedEndpoints.insert(Pair.B); + Result.OpenGapMetres=std::max(Result.OpenGapMetres,Pair.Distance); + ++Result.ClosedOpenContours; + } + std::vector> Continuation(Adjacency.size()); + for(std::size_t Node=0;Node Pairs; + for(std::size_t I=0;I Paired; + for(const FTurnPair& Pair:Pairs) + { + if(Pair.Dot>0.25||Paired.contains(Pair.A)||Paired.contains(Pair.B))continue; + Continuation[Node][Pair.A]=Pair.B;Continuation[Node][Pair.B]=Pair.A; + Paired.insert(Pair.A);Paired.insert(Pair.B); + } + } + std::set> UsedSegments; + std::vector> Loops; + for(const auto& Segment:Segments) + { + if(UsedSegments.contains(Segment))continue; + std::vector Loop{Segment.first}; + std::size_t Previous=Segment.first,Current=Segment.second; + UsedSegments.insert(Segment);bool Closed=false,Branched=false; + for(std::size_t Guard=0;Guard<=Segments.size();++Guard) + { + if(Current==Loop.front()){Closed=true;break;} + Loop.push_back(Current); + const auto ContinuationIt=Continuation[Current].find(Previous); + if(ContinuationIt==Continuation[Current].end()) + {Branched=true;break;} + const std::size_t Next=ContinuationIt->second; + const auto NextEdge=std::minmax(Current,Next); + if(UsedSegments.contains(NextEdge)) + {Branched=true;break;} + UsedSegments.insert(NextEdge);Previous=Current;Current=Next; + } + if(Closed&&Loop.size()>=3)Loops.push_back(std::move(Loop)); + else if(Branched||!Closed)++Result.OpenContours; + } + Result.Loops=Loops.size(); + if(Loops.empty())return Result; + + struct FPlaneEdge {std::array A{},B{};}; + std::vector Edges; + std::vector Ys; + for(const auto& Loop:Loops) + for(std::size_t I=0;I& A, + const std::array& B,const std::array& C) + { + const std::array,3> PlaneVertices={A,B,C}; + const std::uint32_t Base=static_cast(Scene.Vertices.size()); + for(const auto& PlaneVertex:PlaneVertices) + { + FVertex Vertex{}; + for(std::size_t Axis=0;Axis<3;++Axis) + { + const double World=Origin[Axis]+U[Axis]*PlaneVertex[0] + +V[Axis]*PlaneVertex[1]+N[Axis]*0.001; + Vertex.Position[Axis]=static_cast(World); + Vertex.WorldPosition[Axis]=static_cast(World); + Vertex.Normal[Axis]=static_cast(-N[Axis]); + } + Vertex.Height=Vertex.Position[2]; + Scene.Vertices.push_back(Vertex); + } + Scene.Indices.insert(Scene.Indices.end(),{Base,Base+1,Base+2}); + ++Result.Triangles; + }; + for(std::size_t Slab=0;Slab+1 Crossings; + for(const FPlaneEdge& Edge:Edges) + { + const double Low=std::min(Edge.A[1],Edge.B[1]); + const double High=std::max(Edge.A[1],Edge.B[1]); + if(Mid<=Low||Mid>=High)continue; + const double T=(Mid-Edge.A[1])/(Edge.B[1]-Edge.A[1]); + Crossings.push_back({std::lerp(Edge.A[0],Edge.B[0],T),&Edge}); + } + std::sort(Crossings.begin(),Crossings.end(),[](const auto& A,const auto& B) + {return A.X A={XAt(Left,Y0),Y0}; + const std::array B={XAt(Right,Y0),Y0}; + const std::array C={XAt(Right,Y1),Y1}; + const std::array E={XAt(Left,Y1),Y1}; + if(std::abs(A[0]-B[0])+std::abs(E[0]-C[0])<1.0e-7)continue; + AppendTriangle(A,B,C);AppendTriangle(A,C,E); + } + } + Scene.DrawnTriangles=Scene.Indices.size()/3; + return Result; + } + EGLDisplay MakeDisplay() { using TGetPlatformDisplay=EGLDisplay(*)(EGLenum,void*,const EGLint*); @@ -537,7 +812,7 @@ int main(int argc,char** argv) { 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-edge-width-m=N] [--clip-plane=NX,NY,NZ,D]\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] [--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; @@ -545,8 +820,10 @@ 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 ReadableMode=true,HeightTint=true,TileEdges=false,Headlamp=false;double TileEdgeWidthMeters=0.15; + bool ReadableMode=true,HeightTint=true,TileEdges=false,TileSkirts=true,Headlamp=false; + double TileEdgeWidthMeters=0.15; bool ClipPlaneEnabled=false;std::array ClipPlane{}; + bool FocusRegionEnabled=false;std::array FocusCenter{};double FocusRadius=0.0; for(int I=3;I(ClipCap.Intersections), + static_cast(ClipCap.Loops), + static_cast(ClipCap.OpenContours), + static_cast(ClipCap.ClosedOpenContours), + static_cast(ClipCap.DegreeOneNodes), + static_cast(ClipCap.BranchNodes), + ClipCap.OpenGapMetres,ClipCap.NearestOpenGapMetres, + static_cast(ClipCap.Triangles),Capped?"PASS":"FAIL"); + if(!Capped)return 3; + } + if(!TileSkirts) + { + const std::size_t SurfaceTriangleCount=Scene.SurfaceIndices.size()/3; + std::vector SurfaceAndCaps=std::move(Scene.SurfaceIndices); + // Caps were appended after the original mesh indices. Keep them while dropping + // the LOD seam skirts, which are useful for streamed play but obscure close captures. + if(ClipPlaneEnabled&&Scene.Indices.size()>CapIndexBegin) + SurfaceAndCaps.insert(SurfaceAndCaps.end(),Scene.Indices.begin()+CapIndexBegin, + Scene.Indices.end()); + Scene.Indices=std::move(SurfaceAndCaps); + Scene.DrawnTriangles=Scene.Indices.size()/3; + std::printf("[OffscreenMeshDisplay] tile_skirts=off kept_surface_triangles=%llu " + "cap_triangles=%llu status=PASS\n", + static_cast(SurfaceTriangleCount), + static_cast(Scene.Indices.size()/3- + SurfaceTriangleCount)); + } + if(FocusRegionEnabled) + { + std::vector FocusedIndices; + FocusedIndices.reserve(Scene.Indices.size()); + const double RadiusSquared=FocusRadius*FocusRadius; + for(std::size_t Triangle=0;Triangle+2 Center{}; + for(std::size_t Corner=0;Corner<3;++Corner) + { + const auto& Vertex=Scene.Vertices[Scene.Indices[Triangle+Corner]]; + for(std::size_t Axis=0;Axis<3;++Axis) + Center[Axis]+=Vertex.WorldPosition[Axis]/3.0; + } + const double DX=Center[0]-FocusCenter[0],DY=Center[1]-FocusCenter[1], + DZ=Center[2]-FocusCenter[2]; + if(DX*DX+DY*DY+DZ*DZ>RadiusSquared)continue; + FocusedIndices.insert(FocusedIndices.end(),Scene.Indices.begin()+Triangle, + Scene.Indices.begin()+Triangle+3); + } + if(FocusedIndices.empty()) + std::printf("[OffscreenFocusRegion] center_m=(%.3f,%.3f,%.3f) radius_m=%.3f " + "triangles=0 status=EMPTY_FALLBACK full_scene_triangles=%llu\n", + FocusCenter[0],FocusCenter[1],FocusCenter[2],FocusRadius, + static_cast(Scene.DrawnTriangles)); + else + { + Scene.Indices=std::move(FocusedIndices); + Scene.DrawnTriangles=Scene.Indices.size()/3; + std::printf("[OffscreenFocusRegion] center_m=(%.3f,%.3f,%.3f) radius_m=%.3f " + "triangles=%llu status=PASS\n",FocusCenter[0],FocusCenter[1],FocusCenter[2], + 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", 1000000.0/Scene.VoxelSizeMicrons,Scene.CameraMeters[0],Scene.CameraMeters[1],Scene.CameraMeters[2], Scene.YawDegrees,Scene.PitchDegrees,Scene.MinimumHeight,Scene.MaximumHeight, diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index 74a1825..8afff40 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -805,8 +805,241 @@ namespace StandaloneStreamBenchmark std::uint64_t wallSamples=0,missingWallSamples=0; bool passed=false; }; + struct FPassageMouthProfileAudit + { + double floorFlatStepRunMetres=0.0,floorStepMetres=0.0; + double wallFlatStepRunMetres=0.0,wallStepMetres=0.0; + std::uint64_t floorSamples=0,wallSamples=0,missingFloorSamples=0,missingWallSamples=0; + bool passed=false; + }; constexpr double MaximumFlatRunMetres=8.0; constexpr double MinimumWallReliefMetres=0.20; + constexpr double PassageProfileSpacingMetres=0.125; + constexpr double PassageProfilePlateauMinimumMetres=0.50; + constexpr double PassageProfilePlateauEpsilonMetres=0.020; + constexpr double PassageProfileStepThresholdMetres=0.100; + constexpr double PassageMouthProfileReachMetres=12.0; + const auto auditProfilePlateaus=[&](const std::vector>& profile) + { + std::pair result{}; + if(profile.size()<2)return result; + std::size_t runStart=0; + for(std::size_t i=1;iPassageProfileSpacingMetres*1.5) + {runStart=i;continue;} + if(std::abs(profile[i][1]-profile[runStart][1]) + <=PassageProfilePlateauEpsilonMetres)continue; + const double flatLength=profile[i-1][0]-profile[runStart][0]; + const double step=std::abs(profile[i][1]-profile[i-1][1]); + if(flatLength>=PassageProfilePlateauMinimumMetres + &&step>=PassageProfileStepThresholdMetres) + { + result.first=std::max(result.first,flatLength); + result.second=std::max(result.second,step); + } + runStart=i; + } + return result; + }; + const auto auditPassageMouthProfiles=[&](const VoxelForgeCore::World& Field, + const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + { + FPassageMouthProfileAudit audit; + if(passage.controlPoints.size()<2)return audit; + const std::size_t end=std::min(passage.lowerMouthControlIndex, + passage.controlPoints.size()-1); + if(end<1)return audit; + struct FProfilePose + { + double distance=0.0,x=0.0,y=0.0,z=0.0,radius=0.0; + }; + std::vector path; + path.reserve(end*8+1); + double distance=0.0; + for(std::size_t segment=0;segment1.0e-8))continue; + const std::size_t steps=std::max(1, + static_cast(std::ceil(length/PassageProfileSpacingMetres))); + for(std::size_t step=segment==0?0:1;step<=steps;++step) + { + const double t=static_cast(step)/steps; + path.push_back({distance+length*t,std::lerp(ax,bx,t), + std::lerp(ay,by,t),std::lerp(az,bz,t),std::lerp(ar,br,t)}); + } + distance+=length; + } + if(path.size()<3)return audit; + const double lowerMouthDistance=distance; + constexpr double DensitySearchStepMetres=0.0625; + const auto densityMetres=[&](double x,double y,double z) + { + const float value=Field.densityAt({x/coreMetres,y/coreMetres,z/coreMetres}); + return std::isfinite(value)?static_cast(value)*coreMetres + :std::numeric_limits::quiet_NaN(); + }; + const auto firstFloorCrossing=[&](const FProfilePose& pose,double x,double y)->double + { + const double expectedFloor=pose.z-pose.radius; + const double maximumRise=std::min(2.0*pose.radius-0.25, + std::max(0.75,pose.radius-1.20+0.50)); + double previousZ=expectedFloor-1.50; + double previous=densityMetres(x,y,previousZ); + if(!std::isfinite(previous))return std::numeric_limits::quiet_NaN(); + double highestFloor=std::numeric_limits::quiet_NaN(); + for(double z=previousZ+DensitySearchStepMetres; + z<=expectedFloor+maximumRise+DensitySearchStepMetres*0.25; + z+=DensitySearchStepMetres) + { + const double current=densityMetres(x,y,z); + if(!std::isfinite(current))return std::numeric_limits::quiet_NaN(); + if(previous<=0.0&¤t>=0.0) + { + const double denominator=current-previous; + const double t=std::abs(denominator)>1.0e-12 + ?std::clamp(-previous/denominator,0.0,1.0):0.0; + highestFloor=std::lerp(z-DensitySearchStepMetres,z,t); + } + previous=current; + } + return highestFloor; + }; + const auto findWallRadius=[&](const FProfilePose& pose,double nx,double ny) + { + const double maximum=pose.radius+2.0; + double previousRadius=0.0; + double previous=densityMetres(pose.x,pose.y,pose.z); + if(!std::isfinite(previous)||previous<0.0) + return std::numeric_limits::quiet_NaN(); + for(double radius=DensitySearchStepMetres;radius<=maximum; + radius+=DensitySearchStepMetres) + { + const double current=densityMetres(pose.x+nx*radius, + pose.y+ny*radius,pose.z); + if(!std::isfinite(current))return std::numeric_limits::quiet_NaN(); + if(previous>=0.0&¤t<=0.0) + { + const double denominator=previous-current; + const double t=std::abs(denominator)>1.0e-12 + ?std::clamp(previous/denominator,0.0,1.0):0.0; + return std::lerp(previousRadius,radius,t); + } + previous=current;previousRadius=radius; + } + return std::numeric_limits::quiet_NaN(); + }; + std::array>,3>,2> floorProfiles; + std::array>,2>,2> wallProfiles; + std::array endpointFloorCounts{}; + for(std::size_t i=0;i=path.size()?path[i].x-path[i-1].x + :path[i+1].x-path[i-1].x; + const double tangentY=i==0?path[i+1].y-path[i].y + :i+1>=path.size()?path[i].y-path[i-1].y + :path[i+1].y-path[i-1].y; + const double tangentLength=std::hypot(tangentX,tangentY); + if(tangentLength<=1.0e-6) + {audit.missingFloorSamples+=3;audit.missingWallSamples+=2;continue;} + const double nx=-tangentY/tangentLength,ny=tangentX/tangentLength; + for(std::size_t lane=0;lane<3;++lane) + { + const double lateral=lane==0?0.0:lane==1?0.75:-0.75; + const double floor=firstFloorCrossing(pose, + pose.x+nx*lateral,pose.y+ny*lateral); + if(lane!=0&&localDistance>=4.0&&localDistance<=5.5) + std::printf("[PassageMouthProfileProbe] id=%s endpoint=%s d_m=%.3f lane_m=%.2f x_m=%.3f y_m=%.3f route_floor_m=%.3f field_floor_m=%.3f\n", + passage.stableId.c_str(),endpoint==0?"upper":"lower", + localDistance,lateral,pose.x+nx*lateral, + pose.y+ny*lateral,pose.z-pose.radius,floor); + if(std::isfinite(floor)) + { + floorProfiles[endpoint][lane].push_back({localDistance,floor}); + ++endpointFloorCounts[endpoint];++audit.floorSamples; + } + else ++audit.missingFloorSamples; + } + if(i%4!=0)continue; + for(std::size_t side=0;side<2;++side) + { + const double sign=side==0?-1.0:1.0; + const double radius=findWallRadius(pose,sign*nx,sign*ny); + if(std::isfinite(radius)) + { + wallProfiles[endpoint][side].push_back({localDistance,radius}); + ++audit.wallSamples; + } + else ++audit.missingWallSamples; + } + } + } + double worstEndpointFloorCoverage=1.0; + for(std::size_t endpoint=0;endpoint<2;++endpoint) + { + for(std::size_t lane=0;lane<3;++lane) + std::sort(floorProfiles[endpoint][lane].begin(), + floorProfiles[endpoint][lane].end(), + [](const auto& a,const auto& b){return a[0](path.size(), + PassageMouthProfileReachMetres/PassageProfileSpacingMetres)+1.0; + worstEndpointFloorCoverage=std::min(worstEndpointFloorCoverage, + expectedFloor>0?endpointFloorCounts[endpoint]/expectedFloor:0.0); + // Lateral probes confirm floor coverage, but do not define a longitudinal + // floor profile: the normal rotates around tight bends and can jump across + // unrelated terrain. The centerline is the stable passage-floor trace. + const auto floorStep=auditProfilePlateaus(floorProfiles[endpoint][0]); + audit.floorFlatStepRunMetres=std::max(audit.floorFlatStepRunMetres, + floorStep.first); + audit.floorStepMetres=std::max(audit.floorStepMetres,floorStep.second); + for(std::size_t side=0;side<2;++side) + { + const auto wallStep=auditProfilePlateaus(wallProfiles[endpoint][side]); + audit.wallFlatStepRunMetres=std::max(audit.wallFlatStepRunMetres,wallStep.first); + audit.wallStepMetres=std::max(audit.wallStepMetres,wallStep.second); + } + } + audit.passed=worstEndpointFloorCoverage>=0.75 + &&audit.wallSamples>=8 + &&audit.floorFlatStepRunMetres==0.0&&audit.wallFlatStepRunMetres==0.0; + return audit; + }; + std::vector> l23TerracedControl; + for(std::size_t tread=0;tread<8;++tread) + for(std::size_t sample=0;sample<=16;++sample) + l23TerracedControl.push_back({(tread*16+sample)*PassageProfileSpacingMetres, + static_cast(tread)*0.25}); + const auto l23TerraceControlResult=auditProfilePlateaus(l23TerracedControl); + const bool l23TerraceControlDetected=l23TerraceControlResult.first + >=PassageProfilePlateauMinimumMetres + &&l23TerraceControlResult.second>=PassageProfileStepThresholdMetres; const auto auditPassageNaturalness=[&](const VoxelForgeCore::World& Field, const VoxelForgeCore::ResolvedLayoutPassageV1& passage) { @@ -1498,6 +1731,7 @@ namespace StandaloneStreamBenchmark return zUm>=stratum->content.bottomMicrometres&&zUmcontent.topMicrometres; }; std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0; + std::uint64_t mouthProfilePasses=0; std::uint64_t openAirViolations=0,openAirLegacyViolations=0,openAirSamples=0; std::uint64_t openAirAudits=0,openAirColumnSamples=0,openAirShortSpanSamples=0; std::uint64_t columnCrossings=0,shortGroundedSpans=0,columnConnectedEnds=0; @@ -1545,6 +1779,8 @@ namespace StandaloneStreamBenchmark const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45, &blockedWorld,&segmentSupport); const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage); + const FPassageMouthProfileAudit mouthProfileAudit= + auditPassageMouthProfiles(Shape,passage); const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld, passage,passageIndex); const FPassageColumnAudit columnAudit=auditPassageColumns(Shape,blockedWorld, @@ -1574,8 +1810,9 @@ namespace StandaloneStreamBenchmark const bool mouthsInContent=mouthInContent(passage.upperStrateIndex,passage.upperMouthSubvoxels) &&mouthInContent(passage.lowerStrateIndex,passage.lowerMouthSubvoxels); ++passageCount;naturalPasses+=naturalAudit.passed; + mouthProfilePasses+=mouthProfileAudit.passed; passagePasses+=passageAudit.passed&&mouthsInRadius&&mouthsInContent - &&naturalAudit.passed; + &&naturalAudit.passed&&mouthProfileAudit.passed; std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu support_samples=%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), @@ -1591,6 +1828,15 @@ namespace StandaloneStreamBenchmark static_cast(naturalAudit.wallSamples), static_cast(naturalAudit.missingWallSamples), naturalAudit.passed?"PASS":"FAIL"); + std::printf("[PassageMouthProfileAudit] id=%s floor_samples=%llu floor_missing=%llu wall_samples=%llu wall_missing=%llu floor_step_scan=centerline floor_flat_step_run_m=%.3f floor_step_m=%.3f wall_flat_step_run_m=%.3f wall_step_m=%.3f spacing_m=%.3f plateau=(%.3f,%.3f) status=%s\n", + passage.stableId.c_str(),static_cast(mouthProfileAudit.floorSamples), + static_cast(mouthProfileAudit.missingFloorSamples), + static_cast(mouthProfileAudit.wallSamples), + static_cast(mouthProfileAudit.missingWallSamples), + mouthProfileAudit.floorFlatStepRunMetres,mouthProfileAudit.floorStepMetres, + mouthProfileAudit.wallFlatStepRunMetres,mouthProfileAudit.wallStepMetres, + PassageProfileSpacingMetres,PassageProfilePlateauMinimumMetres, + PassageProfileStepThresholdMetres,mouthProfileAudit.passed?"PASS":"FAIL"); std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu column_samples=%llu short_span_samples=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n", passage.stableId.c_str(),static_cast(openAirAudit.supportSamples), static_cast(openAirAudit.violations), @@ -1891,12 +2137,23 @@ namespace StandaloneStreamBenchmark const bool l23SmoothWallDetected=!looksNatural(0.0,0.0); std::printf("[PassageNaturalnessNegativeControl] source=L23_smooth_unrelieved_wall relief_p2p_m=0.000 threshold_m=%.3f detected=%s\n", MinimumWallReliefMetres,l23SmoothWallDetected?"true":"false"); + std::printf("[PassageMouthProfileNegativeControl] source=L23_terraced_geometry flat_run_m=%.3f following_step_m=%.3f thresholds=(%.3f,%.3f) detected=%s\n", + l23TerraceControlResult.first,l23TerraceControlResult.second, + PassageProfilePlateauMinimumMetres,PassageProfileStepThresholdMetres, + l23TerraceControlDetected?"true":"false"); std::printf("[PassageNaturalnessSummary] passed=%llu/%llu l23_negative_control=%s flat_run_limit_m=%.3f wall_relief_min_m=%.3f status=%s\n", static_cast(naturalPasses),static_cast(passageCount), l23SmoothWallDetected?"DETECTED":"MISSED",MaximumFlatRunMetres, MinimumWallReliefMetres,naturalPasses==passageCount&&l23SmoothWallDetected?"PASS":"FAIL"); + std::printf("[PassageMouthProfileSummary] passed=%llu/%llu spacing_m=%.3f plateau_min_m=%.3f following_step_min_m=%.3f l23_terrace_negative_control=%s status=%s\n", + static_cast(mouthProfilePasses), + static_cast(passageCount),PassageProfileSpacingMetres, + PassageProfilePlateauMinimumMetres,PassageProfileStepThresholdMetres, + l23TerraceControlDetected?"DETECTED":"MISSED", + mouthProfilePasses==passageCount&&l23TerraceControlDetected?"PASS":"FAIL"); const bool auditPassed=passageCount>0&&passagePasses==passageCount &&naturalPasses==passageCount&&l23SmoothWallDetected + &&mouthProfilePasses==passageCount&&l23TerraceControlDetected &&openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected &&columnAuditsPassed&&noLongBridgeAuditPassed &&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings