From 8eef918d60e9d1497cbb498222f0d18125170a3e Mon Sep 17 00:00:00 2001 From: copygirl Date: Mon, 30 Sep 2024 23:46:50 +0200 Subject: [PATCH] Make terrain mesh generate vertical walls --- GodotExtensions.cs | 8 +- level.tscn | 172 +++++++++++++++++++++++++++---------- terrain/Terrain+Editing.cs | 1 - terrain/Terrain.cs | 61 +++++++++++-- 4 files changed, 187 insertions(+), 55 deletions(-) diff --git a/GodotExtensions.cs b/GodotExtensions.cs index f00501b..b16fb01 100644 --- a/GodotExtensions.cs +++ b/GodotExtensions.cs @@ -5,10 +5,10 @@ public static class GodotExtensions public static (Corner, Corner) GetCorners(this Side side) => side switch { - Side.Left => (Corner.TopLeft, Corner.BottomLeft), - Side.Top => (Corner.TopLeft, Corner.TopRight), - Side.Right => (Corner.TopRight, Corner.BottomRight), - Side.Bottom => (Corner.BottomLeft, Corner.BottomRight), + Side.Left => (Corner.BottomLeft , Corner.TopLeft ), + Side.Top => (Corner.TopLeft , Corner.TopRight ), + Side.Right => (Corner.TopRight , Corner.BottomRight), + Side.Bottom => (Corner.BottomRight, Corner.BottomLeft ), _ => throw new ArgumentException($"Invalid Side value '{side}'", nameof(side)), }; diff --git a/level.tscn b/level.tscn index a9133e9..50e1704 100644 --- a/level.tscn +++ b/level.tscn @@ -307,7 +307,7 @@ Vector2i(23, 23): { "texture": 2 }, Vector2i(23, 24): { -"heights": PackedFloat32Array(6.5, 3, 1.5, 4), +"heights": PackedFloat32Array(6.5, 3, 3, 4), "texture": 2 }, Vector2i(23, 25): { @@ -371,11 +371,11 @@ Vector2i(24, 22): { "texture": 2 }, Vector2i(24, 23): { -"heights": PackedFloat32Array(5, 3.5, 0, 3), +"heights": PackedFloat32Array(5, 3.5, 2, 3), "texture": 2 }, Vector2i(24, 24): { -"heights": PackedFloat32Array(3, 0, 0, 1.5), +"heights": PackedFloat32Array(3, 1, 0, 3), "texture": 2 }, Vector2i(24, 25): { @@ -435,15 +435,15 @@ Vector2i(25, 22): { "texture": 2 }, Vector2i(25, 23): { -"heights": PackedFloat32Array(3.5, 3, -0.5, 0), +"heights": PackedFloat32Array(3.5, 3, 0.5, 2), "texture": 2 }, Vector2i(25, 24): { -"heights": PackedFloat32Array(0, -0.5, -0.5, 0), +"heights": -0.5, "texture": 0 }, Vector2i(25, 25): { -"heights": PackedFloat32Array(0, -0.5, -1.5, 0), +"heights": PackedFloat32Array(-0.5, -0.5, -1.5, 0), "texture": 0 }, Vector2i(25, 26): { @@ -515,7 +515,7 @@ Vector2i(26, 22): { "texture": 2 }, Vector2i(26, 23): { -"heights": PackedFloat32Array(3, 3.5, -0.5, -0.5), +"heights": PackedFloat32Array(3, 2.5, 0.5, 0.5), "texture": 2 }, Vector2i(26, 24): { @@ -575,11 +575,11 @@ Vector2i(27, 17): { "texture": 2 }, Vector2i(27, 18): { -"heights": PackedFloat32Array(1, 3, 6, 1), +"heights": PackedFloat32Array(1, 3, 5.5, 1), "texture": 2 }, Vector2i(27, 19): { -"heights": PackedFloat32Array(1, 6, 5.5, 2.5), +"heights": PackedFloat32Array(1, 5.5, 5.5, 2.5), "texture": 2 }, Vector2i(27, 20): { @@ -587,15 +587,15 @@ Vector2i(27, 20): { "texture": 2 }, Vector2i(27, 21): { -"heights": PackedFloat32Array(1.5, 4, 5.5, 3.5), +"heights": PackedFloat32Array(1.5, 4, 4.5, 3.5), "texture": 2 }, Vector2i(27, 22): { -"heights": PackedFloat32Array(3.5, 5.5, 3, 3.5), +"heights": PackedFloat32Array(3.5, 4.5, 3, 3.5), "texture": 2 }, Vector2i(27, 23): { -"heights": PackedFloat32Array(3.5, 3, -0.5, -0.5), +"heights": PackedFloat32Array(2.5, 3, -0.5, 0.5), "texture": 2 }, Vector2i(27, 24): { @@ -659,11 +659,11 @@ Vector2i(28, 17): { "texture": 2 }, Vector2i(28, 18): { -"heights": PackedFloat32Array(3, 3, 6, 6), +"heights": PackedFloat32Array(3, 3, 6, 5.5), "texture": 2 }, Vector2i(28, 19): { -"heights": PackedFloat32Array(6, 6, 7, 5.5), +"heights": PackedFloat32Array(5.5, 6, 7, 5.5), "texture": 2 }, Vector2i(28, 20): { @@ -671,11 +671,11 @@ Vector2i(28, 20): { "texture": 2 }, Vector2i(28, 21): { -"heights": PackedFloat32Array(4, 5.5, 4, 5.5), +"heights": PackedFloat32Array(4, 5.5, 4, 4.5), "texture": 2 }, Vector2i(28, 22): { -"heights": PackedFloat32Array(5.5, 4, 1.5, 3), +"heights": PackedFloat32Array(4.5, 4, 1.5, 3), "texture": 2 }, Vector2i(28, 23): { @@ -751,11 +751,11 @@ Vector2i(29, 17): { "texture": 2 }, Vector2i(29, 18): { -"heights": PackedFloat32Array(3, 2, 5, 6), +"heights": PackedFloat32Array(3, 2, 6, 6), "texture": 2 }, Vector2i(29, 19): { -"heights": PackedFloat32Array(6, 5, 6, 7), +"heights": PackedFloat32Array(6, 6, 6, 7), "texture": 2 }, Vector2i(29, 20): { @@ -827,15 +827,15 @@ Vector2i(30, 17): { "texture": 2 }, Vector2i(30, 18): { -"heights": PackedFloat32Array(2, 3.5, 6, 5), +"heights": PackedFloat32Array(2, 3.5, 6, 6), "texture": 2 }, Vector2i(30, 19): { -"heights": PackedFloat32Array(5, 6, 5, 6), +"heights": PackedFloat32Array(6, 6, 5, 6), "texture": 2 }, Vector2i(30, 20): { -"heights": PackedFloat32Array(6, 5, 0, 2), +"heights": PackedFloat32Array(5, 4, 0, 2), "texture": 2 }, Vector2i(30, 21): { @@ -903,11 +903,11 @@ Vector2i(31, 18): { "texture": 2 }, Vector2i(31, 19): { -"heights": PackedFloat32Array(6, 5, 4, 5), +"heights": PackedFloat32Array(6, 5, 4.5, 4.5), "texture": 2 }, Vector2i(31, 20): { -"heights": PackedFloat32Array(5, 4, 0, 0), +"heights": PackedFloat32Array(2.5, 3.5, 0.5, 0), "texture": 2 }, Vector2i(31, 21): { @@ -971,11 +971,11 @@ Vector2i(31, 37): { "texture": 0 }, Vector2i(32, 16): { -"heights": PackedFloat32Array(0, 0, 5.5, 2.5), +"heights": PackedFloat32Array(0, 1, 4.5, 2.5), "texture": 2 }, Vector2i(32, 17): { -"heights": PackedFloat32Array(2.5, 5.5, 5.5, 2.5), +"heights": PackedFloat32Array(2.5, 4.5, 5.5, 2.5), "texture": 2 }, Vector2i(32, 18): { @@ -987,7 +987,7 @@ Vector2i(32, 19): { "texture": 2 }, Vector2i(32, 20): { -"heights": PackedFloat32Array(4, 5.5, 0.5, 0), +"heights": PackedFloat32Array(3, 5, 1.5, 0.5), "texture": 2 }, Vector2i(32, 21): { @@ -1051,11 +1051,11 @@ Vector2i(32, 37): { "texture": 0 }, Vector2i(33, 16): { -"heights": PackedFloat32Array(0, 0, 4.5, 5.5), +"heights": PackedFloat32Array(1, 2, 4.5, 4.5), "texture": 2 }, Vector2i(33, 17): { -"heights": PackedFloat32Array(5.5, 4.5, 4.5, 5.5), +"heights": PackedFloat32Array(4.5, 4.5, 4.5, 5.5), "texture": 2 }, Vector2i(33, 18): { @@ -1067,7 +1067,7 @@ Vector2i(33, 19): { "texture": 2 }, Vector2i(33, 20): { -"heights": PackedFloat32Array(5.5, 3.5, 0.5, 0.5), +"heights": PackedFloat32Array(5, 3.5, 1, 1.5), "texture": 2 }, Vector2i(33, 21): { @@ -1123,7 +1123,7 @@ Vector2i(33, 36): { "texture": 0 }, Vector2i(34, 16): { -"heights": PackedFloat32Array(0, 0, 4, 4.5), +"heights": PackedFloat32Array(2, 2, 4, 4.5), "texture": 2 }, Vector2i(34, 17): { @@ -1139,15 +1139,15 @@ Vector2i(34, 19): { "texture": 2 }, Vector2i(34, 20): { -"heights": PackedFloat32Array(3.5, 4, 0, 0.5), +"heights": PackedFloat32Array(3.5, 4, 2, 1), "texture": 2 }, Vector2i(34, 21): { -"heights": PackedFloat32Array(0.5, 0, 0, 0.5), +"heights": PackedFloat32Array(0.5, 1, 0.5, 0.5), "texture": 0 }, Vector2i(34, 22): { -"heights": PackedFloat32Array(0.5, 0, -0.5, 0.5), +"heights": PackedFloat32Array(0.5, 0.5, -0.5, 0.5), "texture": 1 }, Vector2i(34, 23): { @@ -1195,7 +1195,7 @@ Vector2i(34, 36): { "texture": 0 }, Vector2i(35, 16): { -"heights": PackedFloat32Array(0, 0, 1, 4), +"heights": PackedFloat32Array(2, 0, 1, 4), "texture": 2 }, Vector2i(35, 17): { @@ -1203,23 +1203,23 @@ Vector2i(35, 17): { "texture": 2 }, Vector2i(35, 18): { -"heights": PackedFloat32Array(4, 2.5, 6.5, 5), +"heights": PackedFloat32Array(4, 2.5, 6, 5), "texture": 2 }, Vector2i(35, 19): { -"heights": PackedFloat32Array(5, 6.5, 5.5, 4), +"heights": PackedFloat32Array(5, 6, 5.5, 4), "texture": 2 }, Vector2i(35, 20): { -"heights": PackedFloat32Array(4, 5.5, 1.5, 0), +"heights": PackedFloat32Array(4, 5.5, 2.5, 2.5), "texture": 2 }, Vector2i(35, 21): { -"heights": PackedFloat32Array(0, 1.5, 0, 0), +"heights": PackedFloat32Array(2.5, 2.5, 2, 2), "texture": 2 }, Vector2i(35, 22): { -"heights": PackedFloat32Array(0, 0, -0.5, -0.5), +"heights": PackedFloat32Array(0.5, 0.5, -0.5, -0.5), "texture": 1 }, Vector2i(35, 23): { @@ -1259,23 +1259,23 @@ Vector2i(36, 17): { "texture": 2 }, Vector2i(36, 18): { -"heights": PackedFloat32Array(2.5, 4, 4, 6.5), +"heights": PackedFloat32Array(2.5, 4, 4, 6), "texture": 2 }, Vector2i(36, 19): { -"heights": PackedFloat32Array(6.5, 4, 4.5, 5.5), +"heights": PackedFloat32Array(6, 4, 4.5, 5.5), "texture": 2 }, Vector2i(36, 20): { -"heights": PackedFloat32Array(5.5, 4.5, 4.5, 1.5), +"heights": PackedFloat32Array(5.5, 4.5, 4.5, 2.5), "texture": 2 }, Vector2i(36, 21): { -"heights": PackedFloat32Array(1.5, 4.5, 3, 0), +"heights": PackedFloat32Array(2.5, 4.5, 3, 2), "texture": 2 }, Vector2i(36, 22): { -"heights": PackedFloat32Array(0, 3, 0, -0.5), +"heights": PackedFloat32Array(1, 3, 0, -0.5), "texture": 2 }, Vector2i(36, 23): { @@ -1518,6 +1518,18 @@ Vector2i(41, 24): { "heights": PackedFloat32Array(-0.5, 0, 0, 0), "texture": 0 }, +Vector2i(41, 25): { +"heights": PackedFloat32Array(0, 0, 0.5, 0), +"texture": 0 +}, +Vector2i(41, 26): { +"heights": PackedFloat32Array(0, -0.5, -0.5, 0), +"texture": 0 +}, +Vector2i(41, 27): { +"heights": PackedFloat32Array(0, -1, 0, 0), +"texture": 0 +}, Vector2i(42, 19): { "heights": PackedFloat32Array(0, 0, 4.5, 3), "texture": 2 @@ -1534,6 +1546,18 @@ Vector2i(42, 22): { "heights": PackedFloat32Array(4, 5.5, 0, 0), "texture": 2 }, +Vector2i(42, 25): { +"heights": PackedFloat32Array(0, 0, -0.5, -0.5), +"texture": 0 +}, +Vector2i(42, 26): { +"heights": -0.5, +"texture": 0 +}, +Vector2i(42, 27): { +"heights": PackedFloat32Array(-0.5, -0.5, 0, 0), +"texture": 0 +}, Vector2i(43, 19): { "heights": PackedFloat32Array(0, 0, 4.5, 4.5), "texture": 2 @@ -1550,6 +1574,26 @@ Vector2i(43, 22): { "heights": PackedFloat32Array(5.5, 4.5, 0, 0), "texture": 2 }, +Vector2i(43, 25): { +"heights": PackedFloat32Array(0, 0, 0, 1), +"texture": 0 +}, +Vector2i(43, 26): { +"heights": PackedFloat32Array(-0.5, 0, 0, -0.5), +"texture": 0 +}, +Vector2i(43, 27): { +"heights": PackedFloat32Array(1.5, 0, 1, 0), +"texture": 0 +}, +Vector2i(43, 28): { +"heights": PackedFloat32Array(0, 1, 1, 0), +"texture": 0 +}, +Vector2i(43, 29): { +"heights": PackedFloat32Array(0, 1, 0, 0), +"texture": 0 +}, Vector2i(44, 19): { "heights": PackedFloat32Array(0, 0, 3, 4.5), "texture": 2 @@ -1566,6 +1610,18 @@ Vector2i(44, 22): { "heights": PackedFloat32Array(4.5, 3, 0, 0), "texture": 2 }, +Vector2i(44, 27): { +"heights": PackedFloat32Array(0, 0, 2, 1), +"texture": 0 +}, +Vector2i(44, 28): { +"heights": PackedFloat32Array(2, 4, 5.5, 4.5), +"texture": 0 +}, +Vector2i(44, 29): { +"heights": PackedFloat32Array(1, 2, 0, 0), +"texture": 0 +}, Vector2i(45, 19): { "heights": PackedFloat32Array(0, 0, 0, 3), "texture": 2 @@ -1581,6 +1637,34 @@ Vector2i(45, 21): { Vector2i(45, 22): { "heights": PackedFloat32Array(3, 0, 0, 0), "texture": 2 +}, +Vector2i(45, 25): { +"heights": PackedFloat32Array(0.5, 1, 1.5, 2), +"texture": 0 +}, +Vector2i(45, 27): { +"heights": 2.0, +"texture": 0 +}, +Vector2i(45, 28): { +"heights": PackedFloat32Array(3.5, 3.5, 4.5, 4.5), +"texture": 0 +}, +Vector2i(45, 29): { +"heights": PackedFloat32Array(2, 1, 0, 0), +"texture": 0 +}, +Vector2i(46, 27): { +"heights": PackedFloat32Array(0, 0, 0, 1), +"texture": 0 +}, +Vector2i(46, 28): { +"heights": PackedFloat32Array(1, 0, 0, 1), +"texture": 0 +}, +Vector2i(46, 29): { +"heights": PackedFloat32Array(1, 0, 0, 0), +"texture": 0 } } diff --git a/terrain/Terrain+Editing.cs b/terrain/Terrain+Editing.cs index 7ac505c..22dae10 100644 --- a/terrain/Terrain+Editing.cs +++ b/terrain/Terrain+Editing.cs @@ -75,7 +75,6 @@ public partial class Terrain // TODO: Handle different tool modes, such as painting. // TODO: Allow click-dragging which doesn't affect already changed tiles / corners. - // TODO: Make mesh generation generate vertical walls between disconnected corners. // TODO: Use ArrayMesh instead of ImmediateMesh. // TODO: Dynamically expand terrain instead of having it be a set size. diff --git a/terrain/Terrain.cs b/terrain/Terrain.cs index 8742ddf..dda52da 100644 --- a/terrain/Terrain.cs +++ b/terrain/Terrain.cs @@ -63,13 +63,12 @@ public partial class Terrain var num_textures = 4; var num_blend_textures = 7; - var rnd = new Random(); + var rnd = new Random(); for (var x = 0; x < Size.X; x++) for (var z = 0; z < Size.Y; z++) { var tile = GetTile(new(x, z)); var corners = GetTileCornerPositions(new(x, z), tile); - // Randomly select two different textures and one blend texture. mesh.SurfaceSetColor(new( (float)tile.TexturePrimary / num_textures, (float)tile.TextureSecondary / num_textures, @@ -77,10 +76,10 @@ public partial class Terrain )); var sorted = new (Corner Corner, float Height)[] { - (Corner.TopLeft , tile.Height.TopLeft ), - (Corner.TopRight , tile.Height.TopRight ), - (Corner.BottomRight , tile.Height.BottomRight), - (Corner.BottomLeft , tile.Height.BottomLeft ), + (Corner.TopLeft , tile.Height.TopLeft ), + (Corner.TopRight , tile.Height.TopRight ), + (Corner.BottomRight, tile.Height.BottomRight), + (Corner.BottomLeft , tile.Height.BottomLeft ), }; Array.Sort(sorted, (a, b) => a.Height.CompareTo(b.Height)); @@ -105,6 +104,56 @@ public partial class Terrain corners.BottomLeft , new(0.0f, 1.0f), corners.TopLeft , new(0.0f, 0.0f)); } + + // Set stone texture for walls. + mesh.SurfaceSetColor(new( + (float)2 / num_textures, + (float)2 / num_textures, + (float)0 / num_blend_textures + )); + + void DrawWall(TilePos nbrPos, Side side) { + var nbrTile = GetTile(nbrPos); + var nbrCorners = GetTileCornerPositions(nbrPos, nbrTile); + + var (c1, c2) = side.GetCorners(); + var (c3, c4) = side.GetOpposite().GetCorners(); + + var corner1 = corners[c1]; // "TopRight" + var corner2 = corners[c2]; // "TopLeft" + var corner3 = nbrCorners[c3]; // "BottomLeft" + var corner4 = nbrCorners[c4]; // "BottomRight" + + var equal1 = IsEqualApprox(corner1.Y, corner4.Y); + var equal2 = IsEqualApprox(corner2.Y, corner3.Y); + + switch (equal1, equal2) { + case (true, true): + // Both corners are connected, no wall needed. + break; + case (true, false): + AddTriangle(corner1, new(1.0f, corner1.Y / TileSize), + corner3, new(0.0f, corner3.Y / TileSize), + corner2, new(0.0f, corner2.Y / TileSize)); + break; + case (false, true): + AddTriangle(corner1, new(1.0f, corner1.Y / TileSize), + corner4, new(1.0f, corner4.Y / TileSize), + corner2, new(0.0f, corner2.Y / TileSize)); + break; + case (false, false): + AddTriangle(corner1, new(1.0f, corner1.Y / TileSize), + corner4, new(1.0f, corner4.Y / TileSize), + corner2, new(0.0f, corner2.Y / TileSize)); + AddTriangle(corner2, new(0.0f, corner2.Y / TileSize), + corner4, new(1.0f, corner4.Y / TileSize), + corner3, new(0.0f, corner3.Y / TileSize)); + break; + } + } + + if (x < Size.X - 1) DrawWall(new(x + 1, z), Side.Right); + if (z < Size.Y - 1) DrawWall(new(x, z + 1), Side.Bottom); } mesh.SurfaceEnd();