feat(render) Campaign FW3.1: production walk world data behind the seam
The retail frame walk's world model now materializes from production landblock-build owners through the legal IDatReaderWriter seam, with zero frame wiring (FW3.2 roots the frame): - WalkCellFactory: WalkCell built in the SAME pass as LoadedCell (EnvCellLandblockBuild.BuildVisibilityCell) from the raw portal Flags/polygons/planes/stab lists already parsed there; stored as LoadedCell.Walk, committed atomically with the cell. The fixture-pinned decodes (inverse-0x2 portal side, 0xFFFF->0xFFFFFFFF exit widening) live here. - WalkBuildingFactory + WalkBuildingRegistry: the production WalkBuilding build (drawing BSP with PORT nodes, degrade ladder, portal sides/stab lists, sort center, model frame) from the SAME LandBlockInfo the streaming build already fetches, under the factory's existing DAT lock - closing the gap where BuildingLoader drops every walk field at load. - WalkLandscapeAssembler: the retail 51x51 viewer-centred grid (mid_radius 25) fed incrementally from landblock publish/retire; per-block z-slab (heightTable[max]+200 / [min]-1) computed worker-side in LandblockBuildFactory from the heights already in hand. O(1) SetViewer on same-block frames. - WalkProductionFrameContext: the walk's frame contexts over CellVisibility + WalkBuildingRegistry with a generic inverse-view-projection ray caster (rays feed cross products only - scale-free) and the znear=0.1 CY plane. - Publication: LandblockRenderPublisher owns both walk registries, publishing in the same AdvanceCompleteOne step as BuildingRegistry and retiring in RemoveBuildingRegistry - same commit, same retirement, no new ticket stage. Conformance: ALL TEN oracle fixtures replay identically through the PRODUCTION builders (WalkProductionWorldConformanceTests) - same signatures as the test adapter, first run. Known gap documented for FW3.2: far-tier landblocks carry no EnvCell transaction, so their z-slab never reaches the assembler. Suites: full Release build 0 warnings; Walk lane 186/1 skip; hermetic 6,738/0 (+24); RuntimeDatAccessArchitectureTests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b95850defe
commit
b10ad662b0
14 changed files with 1711 additions and 2 deletions
|
|
@ -89,6 +89,74 @@ public sealed class LandblockBuildFactoryTests
|
|||
Assert.Empty(result.Collisions.EnvCells);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildNear_PopulatesWalkZSlabUnconditionallyAndWalkBuildingsFromLandBlockInfo()
|
||||
{
|
||||
// Campaign FW3.1: EnvCellLandblockBuild.WalkMaxZ/WalkMinZ/WalkBuildings
|
||||
// must be populated by the production streaming build — hermetic
|
||||
// (no installed DAT needed), mirroring the RecordingDatProxy fixture
|
||||
// pattern the rest of this file already uses.
|
||||
var dat = CreateDat(out RecordingDatProxy proxy);
|
||||
AddNearFixture(proxy, LandblockId, environmentId: 1);
|
||||
var heights = new byte[81];
|
||||
Array.Fill(heights, (byte)10);
|
||||
heights[0] = 200; // one outlier byte -> a distinct maxByte from the rest.
|
||||
proxy.Add(LandblockId, new LandBlock { Id = LandblockId, Height = heights });
|
||||
proxy.Add(
|
||||
(LandblockId & 0xFFFF0000u) | 0xFFFEu,
|
||||
new LandBlockInfo
|
||||
{
|
||||
NumCells = 1,
|
||||
Buildings = new List<BuildingInfo>
|
||||
{
|
||||
new BuildingInfo
|
||||
{
|
||||
ModelId = 0x01234567u,
|
||||
Frame = new Frame
|
||||
{
|
||||
Origin = new Vector3(12f, 12f, 0f),
|
||||
Orientation = Quaternion.Identity,
|
||||
},
|
||||
Portals = new List<BuildingPortal>(),
|
||||
},
|
||||
},
|
||||
});
|
||||
var heightTable = new float[256];
|
||||
heightTable[10] = 5f;
|
||||
heightTable[200] = 40f;
|
||||
var factory = new LandblockBuildFactory(
|
||||
dat, TestPreparedCollisionSource.Instance, new object(), heightTable);
|
||||
|
||||
LandblockBuild? result = factory.Build(Request(LandblockStreamJobKind.LoadNear));
|
||||
|
||||
Assert.NotNull(result);
|
||||
var envCells = Assert.IsType<AcDream.App.Rendering.Wb.EnvCellLandblockBuild>(
|
||||
result.EnvCells);
|
||||
Assert.Equal(240f, envCells.WalkMaxZ); // heightTable[200] + 200
|
||||
Assert.Equal(4f, envCells.WalkMinZ); // heightTable[10] - 1
|
||||
AcDream.App.Rendering.Walk.WalkBuildingFactory.Entry buildingEntry =
|
||||
Assert.Single(envCells.WalkBuildings);
|
||||
// origin (12,12) -> cellX=cellY=0 -> low word 0*8+0+1 = 1.
|
||||
Assert.Equal((LandblockId & 0xFFFF0000u) | 1u, buildingEntry.Building.PositionCellId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildFar_NeverPopulatesWalkDataBecauseEnvCellsIsNull()
|
||||
{
|
||||
// Documents the known FW3.1 scope gap: far-tier (LoadFar) landblocks
|
||||
// carry no EnvCellLandblockBuild transaction at all (terrain-only),
|
||||
// so their z-slab/buildings never reach WalkLandscapeAssembler until
|
||||
// a follow-up wires the far-tier path too.
|
||||
var dat = CreateDat(out RecordingDatProxy proxy);
|
||||
proxy.Add(LandblockId, new LandBlock { Id = LandblockId });
|
||||
var factory = Factory(dat, new object());
|
||||
|
||||
LandblockBuild? result = factory.Build(Request(LandblockStreamJobKind.LoadFar));
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Null(result.EnvCells);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NearPreparedFaultRejectsWholeGenerationWhileFarNeverReadsCollision()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue