#include "graphics/chunkmesh.h" #include "world.h" #include "chunk.h" #include #include #include #include namespace vtk { ChunkMesh::ChunkMesh(World& world, glm::ivec3 chunkPos) : mLinkedWorld(world), mLinkedChunkPos(chunkPos), mLocked(false) { glGenBuffers(1, &mGeometryTexVBO); glGenBuffers(1, &mLightVBO); glGenBuffers(1, &mFaceAttribsVBO); glGenVertexArrays(1, &mVAO); glBindVertexArray(mVAO); glBindBuffer(GL_ARRAY_BUFFER, mGeometryTexVBO); //vertices glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, GL_FALSE, 0); glEnableVertexAttribArray(0); //face attribs glBindBuffer(GL_ARRAY_BUFFER, mFaceAttribsVBO); glVertexAttribIPointer(1, 1, GL_UNSIGNED_INT, GL_FALSE, 0); glEnableVertexAttribArray(1); } void ChunkMesh::rebuildChunkGeometry() { // check if it's currently rebuilding if (mLocked) return; mLocked = true; //get the chunk from position auto chunk = mLinkedWorld.getChunk(mLinkedChunkPos); // geometry format: x,y,z,u,v,i mGeometry.clear(); mFaceAttribs.clear(); mFaceCount = 0; int chunkSize = 16; for (int i = 0; i < chunkSize; ++i) { for (int j = 0; j < chunkSize; ++j) { for (int k = 0; k < chunkSize; ++k) { if (chunk->isVoxelSolid(i,j,k)) { //build face attrib // 0b00000000000000000xxxxxyyyyyzzzzz unsigned faceAttrib = 0; faceAttrib = faceAttrib | i; faceAttrib = (faceAttrib << 5) | j; faceAttrib = (faceAttrib << 5) | k; //lambda expression for adding vertices auto addFaceModel = [&](int faceIndex) { auto mesh = mVoxelModel.getFaceMesh(faceIndex); ++mFaceCount; for (int l = 0; l < 6; ++l) { mGeometry.push_back(mesh[l]); mFaceAttribs.push_back(faceAttrib); } }; if (!chunk->isVoxelSolid(i,j+1,k)) addFaceModel(0); // T if (!chunk->isVoxelSolid(i,j-1,k)) addFaceModel(1); // B if (!chunk->isVoxelSolid(i,j,k+1)) addFaceModel(2); // N if (!chunk->isVoxelSolid(i,j,k-1)) addFaceModel(3); // S if (!chunk->isVoxelSolid(i+1,j,k)) addFaceModel(4); // E if (!chunk->isVoxelSolid(i-1,j,k)) addFaceModel(5); // W } } } } mUpdated = true; mLocked = false; } void ChunkMesh::rebuildChunkLighting() { //this doesn't do anything yet } void ChunkMesh::draw() { if (mFaceCount > 0) { 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(unsigned) * mGeometry.size(), mGeometry.data(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, mFaceAttribsVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned) * mFaceAttribs.size(), mFaceAttribs.data(), GL_STATIC_DRAW); mGeometryFaceCount = mFaceCount; return true; } return false; } } //namespace vtk