Publish prepared GfxObj, Setup, CellStruct, and EnvCell collision records without retaining their parsed DAT BSP, polygon, vertex, or shape graphs. Strip temporary physics bundles at stable world commit, keep graph traversal only as an explicit test/tooling oracle, and report graph residency from actual retained fields. Validated by 115 focused collision/streaming tests, a zero-warning Release build, and 8,413 passing Release tests with five pre-existing skips. Co-authored-by: Codex <codex@openai.com>
163 lines
5.2 KiB
C#
163 lines
5.2 KiB
C#
using System.Collections.Immutable;
|
|
using System.Numerics;
|
|
using AcDream.Core.Physics;
|
|
using DatReaderWriter.DBObjs;
|
|
using DatReaderWriter.Enums;
|
|
|
|
namespace AcDream.Core.Tests.Physics;
|
|
|
|
public sealed class PhysicsDataCacheProductionTests
|
|
{
|
|
[Fact]
|
|
public void CreateProduction_SelectsFlatTraversal()
|
|
{
|
|
PhysicsDataCache cache = PhysicsDataCache.CreateProduction();
|
|
|
|
Assert.Equal(
|
|
CollisionTraversalMode.Flat,
|
|
cache.CollisionTraversalMode);
|
|
}
|
|
|
|
[Fact]
|
|
public void ProductionSetupPublication_RejectsMissingPreparedAsset()
|
|
{
|
|
PhysicsDataCache cache = PhysicsDataCache.CreateProduction();
|
|
|
|
InvalidOperationException fault = Assert.Throws<InvalidOperationException>(
|
|
() => cache.CacheSetup(0x0200_0001u, new Setup()));
|
|
|
|
Assert.Contains(
|
|
"no prepared collision asset",
|
|
fault.Message,
|
|
StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void GraphOracleFixture_StillAcceptsSourceSetup()
|
|
{
|
|
var cache = new PhysicsDataCache();
|
|
|
|
cache.CacheSetup(0x0200_0001u, new Setup());
|
|
|
|
Assert.NotNull(cache.GetSetup(0x0200_0001u));
|
|
}
|
|
|
|
[Fact]
|
|
public void ProductionSetupPublication_AllowsIdempotentCachedFlatAsset()
|
|
{
|
|
PhysicsDataCache cache = PhysicsDataCache.CreateProduction();
|
|
var setup = new Setup();
|
|
var prepared = new FlatSetupCollision(
|
|
ImmutableArray<FlatCollisionCylinder>.Empty,
|
|
ImmutableArray<FlatCollisionSphere>.Empty,
|
|
0f,
|
|
0f,
|
|
0f,
|
|
0f);
|
|
|
|
cache.CacheSetup(0x0200_0001u, setup, prepared);
|
|
cache.CacheSetup(0x0200_0001u, setup);
|
|
|
|
Assert.Same(prepared, cache.GetFlatSetup(0x0200_0001u));
|
|
}
|
|
|
|
[Fact]
|
|
public void ProductionPreparedRecords_RetainNoParsedCollisionGraph()
|
|
{
|
|
const uint gfxObjId = 0x0100_0001u;
|
|
const uint setupId = 0x0200_0001u;
|
|
const uint cellId = 0xA9B4_0100u;
|
|
PhysicsDataCache cache = PhysicsDataCache.CreateProduction();
|
|
Assert.Null(cache.CollisionShadow);
|
|
|
|
var node = new FlatPhysicsBspNode(
|
|
BSPNodeType.Leaf,
|
|
default,
|
|
-1,
|
|
-1,
|
|
0,
|
|
0,
|
|
new FlatCollisionSphere(Vector3.Zero, 3f),
|
|
new FlatIndexRange(0, 0));
|
|
var physicsBsp = new FlatPhysicsBsp(
|
|
0,
|
|
ImmutableArray.Create(node),
|
|
ImmutableArray<int>.Empty,
|
|
FlatPolygonTable.Empty);
|
|
var gfx = new FlatGfxObjCollisionAsset(
|
|
physicsBsp,
|
|
new FlatCollisionSphere(Vector3.Zero, 3f),
|
|
new FlatGfxObjVisualBounds(
|
|
-Vector3.One,
|
|
Vector3.One,
|
|
Vector3.Zero,
|
|
1.7320508f,
|
|
Vector3.One));
|
|
var setup = new FlatSetupCollision(
|
|
ImmutableArray.Create(
|
|
new FlatCollisionCylinder(
|
|
Vector3.UnitZ,
|
|
0.4f,
|
|
1.2f)),
|
|
ImmutableArray<FlatCollisionSphere>.Empty,
|
|
1.2f,
|
|
0.4f,
|
|
0.5f,
|
|
0.5f);
|
|
var structure = new FlatCellStructureCollisionAsset(
|
|
physicsBsp,
|
|
new FlatCellContainmentBsp(
|
|
-1,
|
|
ImmutableArray<FlatCellBspNode>.Empty),
|
|
FlatPolygonTable.Empty);
|
|
var topology = new FlatEnvCellTopology(
|
|
ImmutableArray<FlatEnvCellPortal>.Empty,
|
|
ImmutableArray<uint>.Empty,
|
|
seenOutside: false);
|
|
|
|
cache.CacheGfxObj(gfxObjId, gfx);
|
|
cache.CacheSetup(setupId, setup);
|
|
cache.CacheCellStruct(
|
|
cellId,
|
|
new EnvCell(),
|
|
Matrix4x4.Identity,
|
|
structure,
|
|
topology);
|
|
|
|
GfxObjPhysics retainedGfx = Assert.IsType<GfxObjPhysics>(
|
|
cache.GetGfxObj(gfxObjId));
|
|
Assert.Null(retainedGfx.BSP);
|
|
Assert.Null(retainedGfx.PhysicsPolygons);
|
|
Assert.Null(retainedGfx.Vertices);
|
|
Assert.Empty(retainedGfx.Resolved);
|
|
|
|
SetupPhysics retainedSetup = Assert.IsType<SetupPhysics>(
|
|
cache.GetSetup(setupId));
|
|
Assert.Empty(retainedSetup.CylSpheres);
|
|
Assert.Empty(retainedSetup.Spheres);
|
|
|
|
CellPhysics retainedCell = Assert.IsType<CellPhysics>(
|
|
cache.GetCellStruct(cellId));
|
|
Assert.Null(retainedCell.BSP);
|
|
Assert.Null(retainedCell.CellBSP);
|
|
Assert.Null(retainedCell.PhysicsPolygons);
|
|
Assert.Null(retainedCell.Vertices);
|
|
Assert.Null(retainedCell.PortalPolygons);
|
|
Assert.Empty(retainedCell.Resolved);
|
|
|
|
Assert.Equal(0, cache.GraphGfxObjCount);
|
|
Assert.Equal(0, cache.GraphSetupCount);
|
|
Assert.Equal(0, cache.GraphCellStructCount);
|
|
Assert.Equal(1, cache.FlatGfxObjCount);
|
|
Assert.Equal(1, cache.FlatSetupCount);
|
|
Assert.Equal(1, cache.FlatCellStructCount);
|
|
Assert.Equal(1, cache.FlatEnvCellCount);
|
|
var runtimeCell =
|
|
Assert.IsType<AcDream.Core.World.Cells.EnvCell>(
|
|
cache.CellGraph.GetVisible(cellId));
|
|
Assert.Null(runtimeCell.ContainmentBsp);
|
|
Assert.Same(
|
|
structure.ContainmentBsp,
|
|
runtimeCell.FlatContainmentBsp);
|
|
}
|
|
}
|