feat(render): Campaign OVERHAUL S2 chunk 5 + closeout — registry is the only render membership owner
Chunk 5 (consumer cutover): WalkProductionWorldData's per-cell views are borrowed from ShadowObjectRegistry.GetRetailPartEntriesInCell and resolved through RenderSceneQuery.TryGetByLocalEntityId; every render-side sweep, bucket, parent-cell and root-position fallback is deleted (AD-116 for the one-frame registry→scene window, counted in UnregisteredRenderMembershipCount). A live entity with visual parts but no collision geometry registers render-only (LiveEntityCollisionBuilder computes the part array before the empty-shapes gate). Closeout fixes found while landing it: - RefloodOwnerForLandblock forwards the retained part array — a reflood is retail's recalc_cross_cells over the SAME CPartArray; without it every owner touched by a landblock replacement commit lost its render membership. - Non-colliding DAT statics register render-only from BOTH publishers (LandblockPhysicsPublisher.PublishStaticEntity, LandblockPhysicsContentBuilder.RegisterRenderOnlyStatic). The G2 self-gate pixel diff caught them vanishing (Facility Hub wall panels): retail floods every object regardless of collision (CEnvCell::init_static_objects 0x0052c350, add_shadows_to_cells 0x00514ae0). - S2 dual review fix batch (arch + retail lens, lead-verified): Suspend clears the retail product (remove_shadows_from_cells 0x00511230 is one transaction); AttachChild/DetachChild advance the mutation revision so a prepared SetPosition cannot clobber a child's rows; an attached child never floods on its own re-registration; RemoveLandblock and the non-rooted RetireOwnerFromLandblock prune retail rows (render-only statics end with their landblock); a render-only owner's no-cell-array commit republishes at its destination cell (AD-117); an empty non-null part array is treated as null; per-move closures/LINQ replaced by index loops; EnvCell shells stay out of the scene's LocalEntityId index (payload-less records); the index predicate compares the id; the dead per-cell scene indices are deleted. Register: AD-116 (chunk 5), AD-117 (four residual Contract A/B readings). Evidence: s2-membership-ownership-map.md §8 (chunk 5) and §9 (closeout). Gates (Release): Core 4,984/4,984; Content 214/214; Runtime 1,884/1,884; App hermetic lane 6,760/6,760; App InstalledDat lane 217 pass / 1 skip / 2 pre-existing #383 layout-fixture failures; App Windows lane 1/1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
f30039d3d9
commit
c94a1a407e
20 changed files with 2141 additions and 1026 deletions
|
|
@ -193,19 +193,47 @@ per-entity retail CELLARRAY (`TryGetRetailCellArray`) plus per-cell part
|
|||
entries (`GetRetailPartEntriesInCell`) — not two independent floods, and not
|
||||
rebuilt per frame. A caller that supplies no part array (only test/legacy
|
||||
call sites remain) keeps the pre-chunk-3 collision-only dispatch untouched.
|
||||
`WalkProductionWorldData`'s indoor and outdoor static sweeps BORROW the
|
||||
retail array whole per record; they no longer recompute membership from each
|
||||
MeshRef's prepared visual AABB (the deleted `ResolveStaticRenderCells` /
|
||||
`ShadowObjectRegistry.ComputeStaticRenderCells` pair). A structural
|
||||
consequence: an object mixing a colliding BSP part with a decorative
|
||||
non-BSP part now gets a collision row for its BSP part in every cell the
|
||||
**Consumer cutover to a borrowed per-cell view (S2 chunk 5, 2026-09-03).**
|
||||
`WalkProductionWorldData`'s three per-frame scene sweeps (indoor static,
|
||||
outdoor static, dynamic) and their five per-cell bucket dictionaries are
|
||||
deleted. `GetCellStatics`/`GetCellDynamics`/`GetOutdoorStatics`/
|
||||
`GetOutdoorDynamics` instead read
|
||||
`ShadowObjectRegistry.GetRetailPartEntriesInCell` for the QUERIED cell
|
||||
directly — already in retail CELLARRAY-then-part-array insertion order —
|
||||
collapse the entries to their distinct owning entity ids (an entity's own
|
||||
run of entries for one cell is always contiguous, since the registry
|
||||
removes-then-re-adds a whole entity's rows atomically), and resolve each id
|
||||
back to its `RenderProjectionRecord` through
|
||||
`RenderSceneQuery.TryGetByLocalEntityId` — a new presentation-side index
|
||||
`ArchRenderScene` maintains alongside its existing per-cell/per-class
|
||||
indices, keyed by the SAME `RenderSourceMetadata.LocalEntityId` the
|
||||
registry is keyed by (App-only presentation state, never a second
|
||||
membership source). Statics vs. dynamics is the record's own
|
||||
`ProjectionClass` (`LiveDynamicRoot`/`EquippedChild` are dynamic; every
|
||||
other class, including `ActiveAnimatedStatic`, is static — the same split
|
||||
`ArchRenderScene`'s own internal indexing already used); building shells
|
||||
are excluded from both — they draw at their own building's shell turn
|
||||
(`_shellsByAnchor`, still filled by the ONE surviving narrow sweep, since
|
||||
buildings are the landcell building channel, out of S2's scope), never at
|
||||
the cell's ordinary object-list turn. A structural consequence carried
|
||||
over from chunk 3: an object mixing a colliding BSP part with a decorative
|
||||
non-BSP part gets a collision row for its BSP part in every cell the
|
||||
combined CELLARRAY reaches, including cells the BSP part alone would not
|
||||
have crossed — membership is decided by the whole-part-array flood, not per
|
||||
part; the BSP polygon test still decides actual contact at query time. 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`.
|
||||
have crossed — membership is decided by the whole-part-array flood, not
|
||||
per part; the BSP polygon test still decides actual contact at query time.
|
||||
An entity the registry HAS flooded into a cell but whose projected record
|
||||
the presentation journal has not applied yet this frame (the transient
|
||||
race between the physics publisher and the projection journal — AD-116)
|
||||
contributes to NO cell for that frame; there is no fallback to an authored
|
||||
parent cell or a root-position cell any more (both deleted this chunk),
|
||||
matching retail's own rule that an object not yet in a cell is not drawn.
|
||||
Every distinct entity id this happens for in one frame is counted once in
|
||||
`WalkProductionWorldData.UnregisteredRenderMembershipCount` (renamed from
|
||||
`UnregisteredStaticRenderFallbackCount`, which under the pre-chunk-5 model
|
||||
also covered the separate dynamic-record fallback) and reported by one
|
||||
print-only `[walk-membership]` line — gated on
|
||||
`RenderingDiagnostics.ProbeFacilityStairsEnabled`, the walk family's
|
||||
existing diagnostic flag — at the start of the next frame when nonzero.
|
||||
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
|
||||
|
|
@ -217,13 +245,15 @@ Moving multipart objects follow the sibling retail route rather than their
|
|||
authored/feet cell alone: `CPhysicsObj::add_shadows_to_cells` installs every
|
||||
`CPartArray` part in every cell of the object's retained `CELLARRAY`, and
|
||||
`CPhysicsPart::Draw` stamps each part only after that part passes a cell's
|
||||
portal test. `WalkProductionWorldData.ResolveDynamicRenderCells` therefore
|
||||
reads `ShadowObjectRegistry.TryGetRetailCellArray` directly for every dynamic
|
||||
record — the SAME borrow-not-recompute recipe the static sweeps already use
|
||||
— falling back to `GetOwnerCells` (counted by the shared
|
||||
`UnregisteredStaticRenderFallbackCount`) only when the registry has not
|
||||
registered an array yet, while the walk classifier owns a separate
|
||||
projection+part drawn-pass stamp. Retail advances that stamp after
|
||||
portal test. `WalkProductionWorldData.GetCellDynamics`/`GetOutdoorDynamics`
|
||||
therefore read the SAME per-cell `GetRetailPartEntriesInCell` borrowed view
|
||||
the static getters use (S2 chunk 5), filtered to the dynamic
|
||||
`ProjectionClass`es — not a per-record `TryGetRetailCellArray` lookup with
|
||||
its own fallback any more; an entity the registry has flooded into a cell
|
||||
but the presentation scene cannot resolve yet contributes to no cell there,
|
||||
counted by the shared `UnregisteredRenderMembershipCount` (AD-116), while
|
||||
the walk classifier owns a separate projection+part drawn-pass stamp.
|
||||
Retail advances that stamp after
|
||||
`LScape::draw` + `FlushAlphaList` and before the interior depth clear
|
||||
(`PView::DrawCells` @0x005A4886), so a part may draw once in the landscape
|
||||
pass and once again in the post-clear interior-cell pass; acdream re-arms the
|
||||
|
|
@ -260,9 +290,11 @@ moment an attached projection's `WorldEntity` is registered against its
|
|||
accepted parent; `CommitProjectionRemoval` (the withdrawal/unparent/teardown
|
||||
funnel) calls `DetachChild`. A nested attachment (a child of a child)
|
||||
resolves to the ultimate root by walking the existing attach chain at the
|
||||
registry, bounded and cycle-safe — `WalkProductionWorldData` no longer walks
|
||||
an accepted-parent chain of its own; it reads the child's own id straight off
|
||||
`TryGetRetailCellArray`, identically to any other dynamic record.
|
||||
registry, bounded and cycle-safe — `WalkProductionWorldData` never walks an
|
||||
accepted-parent chain of its own; a child's part entries surface through the
|
||||
SAME per-cell borrowed view (S2 chunk 5) every other dynamic record uses,
|
||||
resolved to its own projection via `RenderSceneQuery.TryGetByLocalEntityId`,
|
||||
identically to any other dynamic record.
|
||||
|
||||
**Slice I3 prepared collision extension (2026-07-25).** At its introduction,
|
||||
the package remained format 1 and retained mesh type values 1–3; bake-tool 4
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue