Shared halo + deterministic border-quad ownership + T-junction conformance: 625/625 same-LOD for all three. LOD 2:1 prototype (collar zipper) fails MC 5 / hybrid 38 / DC 40 cases (corners, overhangs). Hybrid is bit-identical to MC on a sampled native SurfaceWorld cliff; DC rougher. Standalone only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
13 KiB
World assembler M2 round 2 — standalone border closure
Date: 2026-10-10
Status: same-LOD gate passed; full LOD0/LOD1 gate failed; no production mesher selected.
Decision
The hybrid now closes the same-LOD tile-border suite: 625/625 cases, with zero unmatched contour probes, open edges, or nonmanifold edges. MC retains its 625/625 pass, and DC also passes as a reference after the same assembly repair.
The 2:1 LOD transition is still not ready. The sharp cliff crossing fixture passes for MC, hybrid, and DC, but the complete 625-case suite has failures on corners, overhangs, a doorway, and two DC cave cases. The contact sheet makes the sharp-feature improvement visible, but the failed full transition gate blocks a production choice and an Unreal implementation this round.
Keep MC as the baseline and hybrid as the sharp-feature candidate. Keep DC-everywhere as a reference; it remains rougher on the sampled native patch. Continue standalone work on a topology-aware 2:1 transition before taking a candidate into Unreal.
Harness and gates
The standalone C++20 spike uses 25 cm cells and five fixtures: a 90-degree corner, doorway, one-metre riser, cliff ledge/overhang, and analytic cave chamber. Each fixture is translated through 125 lattice phases (0, 5, 10, 15, and 20 cm per axis). The retained outputs are phase_sweep.csv, cost.csv, determinism.csv, and seams.csv.
Same-LOD neighbors are sampled independently with a shared field halo and deterministic ownership of border quads. The assembled pair is checked after open-edge T-junction subdivision; the subdivision preserves the source triangle footprint. Hybrid/DC independent contours are also compared from temporary witness meshes. No shared surface mesh is clipped and reused for the neighbor comparison.
LOD0/LOD1 uses independent 25 cm and 50 cm half-grids at a 2:1 ratio. The spike clips their surfaces at the border and tries a collar/chain zipper; a residual closed seam loop is capped only when its own sampled field residual is within budget. This is a tested transition prototype, not a complete Transvoxel table.
The physical error budget is 0.50 m, one LOD1 sample interval. This is a conservative, camera-independent limit that is easy to audit in the field. It does not establish a screen-space guarantee; round 3 must also check projected error at the target cameras.
Same-LOD border results
Each method has 625 independently generated neighbor cases. “Bad” includes unmatched probes, boundary edges, and nonmanifold edges after assembly.
| Method | Bad cases | Unmatched probes | Open edges | Nonmanifold edges | Maximum contour mismatch |
|---|---|---|---|---|---|
| MC | 0 / 625 | 0 | 0 | 0 | 0 m |
| Hybrid | 0 / 625 | 0 | 0 | 0 | 0 m |
| DC | 0 / 625 | 0 | 0 | 0 | 0 m |
The merge-time T-junction conformance added 52 triangles across Hybrid’s suite and 40 across DC’s; MC needed none. Its measured added-triangle field residual is 0 m at the CSV precision. The full per-case data is in seams.csv.
2:1 LOD transition results
The full gate still fails. Raw fine/coarse contour comparisons stay below the 0.50 m budget, but the transition surface/topology does not close all cases.
| Method | Bad cases | Seam-band open edges | Seam-band nonmanifold edges | Worst raw contour mismatch | Worst transition field residual |
|---|---|---|---|---|---|
| MC | 5 / 625 | 15 | 5 | 0.318199 m | 0.250008 m |
| Hybrid | 38 / 625 | 4,213 | 47 | 0.158352 m | 1.24975 m |
| DC | 40 / 625 | 4,465 | 49 | 0.158352 m | 1.96263 m |
Failures by fixture: MC has five doorway cases; Hybrid has 25 corner and 13 overhang cases; DC has those same 38 plus two organic-cave cases. Hybrid/DC transition residuals exceed the 0.50 m budget on the corner cases. Some remaining rows have open or nonmanifold seam edges even when the raw contour mismatch is small. The full CSV keeps pre-transition and internal topology counts separate. The unrestricted-cap diagnostic is preserved in seams_cap_unbounded_diagnostic.csv.
The dedicated sharp cliff crossing case passes all three methods: zero unmatched probes, open edges, and nonmanifold edges. Its maximum raw contour mismatch is 0.249977 m for MC and 0.419411 m for Hybrid/DC; the transition field residual maxima are 0.233333 m and 0.238888 m respectively. See lod_cliff_crossing.csv.
The remaining Unreal-only checks are actual UBodySetup collision cooking/contact, projected pixel error at the game cameras, and runtime task scheduling/upload against the plugin mesher. None of those can repair the standalone topology failures; the topology gate is still the reason to defer Unreal integration.
Production skirt baseline
The current plugin skirt depth is max(1, SkirtCells) × Step × GeometryVoxelSize; skirts are normal-extruded, double-sided visual strips. With Core’s 25 cm geometry voxel size and the default SkirtCells = 4, nominal depth is 1 m at LOD0 and 2 m at LOD1. Project settings can override these defaults. Skirts hide many visual gaps but do not make the neighboring surface topologically watertight. The new transition has not yet replaced that production behavior.
Surface residual and crease splits
Residual is the absolute field value sampled at triangle vertices, edge midpoints, and centroids; it is not a symmetric Hausdorff distance. Values below average the 625 phase rows per method; maxima are the worst sampled value.
| Method | Mean residual | Worst residual | Tagged crease pairs | Normal split pairs | Split rate on tagged creases | Mean triangles / vertices |
|---|---|---|---|---|---|---|
| MC | 0.5664 cm | 16.6670 cm | 10,926 | 1,847 | 16.90% | 3,363.1 / 1,728.8 |
| Hybrid | 0.2552 cm | 12.5027 cm | 140,876 | 140,806 | 99.95% | 3,365.3 / 3,469.2 |
| DC | 0.2786 cm | 12.5027 cm | 140,876 | 140,806 | 99.95% | 3,365.8 / 1,985.6 |
The hybrid keeps untagged/organic components on MC and uses DC for tagged sharp features. It preserves the sharp corner/riser/ledge better than MC in the analytic fixtures, while its feature splits roughly double the vertex count.
Sampled native SurfaceWorld cliff
The native comparison samples the 8 m patch at 25 cm from the M1 SurfaceWorld manifest (feature type 4, feature 0x9812c26310b90c9, manifest hash 0x8933693d9560ba9f). MC and Hybrid emit bit-identical vertex and triangle arrays, with identical mesh hash 0x9d58e0603f1bf9c7: 2,345 vertices and 4,496 triangles each. This confirms that the hybrid leaves this untagged native patch unchanged.
The sampled scalar-field residual is 0.212167 m mean and 16.0068 m max for both MC and Hybrid. This patch is cropped at the 8 m volume boundary and has 192 boundary edges; these values are not a seam result, and the scalar field is not a signed-distance guarantee. DC-everywhere differs (2,247 vertices, 3,961 triangles, 4.57272 m mean / 16.5898 m max, 504 boundary edges and 74 nonmanifold edges). The native CSV is native_surface.csv.
Cost and determinism
The timer starts after the 32³ field grid is sampled, measures meshing only, and excludes Unreal scheduling, upload, collision cooking, and rendering. Values below are the median of five fixture medians; W1/W8 use three builds, while W16 uses one timed build because repeated W16 thread creation had caused a host access violation. Hash determinism is still checked at all three worker counts.
| Workers | MC ms/tile | Hybrid ms/tile | DC ms/tile |
|---|---|---|---|
| 1 | 16.316 | 17.534 | 16.417 |
| 8 | 53.914 | 54.840 | 52.606 |
| 16 | 86.961 | 90.490 | 89.476 |
All 45 W1/W8/W16 rows match the W1 hash for that method and fixture. The standalone collision proxy copies the render mesh: all hashes match and measured geometry delta is 0 m. This does not test Unreal collision cooking.
These timings are not comparable to the optimized production MC mesher. The harness is a separate STL/map-based implementation with its own worker dispatch and already-sampled grid; the strong slowdown at W8/W16 is further evidence not to use these numbers as a production estimate. They are useful only for comparisons within this harness.
Contact sheet
The updated offline contact sheet is 864 × 1,968 pixels. It contains the five analytic fixtures, the sampled SurfaceWorld cliff, and both LOD seam views, with MC/Hybrid/DC columns. The 24 individual JPEGs are 288 × 246 pixels; all 25 files including the sheet are below 300 KB. No viewer or GPU path was used.
Recommendation and round-3 Unreal plan
Do not select or enable the hybrid in the owner project yet. The same-LOD gate is closed, but the full LOD gate is not. The current Core world hash/default path is untouched.
When the standalone LOD gate passes, round 3 should:
- Add an opt-in, versioned recipe such as
WorldAssemblerHybridV1, default off, with its mesher, feature ownership, transition, and collision settings recorded as part of the version. Keep the existing Core recipe and default hashes unchanged. - Add an Unreal test map with the five analytic fixtures, the sampled SurfaceWorld cliff, and a native Core cave tile. Include independent same-LOD neighbors and a sharp cliff crossing from LOD0 to LOD1. Compare skirts on/off and use matched cameras plus wireframe views.
- Cook collision through the real Unreal path. Wait for cooking completion, then run capsule sweeps/walk tests over the doorway, riser, cliff underside, cave wall, and both borders. Check collision/render agreement and recooking after a local edit.
- Record mesh and collision cook latency, CPU/memory, triangle/vertex counts, LOD error in pixels at the fixture cameras, and player contact results. Keep MC as the direct baseline and preserve a one-switch rollback to the existing recipe.
Run ledger and scope
| Run/check | Result |
|---|---|
| Final MSVC C++20 build | Passed in 5.44 s, BelowNormal, affinity 0xFF00. |
| Full seam run with unrestricted residual-loop caps | Completed in 602.78 s; 83 LOD cases failed. Preserved as results/seams_cap_unbounded_diagnostic.csv. |
| Final full seam run with 0.50 m cap-residual guard | Completed in 601.31 s; same-LOD passed 625/625 for all methods, LOD failures were MC 5, Hybrid 38, DC 40. No crash or guard trip. |
| Cost/phase/native analysis | Completed in 120.95 s; 1,875 phase rows, 45 determinism rows, native patch comparison. |
| Final offline renderer | Passed in 3.14 s; 25 JPEGs under the 300 KB cap. |
| Earlier full seam variants | Completed in 559.32 s and 566.44 s. Both failed earlier same-LOD Hybrid/DC cases (36/625 each); superseded by the final T-junction conformance pass. |
| Focused transition prototypes | Completed within seconds. Earlier MC doorway variants left 64, then 3–4 open edges; whole-mesh endpoint snapping introduced nonmanifold edges. Those variants were rejected. The bounded residual-loop cap closes this focused doorway case, but the full LOD matrix still fails. |
| Earlier native halo diagnostic | An initial process exited 0xC0000005; an AddressSanitizer launch first failed 0xC0000135 because its runtime DLL was unavailable. After using the Visual Studio runtime path, ASan found the halo index overflow; the indexing was fixed, and subsequent harness runs completed. |
| W16 timing diagnostic | Repeated creation/timing of 16 OS workers caused a host access violation. W16 now uses one timed build; hash determinism remains checked. |
| Aggregation tools | Two PowerShell summary attempts had query errors, including a missing vertices field in phase_sweep.csv; corrected queries ran without launching a mesher. No 0xC0000142 retry was needed. |
Every final build, mesher, analysis, and renderer process ran BelowNormal with affinity 0xFF00; the scripts enforce an 8 GB private-memory limit and 15-minute timeout. Peak observed mesher private memory was under 0.2 GB. No final process crashed, exceeded a limit, or needed a retry.
All edits and outputs are under Plugins/VoxelForge/Standalone/Research/WorldAssemblerM2, plus this dialogue log. No Source/ file, Core source, owner project file, .uasset, or editor was touched. No commit, push, or stash was made.
Files changed and new source files
Updated existing standalone files: SharpMesherSpike.cpp, BuildSharpMesherSpike.ps1, RunSharpMesherSpike.ps1, and RenderSharpMesherCaptures.py. Updated this report and appended the M2 round-2 dialogue entry.
New source files this round: none. CSVs, OBJ meshes, JPEG captures, logs, and local build outputs are generated research artifacts; none were committed.