Adds AabbMin/AabbMax (per-entity world-space bounding box) and AabbDirty flag to WorldEntity. RefreshAabb() recomputes the box from Position ±5 m (DefaultAabbRadius). SetPosition() writes Position and marks the cache dirty so the dispatcher calls RefreshAabb on first read rather than carrying stale bounds. AabbDirty defaults to true on construction — freshly-built entities have zero AabbMin/AabbMax until RefreshAabb is called. Two new conformance tests verify the ±5 m geometry and the dirty/clean state machine. Per Phase A.5 spec §4.6 Change #2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
47 lines
1.3 KiB
C#
47 lines
1.3 KiB
C#
using System.Numerics;
|
|
using AcDream.Core.World;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Tests.World;
|
|
|
|
public class WorldEntityAabbTests
|
|
{
|
|
[Fact]
|
|
public void Aabb_DefaultRadius_PositionPlusMinus5()
|
|
{
|
|
var entity = new WorldEntity
|
|
{
|
|
Id = 1,
|
|
SourceGfxObjOrSetupId = 0,
|
|
Position = new Vector3(10, 20, 30),
|
|
Rotation = System.Numerics.Quaternion.Identity,
|
|
MeshRefs = System.Array.Empty<MeshRef>(),
|
|
};
|
|
entity.RefreshAabb();
|
|
|
|
Assert.Equal(new Vector3(5, 15, 25), entity.AabbMin);
|
|
Assert.Equal(new Vector3(15, 25, 35), entity.AabbMax);
|
|
}
|
|
|
|
[Fact]
|
|
public void Aabb_DirtyFlag_SetByMutator_ClearedByRefresh()
|
|
{
|
|
var entity = new WorldEntity
|
|
{
|
|
Id = 1,
|
|
SourceGfxObjOrSetupId = 0,
|
|
Position = new Vector3(10, 20, 30),
|
|
Rotation = System.Numerics.Quaternion.Identity,
|
|
MeshRefs = System.Array.Empty<MeshRef>(),
|
|
};
|
|
entity.RefreshAabb();
|
|
Assert.False(entity.AabbDirty);
|
|
|
|
entity.SetPosition(new Vector3(100, 200, 300));
|
|
Assert.True(entity.AabbDirty);
|
|
|
|
entity.RefreshAabb();
|
|
Assert.False(entity.AabbDirty);
|
|
Assert.Equal(new Vector3(95, 195, 295), entity.AabbMin);
|
|
}
|
|
}
|