Browse Source

threaded queues for mesh updates

testing
totallyfake 1 year ago
parent
commit
2cb2e9a494

+ 3
- 0
.gitmodules View File

@@ -4,3 +4,6 @@
[submodule "libcuckoo"]
path = libcuckoo
url = https://github.com/efficient/libcuckoo.git
[submodule "external/concurrentqueue"]
path = external/concurrentqueue
url = https://github.com/cameron314/concurrentqueue.git

+ 1
- 0
external/concurrentqueue

@@ -0,0 +1 @@
Subproject commit 3e0eac9b7a611bb8142db82789f307f2f0ad1c33

+ 1
- 0
include/blockingconcurrentqueue.h View File

@@ -0,0 +1 @@
../external/concurrentqueue/blockingconcurrentqueue.h

+ 5
- 0
include/chunk.h View File

@@ -29,6 +29,7 @@ namespace vtk {
class World;

class Chunk {
friend class World;
public:
Chunk(World& world);
bool isLoaded();
@@ -45,10 +46,14 @@ public:

ChunkRenderer renderer;
protected:
void setQueuedForMeshRebuild(const bool& rebuild = true);
bool isQueuedForMeshRebuild();

std::array<unsigned, 4096> voxels;
World& mLinkedWorld;
glm::ivec3 mPos;
std::atomic<bool> mLoaded;
std::atomic<bool> mQueuedForMeshRebuild;
};

}

+ 1
- 0
include/concurrentqueue.h View File

@@ -0,0 +1 @@
../external/concurrentqueue/concurrentqueue.h

+ 2
- 0
include/threadpool.h View File

@@ -27,6 +27,8 @@ public:
void addThreads(const int& count); // add new threads to the pool
void addJob(std::function<void()> newJob); // add a job to the pool

int threadCount();

private:
void threadIdle();


+ 10
- 3
include/world.h View File

@@ -23,7 +23,9 @@
#include "voxelmath.h"
#include "terraingen.h"
#include "graphics/chunkmesh.h"

#include "cuckoohash_map.hh"
#include "concurrentqueue.h"

#include <unordered_map>
#include <vector>
@@ -35,6 +37,7 @@ namespace vtk {
class Chunk;

class World {
friend class Chunk;
public:
World();
bool isVoxelSolid(const int& x, const int& y, const int& z);
@@ -49,8 +52,8 @@ public:

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 queueChunkUpdate(const int& x, const int& y, const int& z, const bool& highpriority = false);
void queueChunkUpdate(const glm::ivec3& pos, const bool& highpriority = false);

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

@@ -63,11 +66,15 @@ public:

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

// mesh update queues
moodycamel::ConcurrentQueue<glm::ivec3> mMeshUpdateQueue; // regular one
moodycamel::ConcurrentQueue<glm::ivec3> mMeshUpdateQueueSoon; // high priority one

unsigned chunkSize;
float voxelSize;


+ 10
- 1
src/chunk.cpp View File

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

Chunk::Chunk(World& world) :
mLinkedWorld(world),
mLoaded(false)
mLoaded(false),
mQueuedForMeshRebuild(false)
{
mPos = glm::ivec3(0,0,0);
renderer.linkedChunk = this;
@@ -93,4 +94,12 @@ World& Chunk::getWorld() {
return mLinkedWorld;
}

void Chunk::setQueuedForMeshRebuild(const bool& rebuild) {
mQueuedForMeshRebuild = rebuild;
}

bool Chunk::isQueuedForMeshRebuild() {
return mQueuedForMeshRebuild.load();
}

}

+ 0
- 394
src/chunkrenderer.cpp View File

@@ -1,394 +0,0 @@
/*
* =====================================================================================
*
* Filename: chunkrenderer.cpp
*
* Description:
*
* Version: 1.0
* Created: 04/04/2014 11:34:53 PM
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Organization:
*
* =====================================================================================
*/

#include "chunkrenderer.h"

#include "chunk.h"
#include "world.h"

#include <GL/glew.h>
#include <GL/gl.h>
#include <iostream>

namespace vtk {

void ChunkRenderer::init() {
hasGeometryChanged = false;
hasTexturesChanged = false;
hasLightingChanged = false;
updatingGeometry = false;

chunkSize = 16;
lightingMethod = 0;
voxelSize = 1.0f;

//generate VBOs
for (auto& i : vertexBuffers) {
for(auto& j : i) {
glGenBuffers(1, &j);
}
}

//generate VAOs
for (auto& i : vertexArrays) {
glGenVertexArrays(1, &i);
}

//bind VAOs
for (int i = 0; i < 6; i++) {
glBindVertexArray(vertexArrays[i]);

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][2]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(2);
}
}

void ChunkRenderer::drawChunk() {
for (int i = 0; i < 6; i++) {
glBindVertexArray(vertexArrays[i]);
glDrawArrays(GL_TRIANGLES, 0, vertexCounts[i]);
}
}

void ChunkRenderer::setChunkPosition(const int&x, const int& y, const int&z) {
chunkPos = std::make_tuple(x, y, z);
}

void ChunkRenderer::updateGeometry() {
updatingGeometry = true;

for (auto& i : geometryVertices)
i.clear();

for (auto& i : faceCounts)
i = 0;

for (unsigned i = 0; i < chunkSize; i++) {
for (unsigned j = 0; j < chunkSize; j++) {
for (unsigned k = 0; k < chunkSize; k++) {
if (linkedChunk->isVoxelSolid(i,j,k)) {
if (!linkedChunk->isVoxelSolid(i+1,j,k)) {
//right face
//top left
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top right
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//bottom left
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom right
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize);
//bottom left
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//top right
addVertex(geometryVertices[0], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize);
faceCounts[0]++;
}
if (!linkedChunk->isVoxelSolid(i-1,j,k)) {
//left face
//top left
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//top right
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//bottom left
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize, k * voxelSize);
//bottom right
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom left
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize, k * voxelSize);
//top right
addVertex(geometryVertices[1], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
faceCounts[1]++;
}

if (!linkedChunk->isVoxelSolid(i,j+1,k)) {
//top face
//bottom left
addVertex(geometryVertices[2], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top left
addVertex(geometryVertices[2], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//bottom right
addVertex(geometryVertices[2], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top right
addVertex(geometryVertices[2], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//bottom right
addVertex(geometryVertices[2], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top left
addVertex(geometryVertices[2], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize);
faceCounts[2]++;
}
if (!linkedChunk->isVoxelSolid(i,j-1,k)) {
//bottom face
//top right
addVertex(geometryVertices[3], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom right
addVertex(geometryVertices[3], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize);
//top left
addVertex(geometryVertices[3], i * voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom left
addVertex(geometryVertices[3], i * voxelSize, j * voxelSize, k * voxelSize);
//top left
addVertex(geometryVertices[3], i * voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom right
addVertex(geometryVertices[3], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize);
faceCounts[3]++;
}

if (!linkedChunk->isVoxelSolid(i,j,k-1)) {
//back face
//top left
addVertex(geometryVertices[4], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//top right
addVertex(geometryVertices[4], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize);
//bottom left
addVertex(geometryVertices[4], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize);
//bottom right
addVertex(geometryVertices[4], i * voxelSize, j * voxelSize, k * voxelSize);
//bottom left
addVertex(geometryVertices[4], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize);
//top right
addVertex(geometryVertices[4], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize);
faceCounts[4]++;
}

if (!linkedChunk->isVoxelSolid(i,j,k+1)) {
//front face
//bottom right
addVertex(geometryVertices[5], i * voxelSize + voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//bottom left
addVertex(geometryVertices[5], i * voxelSize, j * voxelSize, k * voxelSize + voxelSize);
//top right
addVertex(geometryVertices[5], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top left
addVertex(geometryVertices[5], i * voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//top right
addVertex(geometryVertices[5], i * voxelSize + voxelSize, j * voxelSize + voxelSize, k * voxelSize + voxelSize);
//bottom left
addVertex(geometryVertices[5], i * voxelSize, j * voxelSize, k * voxelSize + voxelSize);
faceCounts[5]++;
}
}
}
}
}

hasGeometryChanged = true;

updateTexCoords();
updateLighting();

updatingGeometry = false;
}

void ChunkRenderer::updateTexCoords() {
auto linkedWorld = linkedChunk->getWorld();
for (auto& i : textureCoords)
i.clear();

for (unsigned i = 0; i < chunkSize; i++) {
for (unsigned j = 0; j < chunkSize; j++) {
for (unsigned k = 0; k < chunkSize; k++) {
if (linkedChunk->isVoxelSolid(i,j,k)) {
if (!linkedChunk->isVoxelSolid(i+1,j,k)) {
//right face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[0], linkedChunk->getWorldCoords(i,j,k), Face3D::RIGHT, Corner2D::TOPRIGHT);
}
if (!linkedChunk->isVoxelSolid(i-1,j,k)) {
//left face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[1], linkedChunk->getWorldCoords(i,j,k), Face3D::LEFT, Corner2D::TOPRIGHT);
}
if (!linkedChunk->isVoxelSolid(i,j+1,k)) {
//top face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[2], linkedChunk->getWorldCoords(i,j,k), Face3D::TOP, Corner2D::TOPLEFT);
}
if (!linkedChunk->isVoxelSolid(i,j-1,k)) {
//bottom face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[3], linkedChunk->getWorldCoords(i,j,k), Face3D::BOTTOM, Corner2D::BOTTOMRIGHT);
}
if (!linkedChunk->isVoxelSolid(i,j,k-1)) {
//back face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[4], linkedChunk->getWorldCoords(i,j,k), Face3D::BACK, Corner2D::TOPRIGHT);

}
if (!linkedChunk->isVoxelSolid(i,j,k+1)) {
//front face
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::BOTTOMRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::BOTTOMLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::TOPLEFT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::TOPRIGHT);
linkedWorld.voxelInfo.pushTexCoordFromWorldCoords(textureCoords[5], linkedChunk->getWorldCoords(i,j,k), Face3D::FRONT, Corner2D::BOTTOMLEFT);
}
}
}
}
}
hasTexturesChanged = true;
}

void ChunkRenderer::updateLighting() {
for (auto& i : lightingData)
i.clear();

for (unsigned i = 0; i < chunkSize; i++) {
for (unsigned j = 0; j < chunkSize; j++) {
for (unsigned k = 0; k < chunkSize; k++) {
if (linkedChunk->isVoxelSolid(i,j,k)) {
if (lightingMethod == 0) { //fullbright lighting
//face U , V , I
//right face
if (!linkedChunk->isVoxelSolid(i+1,j,k)) {
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //TL
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //TR
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //BL
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //BR
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //BL
addVertex(lightingData[0], 0.8f, 0.8f, 0.8f); //TR
}
if (!linkedChunk->isVoxelSolid(i-1,j,k)) {
//left face
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //TL
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //TR
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //BL
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //BR
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //BL
addVertex(lightingData[1], 0.8f, 0.8f, 0.8f); //TR
}
if (!linkedChunk->isVoxelSolid(i,j+1,k)) {
//top face
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //TL
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //TR
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //BL
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //BR
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //BL
addVertex(lightingData[2], 1.0f, 1.0f, 1.0f); //TR
}
if (!linkedChunk->isVoxelSolid(i,j-1,k)) {
//bottom face
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //TL
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //TR
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //BL
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //BR
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //BL
addVertex(lightingData[3], 0.5f, 0.5f, 0.5f); //TR
}
if (!linkedChunk->isVoxelSolid(i,j,k-1)) {
//back face
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //TL
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //TR
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //BL
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //BR
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //BL
addVertex(lightingData[4], 0.7f, 0.7f, 0.7f); //TR
}
if (!linkedChunk->isVoxelSolid(i,j,k+1)) {
//front face
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //TL
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //TR
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //BL
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //BR
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //BL
addVertex(lightingData[5], 0.9f, 0.9f, 0.9f); //TR
}
} else if (lightingMethod == 1) { //blocky lighting (Need to implement!)

} else if (lightingMethod == 2) { //smooth lighting (Need to implement!)

}
}
}
}
}
hasLightingChanged = true;
}

void ChunkRenderer::updateVertexData() {
if (!updatingGeometry) {
//std::cout << "testing";
for (unsigned i = 0; i < 6; i++) {
if (hasGeometryChanged) {
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * geometryVertices[i].size(), geometryVertices[i].data(), GL_STATIC_DRAW);
//hasGeometryChanged = false;
}
if (hasTexturesChanged) {
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * textureCoords[i].size(), textureCoords[i].data(), GL_STATIC_DRAW);
//hasTexturesChanged = false;
}
if (hasLightingChanged) {
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers[i][2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * lightingData[i].size(), lightingData[i].data(), GL_STATIC_DRAW);
//hasLightingChanged = false;
}
}

if (hasGeometryChanged) hasGeometryChanged = false;
if (hasTexturesChanged) hasTexturesChanged = false;
if (hasLightingChanged) hasLightingChanged = false;

for (int i = 0; i < 6; i++) {
vertexCounts[i] = faceCounts[i] * 6;
}
}
}

void ChunkRenderer::addVertex(std::vector<float>& data, const float& x, const float& y, const float& z) {
data.push_back(x);
data.push_back(y);
data.push_back(z);
}

}

+ 28
- 3
src/scenes/testscene.cpp View File

@@ -86,6 +86,7 @@ void TestScene::init() {
handler.setAction("Delete Voxel", conf->getValue<std::string>("controls.bindings.action.delvoxel", "Mouse Right"));
handler.setAction("Select Type 1", conf->getValue<std::string>("controls.bindings.typesel.type1", "1" ));
handler.setAction("Select Type 2", conf->getValue<std::string>("controls.bindings.typesel.type2", "2" ));
handler.setAction("Toggle Noclip", conf->getValue<std::string>("controls.bindings.noclip", "V"));

//set signals for handler
handler.getEventSignal(SDL_QUIT ).connect<Game , &Game::stop >(linkedGame);
@@ -120,6 +121,8 @@ void TestScene::init() {
//world.forceGlobalGeometryUpdate();

voxelType = 1;
mNoclip = true;
mNoclipDebounce = false;
}

void TestScene::reInit() {
@@ -138,11 +141,18 @@ void TestScene::update(const float& dTime) {
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("Move Up" ) && mNoclip) camera.move(glm::vec3( 0.0f, 1.0f, 0.0f) * dTime * 8.0f);
if (handler.isActionDown("Move Down" ) && mNoclip) 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;
if (!mNoclipDebounce && handler.isActionDown("Toggle Noclip")) {
mNoclipDebounce = true;
mNoclip = !mNoclip;
std::cout << mNoclip << "\n" << std::flush;
} else {
//mNoclipDebounce = false;
}

//place voxel testing
if ((handler.isActionDown("Place Voxel") || handler.isActionDown("Delete Voxel")) && !placeVoxel) {
@@ -169,7 +179,22 @@ void TestScene::update(const float& dTime) {
mCamLastLoadPosition = camera.getPosition();
world.queueChunkLoadsAroundPoint(camera.getPosition(), 16);
}

//player "physics"
if (!mNoclip) {
mVelocity = glm::vec3(0.0f, mVelocity.y + (-9.8f * dTime), 0.0f);
// check ground collision
glm::ivec3 cameraIPos = camera.getPosition();
cameraIPos.y = cameraIPos.y - 2;
if (world.isVoxelSolid(cameraIPos.x, cameraIPos.y, cameraIPos.z)) {
std::cout << cameraIPos.y << "\n" << std::flush;
auto newCameraPos = camera.getPosition();
newCameraPos.y = (float)cameraIPos.y + 2.8f;
camera.setPosition(newCameraPos);
mVelocity.y = 0.0f;
}
camera.move(mVelocity * dTime);
}
}

void TestScene::draw() {

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

@@ -63,6 +63,10 @@ protected:
bool placeVoxel;
unsigned voxelType;

bool mNoclip;
bool mNoclipDebounce;
glm::vec3 mVelocity;

//controls
InputHandler handler;


+ 4
- 0
src/threadpool.cpp View File

@@ -48,5 +48,9 @@ void ThreadPool::addJob(std::function<void ()> newJob) {
}
mCondition.notify_one();
}

int ThreadPool::threadCount() {
return mThreads.size();
}
}

+ 42
- 16
src/world.cpp View File

@@ -106,7 +106,7 @@ bool World::generateChunk(const int& x, const int& y, const int& z) {

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

@@ -117,21 +117,20 @@ Chunk* World::getChunk(const glm::ivec3& pos) {
else return nullptr;
}

void World::queueChunkUpdate(const int& x, const int& y, const int& z, const bool& back) {
void World::queueChunkUpdate(const int& x, const int& y, const int& z, const bool& highpriority) {
queueChunkUpdate(glm::ivec3(x,y,z));
}

void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) {
if (!getChunk(pos)) return; //chunk doesn't exist
for (auto& i : mChunkUpdateQueue) {
if (i == pos) return; //chunk is already in queue, we don't need to update multiple times
}
void World::queueChunkUpdate(const glm::ivec3& pos, const bool& highpriority) {
auto chunk = getChunk(pos);
if (!chunk || chunk->isQueuedForMeshRebuild()) return;
chunk->setQueuedForMeshRebuild(true);

if (back) {
mChunkUpdateQueue.push_back(pos);
} else {
mChunkUpdateQueue.push_front(pos);
if (highpriority) { // queue for higher rebuild priority
mMeshUpdateQueueSoon.enqueue(pos);
return;
}
mMeshUpdateQueue.enqueue(pos);
}

void World::queueChunkLoad(const glm::ivec3 &pos) {
@@ -145,28 +144,53 @@ void World::queueChunkLoad(const glm::ivec3 &pos) {
}

void World::draw() {
for (auto& i : mChunkMeshes) {
auto lt = mChunkMeshes.lock_table();
for (const auto& i : lt) {
glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3((float)i.first.x * 16,
(float)i.first.y * 16,
(float)i.first.z * 16
));

glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat));
i.second.draw();
i.second->draw();
}
}

void World::update() {
if (!rebuildThreadActive && !mChunkUpdateQueue.empty( )) {
//if the rebuild thread is not active and there are meshes to be updated
if (!rebuildThreadActive && (mMeshUpdateQueueSoon.size_approx() > 0 ||
mMeshUpdateQueue.size_approx() > 0)) {
auto updatefunc = [&]() {
glm::ivec3 pos;
while (mMeshUpdateQueueSoon.try_dequeue(pos)) {
ChunkMesh* mesh;
mChunkMeshes.find(pos, mesh);
if (mesh) {
mesh->rebuildChunkGeometry();
}
getChunk(pos)->setQueuedForMeshRebuild(false);
}
while (mMeshUpdateQueue.try_dequeue(pos)) {
ChunkMesh* mesh;
mChunkMeshes.find(pos, mesh);
if (mesh) {
mesh->rebuildChunkGeometry();
}
getChunk(pos)->setQueuedForMeshRebuild(false);
}
rebuildThreadActive = false;
/*
while (!mChunkUpdateQueue.empty()) {
auto& pos = mChunkUpdateQueue.back();
auto& mesh = mChunkMeshes.find(pos)->second;
ChunkMesh* mesh;
mChunkMeshes.find(pos, mesh);
mChunkUpdateQueue.pop_back();
if (!mesh.rebuildChunkGeometry())
if (!mesh->rebuildChunkGeometry())
queueChunkUpdate(pos);
}
rebuildThreadActive = false;
*/
};

rebuildThreadActive = true;
@@ -189,6 +213,7 @@ void World::update() {
}

void World::forceGlobalGeometryUpdate() {
/*
int chunkCount = 1;
chunkCount = 1;
for (auto& i : mChunkMeshes) {
@@ -197,6 +222,7 @@ void World::forceGlobalGeometryUpdate() {
i.second.updateGeometry();
++chunkCount;
}
*/
}

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

Loading…
Cancel
Save