refactor(render): Phase U.1 — delete two-pipe inside-out machinery
Remove IndoorCellStencilPipeline + portal_stencil shaders, RenderInsideOutAcdream, RenderOutsideInAcdream, the A8-perf instrumentation, the cameraInsideBuilding / ACDREAM_A8_INDOOR_BRANCH branch, and the dead EntitySet partition values. Collapse the render branch to the default Draw(All) path (U.4a replaces it with the gated unified pass). Keep all audited EnvCellRenderer / BuildingLoader / CellVisibility / camera-collision fixes. Also deleted with the partition: the two test-only walk helpers (WbDrawDispatcher.WalkEntitiesForTest / WalkEntitiesForTestByCellIds) and their test files (WbDrawDispatcherEntitySetTests, WbDrawDispatcherCellIdsOverloadTests), which existed solely to exercise the removed IndoorPass/OutdoorScenery/ BuildingShells/LiveDynamic partition. EntityMatchesSet / IsShellScopedSet collapse to the All-path constants; the set: parameter is retained as a seam for the unified pass. Note: the depth-clear-if-inside default-path workaround was removed per the U.1 task list — any current indoor-wall degradation persists until a later Phase U task lands the unified pass (expected, not a regression introduced here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0f7b395be1
commit
3fc77be5de
8 changed files with 37 additions and 2612 deletions
|
|
@ -1,92 +0,0 @@
|
|||
// Phase A8 RR5 — verify WbDrawDispatcher.WalkEntitiesForTestByCellIds,
|
||||
// the pure-data companion to the new Draw(cellIds:) production overload.
|
||||
//
|
||||
// Semantics: indoor entities (ParentCellId.HasValue) are gated by explicit
|
||||
// membership in cellIds. Building shells (IsBuildingShell) pass only when their
|
||||
// BuildingShellAnchorCellId belongs to the same cell set.
|
||||
// Outdoor scenery (no ParentCellId, not a shell) is excluded by EntitySet.IndoorPass.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.Core.World;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Rendering.Wb;
|
||||
|
||||
public class WbDrawDispatcherCellIdsOverloadTests
|
||||
{
|
||||
private static WorldEntity CellEnt(uint id, uint cellId) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x01000001u,
|
||||
ParentCellId = cellId,
|
||||
MeshRefs = new List<MeshRef> { new(0x01000001u, Matrix4x4.Identity) },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
private static WorldEntity OutdoorScenery(uint id) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x01000001u,
|
||||
ParentCellId = null,
|
||||
IsBuildingShell = false,
|
||||
MeshRefs = new List<MeshRef> { new(0x01000001u, Matrix4x4.Identity) },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
private static WorldEntity BuildingShell(uint id, uint? anchorCellId) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x02000001u,
|
||||
ParentCellId = null,
|
||||
IsBuildingShell = true,
|
||||
BuildingShellAnchorCellId = anchorCellId,
|
||||
MeshRefs = new List<MeshRef> { new(0x01000001u, Matrix4x4.Identity) },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void WalkEntitiesByCellIds_IncludesOnlyEntitiesInListedCells()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
CellEnt(0x40000001u, 0xA9B40150u), // in listed cells
|
||||
CellEnt(0x40000002u, 0xA9B40151u), // in listed cells
|
||||
CellEnt(0x40000003u, 0xA9B40999u), // OUT — not in list
|
||||
BuildingShell(0xC0000001u, 0xA9B40150u), // in listed building cells
|
||||
BuildingShell(0xC0000003u, 0xA9B40999u), // OUT — another building shell
|
||||
OutdoorScenery(0xC0000002u), // OUT — not a shell, not in cell list
|
||||
};
|
||||
var cellIds = new HashSet<uint> { 0xA9B40150u, 0xA9B40151u };
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTestByCellIds(
|
||||
entities, cellIds, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Equal(3, result.Count);
|
||||
Assert.Contains(0x40000001u, result);
|
||||
Assert.Contains(0x40000002u, result);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.DoesNotContain(0x40000003u, result);
|
||||
Assert.DoesNotContain(0xC0000003u, result);
|
||||
Assert.DoesNotContain(0xC0000002u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WalkEntitiesByCellIds_EmptyCellList_ExcludesBuildingShells()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
CellEnt(0x40000001u, 0xA9B40150u),
|
||||
BuildingShell(0xC0000001u, 0xA9B40150u),
|
||||
};
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTestByCellIds(
|
||||
entities, new HashSet<uint>(), set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Empty(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
// Phase A8 — verify the WbDrawDispatcher EntitySet partition (taxonomy-aware).
|
||||
//
|
||||
// The pure-data WalkEntitiesForTest helper iterates a flat entity list and
|
||||
// returns the IDs that survive the EntitySet filter + visibleCellIds gate.
|
||||
//
|
||||
// EntitySet.IndoorPass — ParentCellId.HasValue OR IsBuildingShell,
|
||||
// and NOT live-dynamic (ServerGuid == 0).
|
||||
// Building shells are gated by their dat anchor;
|
||||
// live-dynamic flows through LiveDynamic instead.
|
||||
// EntitySet.OutdoorScenery — ParentCellId == null AND not live-dynamic.
|
||||
// Includes building shells for exterior/depth repair passes.
|
||||
// EntitySet.BuildingShells — IsBuildingShell only, gated by dat anchor when
|
||||
// visibleCellIds are supplied.
|
||||
// EntitySet.LiveDynamic — ServerGuid != 0 (player, NPCs, dropped items,
|
||||
// idle doors after animation). Drawn last with
|
||||
// stencil disabled.
|
||||
// EntitySet.All — pre-A8 behavior (visibleCellIds gates indoor;
|
||||
// outdoor entities pass through).
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.Core.World;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Rendering.Wb;
|
||||
|
||||
public class WbDrawDispatcherEntitySetTests
|
||||
{
|
||||
private static WorldEntity CellEnt(uint id, uint cellId) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x01000001u,
|
||||
ParentCellId = cellId,
|
||||
MeshRefs = new List<MeshRef> { new() { GfxObjId = 0x01000001u } },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
private static WorldEntity OutdoorScenery(uint id) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x01000001u,
|
||||
ParentCellId = null,
|
||||
IsBuildingShell = false,
|
||||
MeshRefs = new List<MeshRef> { new() { GfxObjId = 0x01000001u } },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
private static WorldEntity BuildingShell(uint id, uint? anchorCellId = null) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x02000001u,
|
||||
ParentCellId = null,
|
||||
IsBuildingShell = true,
|
||||
BuildingShellAnchorCellId = anchorCellId,
|
||||
MeshRefs = new List<MeshRef> { new() { GfxObjId = 0x01000001u } },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
private static WorldEntity LiveDynamic(uint id, uint serverGuid) => new()
|
||||
{
|
||||
Id = id,
|
||||
SourceGfxObjOrSetupId = 0x02000001u,
|
||||
ServerGuid = serverGuid,
|
||||
ParentCellId = null,
|
||||
IsBuildingShell = false,
|
||||
MeshRefs = new List<MeshRef> { new() { GfxObjId = 0x01000001u } },
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void IndoorPass_IncludesCellEntities()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
CellEnt(0x10000001, 0xA9B40143),
|
||||
OutdoorScenery(0x10000002),
|
||||
CellEnt(0x10000003, 0xA9B40144),
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u, 0xA9B40144u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(0x10000001u, result);
|
||||
Assert.Contains(0x10000003u, result);
|
||||
Assert.DoesNotContain(0x10000002u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndoorPass_IncludesBuildingShells_WhenAnchorCellIsVisible()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
BuildingShell(0xC0000001, 0xA9B40143u), // cottage wall
|
||||
OutdoorScenery(0xC0000002), // tree
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(0xC0000001u, result); // building shell included
|
||||
Assert.Contains(0x40000001u, result); // cell entity included
|
||||
Assert.DoesNotContain(0xC0000002u, result); // tree excluded
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndoorPass_WithNullCellFilter_UsesEntitySetOnly()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
BuildingShell(0xC0000001, 0xA9B40143u),
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
CellEnt(0x40000002, 0xA9B40199),
|
||||
OutdoorScenery(0xC0000002),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
};
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: null, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Equal(3, result.Count);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.Contains(0x40000001u, result);
|
||||
Assert.Contains(0x40000002u, result);
|
||||
Assert.DoesNotContain(0xC0000002u, result);
|
||||
Assert.DoesNotContain(0x10000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndoorPass_ExcludesBuildingShells_WhenAnchorCellIsNotVisible()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
BuildingShell(0xC0000001, 0xA9B40150u),
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Contains(0x40000001u, result);
|
||||
Assert.DoesNotContain(0xC0000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndoorPass_ExcludesLiveDynamic()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.IndoorPass);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Contains(0x40000001u, result);
|
||||
Assert.DoesNotContain(0x10000001u, result); // live-dynamic excluded
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OutdoorScenery_IncludesBuildingShells()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
BuildingShell(0xC0000001), // cottage wall — included
|
||||
OutdoorScenery(0xC0000002), // tree — included
|
||||
CellEnt(0x40000001, 0xA9B40143), // cell — excluded
|
||||
};
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: null, set: WbDrawDispatcher.EntitySet.OutdoorScenery);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(0xC0000002u, result);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.DoesNotContain(0x40000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OutdoorScenery_ExcludesLiveDynamic()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
OutdoorScenery(0xC0000001),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
};
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: null, set: WbDrawDispatcher.EntitySet.OutdoorScenery);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.DoesNotContain(0x10000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildingShells_IncludesOnlyAnchoredShells()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
BuildingShell(0xC0000001, 0xA9B40143u),
|
||||
BuildingShell(0xC0000002, 0xA9B40999u),
|
||||
OutdoorScenery(0xC0000003),
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.BuildingShells);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.DoesNotContain(0xC0000002u, result);
|
||||
Assert.DoesNotContain(0xC0000003u, result);
|
||||
Assert.DoesNotContain(0x40000001u, result);
|
||||
Assert.DoesNotContain(0x10000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveDynamic_IncludesOnlyServerSpawned()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
OutdoorScenery(0xC0000001),
|
||||
BuildingShell(0xC0000002),
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
LiveDynamic(0x10000002, serverGuid: 0x50000456u),
|
||||
};
|
||||
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: null, set: WbDrawDispatcher.EntitySet.LiveDynamic);
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(0x10000001u, result);
|
||||
Assert.Contains(0x10000002u, result);
|
||||
Assert.DoesNotContain(0xC0000001u, result);
|
||||
Assert.DoesNotContain(0xC0000002u, result);
|
||||
Assert.DoesNotContain(0x40000001u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void All_MatchesPreA8Behavior()
|
||||
{
|
||||
var entities = new List<WorldEntity>
|
||||
{
|
||||
CellEnt(0x40000001, 0xA9B40143),
|
||||
OutdoorScenery(0xC0000001),
|
||||
BuildingShell(0xC0000002),
|
||||
LiveDynamic(0x10000001, serverGuid: 0x50000123u),
|
||||
CellEnt(0x40000002, 0xA9B40999), // not in visibleCellIds
|
||||
};
|
||||
|
||||
var visible = new HashSet<uint> { 0xA9B40143u };
|
||||
var result = WbDrawDispatcher.WalkEntitiesForTest(
|
||||
entities, visibleCellIds: visible, set: WbDrawDispatcher.EntitySet.All);
|
||||
|
||||
// Pre-A8: visibleCellIds gates indoor entities only; outdoor entities
|
||||
// (regardless of building/scenery/live-dynamic) pass through.
|
||||
Assert.Equal(4, result.Count);
|
||||
Assert.Contains(0x40000001u, result);
|
||||
Assert.Contains(0xC0000001u, result);
|
||||
Assert.Contains(0xC0000002u, result);
|
||||
Assert.Contains(0x10000001u, result);
|
||||
Assert.DoesNotContain(0x40000002u, result);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue