@@ -0,0 +1 @@ | |||
((c-mode . ((mode . c++)))) |
@@ -0,0 +1,33 @@ | |||
// A chunk mesh for batching together other chunk meshes to reduce drawcalls | |||
// chunks OR the supermesh but not both. | |||
// To be used to group together chunks (i.e. 8^3 blocks of chunks) | |||
// If rebuild is started when it's already rebuilding in another thread,it will | |||
// restart rebuilding in the original thread. | |||
#pragma once | |||
#include <vector> | |||
#include <glm/glm.hpp> | |||
namespace vtk { | |||
class ChunkMesh; | |||
class SuperChunkMesh { | |||
public: | |||
SuperChunkMesh(); | |||
bool addMesh(ChunkMesh* mesh); | |||
void rebuild(); | |||
protected: | |||
typedef struct { | |||
unsigned count; | |||
unsigned instanceCount; | |||
unsigned first; | |||
unsigned baseInstance; | |||
} DrawArraysIndirectCommand; | |||
std::vector<ChunkMesh*> mChunkMeshes; | |||
std::vector<glm::mat4> mModelMats; | |||
}; | |||
} |
@@ -59,7 +59,6 @@ public: | |||
std::unordered_map<glm::ivec3, ChunkMesh, ivec3Hash> mChunkMeshes; | |||
std::vector<iPos> chunkUpdateQueue; | |||
std::deque<glm::ivec3> mChunkUpdateQueue; | |||
std::vector<glm::ivec3> mChunkGeometryUpdateQueue; | |||
unsigned chunkSize; | |||
float voxelSize; |
@@ -1,119 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: game.cpp | |||
* | |||
* Description: Game class source | |||
* | |||
* Version: 1.0 | |||
* Created: 03/23/2014 11:33:25 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: YOUR NAME (), | |||
* Organization: | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#include "game.h" | |||
#include "loadShader.h" | |||
#include "graphics/camera.h" | |||
#include "graphics/glstate.h" | |||
#include "scene.h" | |||
//SPAGHETTI INCLUDES | |||
#define GLM_FORCE_RADIANS | |||
#include <glm/glm.hpp> | |||
#include <glm/gtc/matrix_transform.hpp> | |||
#include <glm/gtc/type_ptr.hpp> | |||
#include <chrono> | |||
namespace vtk { | |||
Game::Game() { | |||
activeScene = nullptr; | |||
} | |||
void Game::init() { | |||
SDL_Init(SDL_INIT_VIDEO); | |||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | |||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); | |||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | |||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |||
SDL_GL_SetSwapInterval(conf->getValue<int>("graphics.vsync", 0)); | |||
window.setTitle("OpenGL"); | |||
window.setResolution(conf->getValue<int>("graphics.res.x", 800), | |||
conf->getValue<int>("graphics.res.y", 600)); | |||
window.setFOV(conf->getValue<float>("graphics.fov", 45.0f)); | |||
window.create(); | |||
glewExperimental = GL_TRUE; | |||
glewInit(); | |||
//OpenGL settings | |||
glEnable(GL_DEPTH_TEST); | |||
glDepthFunc(GL_LESS); | |||
glEnable(GL_CULL_FACE); | |||
glCullFace(GL_BACK); | |||
glFrontFace(GL_CW); | |||
running = false; | |||
gls::setTracking(true); | |||
} | |||
void Game::start() { | |||
if (activeScene == nullptr) return; | |||
running = true; | |||
loop(); | |||
} | |||
void Game::loop() { | |||
auto lastFrameTime = std::chrono::steady_clock::now(); | |||
while (running) { | |||
//time | |||
int dTimeMS = SDL_GetTicks() - lastFrameTime; | |||
lastFrameTime = SDL_GetTicks(); | |||
float dTime = (float)dTimeMS / 1000.0f; | |||
activeScene->update(dTime); | |||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||
activeScene->draw(); | |||
SDL_GL_SwapWindow(window.getWindow()); | |||
} | |||
cleanup(); | |||
} | |||
void Game::stop() { | |||
running = false; | |||
} | |||
void Game::cleanup() { | |||
SDL_Quit(); | |||
} | |||
void Game::setScene(Scene* scene) { | |||
activeScene = scene; | |||
scene->link(this); | |||
scene->init(); | |||
} | |||
void Game::setConfig(Config* conf) { | |||
this->conf = conf; | |||
} | |||
Config* Game::getConfig() { | |||
return conf; | |||
} | |||
}; |
@@ -11,224 +11,226 @@ | |||
namespace vtk { | |||
ChunkMesh::ChunkMesh(World& world, glm::ivec3 chunkPos) : | |||
mLinkedWorld(world), | |||
mLinkedChunkPos(chunkPos), | |||
mLocked(false) | |||
{ | |||
glGenBuffers(1, &mGeometryTexVBO); | |||
glGenBuffers(1, &mLightVBO); | |||
glGenVertexArrays(1, &mVAO); | |||
glBindVertexArray(mVAO); | |||
glBindBuffer(GL_ARRAY_BUFFER, mGeometryTexVBO); | |||
//vertices | |||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), NULL); | |||
glEnableVertexAttribArray(0); | |||
//tex uv coords | |||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float))); | |||
glEnableVertexAttribArray(1); | |||
} | |||
void ChunkMesh::rebuildChunkGeometry() { | |||
if (mLocked) return; | |||
mLocked = true; | |||
//get the chunk from position | |||
auto chunk = mLinkedWorld.getChunk(mLinkedChunkPos); | |||
//temporary until I finish mesh providers | |||
float texUV [] = { | |||
0.0f, 1.0f, | |||
1.0f, 1.0f, | |||
0.0f, 0.0f, | |||
1.0f, 0.0f, | |||
0.0f, 0.0f, | |||
1.0f, 1.0f | |||
}; | |||
float topModel [] = { | |||
//x y z | |||
0.0f, 1.0f, 0.0f, //tl | |||
1.0f, 1.0f, 0.0f, //tr | |||
0.0f, 1.0f, 1.0f, //bl | |||
1.0f, 1.0f, 1.0f, //br | |||
0.0f, 1.0f, 1.0f, //bl | |||
1.0f, 1.0f, 0.0f //tr | |||
}; | |||
float bottomModel [] = { | |||
//x y z u v | |||
0.0f, 0.0f, 1.0f, //tl | |||
1.0f, 0.0f, 1.0f, //tr | |||
0.0f, 0.0f, 0.0f, //bl | |||
1.0f, 0.0f, 0.0f, //br | |||
0.0f, 0.0f, 0.0f, //bl | |||
1.0f, 0.0f, 1.0f //tr | |||
}; | |||
float northModel [] = { | |||
//x y z u v | |||
0.0f, 1.0f, 1.0f, //tl | |||
1.0f, 1.0f, 1.0f, //tr | |||
0.0f, 0.0f, 1.0f, //bl | |||
1.0f, 0.0f, 1.0f, //br | |||
0.0f, 0.0f, 1.0f, //bl | |||
1.0f, 1.0f, 1.0f //tr | |||
}; | |||
float southModel [] = { | |||
//x y z u v | |||
1.0f, 1.0f, 0.0f, //tl | |||
0.0f, 1.0f, 0.0f, //tr | |||
1.0f, 0.0f, 0.0f, //bl | |||
0.0f, 0.0f, 0.0f, //br | |||
1.0f, 0.0f, 0.0f, //bl | |||
0.0f, 1.0f, 0.0f //tr | |||
}; | |||
float eastModel [] = { | |||
//x y z u v | |||
1.0f, 1.0f, 1.0f, //tl | |||
1.0f, 1.0f, 0.0f, //tr | |||
1.0f, 0.0f, 1.0f, //bl | |||
1.0f, 0.0f, 0.0f, //br | |||
1.0f, 0.0f, 1.0f, //bl | |||
1.0f, 1.0f, 0.0f //tr | |||
}; | |||
float westModel [] = { | |||
//x y z u v | |||
0.0f, 1.0f, 0.0f, //tl | |||
0.0f, 1.0f, 1.0f, //tr | |||
0.0f, 0.0f, 0.0f, //bl | |||
0.0f, 0.0f, 1.0f, //br | |||
0.0f, 0.0f, 0.0f, //bl | |||
0.0f, 1.0f, 1.0f //tr | |||
}; | |||
// geometry format: x,y,z,u,v,i | |||
geometry.clear(); | |||
mFaceCount = 0; | |||
int chunkSize = 16; // TODO: make this not hardcoded | |||
for (int i = 0; i < chunkSize; ++i) { | |||
for (int j = 0; j < chunkSize; ++j) { | |||
for (int k = 0; k < chunkSize; ++k) { | |||
//for each voxel in the chunk... | |||
// TODO: move this code into a mesh provider system | |||
//top | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j + 1, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(topModel[(l * 3)] + (float)i); | |||
geometry.push_back(topModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(topModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//bottom | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j - 1, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(bottomModel[(l * 3)] + (float)i); | |||
geometry.push_back(bottomModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(bottomModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//north | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j, k + 1)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(northModel[(l * 3)] + (float)i); | |||
geometry.push_back(northModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(northModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//south | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j, k - 1)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(southModel[(l * 3)] + (float)i); | |||
geometry.push_back(southModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(southModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//east | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i + 1, j, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(eastModel[(l * 3)] + (float)i); | |||
geometry.push_back(eastModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(eastModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//west | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i - 1, j, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(westModel[(l * 3)] + (float)i); | |||
geometry.push_back(westModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(westModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
ChunkMesh::ChunkMesh(World& world, glm::ivec3 chunkPos) : | |||
mLinkedWorld(world), | |||
mLinkedChunkPos(chunkPos), | |||
mLocked(false) | |||
{ | |||
glGenBuffers(1, &mGeometryTexVBO); | |||
glGenBuffers(1, &mLightVBO); | |||
glGenVertexArrays(1, &mVAO); | |||
glBindVertexArray(mVAO); | |||
glBindBuffer(GL_ARRAY_BUFFER, mGeometryTexVBO); | |||
//vertices | |||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), NULL); | |||
glEnableVertexAttribArray(0); | |||
//tex uv coords | |||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float))); | |||
glEnableVertexAttribArray(1); | |||
} | |||
void ChunkMesh::rebuildChunkGeometry() { | |||
if (mLocked) return; | |||
mLocked = true; | |||
//get the chunk from position | |||
auto chunk = mLinkedWorld.getChunk(mLinkedChunkPos); | |||
//temporary until I finish mesh providers | |||
float texUV [] = { | |||
0.0f, 1.0f, | |||
1.0f, 1.0f, | |||
0.0f, 0.0f, | |||
1.0f, 0.0f, | |||
0.0f, 0.0f, | |||
1.0f, 1.0f | |||
}; | |||
float topModel [] = { | |||
//x y z | |||
0.0f, 1.0f, 0.0f, //tl | |||
1.0f, 1.0f, 0.0f, //tr | |||
0.0f, 1.0f, 1.0f, //bl | |||
1.0f, 1.0f, 1.0f, //br | |||
0.0f, 1.0f, 1.0f, //bl | |||
1.0f, 1.0f, 0.0f //tr | |||
}; | |||
float bottomModel [] = { | |||
//x y z u v | |||
0.0f, 0.0f, 1.0f, //tl | |||
1.0f, 0.0f, 1.0f, //tr | |||
0.0f, 0.0f, 0.0f, //bl | |||
1.0f, 0.0f, 0.0f, //br | |||
0.0f, 0.0f, 0.0f, //bl | |||
1.0f, 0.0f, 1.0f //tr | |||
}; | |||
float northModel [] = { | |||
//x y z u v | |||
0.0f, 1.0f, 1.0f, //tl | |||
1.0f, 1.0f, 1.0f, //tr | |||
0.0f, 0.0f, 1.0f, //bl | |||
1.0f, 0.0f, 1.0f, //br | |||
0.0f, 0.0f, 1.0f, //bl | |||
1.0f, 1.0f, 1.0f //tr | |||
}; | |||
float southModel [] = { | |||
//x y z u v | |||
1.0f, 1.0f, 0.0f, //tl | |||
0.0f, 1.0f, 0.0f, //tr | |||
1.0f, 0.0f, 0.0f, //bl | |||
0.0f, 0.0f, 0.0f, //br | |||
1.0f, 0.0f, 0.0f, //bl | |||
0.0f, 1.0f, 0.0f //tr | |||
}; | |||
float eastModel [] = { | |||
//x y z u v | |||
1.0f, 1.0f, 1.0f, //tl | |||
1.0f, 1.0f, 0.0f, //tr | |||
1.0f, 0.0f, 1.0f, //bl | |||
1.0f, 0.0f, 0.0f, //br | |||
1.0f, 0.0f, 1.0f, //bl | |||
1.0f, 1.0f, 0.0f //tr | |||
}; | |||
float westModel [] = { | |||
//x y z u v | |||
0.0f, 1.0f, 0.0f, //tl | |||
0.0f, 1.0f, 1.0f, //tr | |||
0.0f, 0.0f, 0.0f, //bl | |||
0.0f, 0.0f, 1.0f, //br | |||
0.0f, 0.0f, 0.0f, //bl | |||
0.0f, 1.0f, 1.0f //tr | |||
}; | |||
// geometry format: x,y,z,u,v,i | |||
geometry.clear(); | |||
mFaceCount = 0; | |||
int chunkSize = 16; // TODO: make this not hardcoded | |||
for (int i = 0; i < chunkSize; ++i) { | |||
for (int j = 0; j < chunkSize; ++j) { | |||
for (int k = 0; k < chunkSize; ++k) { | |||
//for each voxel in the chunk... | |||
// TODO: move this code into a mesh provider system | |||
//top | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j + 1, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(topModel[(l * 3)] + (float)i); | |||
geometry.push_back(topModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(topModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//bottom | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j - 1, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(bottomModel[(l * 3)] + (float)i); | |||
geometry.push_back(bottomModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(bottomModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//north | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j, k + 1)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(northModel[(l * 3)] + (float)i); | |||
geometry.push_back(northModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(northModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//south | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i, j, k - 1)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(southModel[(l * 3)] + (float)i); | |||
geometry.push_back(southModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(southModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//east | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i + 1, j, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(eastModel[(l * 3)] + (float)i); | |||
geometry.push_back(eastModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(eastModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
//west | |||
if (chunk->isVoxelSolid(i,j,k)) { //check that it's solid | |||
if (!chunk->isVoxelSolid(i - 1, j, k)) { | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
geometry.push_back(westModel[(l * 3)] + (float)i); | |||
geometry.push_back(westModel[(l * 3) + 1] + (float)j); | |||
geometry.push_back(westModel[(l * 3) + 2] + (float)k); | |||
geometry.push_back(texUV[l*2]); | |||
geometry.push_back(texUV[(l*2)+1]); | |||
geometry.push_back(mLinkedWorld.voxelInfo.getTexIndexFromID(2, Face3D::TOP)); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
mUpdated = true; | |||
mLocked = false; | |||
} | |||
void ChunkMesh::rebuildChunkLighting() { | |||
//this doesn't do anything yet | |||
} | |||
void ChunkMesh::draw() { | |||
updateGeometry(); | |||
glBindVertexArray(mVAO); | |||
glDrawArrays(GL_TRIANGLES, 0, mGeometryFaceCount * 6); | |||
} | |||
bool ChunkMesh::updateGeometry() { | |||
if (mUpdated) { | |||
mUpdated = false; | |||
glBindBuffer(GL_ARRAY_BUFFER, mGeometryTexVBO); | |||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * geometry.size(), geometry.data(), GL_STATIC_DRAW); | |||
mGeometryFaceCount = mFaceCount; | |||
return true; | |||
} | |||
return false; | |||
} | |||
mUpdated = true; | |||
mLocked = false; | |||
} | |||
void ChunkMesh::rebuildChunkLighting() { | |||
//this doesn't do anything yet | |||
} | |||
void ChunkMesh::draw() { | |||
updateGeometry(); | |||
glBindVertexArray(mVAO); | |||
glDrawArrays(GL_TRIANGLES, 0, mGeometryFaceCount * 6); | |||
} | |||
bool ChunkMesh::updateGeometry() { | |||
if (mUpdated) { | |||
mUpdated = false; | |||
glBindBuffer(GL_ARRAY_BUFFER, mGeometryTexVBO); | |||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * geometry.size(), geometry.data(), GL_STATIC_DRAW); | |||
mGeometryFaceCount = mFaceCount; | |||
return true; | |||
} | |||
return false; | |||
} | |||
} //namespace vtk |
@@ -0,0 +1,16 @@ | |||
#include "graphics/superchunkmesh.h" | |||
namespace vtk { | |||
SuperChunkMesh::SuperChunkMesh() { | |||
} | |||
bool SuperChunkMesh::addMesh(ChunkMesh* mesh) { | |||
return true; | |||
} | |||
} | |||
longFunctionThatDoesStuff(objectWithLongName.x, | |||
objectWithLongName.y, | |||
objectWithLongName.z); |
@@ -15,18 +15,19 @@ int main (int argc, char *argv[]) | |||
vtk::LoggerSetup lSetup; | |||
lSetup.setup(); | |||
spdlog::get("general")->info("Starting Voxeltronik Engine..."); | |||
spdlog::get("general"); | |||
auto conf = new Config; | |||
conf->loadConfigFromFile("res/config.conf"); | |||
conf->addArgumentRule("-w", "graphics.res.x"); | |||
conf->addArgumentRule("-h", "graphics.res.y"); | |||
conf->loadConfigFromArguments(argc, argv); | |||
auto conf = new Config; | |||
conf->loadConfigFromFile("res/config.conf"); | |||
conf->addArgumentRule("-w", "graphics.res.x"); | |||
conf->addArgumentRule("-h", "graphics.res.y"); | |||
conf->loadConfigFromArguments(argc, argv); | |||
vtk::Game game; | |||
game.setConfig(conf); | |||
game.init(); | |||
game.setScene(new vtk::TestScene); | |||
game.start(); | |||
vtk::Game game; | |||
game.setConfig(conf); | |||
game.init(); | |||
game.setScene(new vtk::TestScene); | |||
game.start(); | |||
return 0; | |||
return 0; | |||
} |
@@ -3,15 +3,15 @@ | |||
* | |||
* Filename: testscene.cpp | |||
* | |||
* Description: | |||
* Description: | |||
* | |||
* Version: 1.0 | |||
* Created: 03/24/2014 11:06:32 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: YOUR NAME (), | |||
* Organization: | |||
* Author: YOUR NAME (), | |||
* Organization: | |||
* | |||
* ===================================================================================== | |||
*/ | |||
@@ -40,112 +40,112 @@ namespace vtk { | |||
void TestScene::init() { | |||
Tileset tiles; | |||
tiles.buildTexture(); | |||
tiles.updateTextureAt(0, "res/stone.png"); | |||
tiles.updateTextureAt(1, "res/dirt.png"); | |||
tiles.updateTextureAt(2, "res/test.png"); | |||
Tileset tiles; | |||
tiles.buildTexture(); | |||
tiles.updateTextureAt(0, "res/stone.png"); | |||
tiles.updateTextureAt(1, "res/dirt.png"); | |||
tiles.updateTextureAt(2, "res/test.png"); | |||
//define vertices | |||
float vertices[] { | |||
-0.01f, 0.01f, 0.0f, | |||
0.01f, -0.01f, 0.0f, | |||
-0.01f, -0.01f, 0.0f, | |||
-0.01f, 0.01f, 0.0f, | |||
0.01f, 0.01f, 0.0f, | |||
0.01f, -0.01f, 0.0f | |||
}; | |||
//define vertices | |||
float vertices[] { | |||
-0.01f, 0.01f, 0.0f, | |||
0.01f, -0.01f, 0.0f, | |||
-0.01f, -0.01f, 0.0f, | |||
-0.01f, 0.01f, 0.0f, | |||
0.01f, 0.01f, 0.0f, | |||
0.01f, -0.01f, 0.0f | |||
}; | |||
glGenBuffers(1, &vertVBO); | |||
glBindBuffer(GL_ARRAY_BUFFER, vertVBO); | |||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |||
glGenBuffers(1, &vertVBO); | |||
glBindBuffer(GL_ARRAY_BUFFER, vertVBO); | |||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |||
glGenVertexArrays(1, &vao); | |||
glBindVertexArray(vao); | |||
glBindBuffer(GL_ARRAY_BUFFER, vertVBO); | |||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); | |||
glGenVertexArrays(1, &vao); | |||
glBindVertexArray(vao); | |||
glBindBuffer(GL_ARRAY_BUFFER, vertVBO); | |||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); | |||
glEnableVertexAttribArray(0); | |||
glEnableVertexAttribArray(0); | |||
//shaders | |||
//shaders | |||
mCursorShader.loadShaderFiles("res/shaders/test.vert.glsl", "res/shaders/test.frag.glsl"); | |||
cursorShaders = LoadShaders("res/shaders/test.vert.glsl", "res/shaders/test.frag.glsl"); | |||
shaders = LoadShaders("res/shaders/voxelvert.vert.glsl", "res/shaders/voxelfrag.frag.glsl"); | |||
cursorShaders = LoadShaders("res/shaders/test.vert.glsl", "res/shaders/test.frag.glsl"); | |||
shaders = LoadShaders("res/shaders/voxelvert.vert.glsl", "res/shaders/voxelfrag.frag.glsl"); | |||
glUseProgram(shaders); | |||
glUseProgram(shaders); | |||
camera.setPosition(glm::vec3(0.0f, 5.0f, 5.0f)); | |||
camera.setAspectRatio(linkedGame->window.getAspect()); | |||
camera.setPosition(glm::vec3(0.0f, 5.0f, 5.0f)); | |||
camera.setAspectRatio(linkedGame->window.getAspect()); | |||
viewMatUni = glGetUniformLocation(shaders, "view"); | |||
projMatUni = glGetUniformLocation(shaders, "proj"); | |||
modelMatUni = glGetUniformLocation(shaders, "model"); | |||
world.modelMatUni = modelMatUni; | |||
viewMatUni = glGetUniformLocation(shaders, "view"); | |||
projMatUni = glGetUniformLocation(shaders, "proj"); | |||
modelMatUni = glGetUniformLocation(shaders, "model"); | |||
world.modelMatUni = modelMatUni; | |||
mSkyboxTask = new RenderTask(mSkybox, camera, linkedGame->window); | |||
glUniformMatrix4fv(viewMatUni, 1, GL_FALSE, glm::value_ptr(camera.getViewMatrix())); | |||
glUniformMatrix4fv(projMatUni, 1, GL_FALSE, glm::value_ptr(linkedGame->window.getProjectionMatrix())); | |||
//nanovg | |||
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); | |||
nvgCreateFont(vg, "mono", "res/fonts/DejaVuSansMono.ttf"); | |||
SDL_SetRelativeMouseMode(SDL_TRUE); | |||
sensitivity = linkedGame->getConfig()->getValue<float>("controls.mouse.sensitivity", 5.0f); | |||
//get config | |||
Config* conf = linkedGame->getConfig(); | |||
//add actions to handler | |||
handler.setAction("Move Forward", conf->getValue<std::string>("controls.bindings.movement.forward", "W" )); | |||
handler.setAction("Move Backward", conf->getValue<std::string>("controls.bindings.movement.backward", "S" )); | |||
handler.setAction("Move Left", conf->getValue<std::string>("controls.bindings.movement.left", "A" )); | |||
handler.setAction("Move Right", conf->getValue<std::string>("controls.bindings.movement.right", "D" )); | |||
handler.setAction("Move Up", conf->getValue<std::string>("controls.bindings.movement.up", "Space" )); | |||
handler.setAction("Move Down", conf->getValue<std::string>("controls.bindings.movement.down", "Left Ctrl")); | |||
handler.setAction("Place Voxel", conf->getValue<std::string>("controls.bindings.action.placevoxel", "Mouse Left")); | |||
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" )); | |||
//set signals for handler | |||
handler.getEventSignal(SDL_QUIT ).connect<Game , &Game::stop >(linkedGame); | |||
handler.getEventSignal(SDL_MOUSEMOTION).connect<TestScene, &TestScene::look>(this); | |||
world.voxelInfo.setTextureData(1, Face3D::RIGHT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::LEFT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::TOP, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::BOTTOM, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::FRONT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::BACK, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::RIGHT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::LEFT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::TOP, Orientation2D::UP, 2.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::BOTTOM, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::FRONT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::BACK, Orientation2D::UP, 1.0f); | |||
//world.voxelInfo.setTransparent(1, false); | |||
//world.voxelInfo.setTransparent(2, false); | |||
std::cout << std::endl; | |||
int chunkCount = 1; | |||
for (int i = 0; i < 8; i++) { | |||
for (int j = 0; j < 8; j++) { | |||
for (int k = 0; k < 8; k++) { | |||
std::cout << "\rGenerating chunks (" << chunkCount << "/" << 8*8*8 << ")" << std::flush; | |||
world.generateChunk(i,j,k); | |||
chunkCount++; | |||
} | |||
} | |||
} | |||
//world.forceGlobalGeometryUpdate(); | |||
voxelType = 1; | |||
glUniformMatrix4fv(viewMatUni, 1, GL_FALSE, glm::value_ptr(camera.getViewMatrix())); | |||
glUniformMatrix4fv(projMatUni, 1, GL_FALSE, glm::value_ptr(linkedGame->window.getProjectionMatrix())); | |||
//nanovg | |||
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); | |||
nvgCreateFont(vg, "mono", "res/fonts/DejaVuSansMono.ttf"); | |||
SDL_SetRelativeMouseMode(SDL_TRUE); | |||
sensitivity = linkedGame->getConfig()->getValue<float>("controls.mouse.sensitivity", 5.0f); | |||
//get config | |||
Config* conf = linkedGame->getConfig(); | |||
//add actions to handler | |||
handler.setAction("Move Forward", conf->getValue<std::string>("controls.bindings.movement.forward", "W" )); | |||
handler.setAction("Move Backward", conf->getValue<std::string>("controls.bindings.movement.backward", "S" )); | |||
handler.setAction("Move Left", conf->getValue<std::string>("controls.bindings.movement.left", "A" )); | |||
handler.setAction("Move Right", conf->getValue<std::string>("controls.bindings.movement.right", "D" )); | |||
handler.setAction("Move Up", conf->getValue<std::string>("controls.bindings.movement.up", "Space" )); | |||
handler.setAction("Move Down", conf->getValue<std::string>("controls.bindings.movement.down", "Left Ctrl")); | |||
handler.setAction("Place Voxel", conf->getValue<std::string>("controls.bindings.action.placevoxel", "Mouse Left")); | |||
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" )); | |||
//set signals for handler | |||
handler.getEventSignal(SDL_QUIT ).connect<Game , &Game::stop >(linkedGame); | |||
handler.getEventSignal(SDL_MOUSEMOTION).connect<TestScene, &TestScene::look>(this); | |||
world.voxelInfo.setTextureData(1, Face3D::RIGHT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::LEFT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::TOP, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::BOTTOM, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::FRONT, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(1, Face3D::BACK, Orientation2D::UP, 0.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::RIGHT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::LEFT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::TOP, Orientation2D::UP, 2.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::BOTTOM, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::FRONT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::BACK, Orientation2D::UP, 1.0f); | |||
//world.voxelInfo.setTransparent(1, false); | |||
//world.voxelInfo.setTransparent(2, false); | |||
std::cout << std::endl; | |||
int chunkCount = 1; | |||
for (int i = 0; i < 64; i++) { | |||
for (int j = 0; j < 8; j++) { | |||
for (int k = 0; k < 64; k++) { | |||
std::cout << "\rGenerating chunks (" << chunkCount << "/" << 8*8*8 << ")" << std::flush; | |||
world.generateChunk(i,j,k); | |||
chunkCount++; | |||
} | |||
} | |||
} | |||
//world.forceGlobalGeometryUpdate(); | |||
voxelType = 1; | |||
} | |||
void TestScene::reInit() { | |||
@@ -153,78 +153,78 @@ void TestScene::reInit() { | |||
} | |||
void TestScene::update(const float& dTime) { | |||
this->dTime = dTime; | |||
camera.update(dTime); | |||
handler.update(); | |||
world.update(); | |||
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("Select Type 1")) voxelType = 1; | |||
if (handler.isActionDown("Select Type 2")) voxelType = 2; | |||
//place voxel testing | |||
if ((handler.isActionDown("Place Voxel") || handler.isActionDown("Delete Voxel")) && !placeVoxel) { | |||
placeVoxel = true; | |||
//perform a raycast | |||
glm::vec3 hitPos; | |||
glm::vec3 hitNormal; | |||
bool success; | |||
world.voxelMath.rayCast(hitPos, hitNormal, success, camera.getPosition(), camera.getAngleVector(), 10); | |||
if (success) { | |||
std::cout << "Hit voxel at: " << hitPos.x << ", " << hitPos.y << ", " << hitPos.z << std::endl; | |||
if (handler.isActionDown("Place Voxel")) { | |||
world.setVoxelType((int)(hitPos.x + hitNormal.x), (int)(hitPos.y + hitNormal.y), (int)(hitPos.z + hitNormal.z), voxelType, true); | |||
} else { | |||
world.setVoxelType((int)(hitPos.x), (int)(hitPos.y), (int)(hitPos.z), 0, true); | |||
} | |||
} | |||
} else if (!(handler.isActionDown("Place Voxel") || handler.isActionDown("Delete Voxel")) && placeVoxel) { | |||
placeVoxel = false; | |||
} | |||
//camera.moveRelative(camMovement * dTime); | |||
this->dTime = dTime; | |||
camera.update(dTime); | |||
handler.update(); | |||
world.update(); | |||
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("Select Type 1")) voxelType = 1; | |||
if (handler.isActionDown("Select Type 2")) voxelType = 2; | |||
//place voxel testing | |||
if ((handler.isActionDown("Place Voxel") || handler.isActionDown("Delete Voxel")) && !placeVoxel) { | |||
placeVoxel = true; | |||
//perform a raycast | |||
glm::vec3 hitPos; | |||
glm::vec3 hitNormal; | |||
bool success; | |||
world.voxelMath.rayCast(hitPos, hitNormal, success, camera.getPosition(), camera.getAngleVector(), 10); | |||
if (success) { | |||
std::cout << "Hit voxel at: " << hitPos.x << ", " << hitPos.y << ", " << hitPos.z << std::endl; | |||
if (handler.isActionDown("Place Voxel")) { | |||
world.setVoxelType((int)(hitPos.x + hitNormal.x), (int)(hitPos.y + hitNormal.y), (int)(hitPos.z + hitNormal.z), voxelType, true); | |||
} else { | |||
world.setVoxelType((int)(hitPos.x), (int)(hitPos.y), (int)(hitPos.z), 0, true); | |||
} | |||
} | |||
} else if (!(handler.isActionDown("Place Voxel") || handler.isActionDown("Delete Voxel")) && placeVoxel) { | |||
placeVoxel = false; | |||
} | |||
//camera.moveRelative(camMovement * dTime); | |||
} | |||
void TestScene::draw() { | |||
mSkyboxTask->draw(); | |||
gls::setShader(shaders); | |||
glUniformMatrix4fv(viewMatUni, 1, GL_FALSE, glm::value_ptr(camera.getViewMatrix())); | |||
world.draw(); | |||
glDisable(GL_DEPTH_TEST); | |||
mCursorShader.activate(); | |||
glBindVertexArray(vao); | |||
glDrawArrays(GL_TRIANGLES, 0, 6); | |||
nvgBeginFrame(vg, 1920, 1080, 1); | |||
nvgFontSize(vg, 14.0f); | |||
nvgFontFace(vg, "mono"); | |||
nvgFillColor(vg, nvgRGBA(0, 0, 0, 190)); | |||
std::string fpsString = std::to_string(mFPS); | |||
nvgText(vg, 5, 19, fpsString.data(), NULL); | |||
nvgEndFrame(vg); | |||
glFrontFace(GL_CW); | |||
glEnable(GL_CULL_FACE); | |||
glEnable(GL_DEPTH_TEST); | |||
mSkyboxTask->draw(); | |||
gls::setShader(shaders); | |||
glUniformMatrix4fv(viewMatUni, 1, GL_FALSE, glm::value_ptr(camera.getViewMatrix())); | |||
world.draw(); | |||
glDisable(GL_DEPTH_TEST); | |||
mCursorShader.activate(); | |||
glBindVertexArray(vao); | |||
glDrawArrays(GL_TRIANGLES, 0, 6); | |||
nvgBeginFrame(vg, 1920, 1080, 1); | |||
nvgFontSize(vg, 14.0f); | |||
nvgFontFace(vg, "mono"); | |||
nvgFillColor(vg, nvgRGBA(0, 0, 0, 190)); | |||
std::string fpsString = std::to_string(mFPS); | |||
nvgText(vg, 5, 19, fpsString.data(), NULL); | |||
nvgEndFrame(vg); | |||
glFrontFace(GL_CW); | |||
glEnable(GL_CULL_FACE); | |||
glEnable(GL_DEPTH_TEST); | |||
} | |||
void TestScene::look() { | |||
int x, y; //mouse change | |||
SDL_GetRelativeMouseState(&x, &y); | |||
camera.rotate((float)x * sensitivity * 0.001f, (float)y * sensitivity * 0.001f); | |||
//camera.rotate((float)x, (float)y); | |||
int x, y; //mouse change | |||
SDL_GetRelativeMouseState(&x, &y); | |||
camera.rotate((float)x * sensitivity * 0.001f, (float)y * sensitivity * 0.001f); | |||
//camera.rotate((float)x, (float)y); | |||
} | |||
} |
@@ -3,15 +3,15 @@ | |||
* | |||
* Filename: world.cpp | |||
* | |||
* Description: | |||
* Description: | |||
* | |||
* Version: 1.0 | |||
* Created: 04/03/2014 09:53:00 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: YOUR NAME (), | |||
* Organization: | |||
* Author: YOUR NAME (), | |||
* Organization: | |||
* | |||
* ===================================================================================== | |||
*/ | |||
@@ -32,208 +32,211 @@ | |||
namespace vtk { | |||
{ | |||
asd; | |||
} | |||
World::World() { | |||
chunkSize = 16; | |||
voxelSize = 1.0f; | |||
voxelInfo.linkedWorld = this; | |||
voxelMath.linkedWorld = this; | |||
rebuildThreadActive = false; | |||
chunkSize = 16; | |||
voxelSize = 1.0f; | |||
voxelInfo.linkedWorld = this; | |||
voxelMath.linkedWorld = this; | |||
rebuildThreadActive = false; | |||
} | |||
bool World::isVoxelSolid(const int& x, const int& y, const int& z) { | |||
auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), | |||
floor((float)y / (float)chunkSize), | |||
floor((float)z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk | |||
return true; | |||
} | |||
int relPosX = x - chunkPos.x * chunkSize; | |||
int relPosY = y - chunkPos.y * chunkSize; | |||
int relPosZ = z - chunkPos.z * chunkSize; | |||
return mChunks[chunkPos]->isVoxelSolid(relPosX, relPosY, relPosZ); | |||
auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), | |||
floor((float)y / (float)chunkSize), | |||
floor((float)z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk | |||
return true; | |||
} | |||
int relPosX = x - chunkPos.x * chunkSize; | |||
int relPosY = y - chunkPos.y * chunkSize; | |||
int relPosZ = z - chunkPos.z * chunkSize; | |||
return mChunks[chunkPos]->isVoxelSolid(relPosX, relPosY, relPosZ); | |||
} | |||
bool World::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& updateChunk) { | |||
auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), floor((float)y / (float)chunkSize), floor((float)z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk | |||
return false; | |||
} | |||
int relPosX = x - chunkPos.x * chunkSize; | |||
int relPosY = y - chunkPos.y * chunkSize; | |||
int relPosZ = z - chunkPos.z * chunkSize; | |||
mChunks[chunkPos]->setVoxelType(relPosX, relPosY, relPosZ, type); | |||
if (updateChunk) queueChunkUpdate(chunkPos, true); | |||
return true; | |||
auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), floor((float)y / (float)chunkSize), floor((float)z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk | |||
return false; | |||
} | |||
int relPosX = x - chunkPos.x * chunkSize; | |||
int relPosY = y - chunkPos.y * chunkSize; | |||
int relPosZ = z - chunkPos.z * chunkSize; | |||
mChunks[chunkPos]->setVoxelType(relPosX, relPosY, relPosZ, type); | |||
if (updateChunk) queueChunkUpdate(chunkPos, true); | |||
return true; | |||
} | |||
unsigned World::getVoxelType(const glm::ivec3& pos) { | |||
auto chunkPos = glm::ivec3(floor((float)pos.x / (float)chunkSize), | |||
floor((float)pos.y / (float)chunkSize), | |||
floor((float)pos.z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { | |||
return 0; | |||
} | |||
int relPosX = pos.x - chunkPos.x * chunkSize; | |||
int relPosY = pos.y - chunkPos.y * chunkSize; | |||
int relPosZ = pos.z - chunkPos.z * chunkSize; | |||
return mChunks[chunkPos]->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ); | |||
auto chunkPos = glm::ivec3(floor((float)pos.x / (float)chunkSize), | |||
floor((float)pos.y / (float)chunkSize), | |||
floor((float)pos.z / (float)chunkSize)); | |||
if (mChunks.find(chunkPos) == mChunks.end()) { | |||
return 0; | |||
} | |||
int relPosX = pos.x - chunkPos.x * chunkSize; | |||
int relPosY = pos.y - chunkPos.y * chunkSize; | |||
int relPosZ = pos.z - chunkPos.z * chunkSize; | |||
return mChunks[chunkPos]->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ); | |||
} | |||
bool World::makeChunk(const int& x, const int& y, const int& z) { | |||
auto pos = glm::ivec3(x, y, z); | |||
auto pos = glm::ivec3(x, y, z); | |||
if (mChunks.find(pos) != mChunks.end()) { //chunk already exists | |||
return false; | |||
} | |||
if (mChunks.find(pos) != mChunks.end()) { //chunk already exists | |||
return false; | |||
} | |||
auto newChunk = new Chunk(*this); | |||
mChunks[pos] = newChunk; | |||
auto newChunk = new Chunk(*this); | |||
mChunks[pos] = newChunk; | |||
newChunk->setPos(pos); | |||
newChunk->setPos(pos); | |||
mChunkMeshes.emplace(pos, ChunkMesh(*this, pos)); | |||
mChunkMeshes.emplace(pos, ChunkMesh(*this, pos)); | |||
return true; | |||
return true; | |||
} | |||
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))); | |||
//queue this chunk for geometry update | |||
queueChunkUpdate(x,y,z); | |||
//queue the neighboring 6 chunks. the queue functions throws them out | |||
// if they don't exist | |||
queueChunkUpdate(x+1,y,z); | |||
queueChunkUpdate(x-1,y,z); | |||
queueChunkUpdate(x,y+1,z); | |||
queueChunkUpdate(x,y-1,z); | |||
queueChunkUpdate(x,y,z+1); | |||
queueChunkUpdate(x,y,z-1); | |||
} | |||
return chunkMade; | |||
bool chunkMade = makeChunk(x,y,z); | |||
if (chunkMade) { | |||
terrain.generateChunk(getChunk(glm::ivec3(x,y,z))); | |||
//queue this chunk for geometry update | |||
queueChunkUpdate(x,y,z); | |||
//queue the neighboring 6 chunks. the queue functions throws them out | |||
// if they don't exist | |||
queueChunkUpdate(x+1,y,z); | |||
queueChunkUpdate(x-1,y,z); | |||
queueChunkUpdate(x,y+1,z); | |||
queueChunkUpdate(x,y-1,z); | |||
queueChunkUpdate(x,y,z+1); | |||
queueChunkUpdate(x,y,z-1); | |||
} | |||
return chunkMade; | |||
} | |||
Chunk* World::getChunk(const glm::ivec3& pos) { | |||
auto chunk = mChunks.find(pos)->second; | |||
if (chunk) return chunk; | |||
else return nullptr; | |||
} | |||
void World::queueChunkUpdate(const int& x, const int& y, const int& z, const bool& back) { | |||
queueChunkUpdate(glm::ivec3(x,y,z)); | |||
Chunk* World::getChunk(const glm::ivec3& pos) { | |||
auto chunk = mChunks.find(pos)->second; | |||
if (chunk) return chunk; | |||
else return nullptr; | |||
} | |||
void World::queueChunkUpdate(const int& x, const int& y, const int& z, const bool& back) { | |||
queueChunkUpdate(glm::ivec3(x,y,z)); | |||
} | |||
void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) { | |||
if (mChunks.find(pos) == mChunks.end()) 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 | |||
} | |||
if (back) { | |||
mChunkUpdateQueue.push_back(pos); | |||
} else { | |||
mChunkUpdateQueue.push_front(pos); | |||
} | |||
void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) { | |||
if (mChunks.find(pos) == mChunks.end()) 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 | |||
} | |||
if (back) { | |||
mChunkUpdateQueue.push_back(pos); | |||
} else { | |||
mChunkUpdateQueue.push_front(pos); | |||
} | |||
} | |||
void World::draw() { | |||
/* | |||
for (auto& i : chunks) { | |||
glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3( | |||
(float)i.second->getPos().x * 16, | |||
(float)i.second->getPos().y * 16, | |||
(float)i.second->getPos().z * 16 | |||
)); | |||
glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat)); | |||
i.second->renderer.drawChunk(); | |||
} | |||
*/ | |||
for (auto& i : mChunkMeshes) { | |||
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(); | |||
} | |||
/* | |||
for (auto& i : chunks) { | |||
glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3( | |||
(float)i.second->getPos().x * 16, | |||
(float)i.second->getPos().y * 16, | |||
(float)i.second->getPos().z * 16 | |||
)); | |||
glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat)); | |||
i.second->renderer.drawChunk(); | |||
} | |||
*/ | |||
for (auto& i : mChunkMeshes) { | |||
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(); | |||
} | |||
} | |||
void World::update() { | |||
if (!rebuildThreadActive && !mChunkUpdateQueue.empty( )) { | |||
auto updatefunc = [&]() { | |||
while (!mChunkUpdateQueue.empty()) { | |||
auto& pos = mChunkUpdateQueue.back(); | |||
auto& mesh = mChunkMeshes.find(pos)->second; | |||
mChunkUpdateQueue.pop_back(); | |||
mesh.rebuildChunkGeometry(); | |||
} | |||
rebuildThreadActive = false; | |||
}; | |||
rebuildThreadActive = true; | |||
std::thread(updatefunc).detach(); | |||
} | |||
/* | |||
while (!chunkUpdateQueue.empty()) { | |||
auto chunk = chunks[chunkUpdateQueue.back()]; | |||
chunkUpdateQueue.pop_back(); | |||
std::thread(&ChunkRenderer::updateGeometry, &chunk->renderer).detach(); | |||
auto& pos = chunkUpdateQueue.back(); | |||
auto posVec = glm::ivec3(std::get<0>(pos), std::get<1>(pos), std::get<2>(pos)); | |||
auto& mesh = mChunkMeshes.find(posVec)->second; | |||
chunkUpdateQueue.pop_back(); | |||
//mesh.rebuildChunkGeometry(); | |||
std::thread(&ChunkMesh::rebuildChunkGeometry, &mesh).detach(); | |||
mChunkGeometryUpdateQueue.push_back(posVec); | |||
} | |||
for (auto& i : chunks) { | |||
i.second->renderer.updateVertexData(); | |||
} | |||
auto it = mChunkGeometryUpdateQueue.begin(); | |||
while (it != mChunkGeometryUpdateQueue.end()) { | |||
if (mChunkMeshes.find(*it)->second.updateGeometry()) { | |||
std::cout << "updated chunk " << it->x << "," << it->y << "," << it->z; | |||
mChunkGeometryUpdateQueue.erase(it); | |||
} | |||
else ++it; | |||
} | |||
*/ | |||
if (!rebuildThreadActive && !mChunkUpdateQueue.empty( )) { | |||
auto updatefunc = [&]() { | |||
while (!mChunkUpdateQueue.empty()) { | |||
auto& pos = mChunkUpdateQueue.back(); | |||
auto& mesh = mChunkMeshes.find(pos)->second; | |||
mChunkUpdateQueue.pop_back(); | |||
mesh.rebuildChunkGeometry(); | |||
} | |||
rebuildThreadActive = false; | |||
}; | |||
rebuildThreadActive = true; | |||
std::thread(updatefunc).detach(); | |||
} | |||
/* | |||
while (!chunkUpdateQueue.empty()) { | |||
auto chunk = chunks[chunkUpdateQueue.back()]; | |||
chunkUpdateQueue.pop_back(); | |||
std::thread(&ChunkRenderer::updateGeometry, &chunk->renderer).detach(); | |||
auto& pos = chunkUpdateQueue.back(); | |||
auto posVec = glm::ivec3(std::get<0>(pos), std::get<1>(pos), std::get<2>(pos)); | |||
auto& mesh = mChunkMeshes.find(posVec)->second; | |||
chunkUpdateQueue.pop_back(); | |||
//mesh.rebuildChunkGeometry(); | |||
std::thread(&ChunkMesh::rebuildChunkGeometry, &mesh).detach(); | |||
mChunkGeometryUpdateQueue.push_back(posVec); | |||
} | |||
for (auto& i : chunks) { | |||
i.second->renderer.updateVertexData(); | |||
} | |||
auto it = mChunkGeometryUpdateQueue.begin(); | |||
while (it != mChunkGeometryUpdateQueue.end()) { | |||
if (mChunkMeshes.find(*it)->second.updateGeometry()) { | |||
std::cout << "updated chunk " << it->x << "," << it->y << "," << it->z; | |||
mChunkGeometryUpdateQueue.erase(it); | |||
} | |||
else ++it; | |||
} | |||
*/ | |||
} | |||
void World::forceGlobalGeometryUpdate() { | |||
int chunkCount = 1; | |||
/* | |||
for (auto& i : chunks) { | |||
std::cout << "\rUpdating chunk geometry (" << chunkCount << "/" << chunks.size() << ")" << std::flush; | |||
i.second->renderer.updateGeometry(); | |||
chunkCount++; | |||
//i.second->renderer.updateVertexData(); | |||
} | |||
*/ | |||
chunkCount = 1; | |||
for (auto& i : mChunkMeshes) { | |||
std::cout << "\rUpdating chunk geometry, but better (" << chunkCount << "/" << mChunkMeshes.size() << ")" << std::flush; | |||
i.second.rebuildChunkGeometry(); | |||
i.second.updateGeometry(); | |||
++chunkCount; | |||
} | |||
int chunkCount = 1; | |||
/* | |||
for (auto& i : chunks) { | |||
std::cout << "\rUpdating chunk geometry (" << chunkCount << "/" << chunks.size() << ")" << std::flush; | |||
i.second->renderer.updateGeometry(); | |||
chunkCount++; | |||
//i.second->renderer.updateVertexData(); | |||
} | |||
*/ | |||
chunkCount = 1; | |||
for (auto& i : mChunkMeshes) { | |||
std::cout << "\rUpdating chunk geometry, but better (" << chunkCount << "/" << mChunkMeshes.size() << ")" << std::flush; | |||
i.second.rebuildChunkGeometry(); | |||
i.second.updateGeometry(); | |||
++chunkCount; | |||
} | |||
} | |||
} |