feat(core): UCG Stage 1 — populate CellGraph from CacheCellStruct + AddLandblock (inert)
PhysicsDataCache gains a `CellGraph` property (UCG Stage 1). The env-cell hook is placed at the very top of CacheCellStruct — before the idempotency guard and the null-PhysicsBSP early-return — so BSP-less cells are included in the graph even though they are dropped from the legacy _cellStruct map. PhysicsEngine.AddLandblock/RemoveLandblock mirror terrain registration into the graph via a null-guarded DataCache?.CellGraph call. Zero behavior change: CellGraph has no readers this stage. A using-alias (UcgEnvCell / UcgCellGraph) resolves the EnvCell name collision between AcDream.Core.World.Cells and DatReaderWriter.DBObjs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1aede3d6aa
commit
8e703bef22
3 changed files with 55 additions and 0 deletions
|
|
@ -4,6 +4,8 @@ using DatReaderWriter.DBObjs;
|
||||||
using DatReaderWriter.Enums;
|
using DatReaderWriter.Enums;
|
||||||
using DatReaderWriter.Types;
|
using DatReaderWriter.Types;
|
||||||
using Plane = System.Numerics.Plane;
|
using Plane = System.Numerics.Plane;
|
||||||
|
using UcgEnvCell = AcDream.Core.World.Cells.EnvCell;
|
||||||
|
using UcgCellGraph = AcDream.Core.World.Cells.CellGraph;
|
||||||
|
|
||||||
namespace AcDream.Core.Physics;
|
namespace AcDream.Core.Physics;
|
||||||
|
|
||||||
|
|
@ -23,6 +25,12 @@ public sealed class PhysicsDataCache
|
||||||
// ── Phase 2: building portal cache for outdoor→indoor entry ───────────
|
// ── Phase 2: building portal cache for outdoor→indoor entry ───────────
|
||||||
private readonly ConcurrentDictionary<uint, BuildingPhysics> _buildings = new();
|
private readonly ConcurrentDictionary<uint, BuildingPhysics> _buildings = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UCG Stage 1: the unified cell graph, built alongside the legacy cell caches.
|
||||||
|
/// Consumed by nobody this stage (zero behavior change).
|
||||||
|
/// </summary>
|
||||||
|
public UcgCellGraph CellGraph { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extract and cache the physics BSP + polygon data from a GfxObj,
|
/// Extract and cache the physics BSP + polygon data from a GfxObj,
|
||||||
/// PLUS always cache a visual AABB from the vertex data regardless of
|
/// PLUS always cache a visual AABB from the vertex data regardless of
|
||||||
|
|
@ -155,6 +163,11 @@ public sealed class PhysicsDataCache
|
||||||
public void CacheCellStruct(uint envCellId, DatReaderWriter.DBObjs.EnvCell envCell,
|
public void CacheCellStruct(uint envCellId, DatReaderWriter.DBObjs.EnvCell envCell,
|
||||||
CellStruct cellStruct, Matrix4x4 worldTransform)
|
CellStruct cellStruct, Matrix4x4 worldTransform)
|
||||||
{
|
{
|
||||||
|
// UCG Stage 1: register in the unified graph for ALL cells — before the
|
||||||
|
// idempotency + null-BSP guards below, so BSP-less cells are still included.
|
||||||
|
if (!CellGraph.Contains(envCellId))
|
||||||
|
CellGraph.Add(UcgEnvCell.FromDat(envCellId, envCell, cellStruct, worldTransform));
|
||||||
|
|
||||||
if (_cellStruct.ContainsKey(envCellId)) return;
|
if (_cellStruct.ContainsKey(envCellId)) return;
|
||||||
if (cellStruct.PhysicsBSP?.Root is null) return;
|
if (cellStruct.PhysicsBSP?.Root is null) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ public sealed class PhysicsEngine
|
||||||
float worldOffsetX, float worldOffsetY)
|
float worldOffsetX, float worldOffsetY)
|
||||||
{
|
{
|
||||||
_landblocks[landblockId] = new LandblockPhysics(terrain, cells, portals, worldOffsetX, worldOffsetY);
|
_landblocks[landblockId] = new LandblockPhysics(terrain, cells, portals, worldOffsetX, worldOffsetY);
|
||||||
|
|
||||||
|
// UCG Stage 1: mirror terrain into the unified graph (inert this stage).
|
||||||
|
DataCache?.CellGraph.RegisterTerrain(landblockId, terrain, new Vector3(worldOffsetX, worldOffsetY, 0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -69,6 +72,9 @@ public sealed class PhysicsEngine
|
||||||
{
|
{
|
||||||
_landblocks.Remove(landblockId);
|
_landblocks.Remove(landblockId);
|
||||||
ShadowObjects.RemoveLandblock(landblockId);
|
ShadowObjects.RemoveLandblock(landblockId);
|
||||||
|
|
||||||
|
// UCG Stage 1: mirror removal into the unified graph (inert this stage).
|
||||||
|
DataCache?.CellGraph.RemoveLandblock(landblockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
36
tests/AcDream.Core.Tests/Physics/CellGraphPopulationTests.cs
Normal file
36
tests/AcDream.Core.Tests/Physics/CellGraphPopulationTests.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
using AcDream.Core.Physics;
|
||||||
|
using AcDream.Core.World.Cells;
|
||||||
|
using DatReaderWriter.Types;
|
||||||
|
using Xunit;
|
||||||
|
using DatEnvCell = DatReaderWriter.DBObjs.EnvCell;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Physics;
|
||||||
|
|
||||||
|
public class CellGraphPopulationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CacheCellStruct_AddsEnvCellToGraph_EvenWhenPhysicsBspIsNull()
|
||||||
|
{
|
||||||
|
var cache = new PhysicsDataCache();
|
||||||
|
var cellStruct = new CellStruct
|
||||||
|
{
|
||||||
|
VertexArray = new VertexArray { Vertices = new Dictionary<ushort, SWVertex>() },
|
||||||
|
Polygons = new Dictionary<ushort, Polygon>(),
|
||||||
|
// PhysicsBSP omitted (defaults to null) — triggers the null-BSP drop from _cellStruct
|
||||||
|
};
|
||||||
|
var dat = new DatEnvCell
|
||||||
|
{
|
||||||
|
Flags = (DatReaderWriter.Enums.EnvCellFlags)0,
|
||||||
|
CellPortals = new List<DatReaderWriter.Types.CellPortal>(),
|
||||||
|
VisibleCells = new List<ushort>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.CacheCellStruct(0xA9B40174u, dat, cellStruct, Matrix4x4.Identity);
|
||||||
|
|
||||||
|
Assert.Null(cache.GetCellStruct(0xA9B40174u)); // dropped from physics cache
|
||||||
|
Assert.NotNull(cache.CellGraph.GetVisible(0xA9B40174u)); // but present in the graph
|
||||||
|
Assert.IsType<EnvCell>(cache.CellGraph.GetVisible(0xA9B40174u));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue