Browse Source

threaded chunk generation

testing
totallyfake 2 years ago
parent
commit
6f5aedb7a9

+ 3
- 0
include/chunk.h View File

@@ -31,6 +31,8 @@ class World;
class Chunk {
public:
Chunk(World& world);
bool isLoaded();

bool isVoxelSolid(const int& x, const int& y, const int& z); //Is the voxel not a transparent type?
void setVoxelType(const int& x, const int& y, const int& z, const unsigned& type);
unsigned getVoxelType(const unsigned& x, const unsigned& y, const unsigned& z);
@@ -46,6 +48,7 @@ protected:
std::array<unsigned, 4096> voxels;
World& mLinkedWorld;
glm::ivec3 mPos;
bool mLoaded;
};

}

+ 1
- 1
include/graphics/chunkmesh.h View File

@@ -12,7 +12,7 @@ class World;
class ChunkMesh {
public:
ChunkMesh(World& world, glm::ivec3 linkedChunkPos);
void rebuildChunkGeometry();
bool rebuildChunkGeometry();
void rebuildChunkLighting();
void draw();
bool updateGeometry(); //puts the geometry into the VBOs because OGL can't into threading

+ 8
- 1
include/world.h View File

@@ -42,23 +42,29 @@ public:

unsigned getVoxelType(const glm::ivec3& pos);

bool makeChunk(const int& x, const int& y, const int& z);
Chunk* makeChunk(const int& x, const int& y, const int& z, bool insertAfter = true);
bool generateChunk(const int& x, const int& y, const int& z);
bool insertChunk(Chunk* chunk);

Chunk* getChunk(const glm::ivec3& pos);

void queueChunkUpdate(const int& x, const int& y, const int& z, const bool& back = false);
void queueChunkUpdate(const glm::ivec3& pos, const bool& back = false);

void queueChunkLoad(const glm::ivec3& pos);

void draw();
void update();

void forceGlobalGeometryUpdate(); //Rebuilds all geometry. Don't do this.

void queueChunkLoadsAroundPoint(const glm::vec3& point, const int& chunkRadius);

std::unordered_map<glm::ivec3, Chunk*, ivec3Hash> mChunks;
std::unordered_map<glm::ivec3, ChunkMesh, ivec3Hash> mChunkMeshes;
std::vector<iPos> chunkUpdateQueue;
std::deque<glm::ivec3> mChunkUpdateQueue;
std::deque<glm::ivec3> mChunkLoadQueue;

unsigned chunkSize;
float voxelSize;
@@ -69,6 +75,7 @@ public:
VoxelInfo voxelInfo;
VoxelMath voxelMath;
bool rebuildThreadActive;
bool mLoadThreadActive;
};

}

+ 2
- 2
res/config.conf View File

@@ -2,8 +2,8 @@

graphics {
res {
x = 800; horizontal resolution
y = 600; vertical resolution
x = 1920; horizontal resolution
y = 1080; vertical resolution
}
fov = 90
vsync = 0

+ 7
- 1
src/chunk.cpp View File

@@ -23,7 +23,8 @@
namespace vtk {

Chunk::Chunk(World& world) :
mLinkedWorld(world)
mLinkedWorld(world),
mLoaded(false)
{
mPos = glm::ivec3(0,0,0);
renderer.linkedChunk = this;
@@ -32,6 +33,11 @@ Chunk::Chunk(World& world) :
for (unsigned i = 0; i < 4096; i++) {
voxels[i] = 0;
}
mLoaded = true;
}

bool Chunk::isLoaded() {
return mLoaded;
}

bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) {

+ 8
- 3
src/graphics/chunkmesh.cpp View File

@@ -39,13 +39,17 @@ ChunkMesh::ChunkMesh(World& world, glm::ivec3 chunkPos) :
glEnableVertexAttribArray(1);
}

void ChunkMesh::rebuildChunkGeometry() {
bool ChunkMesh::rebuildChunkGeometry() {
// check if it's currently rebuilding
if (mLocked) return;
if (mLocked) return true;
mLocked = true;

//get the chunk from position
auto chunk = mLinkedWorld.getChunk(mLinkedChunkPos);
auto chunk = mLinkedWorld.getChunk(mLinkedChunkPos);
if (!chunk->isLoaded()) {
mLocked = false; //unlock the builder before returning
return false;
}
// geometry format: x,y,z,u,v,i
mGeometry.clear();
@@ -87,6 +91,7 @@ void ChunkMesh::rebuildChunkGeometry() {
}
mUpdated = true;
mLocked = false;
return true;
}

void ChunkMesh::rebuildChunkLighting() {

+ 18
- 8
src/scenes/testscene.cpp View File

@@ -51,6 +51,7 @@ void TestScene::init() {

glUseProgram(shaders);

mCamLastLoadPosition = glm::vec3(0.0f, 64.0f, 0.0f);
camera.setPosition(glm::vec3(0.0f, 64.0f, 0.0f));
camera.setAspectRatio(linkedGame->window.getAspect());

@@ -115,12 +116,13 @@ void TestScene::init() {
for (int j = 0; j < 8; j++) {
for (int k = 0; k < 32; k++) {
std::cout << "\rGenerating chunks (" << chunkCount << "/" << 8*8*8 << ")" << std::flush;
world.generateChunk(i,j,k);
world.queueChunkLoad(glm::ivec3(i,j,k));
chunkCount++;
}
}
}
*/
world.queueChunkLoadsAroundPoint(glm::vec3(0.0,0.0,0.0), 16);

//world.forceGlobalGeometryUpdate();

@@ -139,12 +141,12 @@ void TestScene::update(const float& dTime) {

mFPS = 1.0f/dTime;

if (handler.isActionDown("Move Forward" )) camera.moveRelative(glm::vec3 (0.0f, 0.0f, 1.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Backward")) camera.moveRelative(glm::vec3( 0.0f, 0.0f, -1.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Left" )) camera.moveRelative(glm::vec3(-1.0f, 0.0f, 0.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Right" )) camera.moveRelative(glm::vec3( 1.0f, 0.0f, 0.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Up" )) camera.move(glm::vec3( 0.0f, 1.0f, 0.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Down" )) camera.move(glm::vec3( 0.0f, -1.0f, 0.0f) * dTime * 4.0f);
if (handler.isActionDown("Move Forward" )) camera.moveRelative(glm::vec3 (0.0f, 0.0f, 1.0f) * dTime * 16.0f);
if (handler.isActionDown("Move Backward")) camera.moveRelative(glm::vec3( 0.0f, 0.0f, -1.0f) * dTime * 16.0f);
if (handler.isActionDown("Move Left" )) camera.moveRelative(glm::vec3(-1.0f, 0.0f, 0.0f) * dTime * 16.0f);
if (handler.isActionDown("Move Right" )) camera.moveRelative(glm::vec3( 1.0f, 0.0f, 0.0f) * dTime * 16.0f);
if (handler.isActionDown("Move Up" )) camera.move(glm::vec3( 0.0f, 1.0f, 0.0f) * dTime * 8.0f);
if (handler.isActionDown("Move Down" )) camera.move(glm::vec3( 0.0f, -1.0f, 0.0f) * dTime * 8.0f);

if (handler.isActionDown("Select Type 1")) voxelType = 1;
if (handler.isActionDown("Select Type 2")) voxelType = 2;
@@ -171,7 +173,14 @@ void TestScene::update(const float& dTime) {

//camera.moveRelative(camMovement * dTime);


float distance = glm::distance(camera.getPosition(), mCamLastLoadPosition);
if (distance >= 16.0f) {
mCamLastLoadPosition = camera.getPosition();
world.queueChunkLoadsAroundPoint(camera.getPosition(), 16);
}
//generate chunks with camera (doesn't work very well :|)
/*
int radius = 2;
auto cPos = camera.getPosition();
glm::ivec3 cPosI = (cPos / 16.0f);
@@ -179,10 +188,11 @@ void TestScene::update(const float& dTime) {
for (int x = -radius; x <= radius; ++x) {
if(x*x + y*y <= radius*radius) {
for (int i = 0; i < 8; ++i)
world.generateChunk(cPosI.x + x, i, cPosI.z + y);
world.queueChunkLoad((glm::ivec3)cPos + glm::ivec3(x, i, y));
}
}
}
*/
}


+ 1
- 0
src/scenes/testscene.h View File

@@ -59,6 +59,7 @@ protected:
//stuff
float sensitivity;
glm::vec3 camMovement;
glm::vec3 mCamLastLoadPosition;
bool placeVoxel;
unsigned voxelType;


+ 59
- 10
src/world.cpp View File

@@ -22,6 +22,7 @@ World::World() {
voxelInfo.linkedWorld = this;
voxelMath.linkedWorld = this;
rebuildThreadActive = false;
mLoadThreadActive = false;
}

bool World::isVoxelSolid(const int& x, const int& y, const int& z) {
@@ -36,6 +37,7 @@ bool World::isVoxelSolid(const int& x, const int& y, const int& z) {
int relPosY = y - chunkPos.y * chunkSize;
int relPosZ = z - chunkPos.z * chunkSize;

if (!mChunks[chunkPos]->isLoaded()) return true;
return mChunks[chunkPos]->isVoxelSolid(relPosX, relPosY, relPosZ);
}

@@ -70,27 +72,28 @@ unsigned World::getVoxelType(const glm::ivec3& pos) {
}


bool World::makeChunk(const int& x, const int& y, const int& z) {
Chunk* World::makeChunk(const int& x, const int& y, const int& z, bool insertAfter) {
auto pos = glm::ivec3(x, y, z);

if (mChunks.find(pos) != mChunks.end()) { //chunk already exists
return false;
return mChunks[pos];
}

auto newChunk = new Chunk(*this);
mChunks[pos] = newChunk;

newChunk->setPos(pos);

mChunkMeshes.emplace(pos, ChunkMesh(*this, pos));
if (insertAfter) {
mChunks[pos] = newChunk;
mChunkMeshes.emplace(pos, ChunkMesh(*this, pos));
}

return true;
return newChunk;
}

bool World::generateChunk(const int& x, const int& y, const int& z) {
bool chunkMade = makeChunk(x,y,z);
if (chunkMade) {
terrain.generateChunk(getChunk(glm::ivec3(x,y,z)));
auto chunkMade = makeChunk(x,y,z, false);
if (chunkMade != nullptr) {
terrain.generateChunk(chunkMade);
//queue this chunk for geometry update
queueChunkUpdate(x,y,z);

@@ -103,9 +106,16 @@ bool World::generateChunk(const int& x, const int& y, const int& z) {
queueChunkUpdate(x,y,z+1);
queueChunkUpdate(x,y,z-1);
}
insertChunk(chunkMade);
return chunkMade;
}

bool World::insertChunk(Chunk* chunk) {
mChunks[chunk->getPos()] = chunk;
mChunkMeshes.emplace(chunk->getPos(), ChunkMesh(*this, chunk->getPos()));
return true;
}


Chunk* World::getChunk(const glm::ivec3& pos) {
auto chunk = mChunks.find(pos)->second;
@@ -130,6 +140,16 @@ void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) {
}
}

void World::queueChunkLoad(const glm::ivec3 &pos) {
if (mChunks.find(pos) != mChunks.end()) return; //chunk already exists
for (auto& i : mChunkLoadQueue) {
if (i == pos) return;
}

makeChunk(pos.x, pos.y, pos.z);
mChunkLoadQueue.push_back(pos);
}

void World::draw() {
for (auto& i : mChunkMeshes) {
glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3((float)i.first.x * 16,
@@ -149,7 +169,8 @@ void World::update() {
auto& pos = mChunkUpdateQueue.back();
auto& mesh = mChunkMeshes.find(pos)->second;
mChunkUpdateQueue.pop_back();
mesh.rebuildChunkGeometry();
if (!mesh.rebuildChunkGeometry())
queueChunkUpdate(pos, false);
}
rebuildThreadActive = false;
};
@@ -157,6 +178,20 @@ void World::update() {
rebuildThreadActive = true;
ThreadPool::getInstance().addJob(updatefunc);
}

if (!mLoadThreadActive && !mChunkLoadQueue.empty()) {
auto loadFunc = [&]() {
while (!mChunkLoadQueue.empty()) {
auto& pos = mChunkLoadQueue.back();
generateChunk(pos.x, pos.y, pos.z);
mChunkLoadQueue.pop_back();
}
mLoadThreadActive = false;
};

mLoadThreadActive = true;
ThreadPool::getInstance().addJob(loadFunc);
}
}

void World::forceGlobalGeometryUpdate() {
@@ -170,4 +205,18 @@ void World::forceGlobalGeometryUpdate() {
}
}

void World::queueChunkLoadsAroundPoint(const glm::vec3 &point, const int &chunkRadius) {
glm::ivec3 chunkPoint = point / 16.0f;
for (int z = -chunkRadius; z <= chunkRadius; ++z) {
for (int x = -chunkRadius; x <= chunkRadius; ++x) {
if (z*z + x*x <= chunkRadius * chunkRadius) {
for (int y = 0; y < 8; ++y) {
queueChunkLoad(glm::ivec3(x + chunkPoint.x, y, z + chunkPoint.z));
}
}
}
}
}

}


Loading…
Cancel
Save