finalize greedy meshing
This commit is contained in:
parent
795dce1272
commit
5585b67a27
6 changed files with 56 additions and 27 deletions
|
@ -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) {};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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"} {};
|
||||||
|
@ -35,7 +38,7 @@ void FirstApp::run() {
|
||||||
renderer.render(loadedChunks, xeEngine.getCamera());
|
renderer.render(loadedChunks, xeEngine.getCamera());
|
||||||
xeEngine.endFrame();
|
xeEngine.endFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadLoadedChunks(viewerObject);
|
reloadLoadedChunks(viewerObject);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue