From 5585b67a272704e136abe830c336603098914415 Mon Sep 17 00:00:00 2001 From: tylermurphy534 Date: Fri, 30 Sep 2022 15:40:42 -0400 Subject: [PATCH] finalize greedy meshing --- engine/xe_model.cpp | 1 + src/chunk.cpp | 60 +++++++++++++++++++++++++++-------------- src/chunk.hpp | 12 ++++++--- src/first_app.cpp | 7 +++-- src/first_app.hpp | 2 +- src/simple_renderer.cpp | 1 + 6 files changed, 56 insertions(+), 27 deletions(-) diff --git a/engine/xe_model.cpp b/engine/xe_model.cpp index 53d0158..5b85932 100644 --- a/engine/xe_model.cpp +++ b/engine/xe_model.cpp @@ -52,6 +52,7 @@ void Model::deleteModel(Model* model) { } void Model::submitDeleteQueue(bool purge) { + if(DELETION_QUEUE.size() < 1) return; vkDeviceWaitIdle(Engine::getInstance()->xeDevice.device()); for(Model* model: DELETION_QUEUE) { try { delete model; } catch(int err) {}; diff --git a/src/chunk.cpp b/src/chunk.cpp index 3542455..21910ac 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -12,11 +12,13 @@ Chunk::Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed) gridX{gridX}, gridZ{gridZ} { chunkMesh = nullptr; + worker = nullptr; + generated = false; + reload = false; + finished = false; } Chunk::~Chunk() { - if(worker.joinable()) - worker.join(); xe::Model::deleteModel(chunkMesh); vertexData.data.clear(); cubes.clear(); @@ -99,11 +101,15 @@ void Chunk::unload() { void Chunk::createMeshAsync(Chunk* c) { if(c == nullptr) return; - if(c->working) return; - c->working = true; - if(c->worker.joinable()) - c->worker.join(); - c->worker = std::thread(createMesh, c); + if(!isGenerated(c->gridX-1, c->gridZ) || + !isGenerated(c->gridX+1, c->gridZ) || + !isGenerated(c->gridX, c->gridZ-1) || + !isGenerated(c->gridX, c->gridZ+1)) { + return; + } + if(c->worker != nullptr && c->finished == false) return; + c->resetThread(); + c->worker = new std::thread(createMesh, c); } struct FMask { @@ -134,6 +140,8 @@ void CreateQuad(xe::Model::Data& data, FMask Mask, glm::vec3 AxisMask, glm::vec3 const auto Normal = glm::vec3(AxisMask) * glm::vec3(Mask.normal); std::vector verticies = {V1, V2, V3, V4}; + if(Mask.block == AIR || Mask.block == INVALID) return; + float uv[4][2]; if(AxisMask.x == 1) { @@ -163,9 +171,10 @@ void Chunk::createMesh(Chunk* c) { !isGenerated(c->gridX+1, c->gridZ) || !isGenerated(c->gridX, c->gridZ-1) || !isGenerated(c->gridX, c->gridZ+1)) { - c->working = false; + c->finished = true; return; } + c->vertexData.data.clear(); for (int Axis = 0; Axis < 3; ++Axis) { const int Axis1 = (Axis + 1) % 3; @@ -194,8 +203,8 @@ void Chunk::createMesh(Chunk* c) { const auto CurrentBlock = c->getBlock(ChunkItr[0], ChunkItr[1], ChunkItr[2]); const auto CompareBlock = c->getBlock(ChunkItr[0] + AxisMask[0], ChunkItr[1] + AxisMask[1] , ChunkItr[2] + AxisMask[2]); - const bool CurrentBlockOpaque = CurrentBlock != AIR; - const bool CompareBlockOpaque = CompareBlock != AIR; + const bool CurrentBlockOpaque = CurrentBlock != AIR && CurrentBlock != INVALID; + const bool CompareBlockOpaque = CompareBlock != AIR && CompareBlock != INVALID; if (CurrentBlockOpaque == CompareBlockOpaque) { Mask[N++] = FMask { INVALID, 0 }; @@ -272,7 +281,7 @@ void Chunk::createMesh(Chunk* c) { } c->reload = true; - c->working = false; + c->finished = false; } // @@ -281,11 +290,9 @@ void Chunk::createMesh(Chunk* c) { void Chunk::generateAsync(Chunk* c) { if(c == nullptr) return; - if(c->working) return; - c->working = true; - if(c->worker.joinable()) - c->worker.join(); - c->worker = std::thread(generate, c); + if(c->worker != nullptr && c->finished == false) return; + c->resetThread(); + c->worker = new std::thread(generate, c); } void Chunk::generate(Chunk* c) { @@ -321,7 +328,7 @@ void Chunk::generate(Chunk* c) { } c->generated = true; - c->working = false; + c->finished = true; } // @@ -334,8 +341,7 @@ xe::Model* Chunk::getMesh() { xe::Model::deleteModel(chunkMesh); chunkMesh = nullptr; } - if(worker.joinable()) - worker.join(); + resetThread(); xe::Model::Builder builder{}; builder.vertexData = vertexData; builder.vertexSize = 36; @@ -347,7 +353,7 @@ xe::Model* Chunk::getMesh() { } uint8_t Chunk::getBlock(int32_t x, int32_t y, int32_t z) { - if(y > 256) return AIR; + if(y >= 256) return AIR; if(y < 0) return INVALID; int chunkX = gridX; int chunkZ = gridZ; @@ -388,4 +394,18 @@ bool Chunk::isGenerated(int32_t gridX, int32_t gridZ) { return chunk->generated; } +bool Chunk::isMeshed(int32_t gridX, int32_t gridZ) { + Chunk* chunk = Chunk::getChunk(gridX, gridZ); + if(chunk == nullptr) return false; + return chunk->chunkMesh != nullptr; +} + +void Chunk::resetThread() { + if(worker != nullptr && worker->joinable()) { + worker->join(); + finished = false; + delete worker; + } +} + } \ No newline at end of file diff --git a/src/chunk.hpp b/src/chunk.hpp index 59df514..33cab10 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #define INVALID -1 #define AIR 0 @@ -68,6 +69,7 @@ class Chunk { void setBlock(int32_t x, int32_t y, int32_t z, uint8_t block); static bool isGenerated(int32_t gridX, int32_t gridZ); + static bool isMeshed(int32_t gridX, int32_t gridZ); const int32_t gridX, gridZ; const uint32_t world_seed, chunk_seed; @@ -77,14 +79,16 @@ class Chunk { Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed); ~Chunk(); - bool generated{false}; - bool reload{false}; - bool working{false}; + void resetThread(); + + bool generated; + bool reload; + bool finished; xe::Model* chunkMesh; xe::Model::Data vertexData; std::vector cubes{}; - std::thread worker; + std::thread* worker; }; diff --git a/src/first_app.cpp b/src/first_app.cpp index 619a810..eb24587 100755 --- a/src/first_app.cpp +++ b/src/first_app.cpp @@ -1,5 +1,8 @@ #include "first_app.hpp" +#include +using namespace std::chrono; + namespace app { FirstApp::FirstApp() : xeEngine{WIDTH, HEIGHT, "Minecraft Vulkan", "res/image/icon.png"} {}; @@ -35,7 +38,7 @@ void FirstApp::run() { renderer.render(loadedChunks, xeEngine.getCamera()); xeEngine.endFrame(); } - + reloadLoadedChunks(viewerObject); } @@ -78,7 +81,7 @@ void FirstApp::reloadLoadedChunks(xe::GameObject& viewer) { Chunk* chunk = Chunk::getChunk(newGridX, newGridZ); if(chunk == nullptr) { chunk = Chunk::newChunk(newGridX, newGridZ, 12345); - Chunk::generate(chunk); + Chunk::generateAsync(chunk); } if(chunk->getMesh() == nullptr){ Chunk::createMeshAsync(chunk); diff --git a/src/first_app.hpp b/src/first_app.hpp index 59cf3df..d361296 100755 --- a/src/first_app.hpp +++ b/src/first_app.hpp @@ -32,7 +32,7 @@ class FirstApp { static constexpr int WIDTH = 800; static constexpr int HEIGHT = 600; - static constexpr int RENDER_DISTANCE = 45; + static constexpr int RENDER_DISTANCE = 10; void createGameObjects(xe::GameObject& viewer); void reloadLoadedChunks(xe::GameObject& viewer); diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp index d13e7ac..9e30fb7 100644 --- a/src/simple_renderer.cpp +++ b/src/simple_renderer.cpp @@ -26,6 +26,7 @@ void SimpleRenderer::render(std::vector &gameObjects, xe::Camera xeRenderSystem->loadUniformObject(0, &ubo); for(auto &obj : gameObjects) { + if(obj.model == nullptr) continue; PushConstant pc{}; pc.modelMatrix = obj.transform.mat4(); pc.normalMatrix = obj.transform.normalMatrix();