Browse Source

threaded chunk generation

testing
totallyfake 4 years ago
parent
commit
6f5aedb7a9
  1. 3
      include/chunk.h
  2. 2
      include/graphics/chunkmesh.h
  3. 9
      include/world.h
  4. 4
      res/config.conf
  5. 8
      src/chunk.cpp
  6. 11
      src/graphics/chunkmesh.cpp
  7. 26
      src/scenes/testscene.cpp
  8. 1
      src/scenes/testscene.h
  9. 69
      src/world.cpp

3
include/chunk.h

@ -31,6 +31,8 @@ class World; @@ -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: @@ -46,6 +48,7 @@ protected:
std::array<unsigned, 4096> voxels;
World& mLinkedWorld;
glm::ivec3 mPos;
bool mLoaded;
};
}

2
include/graphics/chunkmesh.h

@ -12,7 +12,7 @@ class World; @@ -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

9
include/world.h

@ -42,23 +42,29 @@ public: @@ -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: @@ -69,6 +75,7 @@ public:
VoxelInfo voxelInfo;
VoxelMath voxelMath;
bool rebuildThreadActive;
bool mLoadThreadActive;
};
}

4
res/config.conf

@ -2,8 +2,8 @@ @@ -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

8
src/chunk.cpp

@ -23,7 +23,8 @@ @@ -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) : @@ -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) {

11
src/graphics/chunkmesh.cpp

@ -39,13 +39,17 @@ ChunkMesh::ChunkMesh(World& world, glm::ivec3 chunkPos) : @@ -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() { @@ -87,6 +91,7 @@ void ChunkMesh::rebuildChunkGeometry() {
}
mUpdated = true;
mLocked = false;
return true;
}
void ChunkMesh::rebuildChunkLighting() {

26
src/scenes/testscene.cpp

@ -51,6 +51,7 @@ void TestScene::init() { @@ -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() { @@ -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) { @@ -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) { @@ -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) { @@ -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
src/scenes/testscene.h

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

69
src/world.cpp

@ -22,6 +22,7 @@ World::World() { @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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() { @@ -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() { @@ -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() { @@ -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