Files
Fr0zkaandClaude Opus 5.5 dcf0763ec5 wip(assembler): round L18 -- FloatingIslands false floors removed; shared strate ceiling
FI geometry v3 drops the all-XY lower boundary seal that created false floors (3.5/8 m); the
ceiling comes from the shared VF_ApplyUpperBoundarySeal and AppendStratumBoundaryCeilings path
for every generator, at each strate's own configured upper boundary (owner: every strate has a
ceiling). Far-LOD ceiling continuity: 0 gaps at LOD4-8. SurfaceWorld bit-identical to L14
(14 configs + 24 m crossing); FI deterministic (28-row matrix); route parity and proofs pass.
Unreal: FI geometryVersion 2->3 and the shared upper-seal helper extracted (UBT compile needed on
the owner PC). Open: small ceiling holes; lower-stratum LOD ring steps seen through the FI void.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
2026-10-20 07:55:53 +02:00

153 lines
6.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""Trace review-image pixels through the exported clipmap mesh."""
import array
import math
import struct
import sys
def read_exact(f, count):
data = f.read(count)
if len(data) != count:
raise EOFError((len(data), count))
return data
def floor_div(n, d):
q, r = divmod(n, d)
return q - (r < 0)
def visible_mask(key, desired):
x, y, z, lod = key
extent = 32 << lod
origin = (x * extent, y * extent, z * extent)
mask = 0
for axis in range(3):
for side in range(2):
probe = [origin[i] + extent // 2 for i in range(3)]
probe[axis] = origin[axis] + (extent if side else -1)
neighbor = None
for level in range(9):
neighbor_extent = 32 << level
coord = tuple(floor_div(probe[i], neighbor_extent) for i in range(3)) + (level,)
if coord in desired:
neighbor = level
break
if neighbor is None or neighbor != lod:
mask |= 1 << (axis * 2 + side)
return mask
def ray_box(origin, direction, low, high):
lo, hi = 0.1, 20000.0
for axis in range(3):
if abs(direction[axis]) < 1e-12:
if origin[axis] < low[axis] or origin[axis] > high[axis]:
return None
else:
a = (low[axis] - origin[axis]) / direction[axis]
b = (high[axis] - origin[axis]) / direction[axis]
if a > b:
a, b = b, a
lo, hi = max(lo, a), min(hi, b)
if lo > hi:
return None
return lo, hi
def ray_tri(origin, direction, a, b, c):
e1 = tuple(b[i] - a[i] for i in range(3))
e2 = tuple(c[i] - a[i] for i in range(3))
p = (direction[1]*e2[2]-direction[2]*e2[1],
direction[2]*e2[0]-direction[0]*e2[2],
direction[0]*e2[1]-direction[1]*e2[0])
det = sum(e1[i]*p[i] for i in range(3))
if abs(det) < 1e-10:
return None
inv = 1.0/det
tvec = tuple(origin[i]-a[i] for i in range(3))
u = sum(tvec[i]*p[i] for i in range(3))*inv
if u < 0 or u > 1:
return None
q = (tvec[1]*e1[2]-tvec[2]*e1[1],
tvec[2]*e1[0]-tvec[0]*e1[2],
tvec[0]*e1[1]-tvec[1]*e1[0])
v = sum(direction[i]*q[i] for i in range(3))*inv
if v < 0 or u+v > 1:
return None
t = sum(e2[i]*q[i] for i in range(3))*inv
return t if t >= 0.1 else None
if len(sys.argv) < 8 or len(sys.argv) % 2 != 1:
raise SystemExit("usage: ProbeCaptureRays.py scene.vfmesh camX camY camZ yaw pitch pixelX pixelY [pixelX pixelY ...]")
scene_path = sys.argv[1]
cam = tuple(map(float, sys.argv[2:5]))
yaw, pitch = map(math.radians, map(float, sys.argv[5:7]))
pixels = [(int(sys.argv[i]), int(sys.argv[i+1])) for i in range(7, len(sys.argv), 2)]
width, height, fov = 1600, 900, math.radians(90)
tan_h = math.tan(fov/2)
tan_v = tan_h / (width/height)
forward = (math.sin(yaw)*math.cos(pitch), math.cos(yaw)*math.cos(pitch), math.sin(pitch))
right = (math.cos(yaw), -math.sin(yaw), 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])
with open(scene_path, "rb") as f:
if read_exact(f, 8) != b"VFMSH001":
raise SystemExit("bad scene")
version, voxel_um, count = struct.unpack("<3I", read_exact(f, 12))
scene_cam = struct.unpack("<3d", read_exact(f, 24))
scene_yaw, scene_pitch = struct.unpack("<2d", read_exact(f, 16))
voxel_m = voxel_um / 1_000_000.0
tiles = []
desired = set()
for _ in range(count):
key = struct.unpack("<4i", read_exact(f, 16))
surface_vertices, skirt_count, vertex_count, index_count, mask_count = struct.unpack("<5I", read_exact(f, 20))
positions = array.array("f"); positions.frombytes(read_exact(f, vertex_count*12))
normals = array.array("f"); normals.frombytes(read_exact(f, vertex_count*12))
indices = array.array("I"); indices.frombytes(read_exact(f, index_count*4))
masks = read_exact(f, mask_count)
if sys.byteorder != "little":
positions.byteswap(); normals.byteswap(); indices.byteswap()
desired.add(key)
tiles.append((key, surface_vertices, skirt_count, positions, normals, indices, masks))
print(f"scene={scene_path} tiles={count} camera={cam} yaw={math.degrees(yaw):.3f} pitch={math.degrees(pitch):.3f}")
for px, py in pixels:
nx = 2*px/width - 1
ny = 1 - 2*py/height
direction0 = tuple(forward[i] + nx*tan_h*right[i] + ny*tan_v*up[i] for i in range(3))
length = math.sqrt(sum(v*v for v in direction0))
direction = tuple(v/length for v in direction0)
hits = []
candidate_tiles = 0
for key, surface_vertices, skirt_count, positions, normals, indices, masks in tiles:
x,y,z,lod = key
extent = 32*(1<<lod)*voxel_m
low = (x*extent, y*extent, z*extent)
high = tuple(v+extent for v in low)
if ray_box(cam, direction, low, high) is None:
continue
candidate_tiles += 1
show_mask = visible_mask(key, desired)
for tri in range(len(indices)//3):
m = masks[tri] if masks else 0
if m and (m & show_mask) == 0:
continue
ia,ib,ic = indices[tri*3:tri*3+3]
a,b,c = [],[],[]
for idx, out in ((ia,a),(ib,b),(ic,c)):
base=idx*3
out.extend((positions[base],positions[base+1],positions[base+2]))
t=ray_tri(cam,direction,a,b,c)
if t is None: continue
p=tuple(cam[i]+t*direction[i] for i in range(3))
nz=(normals[ia*3+2]+normals[ib*3+2]+normals[ic*3+2])/3
hits.append((t,key,tri,m,p,nz,ia>=surface_vertices or ib>=surface_vertices or ic>=surface_vertices))
hits.sort(key=lambda h:h[0])
print(f"pixel=({px},{py}) ray={direction} candidate_tiles={candidate_tiles} hits={len(hits)}")
for t,key,tri,m,p,nz,skirt in hits[:12]:
print(f" t={t:.3f}m key={key} tri={tri} mask={m} skirt={skirt} z={p[2]:.3f} normal_z={nz:.3f} xyz=({p[0]:.3f},{p[1]:.3f},{p[2]:.3f})")