using System.Numerics; using AcDream.App.Rendering; using Xunit; namespace AcDream.Core.Tests.Rendering; public class FrustumCullerTests { [Fact] public void IdentityVP_EverythingVisible() { // Identity VP: all planes at infinity, every box is visible. // Actually identity VP has degenerate planes — instead use a // simple ortho that covers [-1,1]³. var vp = Matrix4x4.CreateOrthographic(2f, 2f, 0.1f, 100f); var planes = FrustumPlanes.FromViewProjection(vp); // Box at origin, well within the frustum. Assert.True(FrustumCuller.IsAabbVisible(planes, new Vector3(-0.5f, -0.5f, -50f), new Vector3(0.5f, 0.5f, -1f))); } [Fact] public void PerspectiveCamera_BoxInFront_Visible() { var view = Matrix4x4.CreateLookAt( new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.UnitY); var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 1f, 1f, 1000f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Box directly in front of the camera. Assert.True(FrustumCuller.IsAabbVisible(planes, new Vector3(-10f, -10f, -100f), new Vector3(10f, 10f, -10f))); } [Fact] public void PerspectiveCamera_BoxBehind_NotVisible() { var view = Matrix4x4.CreateLookAt( new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.UnitY); var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 1f, 1f, 1000f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Box entirely behind the camera (positive Z). Assert.False(FrustumCuller.IsAabbVisible(planes, new Vector3(-10f, -10f, 10f), new Vector3(10f, 10f, 100f))); } [Fact] public void PerspectiveCamera_BoxFarLeft_NotVisible() { var view = Matrix4x4.CreateLookAt( new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.UnitY); var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 1f, 1f, 1000f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Box way off to the left. Assert.False(FrustumCuller.IsAabbVisible(planes, new Vector3(-1000f, -10f, -50f), new Vector3(-500f, 10f, -10f))); } [Fact] public void PerspectiveCamera_BoxStraddlingNearPlane_Visible() { var view = Matrix4x4.CreateLookAt( new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.UnitY); var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 1f, 1f, 1000f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Box that straddles the near plane (conservative: visible). Assert.True(FrustumCuller.IsAabbVisible(planes, new Vector3(-1f, -1f, -2f), new Vector3(1f, 1f, 0.5f))); } [Fact] public void PerspectiveCamera_BoxBeyondFarPlane_NotVisible() { var view = Matrix4x4.CreateLookAt( new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.UnitY); var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 1f, 1f, 100f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Box far beyond the far plane. Assert.False(FrustumCuller.IsAabbVisible(planes, new Vector3(-10f, -10f, -500f), new Vector3(10f, 10f, -200f))); } [Fact] public void AcdreamCamera_LandblockInFront_Visible() { // Simulate acdream's actual camera setup (Z-up, looking +Y, // positioned at Holtburg). A landblock-sized AABB at the // camera's forward should be visible. var view = Matrix4x4.CreateLookAt( new Vector3(96f, 96f, 150f), // camera pos (center of a landblock, elevated) new Vector3(96f, 288f, 100f), // looking roughly +Y (forward toward next landblock) Vector3.UnitZ); // Z-up var proj = Matrix4x4.CreatePerspectiveFieldOfView( MathF.PI / 3f, 16f / 9f, 1f, 5000f); var planes = FrustumPlanes.FromViewProjection(view * proj); // Landblock-sized AABB 192 units ahead in Y. Assert.True(FrustumCuller.IsAabbVisible(planes, new Vector3(0f, 192f, 50f), new Vector3(192f, 384f, 200f))); // Landblock behind the camera (negative Y relative to camera). Assert.False(FrustumCuller.IsAabbVisible(planes, new Vector3(0f, -384f, 50f), new Vector3(192f, -192f, 200f))); } }