wip(assembler): round L32 -- smooth Gradient interface at full amplitude (no rings, not flat)

Band faces now use signed distance to the displaced solid intervals, continuous across bands, so
MC interpolates the interface instead of terracing at density levels. The Gradient amplitude is
restored to width/8 (about 4 m peak-to-peak at 16 m). Ring/terrace audit at LOD0-8 on the FI floor and SW
ceiling passes; negative controls: L30 (rings) and L31 (flat) both fail. Hole/interface audits,
16 passage rows and 24/24 determinism pass. Evaluator 20. Cost vs L31 SW +1.9%, FI +1.5%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-21 20:27:29 +02:00
1 parent 28069f0d98
commit d0158c6019
31 files changed
+2207 -111

No files matched your search

@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Stream one VFMSH tile at a time to locate LOD/interface patches."""
import argparse
import array
import resource
import struct
import sys
def main():
parser = argparse.ArgumentParser()
parser.add_argument("scene")
parser.add_argument("--lod", type=int, required=True)
parser.add_argument("--surface", choices=("floor", "ceiling"), required=True)
parser.add_argument("--height-min-m", type=float, required=True)
parser.add_argument("--height-max-m", type=float, required=True)
args = parser.parse_args()
candidates = []
scanned = 0
with open(args.scene, "rb") as stream:
if stream.read(8) != b"VFMSH001":
raise SystemExit("invalid VFMSH001 scene")
version, voxel_um, tile_count = struct.unpack("<3I", stream.read(12))
stream.seek(40, 1)
if version != 1:
raise SystemExit("unsupported mesh scene")
for _ in range(tile_count):
key = struct.unpack("<4i", stream.read(16))
surface_count, _, vertex_count, index_count, mask_count = struct.unpack(
"<5I", stream.read(20))
payload = vertex_count * 24 + index_count * 4 + mask_count
if key[3] != args.lod:
stream.seek(payload, 1)
continue
scanned += 1
positions = array.array("f")
positions.frombytes(stream.read(vertex_count * 12))
normals = array.array("f")
normals.frombytes(stream.read(vertex_count * 12))
indices = array.array("I")
indices.frombytes(stream.read(index_count * 4))
masks = stream.read(mask_count)
if sys.byteorder != "little":
positions.byteswap()
normals.byteswap()
indices.byteswap()
hits = 0
sum_x = sum_y = sum_z = 0.0
min_z, max_z = float("inf"), float("-inf")
want_up = args.surface == "floor"
for offset in range(0, index_count, 3):
if masks and masks[offset // 3]:
continue
a, b, c = indices[offset:offset + 3]
if max(a, b, c) >= surface_count:
continue
nz = (normals[a * 3 + 2] + normals[b * 3 + 2] + normals[c * 3 + 2]) / 3.0
if (nz > 0) != want_up:
continue
za, zb, zc = positions[a * 3 + 2], positions[b * 3 + 2], positions[c * 3 + 2]
if ((za + zb + zc) / 3.0 < args.height_min_m
or (za + zb + zc) / 3.0 > args.height_max_m):
continue
hits += 1
sum_x += (positions[a * 3] + positions[b * 3] + positions[c * 3]) / 3.0
sum_y += (positions[a * 3 + 1] + positions[b * 3 + 1] + positions[c * 3 + 1]) / 3.0
z = (za + zb + zc) / 3.0
sum_z += z
min_z, max_z = min(min_z, za, zb, zc), max(max_z, za, zb, zc)
if hits:
extent = 32.0 * (1 << key[3]) * voxel_um / 1_000_000.0
candidates.append((hits, key, sum_x / hits, sum_y / hits,
sum_z / hits, min_z, max_z, extent))
candidates.sort(reverse=True, key=lambda item: item[0])
print(f"[VFMeshTileScan] lod={args.lod} surface={args.surface} scanned_tiles={scanned} "
f"candidate_tiles={len(candidates)} peak_rss_kib="
f"{resource.getrusage(resource.RUSAGE_SELF).ru_maxrss}")
for hits, key, x, y, z, low, high, extent in candidates[:40]:
print(f"[VFMeshTile] key={key} triangles={hits} centroid_m=({x:.3f},{y:.3f},{z:.3f}) "
f"z_m={low:.3f}..{high:.3f} extent_m={extent:.3f}")
if __name__ == "__main__":
main()