diff --git a/terrain/Terrain.cs b/terrain/Terrain.cs index 3454e29..0e190aa 100644 --- a/terrain/Terrain.cs +++ b/terrain/Terrain.cs @@ -143,17 +143,33 @@ public partial class Terrain AddPoint(v3, uv3); } - for (var x = 0; x < Size.X; x++) { + for (var x = 0; x < Size.X; x++) for (var z = 0; z < Size.Y; z++) { var corners = GetCornersPosition(new(x, z)); - AddTriangle(corners.TopLeft , new(0.0f, 0.0f), - corners.TopRight , new(1.0f, 0.0f), - corners.BottomLeft , new(0.0f, 1.0f)); - AddTriangle(corners.TopRight , new(1.0f, 0.0f), - corners.BottomRight, new(1.0f, 1.0f), - corners.BottomLeft , new(0.0f, 1.0f)); + + // Find the "ideal way" to split the quad for the tile into two triangles. + // This is done by finding the corner with the least variance between its neighboring corners. + var sorted = corners.ToSorted((a, b) => a.Y.CompareTo(b.Y)); + var minDiff = Abs(sorted[0].Value.Y - sorted[2].Value.Y); // Difference between lowest and 3rd lowest point. + var maxDiff = Abs(sorted[3].Value.Y - sorted[1].Value.Y); // Difference between highest and 3rd highest point. + + var first = sorted[(minDiff > maxDiff) ? 0 : 3].Corner; + if (first is Corner.TopLeft or Corner.BottomRight) { + AddTriangle(corners.TopLeft , new(0.0f, 0.0f), + corners.TopRight , new(1.0f, 0.0f), + corners.BottomLeft , new(0.0f, 1.0f)); + AddTriangle(corners.TopRight , new(1.0f, 0.0f), + corners.BottomRight, new(1.0f, 1.0f), + corners.BottomLeft , new(0.0f, 1.0f)); + } else { + AddTriangle(corners.TopRight , new(1.0f, 0.0f), + corners.BottomRight, new(1.0f, 1.0f), + corners.TopLeft , new(0.0f, 0.0f)); + AddTriangle(corners.BottomRight, new(1.0f, 1.0f), + corners.BottomLeft , new(0.0f, 1.0f), + corners.TopLeft , new(0.0f, 0.0f)); + } } - } mesh.SurfaceEnd(); mesh.SurfaceSetMaterial(0, _terrainMaterial); @@ -213,7 +229,7 @@ public partial class Terrain (T TopLeft, T TopRight, T BottomRight, T BottomLeft) { public T this[Corner corner] { - readonly get => corner switch { + get => corner switch { Corner.TopLeft => TopLeft, Corner.TopRight => TopRight, Corner.BottomRight => BottomRight, @@ -240,8 +256,20 @@ public partial class Terrain (corner == Corner.BottomRight) ? value : BottomRight, (corner == Corner.BottomLeft) ? value : BottomLeft); - public readonly T[] ToArray() + public T[] ToArray() => [ TopLeft, TopRight, BottomRight, BottomLeft ]; + + public (Corner Corner, T Value)[] ToSorted(Comparison comparison) + { + var result = new (Corner Corner, T Value)[] { + (Corner.TopLeft , TopLeft ), + (Corner.TopRight , TopRight ), + (Corner.BottomRight , BottomRight), + (Corner.BottomLeft , BottomLeft ), + }; + Array.Sort(result, (a, b) => comparison(a.Value, b.Value)); + return result; + } } }