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
74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Copy only tiles for one LOD and spatial window from a VFMSH scene."""
|
|
import argparse
|
|
import resource
|
|
import shutil
|
|
import struct
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("source")
|
|
parser.add_argument("destination")
|
|
parser.add_argument("--lod", type=int, required=True)
|
|
parser.add_argument("--bounds", nargs=6, type=float, required=True,
|
|
metavar=("XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"))
|
|
args = parser.parse_args()
|
|
if not 0 <= args.lod <= 8:
|
|
parser.error("--lod must be between 0 and 8")
|
|
x_min, x_max, y_min, y_max, z_min, z_max = args.bounds
|
|
if x_max <= x_min or y_max <= y_min or z_max <= z_min:
|
|
parser.error("bounds must have positive extents")
|
|
|
|
selected = []
|
|
with open(args.source, "rb") as src:
|
|
prefix = src.read(60)
|
|
if len(prefix) != 60 or prefix[:8] != b"VFMSH001":
|
|
raise SystemExit("source has an invalid VFMSH001 header")
|
|
version, voxel_um, tile_count = struct.unpack_from("<3I", prefix, 8)
|
|
if version != 1 or voxel_um == 0 or tile_count > 1_000_000:
|
|
raise SystemExit("source has an unsupported scene header")
|
|
for _ in range(tile_count):
|
|
header = src.read(36)
|
|
if len(header) != 36:
|
|
raise SystemExit("truncated tile header")
|
|
key = struct.unpack_from("<4i", header)
|
|
_, _, vertex_count, index_count, mask_count = struct.unpack_from("<5I", header, 16)
|
|
payload_offset = src.tell()
|
|
payload_size = vertex_count * 24 + index_count * 4 + mask_count
|
|
extent = 32.0 * (1 << key[3]) * voxel_um / 1_000_000.0
|
|
tx0, ty0, tz0 = key[0] * extent, key[1] * extent, key[2] * extent
|
|
intersects = (key[3] == args.lod and tx0 <= x_max and tx0 + extent >= x_min
|
|
and ty0 <= y_max and ty0 + extent >= y_min
|
|
and tz0 <= z_max and tz0 + extent >= z_min)
|
|
if intersects:
|
|
selected.append((header, payload_offset, payload_size))
|
|
src.seek(payload_size, 1)
|
|
if src.read(1):
|
|
raise SystemExit("source scene has trailing bytes")
|
|
|
|
if not selected:
|
|
raise SystemExit("no tiles matched the requested LOD and bounds")
|
|
with open(args.source, "rb") as src, open(args.destination, "wb") as dst:
|
|
prefix = bytearray(src.read(60))
|
|
struct.pack_into("<I", prefix, 16, len(selected))
|
|
dst.write(prefix)
|
|
for header, payload_offset, payload_size in selected:
|
|
dst.write(header)
|
|
src.seek(payload_offset)
|
|
remaining = payload_size
|
|
while remaining:
|
|
block = src.read(min(1 << 20, remaining))
|
|
if not block:
|
|
raise SystemExit("truncated tile payload")
|
|
dst.write(block)
|
|
remaining -= len(block)
|
|
print(f"[VFMeshLodWindow] source={args.source} lod={args.lod} "
|
|
f"selected_tiles={len(selected)} output={args.destination} "
|
|
f"output_bytes={__import__('os').path.getsize(args.destination)} "
|
|
f"peak_rss_kib={resource.getrusage(resource.RUSAGE_SELF).ru_maxrss} status=PASS")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|