Removed the GameInstance::genChunks & Added World::genChunk

master
aurailus 2018-12-19 00:53:07 -08:00
parent 9812d6adcf
commit a62cadb408
5 changed files with 131 additions and 53 deletions

View File

@ -11,7 +11,6 @@ BlockAtlas::BlockAtlas(TextureAtlas *textureAtlas) {
void BlockAtlas::registerBlock(BlockDef* def) {
definitions.push_back(def);
std::cout << "Registered block" << std::endl;
}
BlockDef* BlockAtlas::getBlock(int id) {

View File

@ -26,7 +26,7 @@ void MeshGenerator::build(BlockChunk* chunk, BlockAtlas* atlas,
glm::vec3 check;
for (int i = 0; i < 4096; i++) {
if (chunk->getBlock(i) == 1) {
if (chunk->getBlock(i) != 0) {
ArrayTrans3D::indAssignVec(i, &off);
BlockModel* model = atlas->getBlock(chunk->getBlock(i))->getModel();

View File

@ -7,39 +7,6 @@
GameInstance::GameInstance() = default;
//TODO: Remove this function
void genChunks(World* world) {
PerlinNoise p(0);
int VIEW_RANGE = 24;
for (int i = -VIEW_RANGE; i < VIEW_RANGE; i++) {
for (int j = -VIEW_RANGE; j < VIEW_RANGE; j++) {
for (int k = -1; k < 1; k++) {
auto* blocks = new std::vector<int>();
blocks->reserve(4096);
glm::vec3 innerPos, pos;
for (int ind = 0; ind < 4096; ind++) {
ArrayTrans3D::indAssignVec(ind, &innerPos);
pos.x = innerPos.x + i * CHUNK_SIZE;
pos.y = innerPos.y + k * CHUNK_SIZE;
pos.z = innerPos.z + j * CHUNK_SIZE;
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, pos.y / (double) 16) - pos.y * 0.08;
blocks->push_back((int)(val > 0.5));
}
world->newChunk(new glm::vec3(i, k, j), new BlockChunk(blocks));
}
}
}
}
void GameInstance::initialize(Renderer* renderer) {
this->renderer = renderer;
@ -59,7 +26,16 @@ void GameInstance::initialize(Renderer* renderer) {
//The world requires the blockAtlas for meshing and handling inputs.
world = new World(blockAtlas);
genChunks(world);
int SIZE = 16;
for (int i = -SIZE; i < SIZE; i++) {
for (int j = -4; j < 4; j++) {
for (int k = -SIZE; k < SIZE; k++) {
world->genChunk(new glm::vec3(i, j, k));
}
}
}
// genChunks(world);
}
void GameInstance::update(GLfloat deltaTime) {

View File

@ -3,6 +3,8 @@
//
#include "World.h"
#include "../engine/PerlinNoise.h"
#include "../engine/helpers/ArrayTrans3D.h"
World::World() {
blockAtlas = nullptr;
@ -12,24 +14,89 @@ World::World(BlockAtlas *atlas) {
blockAtlas = atlas;
}
void World::genChunk(glm::vec3* pos) {
chunkGenQueue.insert(pos);
}
void World::newChunk(glm::vec3* pos, BlockChunk *c) {
blockChunks.insert(std::pair<glm::vec3*, BlockChunk*>(pos, c));
meshGenQueue.insert(pos);
}
void genThread(World::ThreadData* t) {
void chunkGenThread(World::ChunkThreadData *t) {
PerlinNoise p(0);
auto* blocks = new std::vector<int>();
blocks->reserve(4096);
glm::vec3 innerPos, pos;
for (int ind = 0; ind < 4096; ind++) {
ArrayTrans3D::indAssignVec(ind, &innerPos);
pos.x = innerPos.x + t->pos->x * CHUNK_SIZE;
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;
int block = (val > 0) ? (val > 1 ) ? (val > 4) ? 3 : 2 : 1 : 0;
blocks->push_back(block);
}
t->chunk = new BlockChunk(blocks);
t->done = true;
}
void meshGenThread(World::MeshThreadData *t) {
MeshGenerator().build(t->chunk, t->atlas, *(t->vertices), *(t->indices));
t->done = true;
}
void World::update() {
int done = 0;
//Finish Block Gen threads
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) {
done++;
// blockChunks.insert(std::pair<glm::vec3*, BlockChunk*>(threadData->pos, threadData->chunk));
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.
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();
t->thread = thread;
chunkGenThreads.push_back(t);
}
//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 genThreads array and there are chunks waiting to be meshed.
//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");
for (auto iter = genThreads.begin(); iter != genThreads.end(); ) {
ThreadData* threadData = (*iter);
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) {
@ -44,29 +111,30 @@ void World::update() {
// apply.elapsedMs();
delete threadData;
iter = genThreads.erase(iter);
iter = meshGenThreads.erase(iter);
}
//Otherwise ignore it and move to the next MeshChunk
else {
iter++;
}
}
// applyGlobal.elapsedMs();
//Begin processing queued chunks if there are chunks to be processed and there's room for more threads.
while (!meshGenQueue.empty() && genThreads.size() < MAX_CONCURRENT_THREADS) {
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 genThreads vector
auto t = new ThreadData(pos, blockChunks.at(pos), blockAtlas);
auto thread = new std::thread(genThread, t);
//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();
t->thread = thread;
genThreads.push_back(t);
meshGenThreads.push_back(t);
}
}
@ -74,7 +142,7 @@ std::map<glm::vec3*, MeshChunk*>* World::getMeshChunks() {
return &meshChunks;
}
World::ThreadData::ThreadData(glm::vec3 *pos, BlockChunk *chunk, BlockAtlas *atlas) {
World::MeshThreadData::MeshThreadData(glm::vec3 *pos, BlockChunk *chunk, BlockAtlas *atlas) {
this->pos = pos;
this->chunk = chunk;
this->atlas = atlas;
@ -83,11 +151,23 @@ World::ThreadData::ThreadData(glm::vec3 *pos, BlockChunk *chunk, BlockAtlas *atl
this->indices = new std::vector<unsigned int>();
}
World::ThreadData::~ThreadData() {
World::MeshThreadData::~MeshThreadData() {
//Not delete this->pos because it is used in the MeshChunk and BlockChunk vectors.
//delete pos
delete vertices;
delete indices;
//Delete the thread, when the deconstructor is called, the thread is done.
delete thread;
}
World::ChunkThreadData::ChunkThreadData(glm::vec3 *pos, BlockAtlas *atlas) {
this->pos = pos;
this->atlas = atlas;
this->done = false;
this->chunk = nullptr;
}
World::ChunkThreadData::~ChunkThreadData() {
//Delete the thread, when the deconstructor is called, the thread is done.
delete thread;
}

View File

@ -21,6 +21,7 @@ public:
World();
explicit World(BlockAtlas* atlas);
void genChunk(glm::vec3* pos);
void newChunk(glm::vec3* pos, BlockChunk* c);
void update();
@ -29,8 +30,8 @@ public:
~World() = default;
struct ThreadData {
ThreadData(glm::vec3* pos, BlockChunk* chunk, BlockAtlas* atlas);
struct MeshThreadData {
MeshThreadData(glm::vec3* pos, BlockChunk* chunk, BlockAtlas* atlas);
std::thread* thread;
@ -43,7 +44,22 @@ public:
std::vector<float>* vertices;
std::vector<unsigned int>* indices;
~ThreadData();
~MeshThreadData();
};
struct ChunkThreadData {
ChunkThreadData(glm::vec3* pos, BlockAtlas* atlas);
std::thread* thread;
glm::vec3* pos;
BlockAtlas* atlas;
bool done;
BlockChunk* chunk;
~ChunkThreadData();
};
private:
//Note to self:
@ -52,10 +68,17 @@ private:
std::map<glm::vec3*, BlockChunk*> blockChunks;
std::map<glm::vec3*, MeshChunk*> meshChunks;
const int MAX_CONCURRENT_THREADS = 32;
//TODO: Replace this BiQueueThreadArray model with a BiQueueThreadPool model (it's in the name)
//Chunk Gen BiQueue Variables
const int MAX_CHUNK_GEN_THREADS = 16;
std::unordered_set<glm::vec3*> chunkGenQueue;
std::vector<ChunkThreadData*> chunkGenThreads;
//Mesh Gen BiQueue Variables
const int MAX_MESH_GEN_THREADS = 64;
std::unordered_set<glm::vec3*> meshGenQueue;
std::vector<ThreadData*> genThreads;
std::vector<MeshThreadData*> meshGenThreads;
BlockAtlas* blockAtlas;
};