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
127 lines
13 KiB
Markdown
127 lines
13 KiB
Markdown
# 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](results/phase_sweep.csv), [cost.csv](results/cost.csv), [determinism.csv](results/determinism.csv), and [seams.csv](results/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](results/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](results/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](results/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](results/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](results/captures/contact_sheet.jpg) 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:
|
||
|
||
1. 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.
|
||
2. 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.
|
||
3. 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.
|
||
4. 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](SharpMesherSpike.cpp), [BuildSharpMesherSpike.ps1](BuildSharpMesherSpike.ps1), [RunSharpMesherSpike.ps1](RunSharpMesherSpike.ps1), and [RenderSharpMesherCaptures.py](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.
|