Dont generate meshes for empty BlockChunks, and don't push empty meshes.

master
aurailus 2018-12-20 18:03:54 -08:00
parent 5f6c663003
commit 6da513a52c
4 changed files with 43 additions and 34 deletions

View File

@ -8,6 +8,14 @@
BlockChunk::BlockChunk(std::vector<int>* blocks) {
this->blocks = blocks;
this->empty = true;
for (int i : *blocks) {
if (i != 0) {
empty = false;
break;
}
}
}
int BlockChunk::getBlock(glm::vec3* pos) {
@ -25,4 +33,8 @@ int BlockChunk::getBlock(int x, int y, int z) {
unsigned int ind = ArrayTrans3D::vecToInd(x, y, z);
if (ind < 0 || ind >= 4096) return -1;
return blocks->at(ind);
}
bool BlockChunk::isEmpty() {
return empty;
}

View File

@ -17,9 +17,12 @@ public:
int getBlock(glm::vec3* pos);
int getBlock(int x, int y, int z);
bool isEmpty();
//TODO: Add block setting methods as well
private:
std::vector<int>* blocks;
bool empty;
};
#endif //GLPROJECT_BLOCKCHUNK_H

View File

@ -50,7 +50,7 @@ void GameInstance::update(GLfloat deltaTime) {
chunk.y = round(chunk.y / 16);
chunk.z = round(chunk.z / 16);
int SIZE = 32;
int SIZE = 16;
for (int i = -SIZE; i < SIZE; i++) {
for (int j = -4; j < 4; j++) {
for (int k = -SIZE; k < SIZE; k++) {

View File

@ -22,11 +22,14 @@ void World::genChunk(glm::vec3 pos) {
void World::newChunk(glm::vec3 pos, BlockChunk *c) {
blockChunks.insert(std::pair<glm::vec3, BlockChunk*>(pos, c));
meshGenQueue.insert(pos);
if (!c->isEmpty()) {
meshGenQueue.insert(pos);
}
}
void chunkGenThread(World::ChunkThreadData *t) {
PerlinNoise p(0);
PerlinNoise p2(10);
auto* blocks = new std::vector<int>();
blocks->reserve(4096);
@ -40,7 +43,11 @@ void chunkGenThread(World::ChunkThreadData *t) {
pos.y = innerPos.y + t->pos.y * CHUNK_SIZE;
pos.z = innerPos.z + t->pos.z * CHUNK_SIZE;
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, 0) * 16 - pos.y;
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, 0) * 16;
val *= p2.noise((pos.x + 16) / (double) 48, (pos.z + 16) / (double) 48, 0) * 8;
val /= 16;
val *= pow(p.noise(pos.x / (double) 64, pos.z / (double) 64, 0), 2) * 40 + 1;
val -= pos.y;
int block = (val > 0) ? (val > 1 ) ? (val > 4) ? 3 : 2 : 1 : 0;
blocks->push_back(block);
@ -55,32 +62,27 @@ void meshGenThread(World::MeshThreadData *t) {
t->done = true;
}
//Generate block chunks
void World::handleChunkGenQueue() {
//Finish Block Gen threads
//Finalize finished threads by added the BlockChunks to the world via newChunk().
for (auto iter = chunkGenThreads.begin(); iter != chunkGenThreads.end(); ) {
ChunkThreadData* threadData = (*iter);
//If the threadData is done, create a BlockChunk and delete the threadData.
if (threadData->done) {
newChunk(threadData->pos, threadData->chunk);
delete threadData;
iter = chunkGenThreads.erase(iter);
}
//Otherwise ignore it and move to the next BlockChunk
else {
iter++;
}
}
//Create threads for the chunk generation.
//Create new chunk gen threads if there are chunks to be generated.
while (!chunkGenQueue.empty() && chunkGenThreads.size() < MAX_CHUNK_GEN_THREADS) {
//Get and remove the first position from the vector.
auto it = chunkGenQueue.begin();
chunkGenQueue.erase(chunkGenQueue.begin());
glm::vec3 pos = (*it);
//Create a thread for it and add the threadData to the chunkGenThreads vector
auto t = new ChunkThreadData(pos, blockAtlas);
auto thread = new std::thread(chunkGenThread, t);
thread->detach();
@ -90,49 +92,35 @@ void World::handleChunkGenQueue() {
}
void World::handleMeshGenQueue() {
//Run through all of the active generation threads, and finish and remove the ones that are ready to be finished.
//Then, spin up new threads when there is space in the meshGenThreads array and there are chunks waiting to be meshed.
//Create MeshChunks for the finished threads.
Timer applyGlobal("Applying Meshes");
//Finalize finished threads by creating a MeshChunk object from the thread data.
for (auto iter = meshGenThreads.begin(); iter != meshGenThreads.end(); ) {
MeshThreadData* threadData = (*iter);
//If the threadData is done, create a MeshChunk and delete the threadData.
if (threadData->done) {
Timer apply("Applying Mesh");
//Only create the MeshChunk object if there's vertices in it.
if (!threadData->vertices->empty()) {
auto meshChunk = new MeshChunk();
meshChunk->build(threadData->vertices, threadData->indices);
auto meshChunk = new MeshChunk();
meshChunk->build(threadData->vertices, threadData->indices);
glm::vec3 pos = glm::vec3(threadData->pos.x * CHUNK_SIZE, threadData->pos.y * CHUNK_SIZE, threadData->pos.z * CHUNK_SIZE);
meshChunk->setPosition(pos);
meshChunks.insert(std::pair<glm::vec3, MeshChunk*>(threadData->pos, meshChunk));
// apply.printElapsedMs();
glm::vec3 pos = threadData->pos * glm::vec3(CHUNK_SIZE);
meshChunk->setPosition(pos);
meshChunks.insert(std::pair<glm::vec3, MeshChunk *>(threadData->pos, meshChunk));
}
delete threadData;
iter = meshGenThreads.erase(iter);
}
//Otherwise ignore it and move to the next MeshChunk
else {
iter++;
}
}
// applyGlobal.printElapsedMs();
//Begin processing queued chunks if there are chunks to be processed and there's room for more threads.
//Create new mesh gen threads if there are meshes to be made.
while (!meshGenQueue.empty() && meshGenThreads.size() < MAX_MESH_GEN_THREADS) {
//Get and remove the first position from the vector.
auto it = meshGenQueue.begin();
meshGenQueue.erase(meshGenQueue.begin());
glm::vec3 pos = (*it);
//Create a thread for it and add the threadData to the meshGenThreads vector
auto t = new MeshThreadData(pos, blockChunks.at(pos), blockAtlas);
auto thread = new std::thread(meshGenThread, t);
thread->detach();
@ -142,7 +130,10 @@ void World::handleMeshGenQueue() {
}
void World::update() {
//Create / Finalize BlockChunks
handleChunkGenQueue();
//Create / Finalize MeshChunks
handleMeshGenQueue();
}
@ -150,6 +141,9 @@ std::unordered_map<glm::vec3, MeshChunk*, World::vec3cmp>* World::getMeshChunks(
return &meshChunks;
}
//
//Constructors and Destructors for the MeshThreadData / ChunkThreadData structs.
//
World::MeshThreadData::MeshThreadData(glm::vec3 pos, BlockChunk *chunk, BlockAtlas *atlas) {
this->pos = pos;
this->chunk = chunk;