using System.Numerics; using AcDream.Core.Terrain; using DatReaderWriter.DBObjs; using DatReaderWriter.Types; namespace AcDream.Core.Tests.Terrain; public class LandblockMeshTests { /// /// Synthetic height table that mirrors Phase 1's simplified "* 2.0f" scale so /// the existing tests continue to describe the same behavior. Real AC uses a /// non-linear table from Region.LandDefs.LandHeightTable loaded at runtime. /// private static readonly float[] IdentityHeightTable = Enumerable.Range(0, 256).Select(i => i * 2f).ToArray(); private static LandBlock BuildFlatLandBlock(byte heightIndex = 0) { var block = new LandBlock { HasObjects = false, Terrain = new TerrainInfo[81], Height = new byte[81], }; for (int i = 0; i < 81; i++) { block.Terrain[i] = (ushort)0; block.Height[i] = heightIndex; } return block; } [Fact] public void Build_FlatBlock_Produces81VerticesAnd128Triangles() { var block = BuildFlatLandBlock(); var mesh = LandblockMesh.Build(block, IdentityHeightTable); Assert.Equal(81, mesh.Vertices.Length); Assert.Equal(128 * 3, mesh.Indices.Length); } [Fact] public void Build_Vertices_Cover192x192WorldUnits() { var block = BuildFlatLandBlock(); var mesh = LandblockMesh.Build(block, IdentityHeightTable); var minX = mesh.Vertices.Min(v => v.Position.X); var maxX = mesh.Vertices.Max(v => v.Position.X); var minY = mesh.Vertices.Min(v => v.Position.Y); var maxY = mesh.Vertices.Max(v => v.Position.Y); Assert.Equal(0.0f, minX); Assert.Equal(192.0f, maxX); Assert.Equal(0.0f, minY); Assert.Equal(192.0f, maxY); } [Fact] public void Build_FlatBlock_AllVerticesSameZ() { var block = BuildFlatLandBlock(heightIndex: 10); var mesh = LandblockMesh.Build(block, IdentityHeightTable); var zs = mesh.Vertices.Select(v => v.Position.Z).Distinct().ToArray(); Assert.Single(zs); } [Fact] public void Build_HeightValues_ScaleByTwo() { var block = BuildFlatLandBlock(heightIndex: 5); var mesh = LandblockMesh.Build(block, IdentityHeightTable); // AC's Land::LandHeightTable scales height byte index by 2.0f for the simple ramp case. Assert.Equal(10.0f, mesh.Vertices[0].Position.Z); } }