finalize greedy meshing

This commit is contained in:
tylermurphy534 2022-09-30 15:40:42 -04:00
parent 795dce1272
commit 5585b67a27
6 changed files with 56 additions and 27 deletions

View file

@ -52,6 +52,7 @@ void Model::deleteModel(Model* model) {
} }
void Model::submitDeleteQueue(bool purge) { void Model::submitDeleteQueue(bool purge) {
if(DELETION_QUEUE.size() < 1) return;
vkDeviceWaitIdle(Engine::getInstance()->xeDevice.device()); vkDeviceWaitIdle(Engine::getInstance()->xeDevice.device());
for(Model* model: DELETION_QUEUE) { for(Model* model: DELETION_QUEUE) {
try { delete model; } catch(int err) {}; try { delete model; } catch(int err) {};

View file

@ -12,11 +12,13 @@ Chunk::Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed)
gridX{gridX}, gridX{gridX},
gridZ{gridZ} { gridZ{gridZ} {
chunkMesh = nullptr; chunkMesh = nullptr;
worker = nullptr;
generated = false;
reload = false;
finished = false;
} }
Chunk::~Chunk() { Chunk::~Chunk() {
if(worker.joinable())
worker.join();
xe::Model::deleteModel(chunkMesh); xe::Model::deleteModel(chunkMesh);
vertexData.data.clear(); vertexData.data.clear();
cubes.clear(); cubes.clear();
@ -99,11 +101,15 @@ void Chunk::unload() {
void Chunk::createMeshAsync(Chunk* c) { void Chunk::createMeshAsync(Chunk* c) {
if(c == nullptr) return; if(c == nullptr) return;
if(c->working) return; if(!isGenerated(c->gridX-1, c->gridZ) ||
c->working = true; !isGenerated(c->gridX+1, c->gridZ) ||
if(c->worker.joinable()) !isGenerated(c->gridX, c->gridZ-1) ||
c->worker.join(); !isGenerated(c->gridX, c->gridZ+1)) {
c->worker = std::thread(createMesh, c); return;
}
if(c->worker != nullptr && c->finished == false) return;
c->resetThread();
c->worker = new std::thread(createMesh, c);
} }
struct FMask { 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); const auto Normal = glm::vec3(AxisMask) * glm::vec3(Mask.normal);
std::vector<glm::vec3> verticies = {V1, V2, V3, V4}; std::vector<glm::vec3> verticies = {V1, V2, V3, V4};
if(Mask.block == AIR || Mask.block == INVALID) return;
float uv[4][2]; float uv[4][2];
if(AxisMask.x == 1) { if(AxisMask.x == 1) {
@ -163,9 +171,10 @@ void Chunk::createMesh(Chunk* c) {
!isGenerated(c->gridX+1, c->gridZ) || !isGenerated(c->gridX+1, c->gridZ) ||
!isGenerated(c->gridX, c->gridZ-1) || !isGenerated(c->gridX, c->gridZ-1) ||
!isGenerated(c->gridX, c->gridZ+1)) { !isGenerated(c->gridX, c->gridZ+1)) {
c->working = false; c->finished = true;
return; return;
} }
c->vertexData.data.clear(); c->vertexData.data.clear();
for (int Axis = 0; Axis < 3; ++Axis) { for (int Axis = 0; Axis < 3; ++Axis) {
const int Axis1 = (Axis + 1) % 3; 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 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 auto CompareBlock = c->getBlock(ChunkItr[0] + AxisMask[0], ChunkItr[1] + AxisMask[1] , ChunkItr[2] + AxisMask[2]);
const bool CurrentBlockOpaque = CurrentBlock != AIR; const bool CurrentBlockOpaque = CurrentBlock != AIR && CurrentBlock != INVALID;
const bool CompareBlockOpaque = CompareBlock != AIR; const bool CompareBlockOpaque = CompareBlock != AIR && CompareBlock != INVALID;
if (CurrentBlockOpaque == CompareBlockOpaque) { if (CurrentBlockOpaque == CompareBlockOpaque) {
Mask[N++] = FMask { INVALID, 0 }; Mask[N++] = FMask { INVALID, 0 };
@ -272,7 +281,7 @@ void Chunk::createMesh(Chunk* c) {
} }
c->reload = true; c->reload = true;
c->working = false; c->finished = false;
} }
// //
@ -281,11 +290,9 @@ void Chunk::createMesh(Chunk* c) {
void Chunk::generateAsync(Chunk* c) { void Chunk::generateAsync(Chunk* c) {
if(c == nullptr) return; if(c == nullptr) return;
if(c->working) return; if(c->worker != nullptr && c->finished == false) return;
c->working = true; c->resetThread();
if(c->worker.joinable()) c->worker = new std::thread(generate, c);
c->worker.join();
c->worker = std::thread(generate, c);
} }
void Chunk::generate(Chunk* c) { void Chunk::generate(Chunk* c) {
@ -321,7 +328,7 @@ void Chunk::generate(Chunk* c) {
} }
c->generated = true; c->generated = true;
c->working = false; c->finished = true;
} }
// //
@ -334,8 +341,7 @@ xe::Model* Chunk::getMesh() {
xe::Model::deleteModel(chunkMesh); xe::Model::deleteModel(chunkMesh);
chunkMesh = nullptr; chunkMesh = nullptr;
} }
if(worker.joinable()) resetThread();
worker.join();
xe::Model::Builder builder{}; xe::Model::Builder builder{};
builder.vertexData = vertexData; builder.vertexData = vertexData;
builder.vertexSize = 36; builder.vertexSize = 36;
@ -347,7 +353,7 @@ xe::Model* Chunk::getMesh() {
} }
uint8_t Chunk::getBlock(int32_t x, int32_t y, int32_t z) { 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; if(y < 0) return INVALID;
int chunkX = gridX; int chunkX = gridX;
int chunkZ = gridZ; int chunkZ = gridZ;
@ -388,4 +394,18 @@ bool Chunk::isGenerated(int32_t gridX, int32_t gridZ) {
return chunk->generated; 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;
}
}
} }

View file

@ -14,6 +14,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <cstdlib>
#define INVALID -1 #define INVALID -1
#define AIR 0 #define AIR 0
@ -68,6 +69,7 @@ class Chunk {
void setBlock(int32_t x, int32_t y, int32_t z, uint8_t block); 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 isGenerated(int32_t gridX, int32_t gridZ);
static bool isMeshed(int32_t gridX, int32_t gridZ);
const int32_t gridX, gridZ; const int32_t gridX, gridZ;
const uint32_t world_seed, chunk_seed; 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(int32_t gridX, int32_t gridZ, uint32_t world_seed);
~Chunk(); ~Chunk();
bool generated{false}; void resetThread();
bool reload{false};
bool working{false}; bool generated;
bool reload;
bool finished;
xe::Model* chunkMesh; xe::Model* chunkMesh;
xe::Model::Data vertexData; xe::Model::Data vertexData;
std::vector<uint8_t> cubes{}; std::vector<uint8_t> cubes{};
std::thread worker; std::thread* worker;
}; };

View file

@ -1,5 +1,8 @@
#include "first_app.hpp" #include "first_app.hpp"
#include <chrono>
using namespace std::chrono;
namespace app { namespace app {
FirstApp::FirstApp() : xeEngine{WIDTH, HEIGHT, "Minecraft Vulkan", "res/image/icon.png"} {}; FirstApp::FirstApp() : xeEngine{WIDTH, HEIGHT, "Minecraft Vulkan", "res/image/icon.png"} {};
@ -78,7 +81,7 @@ void FirstApp::reloadLoadedChunks(xe::GameObject& viewer) {
Chunk* chunk = Chunk::getChunk(newGridX, newGridZ); Chunk* chunk = Chunk::getChunk(newGridX, newGridZ);
if(chunk == nullptr) { if(chunk == nullptr) {
chunk = Chunk::newChunk(newGridX, newGridZ, 12345); chunk = Chunk::newChunk(newGridX, newGridZ, 12345);
Chunk::generate(chunk); Chunk::generateAsync(chunk);
} }
if(chunk->getMesh() == nullptr){ if(chunk->getMesh() == nullptr){
Chunk::createMeshAsync(chunk); Chunk::createMeshAsync(chunk);

View file

@ -32,7 +32,7 @@ class FirstApp {
static constexpr int WIDTH = 800; static constexpr int WIDTH = 800;
static constexpr int HEIGHT = 600; static constexpr int HEIGHT = 600;
static constexpr int RENDER_DISTANCE = 45; static constexpr int RENDER_DISTANCE = 10;
void createGameObjects(xe::GameObject& viewer); void createGameObjects(xe::GameObject& viewer);
void reloadLoadedChunks(xe::GameObject& viewer); void reloadLoadedChunks(xe::GameObject& viewer);

View file

@ -26,6 +26,7 @@ void SimpleRenderer::render(std::vector<xe::GameObject> &gameObjects, xe::Camera
xeRenderSystem->loadUniformObject(0, &ubo); xeRenderSystem->loadUniformObject(0, &ubo);
for(auto &obj : gameObjects) { for(auto &obj : gameObjects) {
if(obj.model == nullptr) continue;
PushConstant pc{}; PushConstant pc{};
pc.modelMatrix = obj.transform.mat4(); pc.modelMatrix = obj.transform.mat4();
pc.normalMatrix = obj.transform.normalMatrix(); pc.normalMatrix = obj.transform.normalMatrix();