#!/usr/bin/env python3 """Small CPU-only matched views of the legacy and native FloatingIslands fields.""" from __future__ import annotations import ctypes import json import math import struct from pathlib import Path from PIL import Image, ImageDraw ROOT = Path(__file__).resolve().parent RESULTS = ROOT / "results" CAPTURES = RESULTS / "captures" CAPTURES.mkdir(parents=True, exist_ok=True) WIDTH, HEIGHT = 320, 226 BACKGROUND = (236, 240, 242) LEGACY_COLOR = (133, 127, 105) NATIVE_COLOR = (78, 135, 151) ROUTE_COLOR = (223, 72, 45) TILE_COLOR = (178, 60, 52) LOD_COLOR = (211, 136, 45) Q = 256.0 def lower_priority() -> None: if hasattr(ctypes, "windll"): ctypes.windll.kernel32.SetPriorityClass(ctypes.windll.kernel32.GetCurrentProcess(), 0x00004000) def read_mesh(path: Path): raw = path.read_bytes() if len(raw) < 8 or raw[:4] != b"VFMI": raise RuntimeError(f"invalid field mesh: {path}") count = struct.unpack_from(" 1.0e-12 else (0.0, 0.0, 1.0) def dot(a, b): return sum(x * y for x, y in zip(a, b)) def cross(a, b): return (a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]) def project(points, target, view_dir, scale=None): direction = normalize(view_dir) forward = tuple(-value for value in direction) reference_up = (0.0, 1.0, 0.0) if abs(forward[2]) > 0.98 else (0.0, 0.0, 1.0) right = normalize(cross(forward, reference_up)) up = normalize(cross(right, forward)) camera_points = [] for point in points: delta = tuple(point[i] - target[i] for i in range(3)) camera_points.append((dot(delta, right), dot(delta, up), dot(delta, forward))) if scale is None: span_x = max((p[0] for p in camera_points), default=1.0) - min((p[0] for p in camera_points), default=0.0) span_y = max((p[1] for p in camera_points), default=1.0) - min((p[1] for p in camera_points), default=0.0) scale = 0.86 * min((WIDTH - 30) / max(span_x, 1.0e-6), (HEIGHT - 30) / max(span_y, 1.0e-6)) pixels = [ (WIDTH * 0.5 + point[0] * scale, 31 + (HEIGHT - 31) * 0.5 - point[1] * scale, point[2]) for point in camera_points ] return pixels, scale, right, up, forward def common_scale(mesh_pair, target, view_dir): vertices = mesh_pair[0][1] + mesh_pair[1][1] _, scale, _, _, _ = project(vertices, target, view_dir) return scale def projected_line(a, b, target, basis, scale): right, up, forward = basis points = [] for point in (a, b): delta = tuple(point[i] - target[i] for i in range(3)) points.append((WIDTH * 0.5 + dot(delta, right) * scale, 31 + (HEIGHT - 31) * 0.5 - dot(delta, up) * scale)) return points def render(mesh, mesh_pair, method, target, view_dir, title, subtitle, *, route=None, guide=None, camera_eye=None, framing_radius=None): triangles, vertices = mesh perspective = camera_eye is not None if perspective: forward = normalize(tuple(target[i] - camera_eye[i] for i in range(3))) reference_up = (0.0, 1.0, 0.0) if abs(forward[2]) > 0.98 else (0.0, 0.0, 1.0) right = normalize(cross(forward, reference_up)) up = normalize(cross(right, forward)) scale = WIDTH * 0.91 origin = camera_eye else: if framing_radius is None: scale = common_scale(mesh_pair, target, view_dir) else: scale = 0.86 * min((WIDTH - 30) / (2.0 * framing_radius), (HEIGHT - 30) / (2.0 * framing_radius)) _, _, right, up, forward = project((), target, view_dir, scale) origin = target def screen(point): delta = tuple(point[i] - origin[i] for i in range(3)) cx, cy, depth = dot(delta, right), dot(delta, up), dot(delta, forward) if perspective: if depth <= 1.0: return None return (WIDTH * 0.5 + cx * scale / depth, 31 + (HEIGHT - 31) * 0.5 - cy * scale / depth, depth) return (WIDTH * 0.5 + cx * scale, 31 + (HEIGHT - 31) * 0.5 - cy * scale, depth) background = Image.new("RGB", (WIDTH, HEIGHT + 32), BACKGROUND) draw = ImageDraw.Draw(background) draw.rectangle((0, 0, WIDTH - 1, 31), fill=(34, 46, 54)) draw.text((8, 4), title, fill=(250, 252, 253)) draw.text((8, 17), subtitle, fill=(190, 207, 215)) pixels = background.load() zbuffer = [float("inf")] * (WIDTH * (HEIGHT - 31)) camera_fill = forward if perspective else normalize(view_dir) light = normalize((-0.25 + 1.2 * camera_fill[0], -0.35 + 1.2 * camera_fill[1], 0.45 + 1.2 * camera_fill[2])) base = LEGACY_COLOR if method == "legacy" else NATIVE_COLOR for tri in triangles: points = [screen(tri[offset:offset + 3]) for offset in (0, 3, 6)] if any(point is None for point in points): continue x0 = max(0, int(math.floor(min(p[0] for p in points)))) x1 = min(WIDTH - 1, int(math.ceil(max(p[0] for p in points)))) y0 = max(31, int(math.floor(min(p[1] for p in points)))) y1 = min(HEIGHT - 1, int(math.ceil(max(p[1] for p in points)))) if x0 > x1 or y0 > y1: continue (ax, ay, az), (bx, by, bz), (cx, cy, cz) = points denominator = (by - cy) * (ax - cx) + (cx - bx) * (ay - cy) if abs(denominator) < 1.0e-10: continue normal = normalize(tri[9:12]) shade = 0.50 + 0.50 * max(0.0, dot(normal, light)) color = tuple(max(0, min(255, int(channel * shade))) for channel in base) for y in range(y0, y1 + 1): row = (y - 31) * WIDTH for x in range(x0, x1 + 1): sx, sy = x + 0.5, y + 0.5 u = ((by - cy) * (sx - cx) + (cx - bx) * (sy - cy)) / denominator v = ((cy - ay) * (sx - cx) + (ax - cx) * (sy - cy)) / denominator w = 1.0 - u - v if u < -1e-8 or v < -1e-8 or w < -1e-8: continue if perspective: depth = 1.0 / (u / az + v / bz + w / cz) else: depth = u * az + v * bz + w * cz index = row + x if depth < zbuffer[index]: zbuffer[index] = depth pixels[x, y] = color basis = (right, up, forward) if guide: origin = guide["origin_voxels"] top = guide["top_voxels"] for x_delta, color, label in ((32.0, TILE_COLOR, "32v tile"), (64.0, LOD_COLOR, "64v LOD1")): line = projected_line((origin[0] + x_delta, origin[1] - 190.0, top - 65.0), (origin[0] + x_delta, origin[1] + 190.0, top + 14.0), target, basis, scale) draw.line(line, fill=color, width=2) draw.text((max(2, min(WIDTH - 55, int(line[1][0]) + 2)), max(33, min(HEIGHT - 11, int(line[1][1]) - 12))), label, fill=color) if route: points = [screen(point) for point in route] points = [point[:2] for point in points if point is not None] if len(points) >= 2: draw.line(points, fill=(250, 248, 239), width=5, joint="curve") draw.line(points, fill=ROUTE_COLOR, width=3, joint="curve") for index in (0, len(points) - 1): x, y = points[index] draw.ellipse((x - 4, y - 4, x + 4, y + 4), fill=(250, 248, 239), outline=ROUTE_COLOR, width=2) return background def titled_pair(left, right, category): pair = Image.new("RGB", (WIDTH * 2, HEIGHT + 32), (220, 226, 229)) pair.paste(left, (0, 0)) pair.paste(right, (WIDTH, 0)) draw = ImageDraw.Draw(pair) draw.rectangle((0, 0, WIDTH * 2 - 1, HEIGHT + 31), outline=(72, 84, 91), width=1) draw.text((8, HEIGHT + 14), f"{category} | same target, camera and scale", fill=(45, 55, 61)) return pair def main(): lower_priority() data = json.loads((RESULTS / "audit.json").read_text(encoding="utf-8")) anchor = data["comparison_anchor_core_voxels"] route = data["route_points_core_voxels"] profiles = data["island_profiles"] middle_island = profiles[1] cluster = { "legacy": read_mesh(RESULTS / "cluster_legacy.vfmesh"), "native": read_mesh(RESULTS / "cluster_native.vfmesh"), } detail = { "legacy": read_mesh(RESULTS / "detail_legacy.vfmesh"), "native": read_mesh(RESULTS / "detail_native.vfmesh"), } a = anchor scenes = ( ("overview", "Cluster overview", cluster, (a[0], a[1], a[2] - 28.0), (8.0, -10.0, 7.0), None, None), ("underside", "Cluster underside and lobed roots", detail, (middle_island["center_voxels"][0], middle_island["center_voxels"][1], middle_island["bottom_voxels"] - 6.0), (0.12, -0.08, -1.0), None, None), ("edge_cliff", "Thick crust and bounded rock detail", detail, (middle_island["center_voxels"][0], middle_island["center_voxels"][1], middle_island["top_voxels"] - middle_island["radius_voxels"] * 0.65), (1.0, -0.25, 0.18), None, None), ("route", "Supported route across the cluster", cluster, (middle_island["center_voxels"][0], middle_island["center_voxels"][1], middle_island["top_voxels"] - 18.0), (8.0, -10.0, 7.0), route, None), ) pairs = [] for key, title, meshes, target, camera, path, grid in scenes: framing_radius = 28.0 if key in ("underside", "edge_cliff") else None left = render(meshes["legacy"], (meshes["legacy"], meshes["native"]), "legacy", target, camera, title, "Legacy bridge | exact owner field", route=None, guide=grid, framing_radius=framing_radius) route_caption = "Core native | planner route" if path else "Core native | matched field view" right = render(meshes["native"], (meshes["legacy"], meshes["native"]), "native", target, camera, title, route_caption, route=path, guide=grid, framing_radius=framing_radius) pair = titled_pair(left, right, title) out = CAPTURES / f"{key}_matched.jpg" pair.save(out, quality=82, optimize=True) pairs.append(pair) print(f"capture={out.name} bytes={out.stat().st_size} size={pair.size[0]}x{pair.size[1]}") eye_index = 5 eye_route = route[eye_index] eye = (eye_route[0], eye_route[1], eye_route[2] + 3.68) next_island = profiles[1] look = (next_island["center_voxels"][0], next_island["center_voxels"][1], next_island["top_voxels"] + 5.0) perspective_pair = [] for method, meshes in (("legacy", cluster), ("native", cluster)): perspective_pair.append(render(meshes[method], (meshes["legacy"], meshes["native"]), method, look, (0.0, 0.0, -1.0), "Island-edge player view", "Eye at 1.8 m | route span to next island", route=None, camera_eye=eye)) eye_pair = titled_pair(perspective_pair[0], perspective_pair[1], "Island-edge player view") eye_path = CAPTURES / "player_eye_matched.jpg" eye_pair.save(eye_path, quality=80, optimize=True) pairs.insert(3, eye_pair) print(f"capture={eye_path.name} bytes={eye_path.stat().st_size} size={eye_pair.size[0]}x{eye_pair.size[1]}") sheet = Image.new("RGB", (WIDTH * 2, (HEIGHT + 32) * len(pairs)), (218, 225, 228)) for row, pair in enumerate(pairs): sheet.paste(pair, (0, row * (HEIGHT + 32))) sheet_path = CAPTURES / "contact_sheet.jpg" sheet.save(sheet_path, quality=76, optimize=True) oversized = [(path.name, path.stat().st_size) for path in sorted(CAPTURES.glob("*.jpg")) if path.stat().st_size >= 300_000] for path in sorted(CAPTURES.glob("*.jpg")): print(f"capture_size={path.name} bytes={path.stat().st_size}") if oversized: raise RuntimeError(f"captures exceed the 300 KB limit: {oversized}") print(f"contact_sheet={sheet_path.name} bytes={sheet_path.stat().st_size} views=5 matched_pairs=5") if __name__ == "__main__": main()