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 | |
| parent | 6ed978051668c08f5a957c97570f364dd580c807 (diff) | |
| download | meowcraft-20c53c7473fc6cc08944f502f078dfe57bcae1c9.tar.zst meowcraft-20c53c7473fc6cc08944f502f078dfe57bcae1c9.zip | |
Broken infinite world
Diffstat (limited to 'src')
| -rw-r--r-- | src/GFX/Image/PPMParser.cpp | 2 | ||||
| -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 | ||||
| -rw-r--r-- | src/main.cpp | 24 |
9 files changed, 161 insertions, 19 deletions
diff --git a/src/GFX/Image/PPMParser.cpp b/src/GFX/Image/PPMParser.cpp index 7fc2359..b809ef1 100644 --- a/src/GFX/Image/PPMParser.cpp +++ b/src/GFX/Image/PPMParser.cpp @@ -1,5 +1,5 @@ #include <cctype> -#include <string> +#include <stdexcept> #include "PPMParser.hpp" namespace MC::GFX::Image { 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; +}; + +} diff --git a/src/main.cpp b/src/main.cpp index 3a8b55d..960112e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,6 @@ #include <iostream> #include <GL/glew.h> #include <GLFW/glfw3.h> -#include <cstdint> #include "GFX/Window.hpp" #include "GFX/Camera.hpp" @@ -10,7 +9,7 @@ #include "GFX/Shading/Program.hpp" #include "GFX/Texture.hpp" #include "GFX/Image/PPMParser.hpp" -#include "World/Generator.hpp" +#include "World/World.hpp" #define APP_NAME "Meowcraft" @@ -18,7 +17,7 @@ #define WINDOW_HEIGHT 800 #define ASPECT static_cast<float>(WINDOW_WIDTH) / WINDOW_HEIGHT -#define FOV 45 +#define FOV 90 void run(); void render(MC::GFX::BindableMesh&, MC::GFX::Texture&); @@ -53,11 +52,7 @@ void run() { auto image = MC::GFX::Image::PPMParser(MC::Assets::Images::atlas).parse(); auto texture = MC::GFX::Texture(image); - MC::World::Generator generator; - auto chunk = generator.generate(0, 0); - auto chunk_mesh = chunk.mesh(); - - auto mesh = MC::GFX::Binder::load(chunk_mesh); + MC::World::World world; MC::GFX::Camera camera{}; camera.set_position({0.0f, 0.0f, 3.0f}); @@ -72,7 +67,7 @@ void run() { auto projection_uniform = program.uniform("projection_matrix"); program.bind(); - auto projection = Math::MVP::projection(ASPECT, FOV, 0.1f, 100.0f); + auto projection = Math::MVP::projection(ASPECT, FOV, 0.1f, 1000.0f); projection_uniform.set(projection); glEnable(GL_DEPTH_TEST); @@ -94,13 +89,14 @@ void run() { program.bind(); - auto model = Math::MVP::model({}, {}); - model_uniform.set(model); - auto view = Math::MVP::view(camera.position(), camera.angles()); view_uniform.set(view); - render(mesh, texture); + for (auto& chunk : world.get_visible_chunks(camera.position())) { + auto model = Math::MVP::model(chunk.chunk->position(), {}); + model_uniform.set(model); + render(chunk.mesh.value(), texture); + } time++; } } @@ -129,7 +125,7 @@ void process_input(MC::GFX::Window& window, MC::GFX::Camera& camera) { float y = key(GLFW_KEY_SPACE) - key(GLFW_KEY_LEFT_SHIFT); float z = key(GLFW_KEY_S) - key(GLFW_KEY_W); - auto move_speed = 0.05f; + auto move_speed = 0.5f; auto rotation_speed = 0.1f; camera.move_relative({x * move_speed, y * move_speed, z * move_speed}); |
