#!/usr/bin/env python3 """Freeze a 20-degree mouth-crease gate and project its sample spacing at 1440p.""" import ast import contextlib import importlib.util import io import json import math import re import argparse import os from pathlib import Path ROOT = Path(__file__).resolve().parents[4] BASELINES = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l37")) / "baselines" BASE_PATH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux37/RunMouthFragmentAuditL37.py" SPEC = importlib.util.spec_from_file_location("mouth_fragment_l37", BASE_PATH) BASE = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(BASE) # Keep the near limit frozen at 20 degrees. The saved L37 owner overview measures # 25.542 degrees, so the overview regression limit is 26 degrees: it admits that # baseline while still rejecting the saved L36 washboard (27.133 degrees). NEAR_NORMAL_LIMIT_DEG = 20.0 OVERVIEW_NORMAL_LIMIT_DEG = 26.0 MIN_VISIBLE_PAIRS = 20 MIN_PROFILE_COVERAGE = 0.05 CAMERA = (1.691820, -3.424982, -54.224198) TARGET = (6.298233, 1.137233, -55.468264) FOV_DEG = 80.0 WIDTH_1440P = 2560 HEIGHT_1440P = 1440 MOUTH = (5.600, 0.445, -55.156) OVERVIEW_CAMERA = (MOUTH[0] - 9.75, MOUTH[1] - 11.4, MOUTH[2] + 8.0) def normalize(vector): magnitude = math.sqrt(sum(value * value for value in vector)) return tuple(value / magnitude for value in vector) def view_basis(camera, target): forward = normalize(tuple(target[i] - camera[i] for i in range(3))) right = normalize((forward[1], -forward[0], 0.0)) up = (right[1] * forward[2] - right[2] * forward[1], right[2] * forward[0] - right[0] * forward[2], right[0] * forward[1] - right[1] * forward[0]) return forward, right, up def visible_crease(scene_data, camera, target, center=None, preferred=None, inner=None, outer=None): cx, cy = center or BASE.CENTER inner = BASE.INNER if inner is None else inner outer = BASE.OUTER if outer is None else outer bounds = (cx - outer, cx + outer, cy - outer, cy + outer) voxel_um, triangles, _ = scene_data preferred = BASE.PREFERRED if preferred is None else preferred cell = max(2.0, 16.0 * voxel_um / 1_000_000.0) buckets = BASE.RING.build_buckets(triangles, True, bounds, cell) forward, right, up = view_basis(camera, target) tan_h = math.tan(math.radians(FOV_DEG / 2.0)) tan_v = math.tan(math.atan(tan_h * HEIGHT_1440P / WIDTH_1440P)) focal = WIDTH_1440P / (2.0 * tan_h) lines = [] count = round((outer - inner) / BASE.STEP) for degrees in (135.0, 180.0, 225.0, 270.0, 315.0): angle = math.radians(degrees) lines.append([(cx + radius * math.cos(angle), cy + radius * math.sin(angle)) for radius in (inner + index * BASE.STEP for index in range(count + 1))]) tangent_count = round(8.0 / BASE.STEP) for degrees in (225.0, 315.0): angle = math.radians(degrees) normal = (math.cos(angle), math.sin(angle)) tangent = (-normal[1], normal[0]) lines.append([(cx + 6.5 * normal[0] + (-4.0 + index * BASE.STEP) * tangent[0], cy + 6.5 * normal[1] + (-4.0 + index * BASE.STEP) * tangent[1]) for index in range(tangent_count + 1)]) maximum, largest_pixels, worst_depth, visible_pairs = 0.0, 0.0, 0.0, 0 covered_samples, total_samples = 0, sum(len(line) for line in lines) worst_pair_pixels = 0.0 worst_pair = None def project(point): offset = tuple(point[i] - camera[i] for i in range(3)) depth = sum(offset[i] * forward[i] for i in range(3)) x = sum(offset[i] * right[i] for i in range(3)) y = sum(offset[i] * up[i] for i in range(3)) return depth, x, y for points in lines: samples = [BASE.RING.sample_surface(buckets, x, y, True, cell, preferred) for x, y in points] covered_samples += sum(sample is not None for sample in samples) for index in range(1, len(samples)): before, current = samples[index - 1], samples[index] if before is None or current is None: continue p0 = (points[index - 1][0], points[index - 1][1], before[0]) p1 = (points[index][0], points[index][1], current[0]) midpoint = tuple((p0[axis] + p1[axis]) * 0.5 for axis in range(3)) depth, horizontal, vertical = project(midpoint) if (depth <= 0.0 or abs(horizontal) > depth * tan_h or abs(vertical) > depth * tan_v): continue visible_pairs += 1 angle = math.degrees(math.acos(max(-1.0, min(1.0, sum(a * b for a, b in zip(before[1], current[1])))))) d0, x0, y0 = project(p0) d1, x1, y1 = project(p1) pixels = math.hypot(focal * x0 / d0 - focal * x1 / d1, focal * y0 / d0 - focal * y1 / d1) largest_pixels = max(largest_pixels, pixels) if angle > maximum: maximum, worst_pair, worst_depth = angle, (p0, p1), depth worst_pair_pixels = pixels coverage = covered_samples / total_samples if total_samples else 0.0 return (maximum, worst_depth, largest_pixels, visible_pairs, worst_pair, worst_pair_pixels, coverage) def run(path, label, *, center=None, height_min=None, height_max=None, preferred=None, near_camera=None, target=None, overview_camera=None, profile_inner=None, profile_outer=None, profile_coverage_limit=None): path = Path(path) center = center or BASE.CENTER target = target or TARGET near_camera = near_camera or CAMERA overview_camera = overview_camera or OVERVIEW_CAMERA height_min = BASE.HEIGHT_MIN if height_min is None else height_min height_max = BASE.HEIGHT_MAX if height_max is None else height_max profile_inner = BASE.INNER if profile_inner is None else profile_inner profile_outer = BASE.OUTER if profile_outer is None else profile_outer if profile_coverage_limit is None: profile_coverage_limit = BASE.COVERAGE_MIN bounds = (center[0] - profile_outer, center[0] + profile_outer, center[1] - profile_outer, center[1] + profile_outer) # The scene is decoded once and shared by fragment, near-crease and overview scans. scene_data = BASE.RING.read_scene(str(path), 0, height_min, height_max, bounds) stream = io.StringIO() with contextlib.redirect_stdout(stream): passed, maximum = BASE.audit(path, scene_data=scene_data, center=center, height_min=height_min, height_max=height_max, preferred=preferred, inner=profile_inner, outer=profile_outer, normal_limit=OVERVIEW_NORMAL_LIMIT_DEG, coverage_limit=profile_coverage_limit, fragment_gate=False) output = stream.getvalue() print(output, end="") near = visible_crease(scene_data, near_camera, target, center, preferred, profile_inner, profile_outer) far = visible_crease(scene_data, overview_camera, target, center, preferred, profile_inner, profile_outer) print(f"[MouthCreasePixels] build={label} sample_step_m={BASE.STEP:.3f} " f"horizontal_fov_deg={FOV_DEG:.1f} resolution=2560x1440 " f"near_camera_to_mouth_m={math.dist(near_camera, (*center, target[2])):.3f} " f"near_visible_pairs={near[3]} near_max_visible_deg={near[0]:.6f} " f"near_profile_coverage={near[6]:.3f} " f"near_depth_m={near[1]:.3f} near_sample_spacing_px={near[2]:.2f} " f"near_worst_pair_spacing_px={near[5]:.2f} " f"overview_camera_to_mouth_m={math.dist(overview_camera, (*center, target[2])):.3f} " f"overview_visible_pairs={far[3]} overview_max_visible_deg={far[0]:.6f} " f"overview_profile_coverage={far[6]:.3f} " f"overview_depth_m={far[1]:.3f} overview_sample_spacing_px={far[2]:.2f} " f"overview_worst_pair_spacing_px={far[5]:.2f} overall_max_deg={maximum:.6f}") near_ok = (near[3] >= MIN_VISIBLE_PAIRS and near[6] >= MIN_PROFILE_COVERAGE and near[0] <= NEAR_NORMAL_LIMIT_DEG) overview_ok = (far[3] >= MIN_VISIBLE_PAIRS and far[6] >= MIN_PROFILE_COVERAGE and far[0] <= OVERVIEW_NORMAL_LIMIT_DEG) views_pass = near_ok and overview_ok print(f"[MouthCreaseViewGate] build={label} near_limit_deg={NEAR_NORMAL_LIMIT_DEG:.1f} " f"overview_limit_deg={OVERVIEW_NORMAL_LIMIT_DEG:.1f} " f"min_visible_pairs={MIN_VISIBLE_PAIRS} " f"min_profile_coverage={MIN_PROFILE_COVERAGE:.2f} " f"near={'PASS' if near_ok else 'FAIL'} overview={'PASS' if overview_ok else 'FAIL'} " f"status={'PASS' if views_pass else 'FAIL'}") return passed and views_pass, max(maximum, near[0], far[0]) def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--candidate", type=Path, default=ROOT / "Saved/Linux/l37/owner-fi-ground-mouth.vfmesh") parser.add_argument("--candidate-sw", type=Path) parser.add_argument("--layout-sw", type=Path) parser.add_argument("--capture-log-sw", type=Path) args = parser.parse_args() paths = { "L35": BASELINES / "mouth/l35/owner-fi-ground-mouth.vfmesh", "L36": BASELINES / "mouth/l36/owner-fi-ground-mouth.vfmesh", "L37": args.candidate if args.candidate.is_absolute() else ROOT / args.candidate, } results = {label: run(path, label) for label, path in paths.items()} controls = (not results["L35"][0] and not results["L36"][0] and results["L35"][1] > OVERVIEW_NORMAL_LIMIT_DEG and results["L36"][1] > OVERVIEW_NORMAL_LIMIT_DEG) final = (results["L37"][0] and results["L37"][1] <= OVERVIEW_NORMAL_LIMIT_DEG) if args.candidate_sw: if not args.layout_sw or not args.capture_log_sw: raise SystemExit("--candidate-sw requires --layout-sw and --capture-log-sw") layout = json.loads(args.layout_sw.read_text(encoding="utf-8")) passage = layout["passages"][0] q_to_m = layout["core_voxel_size_um"] / (256.0 * 1_000_000.0) mouth = tuple(value * q_to_m for value in passage["lower_mouth_q"]) capture = args.capture_log_sw.read_text(encoding="utf-8", errors="replace") camera_match = re.search(r"\[L37CaptureCamera\] view=owner-sw-ground-mouth .*?" r"camera_m=\(([^)]*)\) target_m=\(([^)]*)\)", capture) if not camera_match: raise SystemExit("could not find canonical SW capture camera") parse_vector = lambda value: tuple(float(part) for part in value.split(",")) near_camera, target = map(parse_vector, camera_match.groups()) overview_camera = (mouth[0] + 2.5 * (near_camera[0] - mouth[0]), mouth[1] + 2.5 * (near_camera[1] - mouth[1]), near_camera[2] + 7.0) sw_final, sw_max = run(args.candidate_sw, "owner-sw-style1", center=mouth[:2], height_min=mouth[2] - 24.0, height_max=mouth[2] + 16.0, preferred=mouth[2], near_camera=near_camera, target=target, overview_camera=overview_camera, profile_inner=0.5, profile_outer=4.5, profile_coverage_limit=0.0) final = final and sw_final and sw_max <= OVERVIEW_NORMAL_LIMIT_DEG print(f"[MouthCreaseGate] near_limit_deg={NEAR_NORMAL_LIMIT_DEG:.1f} " f"overview_limit_deg={OVERVIEW_NORMAL_LIMIT_DEG:.1f} " f"L35_42deg_fail_control={'PASS' if controls else 'FAIL'} " f"L36_27deg_fail_control={'PASS' if controls else 'FAIL'} " f"real_owner_candidates={'PASS' if final else 'FAIL'} " f"status={'PASS' if controls and final else 'FAIL'}") raise SystemExit(0 if controls and final else 1) if __name__ == "__main__": main()