feat(rendering): port retail building degrade walk
Add exact retail building degrade selection, shared FPS/degrade ownership, complete-body gating, selected-shell submission, ordinary ladder mesh residency, frame-scoped retry rearm, Config controls, installed-DAT census, and lifecycle/allocation proofs. Reviews: OpenAI retail pass 3 PASS; OpenAI production pass 5 PASS. Gates: Release 0W/0E; focused 285/285; hermetic 16811/16811; InstalledDat 469 pass, 10 documented fail, 1 documented skip; both manifests 30/30.
This commit is contained in:
parent
d0f45f6a99
commit
c673f767e9
41 changed files with 1829 additions and 167 deletions
|
|
@ -8,6 +8,8 @@ using AcDream.Core.World;
|
|||
using DatReaderWriter;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Types;
|
||||
using DatReaderWriter.Enums;
|
||||
using AcDream.App.Rendering.Walk;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
|
|
@ -140,6 +142,52 @@ public sealed class LandblockBuildFactoryTests
|
|||
Assert.Equal((LandblockId & 0xFFFF0000u) | 1u, buildingEntry.Building.PositionCellId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WalkBuildingFactory_SetupModelUsesExactlyRestingPartZeroAndDefaultScale()
|
||||
{
|
||||
const uint setupId = 0x0200_0100u;
|
||||
const uint partZeroId = 0x0100_0101u;
|
||||
var dat = CreateDat(out RecordingDatProxy proxy);
|
||||
var resting = new AnimationFrame(1);
|
||||
resting.Frames.Add(new Frame
|
||||
{
|
||||
Origin = new Vector3(1f, 2f, 3f),
|
||||
Orientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, 0.25f),
|
||||
});
|
||||
var setup = new Setup();
|
||||
setup.Parts.Add(partZeroId);
|
||||
setup.DefaultScale.Add(new Vector3(2f, 3f, 4f));
|
||||
setup.PlacementFrames[Placement.Resting] = resting;
|
||||
proxy.Add(setupId, setup);
|
||||
proxy.Add(partZeroId, new GfxObj
|
||||
{
|
||||
Id = partZeroId,
|
||||
SortCenter = new Vector3(4f, 5f, 6f),
|
||||
});
|
||||
var info = new BuildingInfo
|
||||
{
|
||||
ModelId = setupId,
|
||||
Frame = new Frame
|
||||
{
|
||||
Origin = new Vector3(12f, 12f, 0f),
|
||||
Orientation = Quaternion.Identity,
|
||||
},
|
||||
Portals = [],
|
||||
};
|
||||
|
||||
WalkBuildingFactory.Entry entry = Assert.Single(
|
||||
WalkBuildingFactory.Build(dat, LandblockId, [info], Vector3.Zero));
|
||||
|
||||
Assert.Equal(partZeroId, entry.Building.GfxObjId);
|
||||
Assert.Equal(new Vector3(4f, 5f, 6f), entry.Building.SortCenter);
|
||||
Assert.Equal(4f, entry.Building.PartZeroScaleZ);
|
||||
Matrix4x4 expected = Matrix4x4.CreateScale(2f, 3f, 4f)
|
||||
* Matrix4x4.CreateFromQuaternion(resting.Frames[0].Orientation)
|
||||
* Matrix4x4.CreateTranslation(1f, 2f, 3f);
|
||||
Assert.Equal(expected, entry.Building.PartZeroTransform);
|
||||
Assert.Equal(expected * entry.WorldTransform, entry.PartZeroWorldTransform);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildFar_NeverPopulatesWalkDataBecauseEnvCellsIsNull()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,14 +1,96 @@
|
|||
using AcDream.App.Streaming;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.App.Rendering.Walk;
|
||||
using AcDream.Core.World;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using System.Collections.Immutable;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
public sealed class StreamingControllerReadinessTests
|
||||
{
|
||||
[Fact]
|
||||
public void NearPublication_OwnsWalkLadderAsOrdinaryReadinessAndReleasesOnRetirement()
|
||||
{
|
||||
const uint landblockId = 0x1236FFFFu;
|
||||
const ulong ladderId = 0x01001234ul;
|
||||
var meshes = new ReadinessMeshAdapter();
|
||||
var state = new GpuWorldState(new LandblockSpawnAdapter(meshes));
|
||||
var outbox = new Queue<LandblockStreamResult>();
|
||||
var building = new WalkBuilding
|
||||
{
|
||||
PositionCellId = 0x12360001u,
|
||||
DegradeLevels =
|
||||
[
|
||||
new WalkBuildingDegradeLevel((uint)ladderId, 1u, 0f, 10f, 20f, null),
|
||||
],
|
||||
};
|
||||
var envCells = new EnvCellLandblockBuild(
|
||||
landblockId,
|
||||
Array.Empty<LoadedCell>(),
|
||||
Array.Empty<EnvCellShellPlacement>(),
|
||||
[new WalkBuildingFactory.Entry(building, Matrix4x4.Identity, Matrix4x4.Identity)]);
|
||||
var build = new LandblockBuild(
|
||||
new LoadedLandblock(landblockId, new LandBlock(), Array.Empty<WorldEntity>()),
|
||||
envCells);
|
||||
outbox.Enqueue(new LandblockStreamResult.Loaded(
|
||||
landblockId,
|
||||
LandblockStreamTier.Near,
|
||||
build,
|
||||
new AcDream.Core.Terrain.LandblockMeshData([], [])));
|
||||
var controller = new StreamingController(
|
||||
enqueueLoad: (_, _) => { },
|
||||
enqueueUnload: _ => { },
|
||||
drainCompletions: maximum =>
|
||||
{
|
||||
var drained = new List<LandblockStreamResult>();
|
||||
while (drained.Count < maximum && outbox.TryDequeue(out var result))
|
||||
drained.Add(result);
|
||||
return drained;
|
||||
},
|
||||
applyTerrain: (_, _) => { },
|
||||
state: state,
|
||||
nearRadius: 0,
|
||||
farRadius: 0);
|
||||
|
||||
for (int frame = 0; frame < 32 && !meshes.ReferenceCounts.ContainsKey(ladderId); frame++)
|
||||
controller.Tick(0x12, 0x36);
|
||||
|
||||
Assert.Equal(1, meshes.ReferenceCounts[ladderId]);
|
||||
Assert.False(controller.IsRenderNeighborhoodResident(landblockId, 0, 0));
|
||||
meshes.ReadyIds.Add(ladderId);
|
||||
Assert.True(controller.IsRenderNeighborhoodResident(landblockId, 0, 0));
|
||||
|
||||
state.RemoveEntitiesFromLandblock(landblockId);
|
||||
Assert.Empty(meshes.ReferenceCounts);
|
||||
GpuLandblockSpatialPublication revisit = state.CommitEntitiesToExistingLandblockSpatial(
|
||||
landblockId,
|
||||
Array.Empty<WorldEntity>(),
|
||||
additionalRenderIds: null,
|
||||
additionalOrdinaryRenderIds: envCells.WalkBuildingMeshDependencies);
|
||||
state.ActivateLandblockPresentation(revisit);
|
||||
Assert.Equal(1, meshes.ReferenceCounts[ladderId]);
|
||||
state.RemoveLandblock(landblockId);
|
||||
Assert.Empty(meshes.ReferenceCounts);
|
||||
|
||||
GpuLandblockSpatialPublication resetPublication =
|
||||
state.CommitLandblockSpatial(
|
||||
build.Landblock,
|
||||
additionalRenderIds: null,
|
||||
tier: LandblockStreamTier.Near,
|
||||
additionalOrdinaryRenderIds:
|
||||
envCells.WalkBuildingMeshDependencies);
|
||||
state.ActivateLandblockPresentation(resetPublication);
|
||||
Assert.Equal(1, meshes.ReferenceCounts[ladderId]);
|
||||
|
||||
GpuWorldRecenterRetirement reset = state.DetachAllForOriginRecenter();
|
||||
Assert.Equal(landblockId, Assert.Single(reset.Landblocks).LandblockId);
|
||||
state.ReleaseLandblockMeshReferences(landblockId);
|
||||
Assert.Empty(meshes.ReferenceCounts);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderNeighborhoodResident_RequiresEveryPublishedLandblockInRing()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue