@@ -1,3 +1,6 @@ | |||
[submodule "spdlog"] | |||
path = spdlog | |||
url = https://github.com/gabime/spdlog.git | |||
[submodule "libcuckoo"] | |||
path = libcuckoo | |||
url = https://github.com/efficient/libcuckoo.git |
@@ -1,7 +1,7 @@ | |||
cmake_minimum_required (VERSION 3.6) | |||
project ("voxeltronik") | |||
file (GLOB_RECURSE SOURCES "src/*.cpp" "src/*.c") | |||
include_directories("./include") | |||
include_directories("./include" "libcuckoo/libcuckoo") | |||
set(CMAKE_CXX_STANDARD 14) | |||
set(CMAKE_CXX_FLAGS "-O2") | |||
set(CMAKE_EXPORT_COMPILE_COMMANDS on) | |||
@@ -11,3 +11,4 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE) | |||
find_package(Threads REQUIRED) | |||
target_link_libraries(vtk SDL2 GL GLEW GLU ${CMAKE_THREAD_LIBS_INIT}) | |||
@@ -34,7 +34,7 @@ public: | |||
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); | |||
void setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& update = false); | |||
unsigned getVoxelType(const unsigned& x, const unsigned& y, const unsigned& z); | |||
glm::ivec3 getWorldCoords(const int& x, const int& y, const int& z); | |||
@@ -48,7 +48,7 @@ protected: | |||
std::array<unsigned, 4096> voxels; | |||
World& mLinkedWorld; | |||
glm::ivec3 mPos; | |||
bool mLoaded; | |||
std::atomic<bool> mLoaded; | |||
}; | |||
} |
@@ -52,6 +52,7 @@ enum class Orientation2D { | |||
struct VoxelData{ | |||
std::map<Face3D, float> faceTextureIndices; | |||
std::map<Face3D, Orientation2D> faceOrientation; | |||
std::map<FaceDirection, unsigned> faceTextures; | |||
bool transparent; | |||
}; | |||
@@ -63,11 +64,15 @@ public: | |||
void pushTexCoordFromWorldCoords(std::vector<float>& data, const glm::ivec3& pos, const Face3D& face, const Corner2D& corner); | |||
void pushTexCoordFromVoxelID(std::vector<float>& data, const unsigned& id, const Face3D& face, const Corner2D& corner); | |||
float getTexIndexFromID(const unsigned& id, const Face3D& face); | |||
unsigned getTextureIndex(const unsigned& id, const FaceDirection& face); | |||
void setTextureIndex(const unsigned& id, const FaceDirection& face, const unsigned& index); | |||
void setAllTextureIndexes(const unsigned& id, const unsigned& index); | |||
void setTextureData(const unsigned& id, const Face3D& face, const Orientation2D& orientation, const float& textureIndex); | |||
void setTransparent(const unsigned& id, const bool& transparent); | |||
bool isTransparent(const unsigned& id); | |||
bool isTransparent(const unsigned& id); | |||
std::pair<float, float> getTexCoordFromID(const unsigned& id, const Face3D& face, const Corner2D& corner); | |||
@@ -23,6 +23,15 @@ | |||
namespace vtk { | |||
enum class FaceDirection { | |||
TOP = 0, | |||
BOTTOM = 1, | |||
NORTH = 2, | |||
SOUTH = 3, | |||
EAST = 4, | |||
WEST = 5 | |||
}; | |||
typedef std::tuple<unsigned, unsigned, unsigned> uPos; //used for voxel positions | |||
struct uPosHash : public std::unary_function<uPos, std::size_t> { | |||
@@ -58,7 +67,11 @@ struct iPosEqual : public std::binary_function<iPos, iPos, bool> { | |||
// basic hash function for glm::ivec3 | |||
struct ivec3Hash : public std::unary_function<iPos, std::size_t> { | |||
std::size_t operator()(const glm::ivec3& k) const { | |||
return k.x ^ k.y ^ k.z; | |||
std::size_t seed = 3; | |||
for(int i = 0; i < 3; ++i) { | |||
seed ^= k[i] + 0x9e3779b9 + (seed << 6) + (seed >> 2); | |||
} | |||
return seed; | |||
} | |||
}; | |||
@@ -23,6 +23,7 @@ | |||
#include "voxelmath.h" | |||
#include "terraingen.h" | |||
#include "graphics/chunkmesh.h" | |||
#include "cuckoohash_map.hh" | |||
#include <unordered_map> | |||
#include <vector> | |||
@@ -60,7 +61,8 @@ public: | |||
void queueChunkLoadsAroundPoint(const glm::vec3& point, const int& chunkRadius); | |||
std::unordered_map<glm::ivec3, Chunk*, ivec3Hash> mChunks; | |||
//std::unordered_map<glm::ivec3, Chunk*, ivec3Hash> mChunks; | |||
cuckoohash_map<glm::ivec3, Chunk*, ivec3Hash> mChunks; | |||
std::unordered_map<glm::ivec3, ChunkMesh, ivec3Hash> mChunkMeshes; | |||
std::vector<iPos> chunkUpdateQueue; | |||
std::deque<glm::ivec3> mChunkUpdateQueue; |
@@ -0,0 +1 @@ | |||
Subproject commit 6591795a944fa8c7268848d181ba2852f4a7897f |
@@ -5,31 +5,33 @@ layout(location = 0) in uint position; | |||
//layout(location = 1) in vec3 texCoord; | |||
layout(location = 1) in uint face_attrib; | |||
uniform mat4 proj, view, model; //transform matrix | |||
uniform mat4 proj, view, model; //transform matrix | |||
out vec3 texCoordInterp; | |||
out vec3 lightDataInterp; | |||
out vec4 eyeSpacePos; | |||
out vec3 texCoordInterp; | |||
out vec3 lightDataInterp; | |||
out vec4 eyeSpacePos; | |||
void main() { | |||
vec3 pos_unpacked; | |||
pos_unpacked.x = float((position >> 8u) & 15u) / 15.0f; | |||
pos_unpacked.y = float((position >> 4u) & 15u) / 15.0f; | |||
pos_unpacked.z = float((position) & 15u) / 15.0f; | |||
void main() { | |||
vec3 pos_unpacked; | |||
pos_unpacked.x = float((position >> 8u) & 15u) / 15.0f; | |||
pos_unpacked.y = float((position >> 4u) & 15u) / 15.0f; | |||
pos_unpacked.z = float((position) & 15u) / 15.0f; | |||
vec2 uv_unpacked; | |||
uv_unpacked.x = float((position >> 16u) & 15u) / 15.0f; | |||
uv_unpacked.y = float((position >> 12u) & 15u) / 15.0f; | |||
vec2 uv_unpacked; | |||
uv_unpacked.x = float((position >> 16u) & 15u) / 15.0f; | |||
uv_unpacked.y = float((position >> 12u) & 15u) / 15.0f; | |||
vec3 offset_unpacked; | |||
offset_unpacked.x = float((face_attrib >> 10u) & 31u); | |||
offset_unpacked.y = float((face_attrib >> 5u) & 31u); | |||
offset_unpacked.z = float((face_attrib) & 31u); | |||
vec3 offset_unpacked; | |||
offset_unpacked.x = float((face_attrib >> 10u) & 31u); | |||
offset_unpacked.y = float((face_attrib >> 5u) & 31u); | |||
offset_unpacked.z = float((face_attrib) & 31u); | |||
float tex_index = float(face_attrib >> 15u); | |||
vec3 final_position = pos_unpacked + offset_unpacked; | |||
vec4 eyeSpacePosVert = view * model * vec4(final_position, 1.0); | |||
gl_Position = proj * eyeSpacePosVert; | |||
texCoordInterp = vec3(uv_unpacked, 2.0f);//texCoord; | |||
texCoordInterp = vec3(uv_unpacked, tex_index);//texCoord; | |||
lightDataInterp = vec3(1.0f, 1.0f, 1.0f); | |||
eyeSpacePos = eyeSpacePosVert; | |||
} |
@@ -0,0 +1,218 @@ | |||
#include "world.h" | |||
#include "chunk.h" | |||
#include "threadpool.h" | |||
#include <cmath> | |||
#include <iostream> | |||
#include <thread> | |||
#include <GL/glew.h> | |||
#include <GL/gl.h> | |||
#define GLM_FORCE_RADIANS | |||
#include <glm/glm.hpp> | |||
#include <glm/gtc/type_ptr.hpp> | |||
#include <glm/gtc/matrix_transform.hpp> | |||
namespace vtk { | |||
World::World() { | |||
chunkSize = 16; | |||
voxelSize = 1.0f; | |||
voxelInfo.linkedWorld = this; | |||
voxelMath.linkedWorld = this; | |||
rebuildThreadActive = false; | |||
mLoadThreadActive = 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)); | |||
auto chunk = getChunk(chunkPos); | |||
if (chunk) //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; | |||
if (!chunk->isLoaded()) return true; | |||
return chunk->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)); | |||
auto chunk = getChunk(chunkPos); | |||
if (!chunk) return false; | |||
int relPosX = x - chunkPos.x * chunkSize; | |||
int relPosY = y - chunkPos.y * chunkSize; | |||
int relPosZ = z - chunkPos.z * chunkSize; | |||
chunk->setVoxelType(relPosX, relPosY, relPosZ, type, updateChunk); | |||
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)); | |||
Chunk* chunk; | |||
if (!mChunks.find(chunkPos, chunk)) { | |||
return 0; | |||
} | |||
int relPosX = pos.x - chunkPos.x * chunkSize; | |||
int relPosY = pos.y - chunkPos.y * chunkSize; | |||
int relPosZ = pos.z - chunkPos.z * chunkSize; | |||
return chunk->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ); | |||
} | |||
Chunk* World::makeChunk(const int& x, const int& y, const int& z, bool insertAfter) { | |||
auto pos = glm::ivec3(x, y, z); | |||
Chunk* chunk; | |||
if (mChunks.find(pos, chunk)) { //chunk already exists | |||
return chunk; | |||
} | |||
chunk = new Chunk(*this); | |||
chunk->setPos(pos); | |||
if (insertAfter) insertChunk(chunk); | |||
return chunk; | |||
} | |||
bool World::generateChunk(const int& x, const int& y, const int& z) { | |||
auto chunkMade = makeChunk(x,y,z, false); | |||
if (chunkMade != nullptr) { | |||
terrain.generateChunk(chunkMade); | |||
//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); | |||
} | |||
insertChunk(chunkMade); | |||
return chunkMade; | |||
} | |||
bool World::insertChunk(Chunk* chunk) { | |||
mChunks.insert(chunk->getPos(), chunk); | |||
mChunkMeshes.emplace(chunk->getPos(), ChunkMesh(*this, chunk->getPos())); | |||
return true; | |||
} | |||
Chunk* World::getChunk(const glm::ivec3& pos) { | |||
Chunk* chunk; | |||
if (mChunks.find(pos, 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 (!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 | |||
} | |||
if (back) { | |||
mChunkUpdateQueue.push_back(pos); | |||
} else { | |||
mChunkUpdateQueue.push_front(pos); | |||
} | |||
} | |||
void World::queueChunkLoad(const glm::ivec3 &pos) { | |||
if (getChunk(pos)) 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, | |||
(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(); | |||
if (!mesh.rebuildChunkGeometry()) | |||
queueChunkUpdate(pos); | |||
} | |||
rebuildThreadActive = false; | |||
}; | |||
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() { | |||
int chunkCount = 1; | |||
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; | |||
} | |||
} | |||
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)); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
@@ -37,7 +37,7 @@ Chunk::Chunk(World& world) : | |||
} | |||
bool Chunk::isLoaded() { | |||
return mLoaded; | |||
return mLoaded.load(); | |||
} | |||
bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) { | |||
@@ -45,7 +45,7 @@ bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) { | |||
y < 0 || y > 15 || | |||
z < 0 || z > 15 ) | |||
{ //position is outside of the chunk | |||
return mLinkedWorld.isVoxelSolid(mPos.x * 16 + x, | |||
return mLinkedWorld.isVoxelSolid(mPos.x * 16 + x, | |||
mPos.y * 16 + y, | |||
mPos.z * 16 + z); | |||
} | |||
@@ -53,7 +53,7 @@ bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) { | |||
return (getVoxelType((unsigned)x,(unsigned)y,(unsigned)z) != 0); | |||
} | |||
void Chunk::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type) { | |||
void Chunk::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& update) { | |||
auto index = x + 16 * (y + 16 * z); | |||
if (index > 4095) { | |||
std::cout << "CHUNK ACCESS ERROR (set voxel): Out of range, doing nothing\n"; | |||
@@ -61,6 +61,8 @@ void Chunk::setVoxelType(const int& x, const int& y, const int& z, const unsigne | |||
} | |||
voxels[index] = type; | |||
if (!update) return; | |||
mLinkedWorld.queueChunkUpdate(mPos); | |||
} | |||
unsigned Chunk::getVoxelType(const unsigned& x, const unsigned& y, const unsigned& z) { |
@@ -65,17 +65,21 @@ bool ChunkMesh::rebuildChunkGeometry() { | |||
//build face attrib | |||
// 0b00000000000000000xxxxxyyyyyzzzzz | |||
unsigned faceAttrib = 0; | |||
faceAttrib = faceAttrib | i; | |||
faceAttrib = (faceAttrib << 5) | i; | |||
faceAttrib = (faceAttrib << 5) | j; | |||
faceAttrib = (faceAttrib << 5) | k; | |||
//lambda expression for adding vertices | |||
auto addFaceModel = [&](int faceIndex) { | |||
auto mesh = mVoxelModel.getFaceMesh(faceIndex); | |||
unsigned texIndex = mLinkedWorld.voxelInfo.getTextureIndex(chunk->getVoxelType(i,j,k), | |||
static_cast<FaceDirection>(faceIndex)); | |||
unsigned faceAttribT = faceAttrib | (texIndex << 15); // pack texture index into faceAttrib | |||
++mFaceCount; | |||
for (int l = 0; l < 6; ++l) { | |||
mGeometry.push_back(mesh[l]); | |||
mFaceAttribs.push_back(faceAttrib); | |||
mFaceAttribs.push_back(faceAttribT); | |||
} | |||
}; | |||
@@ -44,7 +44,7 @@ void TestScene::init() { | |||
tiles.buildTexture(); | |||
tiles.updateTextureAt(0, "res/stone.png"); | |||
tiles.updateTextureAt(1, "res/dirt.png"); | |||
tiles.updateTextureAt(2, "res/test.png"); | |||
tiles.updateTextureAt(2, "res/grass.png"); | |||
//shaders | |||
shaders = LoadShaders("res/shaders/voxelvert.vert.glsl", "res/shaders/voxelfrag.frag.glsl"); | |||
@@ -105,23 +105,16 @@ void TestScene::init() { | |||
world.voxelInfo.setTextureData(2, Face3D::FRONT, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setTextureData(2, Face3D::BACK, Orientation2D::UP, 1.0f); | |||
world.voxelInfo.setAllTextureIndexes(1, 0); | |||
world.voxelInfo.setAllTextureIndexes(2, 1); | |||
world.voxelInfo.setTextureIndex(2, FaceDirection::TOP, 2); | |||
//world.voxelInfo.setTransparent(1, false); | |||
//world.voxelInfo.setTransparent(2, false); | |||
std::cout << std::endl; | |||
/* | |||
int chunkCount = 1; | |||
for (int i = 0; i < 32; i++) { | |||
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.queueChunkLoad(glm::ivec3(i,j,k)); | |||
chunkCount++; | |||
} | |||
} | |||
} | |||
*/ | |||
world.queueChunkLoadsAroundPoint(glm::vec3(0.0,0.0,0.0), 16); | |||
//world.forceGlobalGeometryUpdate(); | |||
@@ -171,28 +164,11 @@ void TestScene::update(const float& dTime) { | |||
placeVoxel = false; | |||
} | |||
//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); | |||
for (int y = -radius; y <= radius; ++y) { | |||
for (int x = -radius; x <= radius; ++x) { | |||
if(x*x + y*y <= radius*radius) { | |||
for (int i = 0; i < 8; ++i) | |||
world.queueChunkLoad((glm::ivec3)cPos + glm::ivec3(x, i, y)); | |||
} | |||
} | |||
} | |||
*/ | |||
} | |||
@@ -32,7 +32,7 @@ namespace vtk { | |||
TerrainGen::TerrainGen() { | |||
std::shared_ptr<noise::NoiseModule> noise = std::make_shared<noise::Noise>(6969696); | |||
std::shared_ptr<noise::NoiseModule> yGrad = std::make_shared<noise::YGradient>(0.0, 128.0); | |||
mNoise = std::make_shared<noise::YTurbulence>(yGrad, noise, 60.0); | |||
mNoise = std::make_shared<noise::YTurbulence>(yGrad, noise, 15.0); | |||
mTerrainScale = 32.0; | |||
} | |||
@@ -48,7 +48,14 @@ void TerrainGen::generateChunk(Chunk* chunk) { | |||
(double)(chunkPos.y * 16 + j), | |||
(double)(chunkPos.z * 16 + k)); | |||
if (nVal <= 0.0) { | |||
chunk->setVoxelType(i,j,k,1); | |||
if (mNoise->get3D((double)(chunkPos.x * 16 + i), | |||
(double)(chunkPos.y * 16 + j + 1), | |||
(double)(chunkPos.z * 16 + k)) >= 0.0) | |||
{ | |||
chunk->setVoxelType(i, j, k, 2); | |||
} else {// block above is air | |||
chunk->setVoxelType(i,j,k,1); | |||
} | |||
} else { | |||
chunk->setVoxelType(i,j,k,0); | |||
} |
@@ -110,6 +110,24 @@ std::pair<float, float> VoxelInfo::getTexCoordFromID(const unsigned& id, const F | |||
return std::make_pair(0.0f, 0.0f); | |||
} | |||
unsigned VoxelInfo::getTextureIndex(const unsigned int &id, const FaceDirection &face) { | |||
return voxelDataMap[id].faceTextures[face]; | |||
} | |||
void VoxelInfo::setTextureIndex(const unsigned int &id, const FaceDirection &face, const unsigned int &index) { | |||
voxelDataMap[id].faceTextures[face] = index; | |||
} | |||
void VoxelInfo::setAllTextureIndexes(const unsigned int &id, const unsigned int &index) { | |||
auto& textures = voxelDataMap[id].faceTextures; | |||
textures[FaceDirection::TOP] = index; | |||
textures[FaceDirection::BOTTOM] = index; | |||
textures[FaceDirection::NORTH] = index; | |||
textures[FaceDirection::SOUTH] = index; | |||
textures[FaceDirection::EAST] = index; | |||
textures[FaceDirection::WEST] = index; | |||
} | |||
void VoxelInfo::setTextureData(const unsigned& id, const Face3D& face, const Orientation2D& orientation, const float& textureIndex) { | |||
voxelDataMap[id].faceOrientation[face] = orientation; | |||
voxelDataMap[id].faceTextureIndices[face] = textureIndex; |
@@ -29,30 +29,28 @@ 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 | |||
auto chunk = getChunk(chunkPos); | |||
if (!chunk) //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; | |||
if (!mChunks[chunkPos]->isLoaded()) return true; | |||
return mChunks[chunkPos]->isVoxelSolid(relPosX, relPosY, relPosZ); | |||
if (!chunk->isLoaded()) return true; | |||
return chunk->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; | |||
} | |||
auto chunk = getChunk(chunkPos); | |||
if (!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); | |||
chunk->setVoxelType(relPosX, relPosY, relPosZ, type, updateChunk); | |||
return true; | |||
} | |||
@@ -60,34 +58,30 @@ 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; | |||
} | |||
Chunk* chunk = getChunk(chunkPos); | |||
if (!chunk) 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); | |||
return chunk->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ); | |||
} | |||
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 mChunks[pos]; | |||
Chunk* chunk; | |||
if (mChunks.find(pos, chunk)) { //chunk already exists | |||
return chunk; | |||
} | |||
auto newChunk = new Chunk(*this); | |||
newChunk->setPos(pos); | |||
if (insertAfter) { | |||
mChunks[pos] = newChunk; | |||
mChunkMeshes.emplace(pos, ChunkMesh(*this, pos)); | |||
} | |||
chunk = new Chunk(*this); | |||
chunk->setPos(pos); | |||
return newChunk; | |||
if (insertAfter) insertChunk(chunk); | |||
return chunk; | |||
} | |||
bool World::generateChunk(const int& x, const int& y, const int& z) { | |||
@@ -111,15 +105,15 @@ bool World::generateChunk(const int& x, const int& y, const int& z) { | |||
} | |||
bool World::insertChunk(Chunk* chunk) { | |||
mChunks[chunk->getPos()] = chunk; | |||
mChunks.insert(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; | |||
if (chunk) return chunk; | |||
Chunk* chunk; | |||
if (mChunks.find(pos, chunk) && chunk->isLoaded()) return chunk; | |||
else return nullptr; | |||
} | |||
@@ -128,7 +122,7 @@ void World::queueChunkUpdate(const int& x, const int& y, const int& z, const boo | |||
} | |||
void World::queueChunkUpdate(const glm::ivec3& pos, const bool& back) { | |||
if (mChunks.find(pos) == mChunks.end()) return; //chunk doesn't exist | |||
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 | |||
} | |||
@@ -141,7 +135,7 @@ 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 | |||
if (getChunk(pos)) return; //chunk already exists | |||
for (auto& i : mChunkLoadQueue) { | |||
if (i == pos) return; | |||
} | |||
@@ -170,7 +164,7 @@ void World::update() { | |||
auto& mesh = mChunkMeshes.find(pos)->second; | |||
mChunkUpdateQueue.pop_back(); | |||
if (!mesh.rebuildChunkGeometry()) | |||
queueChunkUpdate(pos, false); | |||
queueChunkUpdate(pos); | |||
} | |||
rebuildThreadActive = false; | |||
}; |