fix(rendering): preserve exact scene traversal order
This commit is contained in:
parent
06e7754619
commit
e0f36caa70
12 changed files with 500 additions and 77 deletions
|
|
@ -0,0 +1,107 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.World;
|
||||
using DatReaderWriter.DBObjs;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
public sealed class GpuWorldStateRenderTraversalTests
|
||||
{
|
||||
private const uint FirstLandblock = 0x1234FFFFu;
|
||||
private const uint SecondLandblock = 0x1235FFFFu;
|
||||
private const uint ReusedLandblock = 0x1236FFFFu;
|
||||
|
||||
[Fact]
|
||||
public void TraversalKeys_MirrorResidentLandblockAndMutableBucketOrder()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
WorldEntity first = Entity(1, 0x80000001u);
|
||||
WorldEntity moved = Entity(2, 0x80000002u);
|
||||
WorldEntity secondLandblockEntity = Entity(3, 0x80000003u);
|
||||
state.AddLandblock(Landblock(FirstLandblock, first, moved));
|
||||
state.AddLandblock(Landblock(
|
||||
SecondLandblock,
|
||||
secondLandblockEntity));
|
||||
|
||||
AssertSort(state, first, landblockOrder: 1, entityIndex: 0);
|
||||
AssertSort(state, moved, landblockOrder: 1, entityIndex: 1);
|
||||
AssertSort(
|
||||
state,
|
||||
secondLandblockEntity,
|
||||
landblockOrder: 2,
|
||||
entityIndex: 0);
|
||||
|
||||
state.RemoveLiveEntityProjection(first);
|
||||
|
||||
AssertSort(state, moved, landblockOrder: 1, entityIndex: 0);
|
||||
|
||||
WorldEntity replacement = Entity(4, 0x80000004u);
|
||||
state.AddLandblock(Landblock(SecondLandblock, replacement));
|
||||
|
||||
Assert.False(state.TryGetRenderTraversalSortKey(
|
||||
secondLandblockEntity,
|
||||
out _));
|
||||
AssertSort(state, replacement, landblockOrder: 2, entityIndex: 0);
|
||||
|
||||
state.RemoveLandblock(FirstLandblock);
|
||||
WorldEntity reused = Entity(5, 0x80000005u);
|
||||
state.AddLandblock(Landblock(ReusedLandblock, reused));
|
||||
|
||||
AssertSort(state, reused, landblockOrder: 1, entityIndex: 0);
|
||||
Assert.Equal(
|
||||
[ReusedLandblock, SecondLandblock],
|
||||
state.LandblockEntriesWithoutAnimatedIndex
|
||||
.Select(static entry => entry.LandblockId)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TraversalKey_IsUnavailableWhileProjectionIsPending()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
WorldEntity pending = Entity(1, 0x80000001u);
|
||||
|
||||
state.PlaceLiveEntityProjection(FirstLandblock, pending);
|
||||
|
||||
Assert.False(state.TryGetRenderTraversalSortKey(pending, out _));
|
||||
}
|
||||
|
||||
private static void AssertSort(
|
||||
GpuWorldState state,
|
||||
WorldEntity entity,
|
||||
uint landblockOrder,
|
||||
int entityIndex)
|
||||
{
|
||||
Assert.True(state.TryGetRenderTraversalSortKey(
|
||||
entity,
|
||||
out RenderSortKey actual));
|
||||
Assert.Equal(
|
||||
RenderTraversalSortKey.Compose(landblockOrder, entityIndex),
|
||||
actual);
|
||||
}
|
||||
|
||||
private static LoadedLandblock Landblock(
|
||||
uint landblockId,
|
||||
params WorldEntity[] entities) =>
|
||||
new(
|
||||
landblockId,
|
||||
new LandBlock(),
|
||||
entities,
|
||||
PhysicsDatBundle.Empty);
|
||||
|
||||
private static WorldEntity Entity(uint id, uint serverGuid) =>
|
||||
new()
|
||||
{
|
||||
Id = id,
|
||||
ServerGuid = serverGuid,
|
||||
SourceGfxObjOrSetupId = 0x02000001u,
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
MeshRefs =
|
||||
[
|
||||
new MeshRef(0x01000001u, Matrix4x4.Identity),
|
||||
],
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue