wip(assembler): M2 round 2 -- same-LOD borders watertight for MC/hybrid/DC; LOD0/1 transitions still open

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
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-10 03:56:28 +02:00
1 parent 6953254349
commit a3b7d2015e
34 files changed
+5028 -2048

No files matched your search

+79 -78
View File
@@ -1,125 +1,126 @@
# World assembler M2 round 1: sharp-mesher decision spike
# World assembler M2 round 2 — standalone border closure
Date: 2026-10-10
Status: **Gate failed; no production mesher selected.** Hybrid is the leading candidate for an in-game follow-up, but it does not pass independent tile seams. Every candidate fails the tested LOD0/LOD1 seam.
Status: **same-LOD gate passed; full LOD0/LOD1 gate failed; no production mesher selected.**
## Decision
At 25 cm, feature-aware DC substantially reduces sharp-feature field residual and preserves hard normal splits. The hybrid also leaves the smooth cave-chamber wall on the MC path, where its measured residual matches MC. Its 8-worker mesh cost is about 4.4% above MC.
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.
Those gains are not enough to choose it: hybrid fails all 500 tagged-shape independent tile-border cases, and DC everywhere fails all 625. MC passes all 625 same-LOD tile-border cases but retains large sharp-feature bevel residual and also fails every LOD transition case. No candidate passes both border gates. Hold architectural recipes until a real border/transition implementation passes.
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.
Round 2 should take MC and hybrid into Unreal as opt-in, versioned recipe candidates. Hybrid is the primary quality candidate; MC is the baseline and organic fallback. Bring neighbor halo/ownership rules, a 2:1 transition template or equivalent, and actual collision cooking. Compare the five fixtures in-game with matched cameras, including same-LOD and LOD0/LOD1 borders. Keep DC-everywhere as a reference unless its organic quality and border results improve.
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.
## Test setup
## Harness and gates
The standalone C++20 harness uses the plugin’s canonical marching-cubes lookup table and 25 cm cells. It builds a 32³-cell, 8 m tile for each fixture. The lattice phase sweep translates each analytic field by 0, 5, 10, 15, and 20 cm on each axis: 125 phases per fixture and method, 1,875 phase meshes total.
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).
The fixtures are a union-of-boxes 90° corner, a box doorway with an analytic void, a one-metre riser, a cliff ledge/overhang, and a smooth spherical cave-chamber cavity. The chamber has negative density in solid rock and positive density in its air cavity, following the plugin sign convention. It is an analytic curved proxy, not a sampled native cave or SurfaceWorld patch.
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.
The candidates are:
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.
- **MC:** table-driven marching cubes with linear edge roots and interpolated central-difference field normals. This preserves MC geometry while giving it a fair smooth-normal path.
- **Hybrid:** untagged connected surface components use MC. Components connected to analytic sharp-plane feature tags use dual contouring.
- **DC:** dual contouring on every surface component, including the cave-chamber wall.
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.
DC uses Hermite roots, a fixed-order 3×3 QEF solve, a small center penalty for rank-deficient constraints, cell-bound clamping, deterministic feature selection, and position quantization at 1/65,536 voxel. All candidates share a 0.01 mm positive bias for exact-zero lattice samples. No LOD transition template is implemented in this spike; independent fine/coarse half meshes are compared directly to expose that gate.
## Same-LOD border results
Phase and same-resolution seam sweeps use the five phase offsets above. Same-LOD borders compare independently generated 8 m tiles on either side of x=0. LOD borders compare an independently generated 25 cm half tile against an independently generated 50 cm half tile. Border contours are compared in both directions at five points per segment. A missing contour is recorded as unmatched; the topological audit counts geometric boundary and nonmanifold edges after merging the independent meshes.
Each method has 625 independently generated neighbor cases. “Bad” includes unmatched probes, boundary edges, and nonmanifold edges after assembly.
## Surface residual and crease normals
| 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 residual is the absolute analytic field value, in metres, sampled at each triangle’s three vertices, three edge midpoints, and centroid. The table shows the equal-weight mean of the 125 phase means and the maximum sample over all phases. Repeated vertex samples count repeatedly. This is a useful analytic-field residual, not a symmetric Hausdorff distance.
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).
| Fixture | MC mean / max (cm) | Hybrid mean / max (cm) | DC mean / max (cm) |
|---|---:|---:|---:|
| 90° corner | 0.51 / 16.67 | 0.17 / 6.25 | 0.17 / 6.25 |
| Doorway | 0.99 / 16.67 | 0.41 / 12.50 | 0.41 / 12.50 |
| One-metre riser | 0.46 / 16.67 | 0.15 / 6.25 | 0.15 / 6.25 |
| Cliff ledge / overhang | 0.49 / 16.67 | 0.16 / 6.25 | 0.16 / 6.25 |
| Cave-chamber wall | 0.39 / 1.17 | 0.39 / 1.17 | 0.50 / 4.75 |
## 2:1 LOD transition results
MC’s worst sharp residual is 16.67 cm at this phase sample, close to the expected 17.68 cm half-diagonal bevel bound. Hybrid/DC reduce the sharp residual while DC-everywhere is rougher on the smooth chamber than either MC path.
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.
Crease split rate counts adjacent triangles with distinct analytic feature labels and face-normal angle above 30°. A split is counted when their average interpolated/vertex normals also differ by more than 30°.
| 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 |
| Fixture | MC split rate | Hybrid split rate | DC split rate |
|---|---:|---:|---:|
| 90° corner | 11.83% | 99.93% | 99.93% |
| Doorway | 24.31% | 100.00% | 100.00% |
| One-metre riser | 12.98% | 99.99% | 99.99% |
| Cliff ledge / overhang | 15.18% | 99.89% | 99.89% |
| Cave-chamber wall | no tagged crease | no tagged crease | no tagged crease |
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).
## Topology and independent borders
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 phase meshes themselves have no nonmanifold edges. MC has 0 open-edge meshes in 625 fixture/phase cases. Hybrid and DC each have 36 open-edge meshes in 625, summing to 116 open edges across those cases.
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.
Independent-border results aggregate 625 fixture/phase cases per method. “Bad” means unmatched seam probes, boundary edges, or nonmanifold edges. No nonmanifold edges were found.
### Production skirt baseline
| Method | Same-LOD bad cases / 625 | Same-LOD open edges | Same-LOD unmatched probes | LOD0/LOD1 bad cases / 625 | LOD0/LOD1 open edges | LOD0/LOD1 unmatched probes |
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 | 0 | 0 | 625 | 75,494 | 0 |
| Hybrid | 500 | 85,632 | 3,484 | 625 | 75,794 | 5,819 |
| DC | 625 | 101,440 | 3,609 | 625 | 75,790 | 6,128 |
| 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 |
MC’s same-LOD contour match is exact in all cases: zero measured contour distance and zero merged open edges. Hybrid passes only the 125 smooth chamber cases; its 500 tagged-shape cases have open edges. DC also fails the chamber border.
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.
Every LOD0/LOD1 case has open boundary edges. For MC, the per-case maximum sampled contour distance has an 18.57 cm median, 26.41 cm 95th percentile, and 31.82 cm worst case; 39 of 625 cases exceed 25 cm. Hybrid has complete contour comparisons in only 130 cases; five of those exceed 25 cm, with a 560.47 cm worst finite comparison. DC has complete contour comparisons in only five cases, with a 560.47 cm worst finite comparison. The large finite outliers and unmatched probes are direct failures, not a pass hidden by averages. The spike has no transition templates, so these results are a transition gate, not a claim that any candidate’s final transition design has been tuned.
## Sampled native SurfaceWorld cliff
## Cost, determinism, and collision proxy
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.
Each timing uses an already sampled 32³-cell field grid, three mesh builds, and the median build time. Field sampling, Unreal scheduling, upload, collision cooking, and rendering are excluded. All values below average the five fixtures.
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).
| Worker count | MC mean ms/tile | Hybrid mean ms/tile | DC mean ms/tile |
## 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.308 | 17.375 | 16.269 |
| 8 | 14.275 | 14.907 | 13.996 |
| 16 | 14.555 | 15.291 | 14.129 |
| 1 | 16.316 | 17.534 | 16.417 |
| 8 | 53.914 | 54.840 | 52.606 |
| 16 | 86.961 | 90.490 | 89.476 |
At W8, hybrid is 4.4% slower and DC is 2.0% faster than MC. Mean triangle counts are 3,454.4 / 3,456.8 / 3,457.6 for MC / Hybrid / DC. Mean vertex counts are 1,728.8 / 3,469.2 / 1,985.6. Hybrid’s feature-split path therefore roughly doubles output vertices for negligible triangle change.
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.
All 45 determinism rows (five fixtures × three methods × three worker counts) match the W1 reference for that fixture and method: zero cross-worker hash mismatches. W16 is a 16-worker software pool running with process affinity limited to eight logical CPUs.
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.
The standalone collision proxy is the same emitted vertex/triangle mesh. All 45 proxy hashes match the visual mesh hash and report 0 m geometry delta. This verifies the candidate mesh handoff only; there is no independent collision simplification, Unreal physics cook, or contact test in round 1.
## Contact sheet
## Captures
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.
The [contact sheet](results/captures/contact_sheet.jpg) is an offline orthographic rasterization of matched MC, Hybrid, and DC meshes for all five fixtures, plus one LOD seam view per method. It is 864 × 1,476 pixels. The 18 individual captures are 288 × 246 pixels. There are 19 JPEGs including the sheet; all are under 300 KB, and the largest is the 128,260-byte contact sheet. No viewer was launched.
## Recommendation and round-3 Unreal plan
Capture files:
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.
- [90° corner — MC](results/captures/corner90_MC.jpg), [Hybrid](results/captures/corner90_Hybrid.jpg), [DC](results/captures/corner90_DC.jpg)
- [Doorway — MC](results/captures/doorway_MC.jpg), [Hybrid](results/captures/doorway_Hybrid.jpg), [DC](results/captures/doorway_DC.jpg)
- [One-metre riser — MC](results/captures/riser1m_MC.jpg), [Hybrid](results/captures/riser1m_Hybrid.jpg), [DC](results/captures/riser1m_DC.jpg)
- [Cliff ledge — MC](results/captures/cliff_overhang_MC.jpg), [Hybrid](results/captures/cliff_overhang_Hybrid.jpg), [DC](results/captures/cliff_overhang_DC.jpg)
- [Cave chamber — MC](results/captures/organic_cave_chamber_MC.jpg), [Hybrid](results/captures/organic_cave_chamber_Hybrid.jpg), [DC](results/captures/organic_cave_chamber_DC.jpg)
- [LOD seam — MC](results/captures/lodseam_MC.jpg), [Hybrid](results/captures/lodseam_Hybrid.jpg), [DC](results/captures/lodseam_DC.jpg)
When the standalone LOD gate passes, round 3 should:
## Run ledger and constraints
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 4.42 s, BelowNormal, affinity 0xFF00. |
| Final phase/cost/determinism/seam run | Passed in 114.208 s; 1,875 phase meshes and 1,875 independent seam cases, BelowNormal, affinity 0xFF00. |
| Final capture renderer | Passed in 2.61 s, BelowNormal, affinity 0xFF00; 19 files under the 300 KB cap. |
| Earlier phase run 1 | Exited normally in 31.14 s; exact-zero lattice degeneracies exposed topology defects. |
| Earlier phase run 2 | Exited normally in 31.11 s after adding the deterministic exact-zero bias; DC still had boundary defects. |
| Earlier phase run 3 | Exited normally in 35.07 s after splitting disconnected cell patches; remaining boundary defects kept it from acceptance. |
| Earlier phase run 4 | Exited normally in 36.55 s after making MC endpoint-gradient interpolation explicit; used for normal-split comparison. |
| Earlier seam run | Exited normally in 74.21 s, but clipped a shared mesh and did not test independently generated borders. It was superseded by the final independent-neighbor seam run. |
| Tool validation | One early PowerShell parser check used an invalid reference argument. Two later analysis-only PowerShell aggregation commands had syntax errors. All were corrected; none launched a mesher process. One early MSVC environment setup printed a nonfatal vswhere helper warning; compilation succeeded, and the final build emitted no warning. |
| 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/test/render process used BelowNormal priority and affinity 0xFF00, limiting it to eight of the 16 logical processors. The build/test/render scripts enforce an 8 GB private-memory guard and 15-minute timeout. No process hit either limit, crashed, or needed a 0xC0000142 retry. The earlier phase runs above exited normally; their topology/seam measurements failed or were superseded as noted. No viewer or owner editor was opened. No owner project was built and no .uasset was touched.
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.
## Files added for the spike
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.
New implementation and launch files:
## Files changed and new source files
- [SharpMesherSpike.cpp](SharpMesherSpike.cpp)
- [BuildSharpMesherSpike.ps1](BuildSharpMesherSpike.ps1)
- [RunSharpMesherSpike.ps1](RunSharpMesherSpike.ps1)
- [RenderSharpMesherCaptures.ps1](RenderSharpMesherCaptures.ps1)
- [RenderSharpMesherCaptures.py](RenderSharpMesherCaptures.py)
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.
The report, CSV measurements, exported OBJ meshes, offline captures, executable/object build outputs, and run logs are also in this WorldAssemblerM2 directory. No files under Source were changed.
**New source files this round: none.** CSVs, OBJ meshes, JPEG captures, logs, and local build outputs are generated research artifacts; none were committed.