acdream/tests/AcDream.Core.Tests/Terrain/LandblockMeshTests.cs
Erik baf0db303d feat(core): add LandblockMesh flat-terrain generator
Pure CPU mesh generator: takes a DatReaderWriter LandBlock DBObj and
produces 81 vertices + 128 triangles covering 192x192 world units.
Vertices are a readonly record struct (position, normal, texcoord)
so the upcoming GPU upload in Task 8 can sizeof() them directly.
Height byte -> world z uses a simple 2x scale; the real AC height
lookup table is a Phase 2+ concern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 16:37:52 +02:00

76 lines
2 KiB
C#

using System.Numerics;
using AcDream.Core.Terrain;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Types;
namespace AcDream.Core.Tests.Terrain;
public class LandblockMeshTests
{
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);
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);
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);
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);
// 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);
}
}