BugFixes, Optimizations, Speed Improvements
#Fixes * Fix Segfault when you go back to previously generated chunks * Make dimension & BlockChunks use shared_ptrs (finally) * MeshGenStream no longer unnecessarily duplicates BlockChunks * Different Vertical Gen Range to Horizontal # Clean Up * Convert most MeshGenerator functions to using references (safety) * Optimize Flora noise * Remove raw C array Mesh Initializer (it was messy) * Pre-generate ActiveRange positions and remove runtime sortingmaster
parent
a1e5f39652
commit
5e9a0774be
|
@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
|||
set (CMAKE_CXX_STANDARD 14)
|
||||
set (PROJECT_NAME "Zeus")
|
||||
|
||||
#set (CMAKE_CXX_FLAGS "--coverage")
|
||||
#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
|
||||
#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-recover=address")
|
||||
|
||||
project (${PROJECT_NAME})
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ Client::Client(int width, int height) {
|
|||
}
|
||||
|
||||
void Client::start(char* path) {
|
||||
// Start Local Server
|
||||
//Start Local Server
|
||||
if (path != nullptr) {
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
|
@ -57,10 +57,13 @@ void Client::loop() {
|
|||
state->deltaTime = now - timeElapsed;
|
||||
timeElapsed = now;
|
||||
|
||||
count ++;
|
||||
if (count == 20) {
|
||||
if (count == 5) {
|
||||
Scene* g = new GameScene(state);
|
||||
sceneManager.setScene(g); //Main Menu Scene here eventually
|
||||
count = 8;
|
||||
}
|
||||
else {
|
||||
count++;
|
||||
}
|
||||
|
||||
glfwPollEvents();
|
||||
|
|
|
@ -12,11 +12,7 @@ Mesh::Mesh() {
|
|||
}
|
||||
|
||||
void Mesh::create(std::vector<float>* vertices, std::vector<unsigned int>* indices) {
|
||||
create(&(*vertices)[0], &(*indices)[0], (unsigned int)vertices->size(), (unsigned int)indices->size());
|
||||
}
|
||||
|
||||
void Mesh::create(float *vertices, unsigned int *indices, unsigned int vertCount, unsigned int indCount) {
|
||||
this->indCount = indCount;
|
||||
this->indCount = (int)indices->size();
|
||||
|
||||
glGenVertexArrays(1, &VAO);
|
||||
|
||||
|
@ -25,22 +21,20 @@ void Mesh::create(float *vertices, unsigned int *indices, unsigned int vertCount
|
|||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
|
||||
//Have to multiply by indCount because indices is a pointer to *one* number, not the entire array.
|
||||
//Could also be sizeof(unsigned int) * indCount
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indCount, indices, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indCount * sizeof(unsigned int), &indices->front(), GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertCount, vertices, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices->size() * sizeof(float), &vertices->front(), GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, nullptr);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, nullptr);
|
||||
glEnableVertexAttribArray(0); //If dynamic amounts of attrib arrays are needed, then do these before drawing
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void*)(sizeof(vertices[0]) * 3));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void*)(sizeof(float) * 3));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 8, (void*)(sizeof(vertices[0]) * 5));
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void*)(sizeof(float) * 5));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
|
|
@ -13,7 +13,6 @@ public:
|
|||
Mesh();
|
||||
|
||||
void create(std::vector<float>* vertices, std::vector<unsigned int>* indices);
|
||||
void create(float *vertices, unsigned int *indices, unsigned int vertCount, unsigned int indCount);
|
||||
void draw();
|
||||
void cleanup();
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
std::cerr << "State doesn't define cleanup method!" << std::endl;
|
||||
};
|
||||
|
||||
virtual ~Scene() = default;
|
||||
|
||||
ClientState* state;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@ Scene* SceneManager::getScene() {
|
|||
}
|
||||
|
||||
void SceneManager::cleanupScene() {
|
||||
scene->cleanup();
|
||||
delete scene;
|
||||
scene = nullptr;
|
||||
if (scene != nullptr) {
|
||||
scene->cleanup();
|
||||
delete scene;
|
||||
scene = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SceneManager::~SceneManager() {
|
||||
if (scene != nullptr) cleanupScene();
|
||||
cleanupScene();
|
||||
}
|
|
@ -118,6 +118,8 @@ void GameScene::draw() {
|
|||
state->renderer->draw(entity);
|
||||
}
|
||||
|
||||
prevTexture = nullptr;
|
||||
|
||||
//TEMPORARY
|
||||
for (auto &entity : playerEntities) {
|
||||
auto newTexture = entity->getTexture();
|
||||
|
@ -130,6 +132,8 @@ void GameScene::draw() {
|
|||
state->renderer->draw(entity);
|
||||
}
|
||||
|
||||
prevTexture = nullptr;
|
||||
|
||||
state->renderer->enableGuiShader();
|
||||
|
||||
for (auto &entity : guiEntities) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "../../../generic/helpers/VecUtils.h"
|
||||
|
||||
LocalWorld::LocalWorld(BlockAtlas *atlas) :
|
||||
meshGenStream(atlas),
|
||||
meshGenStream(*atlas, dimension),
|
||||
worldGenStream(55) {
|
||||
|
||||
blockAtlas = atlas;
|
||||
|
@ -19,7 +19,7 @@ void LocalWorld::loadChunkPacket(Packet *p) {
|
|||
worldGenStream.pushBack(p);
|
||||
}
|
||||
|
||||
void LocalWorld::commitChunk(glm::vec3 pos, BlockChunk *c) {
|
||||
void LocalWorld::commitChunk(glm::vec3 pos, std::shared_ptr<BlockChunk> c) {
|
||||
dimension.addChunk(pos, c);
|
||||
attemptMeshChunk(pos);
|
||||
}
|
||||
|
@ -58,29 +58,6 @@ bool LocalWorld::getAdjacentExists(glm::vec3 pos, glm::vec3 otherPos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector<bool>* LocalWorld::getAdjacentsCull(glm::vec3 pos) {
|
||||
auto culls = new std::vector<bool>();
|
||||
culls->reserve(1536); //256 * 6
|
||||
|
||||
auto vectors = VecUtils::getCardinalVectors();
|
||||
for (int i = 0; i < vectors.size(); i++) {
|
||||
auto chunk = getChunk(pos + vectors[i]);
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
for (int k = 0; k < 16; k++) {
|
||||
|
||||
int x = (i == 0) ? 0 : (i == 1) ? 15 : (i <= 3) ? j : k;
|
||||
int y = (i == 2) ? 0 : (i == 3) ? 15 : j;
|
||||
int z = (i == 4) ? 0 : (i == 5) ? 15 : k;
|
||||
|
||||
auto block = chunk->getBlock(x, y, z);
|
||||
culls->push_back(blockAtlas->getBlock(block)->isCulling());
|
||||
}
|
||||
}
|
||||
}
|
||||
return culls;
|
||||
}
|
||||
|
||||
void LocalWorld::update() {
|
||||
//Create Finished Messages
|
||||
auto finishedMeshes = meshGenStream.update();
|
||||
|
@ -114,8 +91,7 @@ void LocalWorld::update() {
|
|||
glm::vec3 pos = *it;
|
||||
|
||||
if (!meshGenStream.isQueued(pos)) {
|
||||
moreSpace = meshGenStream.tryToQueue(
|
||||
std::pair<BlockChunk*, std::vector<bool>*>{getChunk(pos), getAdjacentsCull(pos)});
|
||||
moreSpace = meshGenStream.tryToQueue(pos);
|
||||
}
|
||||
|
||||
pendingMesh.erase(it);
|
||||
|
@ -161,7 +137,7 @@ bool LocalWorld::solidAt(glm::vec3 pos) {
|
|||
return blockAtlas->getBlock(blockId)->isSolid();
|
||||
}
|
||||
|
||||
BlockChunk* LocalWorld::getChunk(glm::vec3 chunkPos) {
|
||||
std::shared_ptr<BlockChunk> LocalWorld::getChunk(glm::vec3 chunkPos) {
|
||||
return dimension.getChunk(chunkPos);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
void update();
|
||||
|
||||
//Pushes chunk to the list unless one already exists, then tries to mesh it.
|
||||
void commitChunk(glm::vec3 pos, BlockChunk *c);
|
||||
void commitChunk(glm::vec3 pos, std::shared_ptr<BlockChunk>);
|
||||
|
||||
//Attempts to regenerate a chunk mesh.
|
||||
void remeshChunk(glm::vec3 pos);
|
||||
|
@ -42,11 +42,10 @@ public:
|
|||
void attemptMeshChunk(glm::vec3 pos);
|
||||
//This function also updates the chunk that is being checked's adjacent data, so maybe a rename is in order.
|
||||
bool getAdjacentExists(glm::vec3 pos, glm::vec3 myPos);
|
||||
std::vector<bool>* getAdjacentsCull(glm::vec3 pos);
|
||||
|
||||
std::unordered_map<glm::vec3, MeshChunk*, VecUtils::compareFunc>* getMeshChunks();
|
||||
|
||||
BlockChunk* getChunk(glm::vec3 chunkPos);
|
||||
std::shared_ptr<BlockChunk> getChunk(glm::vec3 chunkPos);
|
||||
|
||||
int getBlock(glm::vec3 pos);
|
||||
void setBlock(glm::vec3 pos, int block);
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
|
||||
MeshGenStream::MeshGenStream() = default;
|
||||
MeshGenStream::MeshGenStream(BlockAtlas &a, Dimension &d) :
|
||||
atlas(a),
|
||||
dimension(d) {
|
||||
|
||||
MeshGenStream::MeshGenStream(BlockAtlas* atlas) {
|
||||
queuedTasks.reserve((unsigned long) TOTAL_QUEUE_SIZE);
|
||||
|
||||
this->atlas = atlas;
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) {
|
||||
threads.emplace_back(this->atlas);
|
||||
threads.emplace_back(atlas);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,12 +27,12 @@ bool MeshGenStream::isQueued(glm::vec3 pos) {
|
|||
return (bool) queuedMap.count(pos);
|
||||
}
|
||||
|
||||
bool MeshGenStream::tryToQueue(std::pair<BlockChunk*, std::vector<bool>*> data) {
|
||||
bool MeshGenStream::tryToQueue(glm::vec3 pos) {
|
||||
unsigned long sizeOfQueue = queuedTasks.size();
|
||||
|
||||
if (sizeOfQueue < TOTAL_QUEUE_SIZE && !queuedMap.count(data.first->pos)) {
|
||||
queuedTasks.push_back(data);
|
||||
queuedMap.insert(data.first->pos);
|
||||
if (sizeOfQueue < TOTAL_QUEUE_SIZE && !queuedMap.count(pos)) {
|
||||
queuedTasks.push_back(pos);
|
||||
queuedMap.insert(pos);
|
||||
}
|
||||
|
||||
return sizeOfQueue + 1 < TOTAL_QUEUE_SIZE;
|
||||
|
@ -53,12 +52,12 @@ std::vector<MeshGenStream::MeshDetails>* MeshGenStream::update() {
|
|||
|
||||
if (!queuedTasks.empty()) {
|
||||
auto it = queuedTasks.begin();
|
||||
auto data = *it;
|
||||
glm::vec3 pos = *it;
|
||||
queuedTasks.erase(it);
|
||||
queuedMap.erase(data.first->pos);
|
||||
queuedMap.erase(pos);
|
||||
|
||||
u.chunk = data.first;
|
||||
u.adjacent = data.second;
|
||||
u.chunk = dimension.getChunk(pos);
|
||||
u.adjacent = getAdjacentsCull(pos);
|
||||
|
||||
//Lock it in to allow the thread to edit it.
|
||||
u.unlocked = false;
|
||||
|
@ -69,8 +68,8 @@ std::vector<MeshGenStream::MeshDetails>* MeshGenStream::update() {
|
|||
return finishedChunks;
|
||||
}
|
||||
|
||||
MeshGenStream::Thread::Thread(BlockAtlas* atlas) {
|
||||
this->atlas = atlas;
|
||||
MeshGenStream::Thread::Thread(BlockAtlas &atlas) :
|
||||
atlas(atlas) {
|
||||
|
||||
thread = new std::thread(MeshGenStream::threadFunction, this);
|
||||
thread->detach();
|
||||
|
@ -88,7 +87,7 @@ void MeshGenStream::threadFunction(MeshGenStream::Thread *thread) {
|
|||
u.vertices = new std::vector<float>();
|
||||
u.indices = new std::vector<unsigned int>();
|
||||
|
||||
MeshGenerator().build(u.chunk, thread->atlas, u.adjacent, *u.vertices, *u.indices);
|
||||
MeshGenerator().build(u.chunk, thread->atlas, *u.adjacent, *u.vertices, *u.indices);
|
||||
|
||||
delete u.adjacent;
|
||||
|
||||
|
@ -112,4 +111,27 @@ MeshGenStream::~MeshGenStream() {
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<bool>* MeshGenStream::getAdjacentsCull(glm::vec3 pos) {
|
||||
auto culls = new std::vector<bool>();
|
||||
culls->reserve(1536); //256 * 6
|
||||
|
||||
auto vectors = VecUtils::getCardinalVectors();
|
||||
for (int i = 0; i < vectors.size(); i++) {
|
||||
auto chunk = dimension.getChunk(pos + vectors[i]);
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
for (int k = 0; k < 16; k++) {
|
||||
|
||||
int x = (i == 0) ? 0 : (i == 1) ? 15 : (i <= 3) ? j : k;
|
||||
int y = (i == 2) ? 0 : (i == 3) ? 15 : j;
|
||||
int z = (i == 4) ? 0 : (i == 5) ? 15 : k;
|
||||
|
||||
auto block = chunk->getBlock(x, y, z);
|
||||
culls->push_back(atlas.getBlock(block)->isCulling());
|
||||
}
|
||||
}
|
||||
}
|
||||
return culls;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
|
@ -13,6 +13,7 @@
|
|||
#include "../../../generic/blocks/BlockAtlas.h"
|
||||
#include "../../graphics/mesh/MeshGenerator.h"
|
||||
#include "../../../generic/helpers/VecUtils.h"
|
||||
#include "../../../generic/world/Dimension.h"
|
||||
|
||||
class MeshGenStream {
|
||||
public:
|
||||
|
@ -20,15 +21,14 @@ public:
|
|||
static const int THREADS = 4;
|
||||
static const int TOTAL_QUEUE_SIZE = THREADS * THREAD_QUEUE_SIZE;
|
||||
|
||||
MeshGenStream();
|
||||
explicit MeshGenStream(BlockAtlas* atlas);
|
||||
explicit MeshGenStream(BlockAtlas& a, Dimension& d);
|
||||
~MeshGenStream();
|
||||
|
||||
bool spaceInQueue();
|
||||
bool isQueued(glm::vec3 pos);
|
||||
//Attempt to add `pos` to the pre-thread queue.
|
||||
//Will return a boolean stating if there is more space left in the queue.
|
||||
bool tryToQueue(std::pair<BlockChunk*, std::vector<bool>*> data);
|
||||
bool tryToQueue(glm::vec3 pos);
|
||||
|
||||
struct MeshDetails {
|
||||
std::vector<float>* vertices;
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
std::vector<MeshDetails>* update();
|
||||
|
||||
struct Unit {
|
||||
BlockChunk* chunk = nullptr;
|
||||
std::shared_ptr<BlockChunk> chunk = nullptr;
|
||||
std::vector<bool>* adjacent = nullptr;
|
||||
|
||||
std::vector<float>* vertices = nullptr;
|
||||
|
@ -57,9 +57,9 @@ public:
|
|||
};
|
||||
|
||||
struct Thread {
|
||||
explicit Thread(BlockAtlas* atlas);
|
||||
explicit Thread(BlockAtlas &atlas);
|
||||
|
||||
BlockAtlas* atlas;
|
||||
BlockAtlas &atlas;
|
||||
|
||||
std::thread* thread;
|
||||
bool keepAlive = true;
|
||||
|
@ -69,11 +69,13 @@ public:
|
|||
|
||||
std::vector<Thread> threads;
|
||||
private:
|
||||
std::vector<bool>* getAdjacentsCull(glm::vec3 pos);
|
||||
static void threadFunction(Thread* thread);
|
||||
|
||||
BlockAtlas* atlas;
|
||||
Dimension& dimension;
|
||||
BlockAtlas& atlas;
|
||||
|
||||
std::vector<std::pair<BlockChunk*, std::vector<bool>*>> queuedTasks;
|
||||
std::vector<glm::vec3> queuedTasks;
|
||||
std::unordered_set<glm::vec3, VecUtils::compareFunc> queuedMap;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ bool WorldInterpolationStream::pushBack(Packet *p) {
|
|||
queuedTasks.push_back(p);
|
||||
}
|
||||
|
||||
std::vector<BlockChunk*> WorldInterpolationStream::update() {
|
||||
std::vector<BlockChunk*> finishedChunks;
|
||||
std::vector<std::shared_ptr<BlockChunk>> WorldInterpolationStream::update() {
|
||||
std::vector<std::shared_ptr<BlockChunk>> finishedChunks;
|
||||
|
||||
for (auto& t : threads) {
|
||||
for (auto& u : t.tasks) {
|
||||
if (!u.unlocked) continue;
|
||||
|
||||
if (u.chunk != nullptr) {
|
||||
finishedChunks.push_back(u.chunk);
|
||||
finishedChunks.push_back(std::shared_ptr<BlockChunk>(u.chunk));
|
||||
u.chunk = nullptr;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,11 @@ std::vector<BlockChunk*> WorldInterpolationStream::update() {
|
|||
Packet* p = *it;
|
||||
queuedTasks.erase(it);
|
||||
|
||||
if (p == nullptr) {
|
||||
cerr << "NULL PACKET IN THE WORLD INTERPOLATION STREAM! (" << __LINE__ << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
u.packet = p;
|
||||
//Lock it to allow the thread to edit it.
|
||||
u.unlocked = false;
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
|
||||
//Will return a vector of BlockChunk pointers containing finished chunks.
|
||||
//Frees up the threads and starts new tasks.
|
||||
std::vector<BlockChunk*> update();
|
||||
std::vector<std::shared_ptr<BlockChunk>> update();
|
||||
|
||||
struct Unit {
|
||||
Packet* packet = nullptr;
|
||||
|
|
|
@ -8,32 +8,32 @@ MeshGenerator::MeshGenerator() {
|
|||
indOffset = 0;
|
||||
}
|
||||
|
||||
BlockDef* blockData(int ind, BlockChunk* chunk, BlockAtlas* atlas) {
|
||||
return atlas->getBlock(chunk->getBlock(ind));
|
||||
BlockDef* blockData(int ind, BlockChunk &chunk, BlockAtlas& atlas) {
|
||||
return atlas.getBlock(chunk.getBlock(ind));
|
||||
}
|
||||
|
||||
BlockDef* blockData(glm::vec3* pos, BlockChunk* chunk, BlockAtlas* atlas) {
|
||||
return atlas->getBlock(chunk->getBlock(pos));
|
||||
BlockDef* blockData(glm::vec3 &pos, BlockChunk &chunk, BlockAtlas &atlas) {
|
||||
return atlas.getBlock(chunk.getBlock(&pos));
|
||||
}
|
||||
|
||||
bool faceOcculudedAt(glm::vec3* pos, BlockChunk* chunk, BlockAtlas* atlas, std::vector<bool>* bools) {
|
||||
if (pos->x < 0 || pos->x > 15 || pos->y < 0 || pos->y > 15 || pos->z < 0 || pos->z > 15) {
|
||||
bool faceOcculudedAt(glm::vec3 &pos, BlockChunk &chunk, BlockAtlas &atlas, std::vector<bool> &bools) {
|
||||
if (pos.x < 0 || pos.x > 15 || pos.y < 0 || pos.y > 15 || pos.z < 0 || pos.z > 15) {
|
||||
|
||||
if (pos->x == -1) return (*bools)[ 256 + (int)pos->y * 16 + (int)pos->z];
|
||||
if (pos->x == 16) return (*bools)[ + (int)pos->y * 16 + (int)pos->z];
|
||||
if (pos.x == -1) return bools[ 256 + (int)pos.y * 16 + (int)pos.z];
|
||||
if (pos.x == 16) return bools[ + (int)pos.y * 16 + (int)pos.z];
|
||||
|
||||
if (pos->y == -1) return (*bools)[ 768 + (int)pos->x * 16 + (int)pos->z];
|
||||
if (pos->y == 16) return (*bools)[ 512 + (int)pos->x * 16 + (int)pos->z];
|
||||
if (pos.y == -1) return bools[ 768 + (int)pos.x * 16 + (int)pos.z];
|
||||
if (pos.y == 16) return bools[ 512 + (int)pos.x * 16 + (int)pos.z];
|
||||
|
||||
if (pos->z == -1) return (*bools)[1280 + (int)pos->y * 16 + (int)pos->x];
|
||||
if (pos->z == 16) return (*bools)[1024 + (int)pos->y * 16 + (int)pos->x];
|
||||
if (pos.z == -1) return bools[1280 + (int)pos.y * 16 + (int)pos.x];
|
||||
if (pos.z == 16) return bools[1024 + (int)pos.y * 16 + (int)pos.x];
|
||||
|
||||
return false;
|
||||
}
|
||||
return blockData(pos, chunk, atlas)->isCulling();
|
||||
}
|
||||
|
||||
void MeshGenerator::build(BlockChunk* chunk, BlockAtlas* atlas, std::vector<bool>* adjacents,
|
||||
void MeshGenerator::build(const std::shared_ptr<BlockChunk> &chunk, BlockAtlas &atlas, std::vector<bool> &adjacents,
|
||||
std::vector<float> &vertices, std::vector<unsigned int> &indices) {
|
||||
|
||||
Timer t("Mesh Generation");
|
||||
|
@ -45,68 +45,66 @@ void MeshGenerator::build(BlockChunk* chunk, BlockAtlas* atlas, std::vector<bool
|
|||
glm::vec3 check;
|
||||
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
if (blockData(i, chunk, atlas)->getModel()->visible) {
|
||||
if (blockData(i, *chunk, atlas)->getModel()->visible) {
|
||||
|
||||
ArrayTrans3D::indAssignVec(i, off);
|
||||
BlockModel* model = blockData(i, chunk, atlas)->getModel();
|
||||
BlockModel* model = blockData(i, *chunk, atlas)->getModel();
|
||||
|
||||
check.x = off.x - 1; check.y = off.y; check.z = off.z;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->leftFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->leftFaces);
|
||||
|
||||
check.x = off.x + 1; check.y = off.y; check.z = off.z;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->rightFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->rightFaces);
|
||||
|
||||
check.x = off.x; check.y = off.y - 1; check.z = off.z;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->bottomFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->bottomFaces);
|
||||
|
||||
check.x = off.x; check.y = off.y + 1; check.z = off.z;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->topFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->topFaces);
|
||||
|
||||
check.x = off.x; check.y = off.y; check.z = off.z - 1;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->backFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->backFaces);
|
||||
|
||||
check.x = off.x; check.y = off.y; check.z = off.z + 1;
|
||||
if (!faceOcculudedAt(&check, chunk, atlas, adjacents))
|
||||
addFaces(off, &vertices, &indices, &model->frontFaces);
|
||||
if (!faceOcculudedAt(check, *chunk, atlas, adjacents))
|
||||
addFaces(off, vertices, indices, model->frontFaces);
|
||||
|
||||
addFaces(off, &vertices, &indices, &model->noCulledFaces);
|
||||
addFaces(off, vertices, indices, model->noCulledFaces);
|
||||
}
|
||||
}
|
||||
|
||||
vertices.shrink_to_fit();
|
||||
indices.shrink_to_fit();
|
||||
|
||||
// t.printElapsedMs();
|
||||
}
|
||||
|
||||
void MeshGenerator::addFaces(glm::vec3 &offset, vector<float>* vertices, vector<unsigned int>* indices, vector<MeshPart*>* meshParts) {
|
||||
for (MeshPart *mp : *meshParts) {
|
||||
void MeshGenerator::addFaces(glm::vec3 &offset, vector<float> &vertices, vector<unsigned int> &indices, vector<MeshPart*> &meshParts) {
|
||||
for (MeshPart *mp : meshParts) {
|
||||
|
||||
MeshVertexIter *vertexIter = mp->getVertexIterator();
|
||||
while (vertexIter->hasNext()) {
|
||||
Vertex *vertex = vertexIter->next();
|
||||
|
||||
vertices->push_back(vertex->pos->x + offset.x);
|
||||
vertices->push_back(vertex->pos->y + offset.y);
|
||||
vertices->push_back(vertex->pos->z + offset.z);
|
||||
vertices.push_back(vertex->pos->x + offset.x);
|
||||
vertices.push_back(vertex->pos->y + offset.y);
|
||||
vertices.push_back(vertex->pos->z + offset.z);
|
||||
|
||||
vertices->push_back(vertex->tex->x);
|
||||
vertices->push_back(vertex->tex->y);
|
||||
vertices.push_back(vertex->tex->x);
|
||||
vertices.push_back(vertex->tex->y);
|
||||
|
||||
vertices->push_back(vertex->nml->x);
|
||||
vertices->push_back(vertex->nml->y);
|
||||
vertices->push_back(vertex->nml->z);
|
||||
vertices.push_back(vertex->nml->x);
|
||||
vertices.push_back(vertex->nml->y);
|
||||
vertices.push_back(vertex->nml->z);
|
||||
}
|
||||
|
||||
MeshIndexIter *indexIter = mp->getIndexIterator();
|
||||
while (indexIter->hasNext()) {
|
||||
unsigned int index = indexIter->next();
|
||||
indices->push_back(indOffset + index);
|
||||
indices.push_back(indOffset + index);
|
||||
}
|
||||
indOffset += mp->getVertexCount();
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ const int CHUNK_SIZE = 16;
|
|||
class MeshGenerator {
|
||||
public:
|
||||
MeshGenerator();
|
||||
void build(BlockChunk* chunk, BlockAtlas* atlas, std::vector<bool>* adjacents,
|
||||
std::vector<float> &vertices, std::vector<unsigned int> &indices);
|
||||
void build(const std::shared_ptr<BlockChunk> &chunk, BlockAtlas &atlas, std::vector<bool> &adjacents,
|
||||
std::vector<float> &vertices, std::vector<unsigned int> &indices);
|
||||
|
||||
~MeshGenerator();
|
||||
private:
|
||||
unsigned int indOffset;
|
||||
|
||||
void addFaces(glm::vec3 &offset, vector<float>* vertices, vector<unsigned int>* indices, vector<MeshPart*>* meshParts);
|
||||
void addFaces(glm::vec3 &offset, vector<float> &vertices, vector<unsigned int> &indices, vector<MeshPart*> &meshParts);
|
||||
|
||||
void cleanup();
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@ void ServerConnection::update(Player &player, std::vector<PlayerEntity*>& player
|
|||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
Packet* p = new Packet(event.packet);
|
||||
auto p = new Packet(event.packet);
|
||||
|
||||
switch (p->type) {
|
||||
case Packet::PLAYER_INFO: {
|
||||
|
|
|
@ -121,9 +121,9 @@ void MapGen::getDensityMap(MapGenJob &job) {
|
|||
}
|
||||
|
||||
void MapGen::fillChunk(MapGenJob &job) {
|
||||
auto grass_sample = NoiseSample::getSample(&grassFinal, job.pos, 16, 1, true);
|
||||
auto flora_type_sample = NoiseSample::getSample(&floraFinal, job.pos, 4, 1, true);
|
||||
auto flora_density_sample = NoiseSample::getSample(&floraDensity, job.pos, 8, 1, true);
|
||||
auto grass_sample = NoiseSample::getSample(&grassFinal, job.pos, 16, 0, true);
|
||||
auto flora_type_sample = NoiseSample::getSample(&floraFinal, job.pos, 4, 0, true);
|
||||
auto flora_density_sample = NoiseSample::getSample(&floraDensity, job.pos, 8, 0, true);
|
||||
|
||||
glm::vec3 lp;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <vec3.hpp>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include "../helpers/TransPos.h"
|
||||
#include "../blocks/BlockChunk.h"
|
||||
|
||||
|
@ -16,15 +17,15 @@ class MapBlock {
|
|||
public:
|
||||
explicit MapBlock(glm::vec3 pos);
|
||||
|
||||
C* operator[](int index);
|
||||
void set(int index, C* block);
|
||||
std::shared_ptr<C> operator[](int index);
|
||||
void set(int index, std::shared_ptr<C> chunk);
|
||||
|
||||
~MapBlock();
|
||||
~MapBlock() = default;
|
||||
private:
|
||||
glm::vec3 pos {};
|
||||
|
||||
const static int arrayLength = TransPos::MAPBLOCK_SIZE * TransPos::MAPBLOCK_SIZE * TransPos::MAPBLOCK_SIZE;
|
||||
std::array<C*, arrayLength> blockChunks;
|
||||
std::array<std::shared_ptr<C>, arrayLength> blockChunks;
|
||||
};
|
||||
|
||||
template<class C>
|
||||
|
@ -37,20 +38,13 @@ MapBlock<C>::MapBlock(glm::vec3 pos) {
|
|||
}
|
||||
|
||||
template<class C>
|
||||
C* MapBlock<C>::operator[](int index) {
|
||||
std::shared_ptr<C> MapBlock<C>::operator[](int index) {
|
||||
return blockChunks[index];
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void MapBlock<C>::set(int index, C* chunk) {
|
||||
void MapBlock<C>::set(int index, std::shared_ptr<C> chunk) {
|
||||
blockChunks[index] = chunk;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MapBlock<C>::~MapBlock() {
|
||||
for (int i = 0; i < arrayLength; i++) {
|
||||
delete blockChunks[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ZEUS_MAPBLOCK_H
|
||||
|
|
|
@ -15,8 +15,8 @@ class RegionHandler {
|
|||
public:
|
||||
RegionHandler() = default;
|
||||
|
||||
void addChunk(glm::vec3 pos, T* chunk);
|
||||
T* getChunk(glm::vec3 pos);
|
||||
void addChunk(glm::vec3 pos, std::shared_ptr<T> chunk);
|
||||
std::shared_ptr<T> getChunk(glm::vec3 pos);
|
||||
|
||||
Region<T>* getRegion(glm::vec3 pos);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
template <class T>
|
||||
void RegionHandler<T>::addChunk(glm::vec3 pos, T *chunk) {
|
||||
void RegionHandler<T>::addChunk(glm::vec3 pos, std::shared_ptr<T> chunk) {
|
||||
|
||||
glm::vec3 regionPos = TransPos::Dimension::regionFromVec(pos);
|
||||
if (!regions.count(regionPos)) regions.insert({regionPos, new Region<T>(regionPos)});
|
||||
|
@ -12,12 +12,11 @@ void RegionHandler<T>::addChunk(glm::vec3 pos, T *chunk) {
|
|||
|
||||
glm::vec3 chunkPos = TransPos::Dimension::chunkOffsetFromMapBlock(pos);
|
||||
unsigned int chunkInd = TransPos::chunkIndFromVec(chunkPos);
|
||||
delete (*mapBlock)[chunkInd];
|
||||
mapBlock->set(chunkInd, chunk);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *RegionHandler<T>::getChunk(glm::vec3 pos) {
|
||||
std::shared_ptr<T> RegionHandler<T>::getChunk(glm::vec3 pos) {
|
||||
|
||||
glm::vec3 regionPos = TransPos::Dimension::regionFromVec(pos);
|
||||
if (!regions.count(regionPos)) return nullptr;
|
||||
|
|
|
@ -45,4 +45,6 @@ ServerPlayer* ConnectionList::createPlayer(ServerPeer *peer, std::string uuid) {
|
|||
packet.sendTo(peer->peer, PacketChannel::PLAYER_INFO);
|
||||
|
||||
world->addPlayer(player);
|
||||
|
||||
return player;
|
||||
}
|
|
@ -48,15 +48,15 @@ void ServerPlayer::setPos(glm::vec3 pos) {
|
|||
}
|
||||
|
||||
std::pair<glm::vec3, glm::vec3> ServerPlayer::getBounds() {
|
||||
glm::vec3 minBounds(chunkPos.x - ACTIVE_RANGE, chunkPos.y - ACTIVE_RANGE, chunkPos.z - ACTIVE_RANGE);
|
||||
glm::vec3 maxBounds(chunkPos.x + ACTIVE_RANGE, chunkPos.y + ACTIVE_RANGE, chunkPos.z + ACTIVE_RANGE);
|
||||
glm::vec3 minBounds(chunkPos.x - ACTIVE_RANGE_H, chunkPos.y - ACTIVE_RANGE_H, chunkPos.z - ACTIVE_RANGE_H);
|
||||
glm::vec3 maxBounds(chunkPos.x + ACTIVE_RANGE_H, chunkPos.y + ACTIVE_RANGE_H, chunkPos.z + ACTIVE_RANGE_H);
|
||||
|
||||
return {minBounds, maxBounds};
|
||||
}
|
||||
|
||||
std::pair<glm::vec3, glm::vec3> ServerPlayer::getOldBounds() {
|
||||
glm::vec3 minBounds(lastChunkPos.x - ACTIVE_RANGE, lastChunkPos.y - ACTIVE_RANGE, lastChunkPos.z - ACTIVE_RANGE);
|
||||
glm::vec3 maxBounds(lastChunkPos.x + ACTIVE_RANGE, lastChunkPos.y + ACTIVE_RANGE, lastChunkPos.z + ACTIVE_RANGE);
|
||||
glm::vec3 minBounds(lastChunkPos.x - ACTIVE_RANGE_H, lastChunkPos.y - ACTIVE_RANGE_H, lastChunkPos.z - ACTIVE_RANGE_H);
|
||||
glm::vec3 maxBounds(lastChunkPos.x + ACTIVE_RANGE_H, lastChunkPos.y + ACTIVE_RANGE_H, lastChunkPos.z + ACTIVE_RANGE_H);
|
||||
|
||||
return {minBounds, maxBounds};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
|
||||
class ServerPlayer {
|
||||
public:
|
||||
const static int ACTIVE_RANGE = 24;
|
||||
const static int ACTIVE_RANGE_H = 25;
|
||||
const static int ACTIVE_RANGE_V = 8;
|
||||
|
||||
//TODO: Refactor instances of UUID to username, or create seperate username flag
|
||||
explicit ServerPlayer(ServerPeer* peer, std::string uuid);
|
||||
|
|
|
@ -8,6 +8,28 @@
|
|||
#include "../../generic/network/PacketChannel.h"
|
||||
#include "../../client/engine/Timer.h"
|
||||
|
||||
World::World(unsigned int seed) : genStream(seed) {
|
||||
//Pregenerate chunk generation order
|
||||
generateOrder.reserve((unsigned long)pow(ServerPlayer::ACTIVE_RANGE_H * 2, 3));
|
||||
|
||||
|
||||
for (int i = 0; i <= ServerPlayer::ACTIVE_RANGE_H; i++) {
|
||||
for (int j = 0; j <= i; j++) {
|
||||
for (int k = -ServerPlayer::ACTIVE_RANGE_V; k <= ServerPlayer::ACTIVE_RANGE_V; k++) {
|
||||
for (int l = -1; l <= 1; l += 2) {
|
||||
for (int m = -1; m <= 1; m += 2) {
|
||||
for (int n = 0; n <= 1; n++) {
|
||||
generateOrder.emplace_back((n ? l*i : m*j), k, (n ? m*j : l*i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Generated Chunk Queue is " << generateOrder.size() << " chunks long.";
|
||||
}
|
||||
|
||||
void World::addPlayer(ServerPlayer *player) {
|
||||
Timer t("New Chunk Allocation");
|
||||
|
||||
|
@ -16,25 +38,14 @@ void World::addPlayer(ServerPlayer *player) {
|
|||
auto bounds = player->getBounds();
|
||||
auto pos = player->getChunkPos();
|
||||
|
||||
std::vector<glm::vec3> toGenerate;
|
||||
toGenerate.reserve((unsigned long)pow(ServerPlayer::ACTIVE_RANGE, 3));
|
||||
|
||||
for (int i = (int)bounds.first.x; i <= (int)bounds.second.x; i++) {
|
||||
for (int j = (int)bounds.first.y; j <= (int)bounds.second.y; j++) {
|
||||
for (int k = (int) bounds.first.z; k <= (int) bounds.second.z; k++) {
|
||||
toGenerate.emplace_back(i, j, k);
|
||||
}
|
||||
for (const auto &c : generateOrder) {
|
||||
glm::vec3 chunkPos = {c.x + pos.x, c.y + pos.y, c.z + pos.z};
|
||||
if (dimension.getChunk(chunkPos) != nullptr) {
|
||||
sendChunk(chunkPos, *player->peer);
|
||||
}
|
||||
else {
|
||||
generate(chunkPos);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(toGenerate.begin(), toGenerate.end(), [&](glm::vec3 a, glm::vec3 b) {
|
||||
using namespace std;
|
||||
return max(max(abs(a.x - pos.x), abs(a.y - pos.y)), abs(a.z - pos.z)) <
|
||||
max(max(abs(b.x - pos.x), abs(b.y - pos.y)), abs(b.z - pos.z));
|
||||
});
|
||||
|
||||
for (glm::vec3 tPos : toGenerate) {
|
||||
generate(tPos);
|
||||
}
|
||||
|
||||
t.printElapsedMs();
|
||||
|
@ -48,40 +59,30 @@ void World::playerChangedChunks(ServerPlayer *player) {
|
|||
auto bounds = player->getBounds();
|
||||
auto oldBounds = player->getOldBounds();
|
||||
|
||||
std::vector<glm::vec3> toGenerate;
|
||||
toGenerate.reserve((unsigned long)pow(ServerPlayer::ACTIVE_RANGE, 3));
|
||||
int generated = 0;
|
||||
|
||||
for (int i = (int)bounds.first.x; i <= (int)bounds.second.x; i++) {
|
||||
for (int j = (int)bounds.first.y; j <= (int)bounds.second.y; j++) {
|
||||
for (int k = (int) bounds.first.z; k <= (int) bounds.second.z; k++) {
|
||||
glm::vec3 tPos(i, j, k);
|
||||
if (!player->isInBounds(tPos, oldBounds)) {
|
||||
toGenerate.push_back(tPos);
|
||||
}
|
||||
for (const auto &c : generateOrder) {
|
||||
glm::vec3 chunkPos = {c.x + pos.x, c.y + pos.y, c.z + pos.z};
|
||||
if (!player->isInBounds(chunkPos, oldBounds)) {
|
||||
if (dimension.getChunk(chunkPos) != nullptr) {
|
||||
sendChunk(chunkPos, *player->peer);
|
||||
}
|
||||
else {
|
||||
generate(chunkPos);
|
||||
generated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(toGenerate.begin(), toGenerate.end(), [&](glm::vec3 a, glm::vec3 b) {
|
||||
using namespace std;
|
||||
return max(max(abs(a.x - pos.x), abs(a.y - pos.y)), abs(a.z - pos.z)) <
|
||||
max(max(abs(b.x - pos.x), abs(b.y - pos.y)), abs(b.z - pos.z));
|
||||
});
|
||||
|
||||
for (glm::vec3 tPos : toGenerate) {
|
||||
generate(tPos);
|
||||
}
|
||||
|
||||
printf("[INFO] %s moved, generating %d chunks.\n",
|
||||
player->getUsername().c_str(), (int)toGenerate.size());
|
||||
player->getUsername().c_str(), generated);
|
||||
t.printElapsedMs();
|
||||
|
||||
player->changedChunks = false;
|
||||
}
|
||||
|
||||
void World::generate(glm::vec3 pos) {
|
||||
if(!generateQueueMap.count(pos) && !chunkMap.count(pos)) {
|
||||
|
||||
if(!generateQueueMap.count(pos) && !dimension.getChunk(pos)) {
|
||||
generateQueueMap.insert(pos);
|
||||
generateQueueList.push_back(pos);
|
||||
}
|
||||
|
@ -103,29 +104,13 @@ void World::update() {
|
|||
generatedChunks = (int)finished.size();
|
||||
|
||||
for (auto chunk : finished) {
|
||||
|
||||
bool didCalcSerialized = false;
|
||||
std::string serialized;
|
||||
dimension.addChunk(chunk->pos, chunk);
|
||||
|
||||
for (auto player : players) {
|
||||
auto bounds = player->getBounds();
|
||||
|
||||
if (player->isInBounds(chunk->pos, bounds)) {
|
||||
|
||||
//Serialize the chunk
|
||||
if (!didCalcSerialized) {
|
||||
serialized = chunk->serialize();
|
||||
didCalcSerialized = true;
|
||||
}
|
||||
|
||||
//Send the Chunk to the player
|
||||
Packet r(Packet::CHUNK_INFO);
|
||||
|
||||
Serializer::encodeInt(r.data, (int)chunk->pos.x);
|
||||
Serializer::encodeInt(r.data, (int)chunk->pos.y);
|
||||
Serializer::encodeInt(r.data, (int)chunk->pos.z);
|
||||
Serializer::encodeString(r.data, serialized);
|
||||
|
||||
r.sendTo(player->peer->peer, PacketChannel::WORLD_INFO);
|
||||
sendChunk(chunk->pos, *player->peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,8 +121,28 @@ void World::update() {
|
|||
for (auto player : players) {
|
||||
r.sendTo(player->peer->peer, PacketChannel::SERVER_INFO);
|
||||
|
||||
//Run update method for players
|
||||
if (player->changedChunks) {
|
||||
playerChangedChunks(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::sendChunk(glm::vec3 pos, ServerPeer &peer) {
|
||||
auto chunk = dimension.getChunk(pos);
|
||||
if (chunk != nullptr) {
|
||||
auto serialized = chunk->serialize();
|
||||
|
||||
Packet r(Packet::CHUNK_INFO);
|
||||
|
||||
Serializer::encodeInt(r.data, (int) chunk->pos.x);
|
||||
Serializer::encodeInt(r.data, (int) chunk->pos.y);
|
||||
Serializer::encodeInt(r.data, (int) chunk->pos.z);
|
||||
Serializer::encodeString(r.data, serialized);
|
||||
|
||||
r.sendTo(peer.peer, PacketChannel::WORLD_INFO);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Tried to send null chunk at " << pos.x << ", " << pos.y << ", " << pos.z << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
#include "../ServerPlayer.h"
|
||||
#include "WorldGenStream.h"
|
||||
#include "../../generic/helpers/VecUtils.h"
|
||||
#include "../../generic/world/Dimension.h"
|
||||
|
||||
class World {
|
||||
public:
|
||||
explicit World(unsigned int seed) : genStream(seed) {};
|
||||
explicit World(unsigned int seed);
|
||||
|
||||
void addPlayer(ServerPlayer* player);
|
||||
void update();
|
||||
|
@ -23,18 +25,20 @@ public:
|
|||
private:
|
||||
void playerChangedChunks(ServerPlayer* player);
|
||||
void generate(glm::vec3 pos);
|
||||
void sendChunk(glm::vec3 pos, ServerPeer& peer);
|
||||
|
||||
WorldGenStream genStream;
|
||||
|
||||
std::vector<ServerPlayer*> players;
|
||||
|
||||
std::unordered_map<glm::vec3, BlockChunk*, VecUtils::compareFunc> chunkMap;
|
||||
std::vector<std::pair<glm::vec3, BlockChunk*>> chunkList;
|
||||
Dimension dimension;
|
||||
|
||||
std::unordered_set<glm::vec3, VecUtils::compareFunc> generateQueueMap;
|
||||
std::vector<glm::vec3> generateQueueList;
|
||||
|
||||
int generatedChunks = 0;
|
||||
|
||||
std::vector<glm::vec3> generateOrder;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -27,15 +27,15 @@ bool WorldGenStream::tryToQueue(glm::vec3 pos) {
|
|||
return sizeOfQueue + 1 < TOTAL_QUEUE_SIZE;
|
||||
}
|
||||
|
||||
std::vector<BlockChunk*> WorldGenStream::update() {
|
||||
std::vector<BlockChunk*> finishedChunks;
|
||||
std::vector<std::shared_ptr<BlockChunk>> WorldGenStream::update() {
|
||||
std::vector<std::shared_ptr<BlockChunk>> finishedChunks;
|
||||
|
||||
for (auto& t : threads) {
|
||||
for (auto& u : t.tasks) {
|
||||
if (!u.unlocked) continue;
|
||||
|
||||
if (u.chunk != nullptr) {
|
||||
finishedChunks.push_back(u.chunk);
|
||||
finishedChunks.push_back(std::shared_ptr<BlockChunk>(u.chunk));
|
||||
u.chunk = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
//Will return a vector of BlockChunk pointers containing finished chunks.
|
||||
//Frees up the threads and starts new tasks.
|
||||
std::vector<BlockChunk*> update();
|
||||
std::vector<std::shared_ptr<BlockChunk>> update();
|
||||
|
||||
struct Unit {
|
||||
glm::vec3 pos {0, 0, 0};
|
||||
|
|
Loading…
Reference in New Issue