feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
|
|
@ -0,0 +1,142 @@
|
|||
using AcDream.App.Streaming;
|
||||
using AcDream.Core.World;
|
||||
using DatReaderWriter.DBObjs;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
public sealed class ResidentStreamingWindowFactTests
|
||||
{
|
||||
[Fact]
|
||||
public void CaptureUsesOnlyLargestCompleteActuallyPublishedWindow()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
AddSquare(state, centerX: 100, centerY: 101, radius: 1);
|
||||
ResidentStreamingWindowFact first =
|
||||
state.CaptureResidentStreamingWindow(100, 101);
|
||||
Assert.True(first.HasPublishedCenter);
|
||||
Assert.Equal(1, first.CompleteRadiusLandblocks);
|
||||
Assert.Equal(192f, first.MaximumReachMeters);
|
||||
|
||||
// A retained outer ring with one unpublished gap is not a safe shadow
|
||||
// reach even though most of its landblocks are live.
|
||||
AddRing(state, 100, 101, radius: 2, skipX: 102, skipY: 101);
|
||||
ResidentStreamingWindowFact incomplete =
|
||||
state.CaptureResidentStreamingWindow(100, 101);
|
||||
Assert.Equal(1, incomplete.CompleteRadiusLandblocks);
|
||||
Assert.Equal(192f, incomplete.MaximumReachMeters);
|
||||
|
||||
Add(state, 102, 101);
|
||||
ResidentStreamingWindowFact complete =
|
||||
state.CaptureResidentStreamingWindow(100, 101);
|
||||
Assert.Equal(2, complete.CompleteRadiusLandblocks);
|
||||
Assert.Equal(384f, complete.MaximumReachMeters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NearToFarDemotionRetainsTerrainReachAndDoesNotRepublishTheWindow()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
AddSquare(state, centerX: 40, centerY: 50, radius: 1);
|
||||
ResidentStreamingWindowFact before =
|
||||
state.CaptureResidentStreamingWindow(40, 50);
|
||||
|
||||
GpuLandblockRetirement? retirement = state.DetachNearLayer(
|
||||
StreamingRegion.EncodeLandblockId(41, 50));
|
||||
ResidentStreamingWindowFact after =
|
||||
state.CaptureResidentStreamingWindow(40, 50);
|
||||
|
||||
Assert.NotNull(retirement);
|
||||
Assert.Equal(before.Revision, after.Revision);
|
||||
Assert.Equal(before.MaximumReachMeters, after.MaximumReachMeters);
|
||||
Assert.Equal(before.PublishedLandblockCount, after.PublishedLandblockCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecenterAndPortalGenerationTurnoverCannotReusePriorReach()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
AddSquare(state, centerX: 12, centerY: 20, radius: 2);
|
||||
ResidentStreamingWindowFact oldGeneration =
|
||||
state.CaptureResidentStreamingWindow(12, 20);
|
||||
Assert.Equal(384f, oldGeneration.MaximumReachMeters);
|
||||
|
||||
_ = state.DetachAllForOriginRecenter();
|
||||
ResidentStreamingWindowFact betweenGenerations =
|
||||
state.CaptureResidentStreamingWindow(12, 20);
|
||||
Assert.False(betweenGenerations.HasPublishedCenter);
|
||||
Assert.Equal(0f, betweenGenerations.MaximumReachMeters);
|
||||
Assert.True(betweenGenerations.Revision > oldGeneration.Revision);
|
||||
|
||||
Add(state, 220, 221);
|
||||
ResidentStreamingWindowFact newGeneration =
|
||||
state.CaptureResidentStreamingWindow(220, 221);
|
||||
Assert.True(newGeneration.HasPublishedCenter);
|
||||
Assert.Equal(0, newGeneration.CompleteRadiusLandblocks);
|
||||
Assert.Equal(0f, newGeneration.MaximumReachMeters);
|
||||
Assert.True(newGeneration.Revision > betweenGenerations.Revision);
|
||||
Assert.False(state.CaptureResidentStreamingWindow(12, 20).HasPublishedCenter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemovingOneResidentEdgeImmediatelyShrinksTheReadOnlyReach()
|
||||
{
|
||||
var state = new GpuWorldState();
|
||||
AddSquare(state, centerX: 80, centerY: 90, radius: 2);
|
||||
ResidentStreamingWindowFact before =
|
||||
state.CaptureResidentStreamingWindow(80, 90);
|
||||
|
||||
state.RemoveLandblock(StreamingRegion.EncodeLandblockId(82, 90));
|
||||
ResidentStreamingWindowFact after =
|
||||
state.CaptureResidentStreamingWindow(80, 90);
|
||||
|
||||
Assert.True(after.Revision > before.Revision);
|
||||
Assert.Equal(1, after.CompleteRadiusLandblocks);
|
||||
Assert.Equal(192f, after.MaximumReachMeters);
|
||||
}
|
||||
|
||||
private static void AddSquare(
|
||||
GpuWorldState state,
|
||||
int centerX,
|
||||
int centerY,
|
||||
int radius)
|
||||
{
|
||||
for (int x = centerX - radius; x <= centerX + radius; x++)
|
||||
{
|
||||
for (int y = centerY - radius; y <= centerY + radius; y++)
|
||||
Add(state, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddRing(
|
||||
GpuWorldState state,
|
||||
int centerX,
|
||||
int centerY,
|
||||
int radius,
|
||||
int skipX,
|
||||
int skipY)
|
||||
{
|
||||
for (int x = centerX - radius; x <= centerX + radius; x++)
|
||||
{
|
||||
for (int y = centerY - radius; y <= centerY + radius; y++)
|
||||
{
|
||||
if (Math.Max(Math.Abs(x - centerX), Math.Abs(y - centerY)) != radius
|
||||
|| (x == skipX && y == skipY))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Add(state, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Add(GpuWorldState state, int x, int y)
|
||||
{
|
||||
uint landblockId = StreamingRegion.EncodeLandblockId(x, y);
|
||||
if (state.TryGetLandblock(landblockId, out _))
|
||||
return;
|
||||
state.AddLandblock(new LoadedLandblock(
|
||||
landblockId,
|
||||
new LandBlock(),
|
||||
Array.Empty<WorldEntity>()));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue