feat(render): S2 chunk 2 - render statics borrow the registry's retail cell array
WalkProductionWorldData no longer floods; its indoor and outdoor static sweeps read ShadowObjectRegistry.TryGetRetailCellArray (retail's calc_cross_cells_static @0x00515160 -> AddPartsShadow @0x00517e40 CELLARRAY, computed once at registration). The App-owned render flood (ResolveStaticRenderCells, its fingerprint cache, the primitive-Setup special case) and Core's ComputeStaticRenderCells are deleted. The one remaining fallback, an entity the physics publisher has not registered yet while the projection journal already published it, buckets to the authored parent cell and is counted per frame (UnregisteredStaticRenderFallbackCount) for chunk 5 to judge on the connected route. The Facility stair pin now registers at the projection's own entity id (the old pure-function test never carried identity) and reads the retail array; the installed-DAT comparator compares retail against collision. Gates (run in the implementer's isolated worktree at identical content): Release build 0/0; Core Physics 2,202/2,202; App hermetic 6,760/6,760 (the two added WalkProductionWorldData tests); installed-DAT walk/flood/stair family 24/24; Runtime 1,884/1,884. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
2b40c0bb38
commit
707d2803a4
10 changed files with 392 additions and 227 deletions
|
|
@ -176,21 +176,33 @@ Likewise `PView::DrawCells` calls `DrawEnvCell` once per admitted cell and
|
|||
draws its complete constructed shell. Portal polygons are not GPU mesh clips;
|
||||
pixel occlusion comes from the ordered walk and depth buffer.
|
||||
|
||||
**Retail static render-shadow cell membership (2026-08-31).** Indoor
|
||||
statics are not rendered solely from their authored parent EnvCell. Retail's
|
||||
**Retail static render-shadow cell membership (2026-08-31; ownership moved
|
||||
to `ShadowObjectRegistry` by Campaign OVERHAUL S2 chunk 2).** Indoor statics
|
||||
are not rendered solely from their authored parent EnvCell. Retail's
|
||||
`CEnvCell::init_static_objects` creates a `CPhysicsObj` for every static,
|
||||
then `calc_cross_cells_static` + `CPartArray::AddPartsShadow` places every
|
||||
visual part in each crossed cell's `shadow_part_list`, including decorative
|
||||
GfxObjs that have no collision BSP. `WalkProductionWorldData` therefore owns
|
||||
a distinct render-only per-cell index built from each MeshRef's prepared
|
||||
visual AABB and the existing exact static part transit walk. This must not be
|
||||
collapsed into `ShadowObjectRegistry`'s collision rows: the two retail lists
|
||||
share transit math but have different membership. A primitive-only Setup may
|
||||
reuse its already-authored cylsphere collision cell set; BSP-bearing and
|
||||
pure-visual statics use the all-visual-part box walk. The Facility Hub stair
|
||||
Setup `0x02000623` is the installed-DAT regression: its authored parent is
|
||||
`0x8A02015F`, while its visual parts also register in `0x8A02015E` and the
|
||||
adjoining vertical cells.
|
||||
GfxObjs that have no collision BSP. `ShadowObjectRegistry` owns this product
|
||||
as a retained per-entity retail CELLARRAY (`TryGetRetailCellArray`) plus
|
||||
per-cell part entries (`GetRetailPartEntriesInCell`), computed once at the
|
||||
SAME registration transaction as the collision flood
|
||||
(`RegisterMultiPart`/`Register`'s optional `partArray:` parameter) — not
|
||||
rebuilt per frame. `WalkProductionWorldData`'s indoor and outdoor static
|
||||
sweeps BORROW that array whole per record; they no longer recompute
|
||||
membership from each MeshRef's prepared visual AABB (the deleted
|
||||
`ResolveStaticRenderCells` / `ShadowObjectRegistry.ComputeStaticRenderCells`
|
||||
pair). The retail CELLARRAY remains distinct from `ShadowObjectRegistry`'s
|
||||
own collision rows (`GetOwnerCells`/`_entityToCells`) — the two retail lists
|
||||
share transit math but have different membership (collision cutover to the
|
||||
same CELLARRAY is S2 chunk 3) — until then, a record whose registry entry has
|
||||
no retail array yet (a streaming-window race between the static-projection
|
||||
journal and the physics publisher) falls back to its authored parent cell
|
||||
alone, counted by `WalkProductionWorldData.UnregisteredStaticRenderFallbackCount`.
|
||||
A primitive-only Setup may reuse its already-authored cylsphere collision
|
||||
cell set; BSP-bearing and pure-visual statics use the all-visual-part box
|
||||
walk. The Facility Hub stair Setup `0x02000623` is the installed-DAT
|
||||
regression: its authored parent is `0x8A02015F`, while its visual parts also
|
||||
register in `0x8A02015E` and the adjoining vertical cells.
|
||||
|
||||
Moving multipart objects follow the sibling retail route rather than their
|
||||
authored/feet cell alone: `CPhysicsObj::add_shadows_to_cells` installs every
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ One transaction per object (`CPhysicsObj::calc_cross_cells_static`
|
|||
| Owner | Inputs | Output | Runs | Consumers |
|
||||
|---|---|---|---|---|
|
||||
| `LandblockPhysicsPublisher.PublishStaticEntity` → `ShadowObjectRegistry.RegisterMultiPart` (`LandblockPhysicsPublisher.cs:930-1079`, `ShadowObjectRegistry.cs:493-584`) | BSP parts only (`ShadowShapeBuilder.FromLandblockBspParts`) or Setup cyl/sphere fallback; `CellTransit.BuildShadowCellSetFromParts` | `_entityToCells[id]` (ordered, the CELLARRAY analog) + `_cells[cell]` `ShadowEntry` rows | once per static at publication | physics broadphase `TransitionTypes.FindObjCollisionsInCell` (`TransitionTypes.cs:3755-3779`); outdoor static render lookup reads it verbatim |
|
||||
| `WalkProductionWorldData.ResolveStaticRenderCells` → `ShadowObjectRegistry.ComputeStaticRenderCells` (`WalkProductionWorldData.cs:285-366`, `ShadowObjectRegistry.cs:371-394`) | ALL visual parts (`ShadowShapeBuilder.FromStaticRenderParts`: physics sphere else visual-AABB circumsphere; exact visual box); same `BuildShadowCellSetFromParts` | per-object cell list, cached by fingerprint; whole `RenderProjectionRecord` bucketed into every cell | every `BeginFrame` sweep of `RenderSceneIndex.IndoorCellStatic` | `WalkFrameDriver.GetCellStatics`; `RetailPViewRenderer` particle owner union |
|
||||
| **DELETED (chunk 2).** Was `WalkProductionWorldData.ResolveStaticRenderCells` → `ShadowObjectRegistry.ComputeStaticRenderCells`. Now: `WalkProductionWorldData.ResolveIndoorStaticRenderCells`/`ResolveOutdoorStaticRenderCells` → `ShadowObjectRegistry.TryGetRetailCellArray` (`WalkProductionWorldData.cs`, `ShadowObjectRegistry.cs:634-663`) | none (borrowed) | chunk 1's retained per-entity retail CELLARRAY, computed once at registration | every `BeginFrame` sweep of `RenderSceneIndex.IndoorCellStatic`/`OutdoorStatic` (a borrow, not a recompute) | `WalkFrameDriver.GetCellStatics`; `RetailPViewRenderer` particle owner union; unregistered fallback (indoor: authored `ParentCellId`; outdoor: `GetOwnerCells`) counted by `WalkProductionWorldData.UnregisteredStaticRenderFallbackCount` |
|
||||
| `LiveEntityCollisionBuilder.Register` / `ShadowObjectRegistry.UpdatePosition` / `CommitSetPosition` (`LiveEntityCollisionBuilder.cs:149-280`, `ShadowObjectRegistry.cs:881-982`) | `ShadowShapeBuilder.FromSetup` (BSP parts, else cylspheres, else spheres) | `_entityToCells` + `_cells` | spawn and every accepted move/appearance change | physics broadphase; dynamic render lookup reads it verbatim |
|
||||
| `WalkProductionWorldData.ResolveDynamicRenderCells` (`WalkProductionWorldData.cs:247-283`) | `GetOwnerCells`; for an `EquippedChild` with no cells, a 64-hop parent-chain walk | whole-record buckets | every `BeginFrame` | `WalkFrameDriver.GetCellDynamics` |
|
||||
| `LightManager.SelectForCell` (`LightManager.cs:594-650`) | flat `_all` list, sphere overlap | per-cell light subset | per cell drawn | lighting (S5 owns; retail selects from the current EnvCell + stab list) |
|
||||
|
|
@ -78,12 +78,25 @@ formation, an outdoor landblock-edge static, a multi-part Setup) reports the
|
|||
three answers side by side: retail CELLARRAY, current collision cells,
|
||||
current render cells. Differences are evidence for chunks 2/3, not failures.
|
||||
|
||||
**Chunk 2 — render statics cut over.** `WalkProductionWorldData` indoor and
|
||||
outdoor static buckets are filled from the registry's per-cell part entries
|
||||
(grouped back to records for the existing draw path; per-part draw
|
||||
admission is S3). `ResolveStaticRenderCells`, `ComputeStaticRenderCells`,
|
||||
the fingerprint cache, and App's use of `FromStaticRenderParts` are deleted.
|
||||
The Facility stair pin moves to the registry.
|
||||
**Chunk 2 — render statics cut over (landed 2026-09-02).** `WalkProductionWorldData`
|
||||
indoor and outdoor static buckets are filled whole-record-per-cell from the
|
||||
registry's retail CELLARRAY (`TryGetRetailCellArray`), not from its per-cell
|
||||
part entries: per-part draw admission is S3's job, and today's draw path
|
||||
still consumes whole `RenderProjectionRecord`s, so grouping
|
||||
`GetRetailPartEntriesInCell` back into records here would be a no-op
|
||||
detour. `ResolveStaticRenderCells`, `ComputeStaticRenderCells`, the
|
||||
fingerprint cache (`_staticRenderCellCache` + its revision/generation
|
||||
invalidation), the `primitiveSetup` special case, and
|
||||
`WalkProductionWorldData`'s use of `ShadowShapeBuilder.FromStaticRenderParts`
|
||||
are deleted. An entity with no retail array yet (the streaming-window race
|
||||
between the static-projection journal and the physics publisher — AD-40's
|
||||
residency reasoning) falls back to a conservative single-cell membership
|
||||
(indoor: authored `ParentCellId`; outdoor: today's `GetOwnerCells`), counted
|
||||
by the new `WalkProductionWorldData.UnregisteredStaticRenderFallbackCount`
|
||||
for chunk 5 to weigh against the connected-route count. The Facility stair
|
||||
pin (`Issue177StairDescentCameraFloodTests.FacilityStairAssembly_*`) moved to
|
||||
registering through the production `RegisterMultiPart(..., partArray:)` +
|
||||
`TryGetRetailCellArray` recipe.
|
||||
|
||||
**Chunk 3 — collision cut over.** `_entityToCells`/`_cells` are populated
|
||||
from the retail CELLARRAY (collision shapes into every array cell). Physics
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue