From 53b1f7f4143bf1207e5899fa2577fab039cba015 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Mon, 28 Aug 2023 14:03:02 +0200 Subject: [PATCH] Use instancing for HexTile3D rendering. --- scenes/Game.tscn | 1 - scenes/HexTile3D.tscn | 1 + scenes/StreamContainer.cs | 57 +++++++++++++++++++++++++++++++------ scenes/StreamContainer.tscn | 11 ++++++- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/scenes/Game.tscn b/scenes/Game.tscn index c496c17..dc1ffe3 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -70,7 +70,6 @@ align = 2 anims/FlashLabel = SubResource( 25 ) [node name="DebugContainer" type="PanelContainer" parent="."] -visible = false self_modulate = Color( 1, 1, 1, 0.443137 ) anchor_left = 1.0 anchor_top = 1.0 diff --git a/scenes/HexTile3D.tscn b/scenes/HexTile3D.tscn index b05e91a..811fbe8 100644 --- a/scenes/HexTile3D.tscn +++ b/scenes/HexTile3D.tscn @@ -23,6 +23,7 @@ script = ExtResource( 1 ) [node name="Mesh" type="MeshInstance" parent="." groups=["GameGeometry"]] transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, -2.5, 0 ) +visible = false mesh = ExtResource( 3 ) material/0 = ExtResource( 2 ) diff --git a/scenes/StreamContainer.cs b/scenes/StreamContainer.cs index b65dc13..f9e52d1 100644 --- a/scenes/StreamContainer.cs +++ b/scenes/StreamContainer.cs @@ -7,11 +7,15 @@ using GoDotLog; public class StreamContainer : Spatial { + // readonly variables + private readonly Transform _deactivatedTileTransform = new Transform(Basis.Identity, Vector3.Up * 1000); + // scene nodes private MeshInstance _bounds; private Spatial _activeTiles; private Queue _unusedTiles; private TileWorld _tileWorld; + private MultiMeshInstance _tileMultiMesh; // resources private PackedScene _hexTileScene = GD.Load("res://scenes/HexTile3D.tscn"); @@ -27,12 +31,12 @@ public class StreamContainer : Spatial delegate void TileHovered(HexTile3D tile3d); // other members - private Rect2 _worldRect; private Rect2 _currentOffsetCoordRect; private Rect2 _oldOffsetCoordRect; private HexGrid _hexGrid; - private Dictionary _coordToTile = new Dictionary(); + private Dictionary _coordToTile = new(); + private Dictionary _tileToInstanceIndex = new(); public List RemovedCoords = new List(); public List AddedCoords = new List(); @@ -52,6 +56,14 @@ public class StreamContainer : Spatial _unusedTiles = new Queue(); _bounds = GetNode("Bounds"); _activeTiles = GetNode("ActiveTiles"); + + _tileMultiMesh = GetNode("TileMultiMesh"); + _tileMultiMesh.Multimesh.InstanceCount = (int)((Dimensions.x + 5) * (Dimensions.y + 5)); + _tileMultiMesh.Multimesh.InstanceCount = 1810; + foreach (int i in Enumerable.Range(0, _tileMultiMesh.Multimesh.InstanceCount)) + { + _tileMultiMesh.Multimesh.SetInstanceTransform(i, _deactivatedTileTransform); + } _hexGrid = new HexGrid(); @@ -69,8 +81,7 @@ public class StreamContainer : Spatial Vector2 bottomLeftCoord = centerPlane - new Vector2(Dimensions.x / 2, Dimensions.y / 2); Vector2 topRightCoord = centerPlane + new Vector2(Dimensions.x / 2, Dimensions.y / 2); - - _worldRect = new Rect2(bottomLeftCoord, Dimensions); + // GD.Print("World rect now: " + _worldRect.ToString() + " center: " + _worldRect.GetCenter()); // y axis needs to be inverted as HexGrid's offset coordinates use the opposite axis direction @@ -78,6 +89,10 @@ public class StreamContainer : Spatial HexCell topRightCell = _hexGrid.GetHexAt(new Vector2(topRightCoord.x, bottomLeftCoord.y)); _currentOffsetCoordRect = new Rect2(bottomLeftCell.OffsetCoords, topRightCell.OffsetCoords - bottomLeftCell.OffsetCoords + Vector2.One); + +// Vector2 centerOffset = _hexGrid.GetHexAt(centerPlane).OffsetCoords; +// _currentOffsetCoordRect = new Rect2(centerOffset + new Vector2(-Dimensions.x / 2, -Dimensions.y / 2), +// Dimensions); // GD.Print("Offset rect now: " + _currentOffsetCoordRect.ToString() + " center: " + // _currentOffsetCoordRect.GetCenter()); @@ -140,10 +155,8 @@ public class StreamContainer : Spatial if (isInOld && !isInCurrent && _coordToTile.Keys.Contains(coord)) { HexTile3D tile3D = _coordToTile[coord]; - tile3D.Type = HexTile3D.TileType.Undefined; - _unusedTiles.Enqueue(tile3D); - _coordToTile.Remove(coord); - RemovedCoords.Add(coord); + + OnTileDeactivate(tile3D, coord); } } } @@ -178,6 +191,8 @@ public class StreamContainer : Spatial tileTransform.origin.y = _tileWorld.GetHeightAtOffset(coord); tile3D.Transform = tileTransform; + OnTileActivate(tile3D); + _coordToTile[coord] = tile3D; } } @@ -205,10 +220,14 @@ public class StreamContainer : Spatial tileTransform.origin.y = _tileWorld.GetHeightAtOffset(offsetCoords); tile3D.Transform = tileTransform; tile3D.Type = _tileWorld.GetTileTypeAtOffset(offsetCoords); + + _tileToInstanceIndex[tile3D] = _tileToInstanceIndex.Count; _coordToTile[offsetCoords] = tile3D; } + OnTileActivate(_coordToTile[offsetCoords]); + return _coordToTile[offsetCoords]; } @@ -231,6 +250,26 @@ public class StreamContainer : Spatial } } + public void OnTileActivate(HexTile3D tile3D) + { + int instanceIndex = _tileToInstanceIndex[tile3D]; + + Transform instanceTransform = new Transform(tile3D.GlobalTransform.basis.Rotated(Vector3.Up, Mathf.Deg2Rad(30)), tile3D.GlobalTransform.origin + Vector3.Up * -2.5f); + + _tileMultiMesh.Multimesh.SetInstanceTransform(instanceIndex, instanceTransform); + } + + public void OnTileDeactivate(HexTile3D tile3D, Vector2 coord) + { + int instanceIndex = _tileToInstanceIndex[tile3D]; + _tileMultiMesh.Multimesh.SetInstanceTransform(instanceIndex, _deactivatedTileTransform); + + tile3D.Type = HexTile3D.TileType.Undefined; + _unusedTiles.Enqueue(tile3D); + _coordToTile.Remove(coord); + RemovedCoords.Add(coord); + } + public void OnTileClicked(HexTile3D tile) { EmitSignal("TileClicked", tile); @@ -254,6 +293,8 @@ public class StreamContainer : Spatial Transform tileTransform = tile.GlobalTransform; tileTransform.origin.y = _tileWorld.GetHeightAtOffset(tile.OffsetCoords); tile.GlobalTransform = tileTransform; + + OnTileActivate(tile); } } } \ No newline at end of file diff --git a/scenes/StreamContainer.tscn b/scenes/StreamContainer.tscn index 7fee255..754bfcd 100644 --- a/scenes/StreamContainer.tscn +++ b/scenes/StreamContainer.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://scenes/StreamContainer.cs" type="Script" id=1] +[ext_resource path="res://assets/Environment/HexTileMesh.tres" type="CylinderMesh" id=2] [sub_resource type="CubeMesh" id=1] size = Vector3( 1, 1, 1 ) @@ -12,6 +13,11 @@ albedo_color = Color( 1, 1, 1, 0.156863 ) [sub_resource type="BoxShape" id=9] extents = Vector3( 20, 1, 20 ) +[sub_resource type="MultiMesh" id=10] +color_format = 2 +transform_format = 1 +mesh = ExtResource( 2 ) + [node name="StreamContainer" type="Spatial"] transform = Transform( 1, 0, 0, 0, 1, 2.98023e-08, 0, -2.98023e-08, 1, 0, 0, -4.76837e-07 ) script = ExtResource( 1 ) @@ -32,3 +38,6 @@ material/0 = SubResource( 2 ) [node name="CollisionShape" type="CollisionShape" parent="Area"] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 ) shape = SubResource( 9 ) + +[node name="TileMultiMesh" type="MultiMeshInstance" parent="."] +multimesh = SubResource( 10 )