feat(physics): S2 chunk 1b - callers supply the visual part array; installed-DAT comparator

Every production registration now hands ShadowObjectRegistry the object's
whole visual part array beside its collision dispatch: static publication
(App LandblockPhysicsPublisher and the headless Content twin) through
ShadowShapeBuilder.FromStaticRenderParts, live entities (Runtime
LiveEntityCollisionBuilder) through the new FromSetupRenderParts, which walks
every Setup part with the same physics-sphere-else-drawing-sphere and
part-box rule from the PhysicsDataCache Runtime already reaches. Nothing
consumes the retail products yet; the App hermetic lane still passes
6,758/6,758.

The Lane=InstalledDat comparator registers five real fixtures through the
real publication inputs and prints retail CELLARRAY, collision cells, and
the old render cells side by side: Facility Hub stair Setup 0x02000623
(7 cells incl. 0x8A02015F/015E), cathedral ramp 0x020009A2 (3 cells, the
genuine multi-part case), the #334 Neftet formation (25 cells), and a
landblock-edge crosser (6 cells, 2 in the neighbor block). All three
answers agree for BSP-bearing objects, as the shared primitive predicts;
the divergence chunk 3 expects appears only for decorative non-BSP parts.

Core Physics 2,202/2,202; Runtime 1,884/1,884; App hermetic 6,758/6,758;
comparator + stair pin 5/5; solution Release build 0 warnings / 0 errors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-02 21:52:35 +02:00
parent 059b8883ab
commit 5a2792d689
7 changed files with 908 additions and 11 deletions

View file

@ -614,6 +614,18 @@ public static class LandblockPhysicsContentBuilder
entity.MeshRefs,
entity.IsBuildingShell,
cache.GetGfxObj);
// Campaign OVERHAUL S2 chunk 1b: retail's WHOLE visual part
// array, mirroring LandblockPhysicsPublisher.PublishStaticEntity
// exactly — same PhysicsDataCache resolver pair, same
// FromStaticRenderParts primitive. A side product only.
IReadOnlyList<ShadowShape> partArray =
ShadowShapeBuilder.FromStaticRenderParts(
entity.MeshRefs,
cache.GetGfxObj,
cache.GetVisualBounds,
out _);
if (bspShapes.Count > 0)
{
engine.ShadowObjects.RegisterMultiPart(
@ -627,7 +639,8 @@ public static class LandblockPhysicsContentBuilder
worldOffsetY: origin.Y,
landblockId: landblock.LandblockId,
seedCellId: entity.ParentCellId ?? 0u,
isStatic: true);
isStatic: true,
partArray: partArray);
bspOwners++;
continue;
}
@ -711,7 +724,8 @@ public static class LandblockPhysicsContentBuilder
worldOffsetY: origin.Y,
landblockId: landblock.LandblockId,
seedCellId: entity.ParentCellId ?? 0u,
isStatic: true);
isStatic: true,
partArray: partArray);
setupOwners++;
}