diff options
| author | Mel <einebeere@gmail.com> | 2022-10-21 17:46:35 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-10-21 17:46:35 +0200 |
| commit | 20c53c7473fc6cc08944f502f078dfe57bcae1c9 (patch) | |
| tree | 7e6b09cea68251d4564a363c1a372d6daf746dcf /src/World | |
| parent | 6ed978051668c08f5a957c97570f364dd580c807 (diff) | |
| download | meowcraft-20c53c7473fc6cc08944f502f078dfe57bcae1c9.tar.zst meowcraft-20c53c7473fc6cc08944f502f078dfe57bcae1c9.zip | |
Broken infinite world
Diffstat (limited to 'src/World')
| -rw-r--r-- | src/World/Chunk.cpp | 4 | ||||
| -rw-r--r-- | src/World/Chunk.hpp | 6 | ||||
| -rw-r--r-- | src/World/ChunkIndex.hpp | 33 | ||||
| -rw-r--r-- | src/World/Generator.cpp | 4 | ||||
| -rw-r--r-- | src/World/Generator.hpp | 2 | ||||
| -rw-r--r-- | src/World/World.cpp | 67 | ||||
| -rw-r--r-- | src/World/World.hpp | 38 |
7 files changed, 150 insertions, 4 deletions
diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp index 0d86ddb..d02e5e5 100644 --- a/src/World/Chunk.cpp +++ b/src/World/Chunk.cpp @@ -45,6 +45,10 @@ GFX::Mesh Chunk::mesh() { return {positions, tex_coords, indices}; } +Vector<3> Chunk::position() { + return m_position; +} + bool Chunk::is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side) { Vector<3, int32_t> offset{}; switch (side) { diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp index 7a93f5a..797a757 100644 --- a/src/World/Chunk.hpp +++ b/src/World/Chunk.hpp @@ -14,9 +14,12 @@ namespace MC::World { class Chunk { public: - Chunk() : m_blocks{} {}; + Chunk(int64_t x, int64_t y) + : m_blocks{}, m_position{(float)x * CHUNK_WIDTH, 0.0f, (float)y * CHUNK_WIDTH} {}; void set(uint32_t x, uint32_t y, uint32_t z, BlockType type); + + Vector<3> position(); GFX::Mesh mesh(); private: bool is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side); @@ -27,6 +30,7 @@ private: BlockType type; }; + Vector<3> m_position; BlockData m_blocks[CHUNK_WIDTH][CHUNK_HEIGHT][CHUNK_WIDTH]; }; diff --git a/src/World/ChunkIndex.hpp b/src/World/ChunkIndex.hpp new file mode 100644 index 0000000..330d202 --- /dev/null +++ b/src/World/ChunkIndex.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include <cstdint> +#include <cstdlib> +#include <functional> + +namespace MC::World { + +struct ChunkIndex { + ChunkIndex(int64_t x, int64_t y) : x(x), y(x) {} + + bool operator==(ChunkIndex& other) const { + return x == other.x && y == other.y; + } + + int64_t x, y; +}; + +} + +template<> struct std::equal_to<MC::World::ChunkIndex> { + bool operator()(const MC::World::ChunkIndex& i1, const MC::World::ChunkIndex& i2) const noexcept { + return i1.x == i2.x && i1.y == i2.y; + } +}; + +template<> struct std::hash<MC::World::ChunkIndex> { + std::size_t operator()(const MC::World::ChunkIndex& i) const noexcept { + std::size_t xh = std::hash<int64_t>{}(i.x); + std::size_t yh = std::hash<int64_t>{}(i.y); + return xh ^ (yh << 1); + } +}; \ No newline at end of file diff --git a/src/World/Generator.cpp b/src/World/Generator.cpp index d7bb038..757abf2 100644 --- a/src/World/Generator.cpp +++ b/src/World/Generator.cpp @@ -2,8 +2,8 @@ namespace MC::World { -Chunk Generator::generate(uint32_t _x, uint32_t _y) { - Chunk chunk; +Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) { + Chunk chunk(chunk_x, chunk_y); for (int y = 0; y < CHUNK_HEIGHT; y++) { BlockType type = BlockType::Air; diff --git a/src/World/Generator.hpp b/src/World/Generator.hpp index 9ddac66..479089f 100644 --- a/src/World/Generator.hpp +++ b/src/World/Generator.hpp @@ -9,7 +9,7 @@ class Generator { public: Generator() = default; - Chunk generate(uint32_t x, uint32_t y); + Chunk generate(int64_t chunk_x, int64_t chunk_y); }; } diff --git a/src/World/World.cpp b/src/World/World.cpp new file mode 100644 index 0000000..5a0d729 --- /dev/null +++ b/src/World/World.cpp @@ -0,0 +1,67 @@ +#include "World.hpp" + +namespace MC::World { + +std::vector<World::ChunkData> World::get_visible_chunks(Vector<3> position) { + auto visible_chunks = get_visible_chunk_indices(position); + + auto difference = visible_chunks; + for (auto index : m_visible_chunks) { + difference.erase(index); + } + + if (!difference.empty()) { + for (auto new_index: difference) { + auto& data = get_or_generate(new_index); + if (!data.mesh.has_value()) { + auto mesh = data.chunk->mesh(); + data.mesh = GFX::Binder::load(mesh); + } + } + m_visible_chunks = visible_chunks; + } + + std::vector<World::ChunkData> chunks{}; + chunks.reserve(visible_chunks.size()); + for (auto index : visible_chunks) { + chunks.push_back(get_or_generate(index)); + } + + return chunks; +} + +std::unordered_set<ChunkIndex> World::get_visible_chunk_indices(Vector<3> position) const { + int64_t center_x = std::round(position.x() / CHUNK_WIDTH); + int64_t center_y = std::round(position.z() / CHUNK_HEIGHT); + + auto upper_x_bound = center_x + m_view_distance_radius; + auto lower_x_bound = center_x - m_view_distance_radius; + auto upper_y_bound = center_y + m_view_distance_radius; + auto lower_y_bound = center_y - m_view_distance_radius; + + std::unordered_set<ChunkIndex> indices{}; + indices.reserve(m_view_distance_radius * m_view_distance_radius * 4); + for (int64_t x = lower_x_bound; x < upper_x_bound; x++) { + for (int64_t y = lower_y_bound; y < upper_y_bound; y++) { + indices.emplace(x, y); + } + } + + return indices; +} + +World::ChunkData& World::get_or_generate(ChunkIndex index) { + auto entry = m_chunks.find(index); + if (entry == m_chunks.end()) { + auto chunk = m_generator.generate(index.x, index.y); + ChunkData data{index, std::make_shared<Chunk>(chunk)}; + + m_chunks.insert({index, data}); + return m_chunks.at(index); + } + + return entry->second; +} + + +} \ No newline at end of file diff --git a/src/World/World.hpp b/src/World/World.hpp new file mode 100644 index 0000000..3453b18 --- /dev/null +++ b/src/World/World.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include <memory> +#include <unordered_set> +#include <utility> +#include "Generator.hpp" +#include "ChunkIndex.hpp" + +namespace MC::World { + +class World { +public: + World() : m_generator(), m_chunks(), m_visible_chunks() {} + + struct ChunkData { + ChunkData(ChunkIndex index, std::shared_ptr<Chunk> chunk) + : index(index), chunk(std::move(chunk)), mesh() {} + + ChunkIndex index; + std::shared_ptr<Chunk> chunk; + std::optional<GFX::BindableMesh> mesh; + }; + + std::vector<ChunkData> get_visible_chunks(Vector<3> position); + +private: + std::unordered_set<ChunkIndex> get_visible_chunk_indices(Vector<3> position) const; + ChunkData& get_or_generate(ChunkIndex index); + + uint8_t m_view_distance_radius = 6; + + Generator m_generator; + + std::unordered_map<ChunkIndex, ChunkData> m_chunks; + std::unordered_set<ChunkIndex> m_visible_chunks; +}; + +} |
