feat(physics): define deterministic flat collision assets
Add immutable indexed physics and containment BSP records, exact-bit polygon and Setup payloads, separated CellStruct/topology ownership, and iterative positive-before-negative flattening. Reject malformed graphs and ranges, and prove source identity over synthetic edge cases and installed retail DAT samples without cutting production traversal over.
This commit is contained in:
parent
16d182c2f0
commit
d9300c7854
11 changed files with 2094 additions and 21 deletions
|
|
@ -1650,13 +1650,17 @@ port in any phase — no separate listing here.
|
|||
> CPU/GPU p50 1.869/1.096 ms. Slice I1 now removes the isolated
|
||||
> transition/query owner: player, remote, projectile, camera, and grounded
|
||||
> walkable-publication profiles each measure 0 B/resolve, and retained
|
||||
> transitions remain bit-identical to the fresh-graph oracle.
|
||||
> transitions remain bit-identical to the fresh-graph oracle. Slice I2 now
|
||||
> defines deterministic immutable collision records and validates exact
|
||||
> source identity over synthetic corruption cases and representative installed
|
||||
> DATs; production traversal remains on the graph oracle until the later
|
||||
> differential gate.
|
||||
> The historical exact cutover
|
||||
> rollback remains
|
||||
> `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. Slice H is complete:
|
||||
> retained UI/frame work, exact bounded light selection, and
|
||||
> pooled/borrowed/direct network I/O pass 8,292 Release tests / 5 skips and the
|
||||
> connected lifecycle/reconnect gate. Slice I is active at I2 from
|
||||
> connected lifecycle/reconnect gate. Slice I is active at I3 from
|
||||
> [its detailed plan](2026-07-25-modern-runtime-slice-i.md).
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-07-05-modern-pipeline-design.md` (the
|
||||
|
|
@ -1681,11 +1685,11 @@ hitch and follows.
|
|||
| MP1a | `AcDream.Content` extraction (GL-free MeshExtractor + boundary records out of App) | ✅ SHIPPED 2026-07-05 — user-gated (renders identical, zero tripwires, perf-neutral); 8 commits `651d041e`..`b0758d77` |
|
||||
| MP1b | Pak format + `acdream-bake` CLI + mmap `PakReader` + equivalence/full-scale gate | ✅ **SHIPPED 2026-07-24** — 729,888 EnvCell keys → 17,117 unique geometries + 712,771 aliases (42.6×), 751,141 total keys / 38,370 physical blobs, zero failures, 28,192.4 MiB, 81.4 s validated atomic publish; full-DAT gate also corrected a real collision in WB's legacy geometry hash. [Report](../research/2026-07-24-slice-b-full-bake-report.md) |
|
||||
| **MP-Alloc (safe batch)** | Reuse per-frame buffers: anim pose, particle draw-list, interior partition, animatedIds/drawableCells sets | ✅ SHIPPED + USER-GATED 2026-07-05 — dense-town frame-time spikes 20–87ms → 6–10ms, alloc spikes (30–75MB single-frame) eliminated, gen2 GC 5–11/window → ~0; user confirms FPS steady. 4 commits `b8c05e2b`..`91afea24` |
|
||||
| MP-Alloc (hard sites) | EnvCell settled-camera rebuild gate + physics `Transition` reuse | 🟡 Physics half SHIPPED 2026-07-25 — retail-shaped reset-complete transition/query scratch is bit-identical and 0 B/resolve across five profiles; flat collision storage continues in Slice I2. |
|
||||
| MP-Alloc (hard sites) | EnvCell settled-camera rebuild gate + physics `Transition` reuse | 🟡 Physics half SHIPPED 2026-07-25 — retail-shaped reset-complete transition/query scratch is bit-identical and 0 B/resolve across five profiles; immutable flat collision storage is defined and package integration continues in Slice I3. |
|
||||
| MP1c | Streaming cutover to pak + hitch gate | ✅ **SHIPPED 2026-07-24** — typed package-only production source, explicit Setup probes, non-allocating Portal-first lookup, exact translucency metadata, and ordered teardown; capped/uncapped/dense physical routes + user visual gate pass. Uncapped CPU p99 7.825→6.496 ms, GPU p99 3.406→2.706 ms, portal frame max 202.9→39.9 MiB, process allocation −41.8%, zero invalid Setup probes. [Report](../research/2026-07-24-slice-c-prepared-asset-cutover-report.md) |
|
||||
| MP2 | Retail particle distance/cell-view degradation: DAT-authored range, exact infinite/finite off-view update branches, emitter-first render scan, user-requested 2× default range | ✅ SHIPPED 2026-07-17 — Aerlinthe hotspot `0x32000223` resolves to retail 64m and defaults to 128m; landscape/entity streaming distance unchanged |
|
||||
| MP3 | Arch ECS render world + delta submission (the 300-FPS lever) | ⚪ — note: does NOT fix the steady-state GC churn (that's MP-Alloc); MP3 is the draw-submission throughput lever |
|
||||
| MP4 | Zero-alloc frame loop + flat physics data (residual, post-MP-Alloc) | 🟡 ACTIVE — Slice I1 zero-allocation transition scratch shipped; I2 immutable flat collision assets in progress. |
|
||||
| MP4 | Zero-alloc frame loop + flat physics data (residual, post-MP-Alloc) | 🟡 ACTIVE — Slice I1 zero-allocation transition scratch and I2 immutable flat collision schema shipped; I3 package serialization/bake is active. |
|
||||
| MP5 | Job-system parallelism | ⚪ stretch, evidence-gated |
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -118,10 +118,14 @@ ordinary production profile pass. The final stable production minute sustains
|
|||
519.7 FPS with CPU/GPU p50 1.869/1.096 ms and 22.34 KiB/frame allocation.
|
||||
Slice I1 subsequently removes the isolated per-resolve owner: player, remote,
|
||||
projectile, camera, and grounded walkable-publication profiles are all
|
||||
0 B/resolve with bit-identical fresh-vs-reused outcomes. The complete I1
|
||||
Release gate is 3,826 App tests / 3 skips and 8,342 solution tests / 5 skips.
|
||||
0 B/resolve with bit-identical fresh-vs-reused outcomes. Slice I2 adds
|
||||
deterministic immutable physics/containment BSP, polygon, Setup, bounds, and
|
||||
EnvCell-topology records without cutting traversal over. Synthetic corruption
|
||||
gates and representative installed-DAT source identity pass bit-for-bit. The
|
||||
complete I2 Release gate is 3,826 App tests / 3 skips and 8,355 solution tests
|
||||
/ 5 skips.
|
||||
Slice H is complete: retained UI/frame work, exact bounded light selection,
|
||||
and pooled/borrowed/direct network I/O pass. Slice I is active at I2 under
|
||||
and pooled/borrowed/direct network I/O pass. Slice I is active at I3 under
|
||||
[`2026-07-25-modern-runtime-slice-i.md`](2026-07-25-modern-runtime-slice-i.md).
|
||||
The historical exact G4 visual rollback remains
|
||||
`git revert ef1d263337997bb030eadb7b8e71d73dc659907a`.
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
**Date:** 2026-07-24
|
||||
|
||||
**Status:** Slices A–H and I0–I1 are complete. Slices F–L were explicitly
|
||||
approved 2026-07-24; Slice I2 is active.
|
||||
**Status:** Slices A–H and I0–I2 are complete. Slices F–L were explicitly
|
||||
approved 2026-07-24; Slice I3 is active.
|
||||
|
||||
**Scope:** Reconcile and sequence the existing Modern Pipeline (`MP`) and
|
||||
Linux/headless (`LH`) tracks using the 2026-07-24 connected performance audit.
|
||||
|
|
@ -1197,12 +1197,18 @@ Frame-thread allocation at the G5 checkpoint was 22.34 KiB median. I1 has now
|
|||
replaced fresh per-resolve transition graphs and query temporaries with
|
||||
reset-complete retained scratch: player, remote, projectile, camera, and
|
||||
grounded walkable-publication profiles each measure 0 B/resolve, while
|
||||
fresh-vs-reused output and body state remain bit-identical. I2 immutable flat
|
||||
collision assets are the current execution point. Evidence:
|
||||
fresh-vs-reused output and body state remain bit-identical. I2 now supplies
|
||||
validated immutable flat collision records: synthetic and installed-DAT
|
||||
source identity, exact float bits, deterministic pre-order, and corruption
|
||||
tripwires pass without changing production traversal. I3 package
|
||||
serialization and complete-catalog baking are the current execution point.
|
||||
Evidence:
|
||||
[`../research/2026-07-25-slice-g5-production-profile.md`](../research/2026-07-25-slice-g5-production-profile.md)
|
||||
and
|
||||
[`../research/2026-07-25-slice-i1-transition-scratch.md`](../research/2026-07-25-slice-i1-transition-scratch.md)
|
||||
and
|
||||
[`../research/2026-07-25-slice-i2-flat-collision-schema.md`](../research/2026-07-25-slice-i2-flat-collision-schema.md)
|
||||
and
|
||||
[`2026-07-25-modern-runtime-slice-i.md`](2026-07-25-modern-runtime-slice-i.md).
|
||||
|
||||
The intended order is therefore:
|
||||
|
|
@ -1216,7 +1222,7 @@ honest metrics + committed baselines (A — exit criteria block C)
|
|||
-> incremental render scene (F)
|
||||
-> delta GPU submission (G)
|
||||
-> residual frame cleanup (H-a, H-b, H-c)
|
||||
-> flat collision assets (I — CURRENT at I2)
|
||||
-> flat collision assets (I — CURRENT at I3)
|
||||
-> presentation-independent runtime (J — §0.3 authorization)
|
||||
-> Linux/headless/multi-session (K)
|
||||
-> evidence-gated GPU jobs (L)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Modern runtime Slice I — flat collision assets and zero-allocation physics
|
||||
|
||||
**Status:** I0–I1 COMPLETE — retail oracle, graph fixtures, and
|
||||
reset-complete zero-allocation transition/query scratch fixed; I2 active
|
||||
**Status:** I0–I2 COMPLETE — retail oracle, zero-allocation transition
|
||||
scratch, and deterministic immutable collision records fixed; I3 active
|
||||
**Parent:** `2026-07-24-modern-runtime-architecture.md`, Slice I
|
||||
**Purpose:** remove parsed DAT object graphs and steady collision allocations
|
||||
without changing one retail collision decision, float, comparison, or traversal
|
||||
|
|
@ -146,7 +146,12 @@ Issue #237 is closed. Evidence:
|
|||
6. Keep source graph and flat asset together only in test/shadow fixtures.
|
||||
|
||||
Gate: round-trip structural equality over synthetic edge cases and installed
|
||||
DAT samples; no traversal cutover yet.
|
||||
DAT samples; no traversal cutover yet. **PASSED 2026-07-25:** 13 focused
|
||||
structural/installed-DAT tests, the 131-test expanded Slice I oracle, complete
|
||||
Core/solution Release gates, exact float-bit comparisons, and corruption
|
||||
tripwires pass. The graph route remains the only executable traversal.
|
||||
Evidence:
|
||||
[`../research/2026-07-25-slice-i2-flat-collision-schema.md`](../research/2026-07-25-slice-i2-flat-collision-schema.md).
|
||||
|
||||
### I3 — package serialization, bake, and prepared collision source
|
||||
|
||||
|
|
|
|||
104
docs/research/2026-07-25-slice-i2-flat-collision-schema.md
Normal file
104
docs/research/2026-07-25-slice-i2-flat-collision-schema.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# Slice I2 — deterministic immutable collision assets
|
||||
|
||||
**Status:** COMPLETE
|
||||
**Parent:** `docs/plans/2026-07-25-modern-runtime-slice-i.md`
|
||||
**Scope:** Core collision storage and preparation only. Production movement,
|
||||
BSP traversal, streaming publication, and package format are unchanged.
|
||||
|
||||
## Result
|
||||
|
||||
Slice I2 defines the immutable representation that will replace parsed
|
||||
collision DBObj graphs after the later shadow and differential gates:
|
||||
|
||||
- physics BSP nodes in deterministic positive-before-negative pre-order;
|
||||
- explicit signed child indices, where `-1` means absent;
|
||||
- one ordered leaf polygon-index stream;
|
||||
- polygon rows with checked vertex ranges and one contiguous vertex stream;
|
||||
- a separate, smaller cell-containment BSP schema;
|
||||
- ordered Setup cylinder/sphere rows and verbatim dimensions;
|
||||
- separate reusable CellStruct geometry and per-EnvCell topology;
|
||||
- direct prepared indices from portals and BSP leaves to polygon rows;
|
||||
- optional GfxObj root bounds and visual bounds.
|
||||
|
||||
All collections are immutable arrays. Per-EnvCell transforms remain
|
||||
publication state and are deliberately absent from reusable CellStruct
|
||||
geometry.
|
||||
|
||||
## Retail and source ordering
|
||||
|
||||
The storage contract is pinned to the existing retail traversal oracle:
|
||||
|
||||
- `BSPTREE::find_collisions` `0x0053A440`
|
||||
- `BSPNODE::find_walkable` `0x0053CC80`
|
||||
- `BSPLEAF::find_walkable` `0x0053D6F0`
|
||||
|
||||
The source graph is flattened iteratively. A stack pushes the negative child
|
||||
before the positive child, so the output records the current node, then its
|
||||
complete positive subtree, then its complete negative subtree. Leaf polygon
|
||||
references stay in their stored order. Polygon-table rows are sorted by ID,
|
||||
which makes output independent of dictionary insertion and bucket order;
|
||||
leaves and portals resolve IDs to direct indices during preparation.
|
||||
|
||||
No plane is reconstructed and no vector is normalized. `Plane`, `Vector3`,
|
||||
sphere, cylinder, Setup-dimension, and visual-bound floats are copied directly.
|
||||
Tests compare all components through `BitConverter.SingleToInt32Bits`.
|
||||
|
||||
## Corruption contracts
|
||||
|
||||
Construction rejects:
|
||||
|
||||
- unsupported BSP node types or child presence inconsistent with the encoded
|
||||
node type;
|
||||
- source cycles and shared child nodes;
|
||||
- flat cycles, shared children, unreachable nodes, and non-pre-order layouts;
|
||||
- child, polygon-index, polygon, or vertex ranges outside their arrays;
|
||||
- missing leaf or portal polygon IDs;
|
||||
- duplicate/unsorted polygon IDs or visible-cell IDs;
|
||||
- polygon key/row-ID disagreement or point-count disagreement;
|
||||
- default immutable arrays and null source rows.
|
||||
|
||||
An empty tree uses root index `-1`. A populated deterministic tree always uses
|
||||
root index `0`.
|
||||
|
||||
## Evidence
|
||||
|
||||
The synthetic suite covers:
|
||||
|
||||
- positive/negative child ordering;
|
||||
- multi-polygon leaf order;
|
||||
- dictionary-order independence;
|
||||
- negative-zero and nontrivial float payload preservation;
|
||||
- source mutation after preparation;
|
||||
- missing IDs, invalid ranges, malformed child patterns, cycles, shared
|
||||
children, and unreachable/non-pre-order shapes;
|
||||
- asymmetric containment trees;
|
||||
- a 20,000-node containment tree without call-stack recursion;
|
||||
- Setup row order and exact dimensions;
|
||||
- portal direct-index resolution and deterministic visible-cell ordering.
|
||||
|
||||
Installed retail DAT coverage:
|
||||
|
||||
- Facility Hub cells `0x8A02016E` and `0x8A02017A`;
|
||||
- Holtburg cottage cell `0xA9B4013F`;
|
||||
- cottage, stair/ramp, and multipart-door GfxObjs `0x01000A2B`,
|
||||
`0x01000AC5`, and `0x010044B5`;
|
||||
- player, wide-low collision-family, and multipart-door Setups `0x02000001`,
|
||||
`0x020019E3`, and `0x020019FF`.
|
||||
|
||||
For every installed sample, tests compare source node type, plane bits,
|
||||
positive/negative child identity, leaf index, solid marker, bounds, polygon
|
||||
order, polygon metadata, vertex bits, Setup shapes, dimensions, and visual
|
||||
bounds.
|
||||
|
||||
Release gates:
|
||||
|
||||
- I2 focused structural/installed-DAT tests: **13 passed**
|
||||
- expanded Slice I graph + flat oracle: **131 passed**
|
||||
- complete Core tests: **3,263 passed / 2 skipped**
|
||||
- `dotnet build AcDream.slnx -c Release --no-restore`: **passed**
|
||||
- complete solution tests: **8,355 passed / 5 skipped**
|
||||
|
||||
There is intentionally no traversal cutover and no new retail divergence in
|
||||
this commit. Slice I3 serializes these records into the package, adds typed
|
||||
prepared collision access, and bakes the complete installed catalog before any
|
||||
flat query can affect gameplay.
|
||||
Loading…
Add table
Add a link
Reference in a new issue