summary refs log tree commit diff
path: root/src/World/Chunk.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World/Chunk.hpp')
-rw-r--r--src/World/Chunk.hpp30
1 files changed, 26 insertions, 4 deletions
diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp
index bab20f2..e958b9a 100644
--- a/src/World/Chunk.hpp
+++ b/src/World/Chunk.hpp
@@ -7,6 +7,7 @@
 #include "BlockType.hpp"
 #include "ChunkIndex.hpp"
 #include "Position.hpp"
+#include "../Common/Iteration.hpp"
 #include "../GFX/Mesh.hpp"
 
 namespace MC::World {
@@ -16,6 +17,8 @@ public:
     static constexpr U32 Width = ChunkDimensions::Width;
     static constexpr U32 Height = ChunkDimensions::Height;
 
+    static constexpr U32 BlockCount = Width * Height * Width;
+
     Chunk(I64 x, I64 y)
         : m_blocks{Width * Height * Width, {BlockType::Air}},
         m_index(x, y),
@@ -48,16 +51,32 @@ public:
     void set_details(const Details& details) { m_details = details; }
     Details& details(){ return m_details; }
 
+    // Cache-friendly iteration through all blocks in the chunk.
     template <typename F>
     void for_each(F f) {
+        for (U32 i = 0; i < BlockCount; ++i) {
+            Iteration control = f(pos(i), m_blocks[i]);
+            if (control == Iteration::Break) break;
+        }
+    }
+
+    // Iteration through all blocks in the chunk by column.
+    // Starts from the top of the chunk and goes down.
+    enum class ColumnIteration { Continue, Break, SkipColumn };
+    template <typename F>
+    void for_each_by_column(F f) {
+        // TODO: Maybe add a way to lookup the highest block in a column
+        // to skip all the air?
         for (U32 x = 0; x < Width; ++x) {
-            for (U32 y = 0; y < Height; ++y) {
-                for (U32 z = 0; z < Width; ++z) {
-                    Position::BlockLocal pos{x, y, z};
-                    f(pos, at(x, y, z));
+            for (U32 z = 0; z < Width; ++z) {
+                for (UInt y = Height - 1; y != 0; y--) {
+                    ColumnIteration control = f({x, y, z}, m_blocks.at(pos(x, y, z)));
+                    if (control == ColumnIteration::Break) goto end;
+                    if (control == ColumnIteration::SkipColumn) break;
                 }
             }
         }
+        end: return;
     }
 
     ChunkIndex index() const;
@@ -70,7 +89,10 @@ public:
     static AABB block_bounds(Position::BlockLocal pos);
     static AABB block_bounds(Position::BlockWorld pos);
 private:
+    // Convert a local position to a chunk block index.
     static U64 pos(U32 x, U32 y, U32 z);
+    // Convert a chunk block index to a local position.
+    static Position::BlockLocal pos(U64 i);
 
     ChunkIndex m_index;
     Vector<3> m_position;