refactor(render): move look-in dynamics onto walk turns

This commit is contained in:
Erik 2026-08-31 03:39:03 +02:00
parent 966836895f
commit f9a80fbc44
9 changed files with 190 additions and 113 deletions

View file

@ -227,17 +227,9 @@ public sealed class RenderScenePViewFrameProductTests
RenderFrameView frame = exchange.BorrowLatest(Generation, 1);
try
{
RenderFrameCandidateRange lookInRange = Assert.Single(
Assert.DoesNotContain(
frame.RouteRanges.ToArray(),
range => range.Route == RenderFrameCandidateRoute.LookInObject);
Assert.Equal(0, lookInRange.RouteIndex);
Assert.Equal(lookInCell, lookInRange.CellId);
Assert.Equal(
[lookInDynamic.Id],
frame.RouteCandidates
.Slice(lookInRange.Offset, lookInRange.Count)
.ToArray()
.Select(static record => record.Id));
RenderFrameCandidateRange outside = Assert.Single(
frame.RouteRanges.ToArray(),
@ -303,15 +295,9 @@ public sealed class RenderScenePViewFrameProductTests
RenderFrameView frame = exchange.BorrowLatest(Generation, 1);
try
{
RenderFrameCandidateRange range = Assert.Single(
Assert.DoesNotContain(
frame.RouteRanges.ToArray(),
candidate => candidate.Route == RenderFrameCandidateRoute.LookInObject);
Assert.Equal(
[lookInDynamic.Id],
frame.RouteCandidates
.Slice(range.Offset, range.Count)
.ToArray()
.Select(static record => record.Id));
Assert.NotNull(frame.WalkLookInViews);
Assert.False(frame.WalkLookInViews!.SphereVisibleInLookInTurn(
routeIndex: 0,

View file

@ -69,15 +69,14 @@ public sealed class WalkFrameDriverTests
log.Add($"PARTICLES:{string.Join(",", sorted.ConvertAll(o => o.ToString("x")))}");
}
public void DrawLookInDynamics(
public void DrawCellParticles(
uint cellId,
int routeIndex,
IReadOnlySet<uint> staticParticleOwnerIds)
{
var sorted = new List<uint>(staticParticleOwnerIds);
sorted.Sort();
log.Add(
$"LOOKIN:{cellId:x8}:{routeIndex}:"
$"CELL-PARTICLES:{cellId:x8}:"
+ string.Join(",", sorted.ConvertAll(o => o.ToString("x"))));
}
}
@ -91,6 +90,7 @@ public sealed class WalkFrameDriverTests
private sealed class FakeWorldData : IWalkFrameWorldData
{
public readonly Dictionary<uint, WalkFrameStaticRecords> CellStaticsByCell = new();
public readonly Dictionary<uint, WalkFrameStaticRecords> CellDynamicsByCell = new();
public readonly Dictionary<uint, WalkFrameStaticRecords> OutdoorStaticsByCell = new();
public readonly Dictionary<WalkBuilding, WalkFrameStaticRecords> ShellByBuilding = new();
public readonly Dictionary<WalkBuilding, Matrix4x4> WorldTransformByBuilding = new();
@ -98,6 +98,9 @@ public sealed class WalkFrameDriverTests
public WalkFrameStaticRecords GetCellStatics(uint cellId) =>
CellStaticsByCell.GetValueOrDefault(cellId, WalkFrameStaticRecords.Empty);
public WalkFrameStaticRecords GetCellDynamics(uint cellId) =>
CellDynamicsByCell.GetValueOrDefault(cellId, WalkFrameStaticRecords.Empty);
public WalkFrameStaticRecords GetOutdoorStatics(uint cellId) =>
OutdoorStaticsByCell.GetValueOrDefault(cellId, WalkFrameStaticRecords.Empty);
@ -364,10 +367,13 @@ public sealed class WalkFrameDriverTests
var log = new List<string>();
const ulong shellGfxObj = 0x0200_0010UL;
const ulong interiorGfxObj = 0x0200_0011UL;
const ulong dynamicGfxObj = 0x0200_0012UL;
InjectRenderData(fx.Manager, shellGfxObj, MakeFlatMesh(
MakeBatch(0x08100010u, TranslucencyKind.Opaque, 0, 0, 3, 1)));
InjectRenderData(fx.Manager, interiorGfxObj, MakeFlatMesh(
MakeBatch(0x08100011u, TranslucencyKind.Opaque, 3, 4, 3, 2)));
InjectRenderData(fx.Manager, dynamicGfxObj, MakeFlatMesh(
MakeBatch(0x08100012u, TranslucencyKind.Opaque, 6, 8, 3, 3)));
var ctx = new TestContext();
var interior = new WalkCell
@ -408,6 +414,8 @@ public sealed class WalkFrameDriverTests
new[] { MakeRecord(201, 0, Vector3.Zero, [new MeshRef((uint)shellGfxObj, Matrix4x4.Identity)]) }, 0x8C04u);
worldData.CellStaticsByCell[0x104] = new WalkFrameStaticRecords(
new[] { MakeRecord(202, 0, Vector3.Zero, [new MeshRef((uint)interiorGfxObj, Matrix4x4.Identity)]) }, 0x8C04u);
worldData.CellDynamicsByCell[0x104] = new WalkFrameStaticRecords(
new[] { MakeRecord(203, 0, Vector3.Zero, [new MeshRef((uint)dynamicGfxObj, Matrix4x4.Identity)], parentCellId: 0x104) }, 0x8C04u);
Matrix4x4 buildingWorld = Matrix4x4.CreateTranslation(10f, 0f, 0f);
worldData.WorldTransformByBuilding[building] = buildingWorld;
@ -434,7 +442,8 @@ public sealed class WalkFrameDriverTests
new[]
{
"ALPHA:12.50", "PUNCH:4@v0", "SHELL:00000104",
"FLUSH:1:LookInStatic", "LOOKIN:00000104:0:ca",
"FLUSH:1:LookInStatic", "FLUSH:1:Dynamic",
"CELL-PARTICLES:00000104:ca,cb",
"FLUSH:1:BuildingShell", "PARTICLES:c9",
},
log);
@ -464,8 +473,8 @@ public sealed class WalkFrameDriverTests
List<GpuRecordedMultiDrawIndirect> mdiCalls =
[.. fx.Device.Calls.OfType<GpuRecordedMultiDrawIndirect>()];
Assert.Equal(2, mdiCalls.Count);
Assert.Equal(2, mdiCalls.Sum(c => (int)c.DrawCount));
Assert.Equal(3, mdiCalls.Count);
Assert.Equal(3, mdiCalls.Sum(c => (int)c.DrawCount));
}
// ── Fail-loud: a DrawCells turn with no preceding DrawInside/Building