From 1491de220ea825f4f40c0d3694cff9f791e36dde Mon Sep 17 00:00:00 2001 From: Octal Date: Fri, 29 Dec 2023 17:25:53 -0600 Subject: [PATCH 1/2] Untested floodfill algorithm --- .../Occlusion/ChunkOcclusionBitSet.cs | 42 +++++++++++++++++++ Client/World/ClientChunk.cs | 3 +- Common/World/Chunk.cs | 34 +++++++++++++++ Core/Game.cs | 2 +- 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 Client/Rendering/Occlusion/ChunkOcclusionBitSet.cs diff --git a/Client/Rendering/Occlusion/ChunkOcclusionBitSet.cs b/Client/Rendering/Occlusion/ChunkOcclusionBitSet.cs new file mode 100644 index 0000000..2d45409 --- /dev/null +++ b/Client/Rendering/Occlusion/ChunkOcclusionBitSet.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Voxel.Client.Rendering.Occlusion; + +/** + * Determines which sides are visible from others in a chunk + * Ex: UpDown means there is a visible pathway from the up face to the down face. + */ +[Flags] +public enum ChunkOcclusionBitSet : ushort { + UpDown = 0b0000000000000001, + UpNorth = 0b0000000000000010, + UpSouth = 0b0000000000000100, + UpEast = 0b0000000000001000, + UpWest = 0b0000000000010000, + DownNorth = 0b0000000000100000, + DownSouth = 0b0000000001000000, + DownEast = 0b0000000010000000, + DownWest = 0b0000000100000000, + NorthSouth = 0b0000001000000000, + NorthEast = 0b0000010000000000, + NorthWest = 0b0000100000000000, + SouthEast = 0b0001000000000000, + SouthWest = 0b0010000000000000, + EastWest = 0b0100000000000000, + + Up = 0b0000000000011111, + Down = 0b0000000111100001, + North = 0b0000111000100010, + South = 0b0011001001000100, + East = 0b0101010010001000, + West = 0b0110100100010000, + + All = 0b0111111111111111, +} + +public static class ChunkOcclusionBitSetExtension { + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static bool Test(this ChunkOcclusionBitSet set, ChunkOcclusionBitSet direction) + => (set ^ direction) == 0; +} diff --git a/Client/World/ClientChunk.cs b/Client/World/ClientChunk.cs index e3d0d31..f4e06dd 100644 --- a/Client/World/ClientChunk.cs +++ b/Client/World/ClientChunk.cs @@ -9,7 +9,8 @@ public class ClientChunk : Chunk { public bool isFilled; public ClientChunk(ivec3 chunkPosition, VoxelWorld world, ChunkStorage? storage = null) : base(chunkPosition, world, storage) { - + if (storage != null) + isFilled = true; } public override void SetStorage(ChunkStorage newStorage) { diff --git a/Common/World/Chunk.cs b/Common/World/Chunk.cs index 791be0f..40827bc 100644 --- a/Common/World/Chunk.cs +++ b/Common/World/Chunk.cs @@ -58,6 +58,40 @@ public uint GetVersion() public void IncrementVersion() { Interlocked.Increment(ref _version); } + + // I don't know if this is the best place to put this.. + public HashSet FloodFill(ivec3 root) { + var connected = new HashSet(); + + var queue = new Stack(); + queue.Push(root.Loop(PositionExtensions.ChunkSize)); + while (queue.Count > 0) { + var node = queue.Pop(); + + if (!GetBlock(node).IsAir) + continue; + + connected.Add(node); + + for (int i = 0; i < 3; i++) { + if (node[i] > 0) { + var newNode = node; + newNode[i] -= 1; + if (!connected.Contains(newNode)) + queue.Push(newNode); + } + if (node[i] < PositionExtensions.ChunkSize) { + var newNode = node; + newNode[i] += 1; + queue.Push(newNode); + if (!connected.Contains(newNode)) + queue.Push(newNode); + } + } + } + + return connected; + } internal void IncrementViewCount() { viewCount++; diff --git a/Core/Game.cs b/Core/Game.cs index 1b72edf..cea98b2 100644 --- a/Core/Game.cs +++ b/Core/Game.cs @@ -37,7 +37,7 @@ public void Run(int tps = 20, string windowTitle = "Game") { var gdo = new GraphicsDeviceOptions { PreferDepthRangeZeroToOne = true, PreferStandardClipSpaceYDirection = true, - SyncToVerticalBlank = true, + SyncToVerticalBlank = false, }; VeldridStartup.CreateWindowAndGraphicsDevice(wci, gdo, GraphicsBackend.Vulkan, out var nw, out var gd); From 74a799b7d7f874a2344213d2475ae27621102563 Mon Sep 17 00:00:00 2001 From: Octal Date: Fri, 29 Dec 2023 17:32:52 -0600 Subject: [PATCH 2/2] Explicitly check for SingleStorage in floodfill algorithm --- Client/Rendering/World/ChunkMeshBuilder.cs | 8 ++++---- Common/Tile/Block.cs | 3 ++- Common/World/Chunk.cs | 7 +++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Client/Rendering/World/ChunkMeshBuilder.cs b/Client/Rendering/World/ChunkMeshBuilder.cs index a593bec..5e45420 100644 --- a/Client/Rendering/World/ChunkMeshBuilder.cs +++ b/Client/Rendering/World/ChunkMeshBuilder.cs @@ -325,10 +325,10 @@ float calculateAO(float s1, float corner, float s2) { AO = vec4.Zero; //if (face <= 1) { - AO[0] = calculateAO(faceBlocks[1].Settings.GetSolidityFloat, faceBlocks[2].Settings.GetSolidityFloat, faceBlocks[3].Settings.GetSolidityFloat); - AO[1] = calculateAO(faceBlocks[3].Settings.GetSolidityFloat, faceBlocks[4].Settings.GetSolidityFloat, faceBlocks[5].Settings.GetSolidityFloat); - AO[2] = calculateAO(faceBlocks[5].Settings.GetSolidityFloat, faceBlocks[6].Settings.GetSolidityFloat, faceBlocks[7].Settings.GetSolidityFloat); - AO[3] = calculateAO(faceBlocks[7].Settings.GetSolidityFloat, faceBlocks[8].Settings.GetSolidityFloat, faceBlocks[1].Settings.GetSolidityFloat); + AO[0] = calculateAO(faceBlocks[1].Settings.Solidity, faceBlocks[2].Settings.Solidity, faceBlocks[3].Settings.Solidity); + AO[1] = calculateAO(faceBlocks[3].Settings.Solidity, faceBlocks[4].Settings.Solidity, faceBlocks[5].Settings.Solidity); + AO[2] = calculateAO(faceBlocks[5].Settings.Solidity, faceBlocks[6].Settings.Solidity, faceBlocks[7].Settings.Solidity); + AO[3] = calculateAO(faceBlocks[7].Settings.Solidity, faceBlocks[8].Settings.Solidity, faceBlocks[1].Settings.Solidity); //} diff --git a/Common/Tile/Block.cs b/Common/Tile/Block.cs index 1ebc346..93774a2 100644 --- a/Common/Tile/Block.cs +++ b/Common/Tile/Block.cs @@ -6,6 +6,7 @@ public class Block { public readonly BlockSettings Settings; public bool IsAir => Settings.IsAir; + public float Solidity => Settings.Solidity; public Block(string name, BlockSettings settings) { Name = name; @@ -24,7 +25,7 @@ public class BlockSettings { public static readonly BlockSettings Default = new Builder().Build(); public readonly bool IsAir; - public float GetSolidityFloat => IsAir ? 0 : 1; + public float Solidity => IsAir ? 0 : 1; private BlockSettings(bool isAir) { IsAir = isAir; diff --git a/Common/World/Chunk.cs b/Common/World/Chunk.cs index 40827bc..f382b1a 100644 --- a/Common/World/Chunk.cs +++ b/Common/World/Chunk.cs @@ -62,6 +62,13 @@ public void IncrementVersion() { // I don't know if this is the best place to put this.. public HashSet FloodFill(ivec3 root) { var connected = new HashSet(); + + if (storage is SingleStorage singleStorage) { + if (singleStorage.Block.IsAir) + foreach (var pos in Iteration.Cubic(0, PositionExtensions.ChunkSize)) + connected.Add(pos); + return connected; + } var queue = new Stack(); queue.Push(root.Loop(PositionExtensions.ChunkSize));