diff --git a/include/chunk.hpp b/include/chunk.hpp index 569a006..e29f226 100644 --- a/include/chunk.hpp +++ b/include/chunk.hpp @@ -56,7 +56,7 @@ namespace Chunk std::unique_ptr getBlocksArray(int* len) { return (this->blocks.toArray(len)); } public: - GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, numVertices{0}; + GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, numTriangles{0}; std::atomic unload_timer{0}; private: diff --git a/include/chunkmesher.hpp b/include/chunkmesher.hpp index ff26f4d..ab5ea3e 100644 --- a/include/chunkmesher.hpp +++ b/include/chunkmesher.hpp @@ -15,6 +15,8 @@ namespace chunkmesher{ struct MeshData{ Chunk::Chunk* chunk; + GLuint numVertices{0}; + std::vector vertices; std::vector colors; std::vector indices; diff --git a/src/chunkmanager.cpp b/src/chunkmanager.cpp index 90644f0..4f9797f 100644 --- a/src/chunkmanager.cpp +++ b/src/chunkmanager.cpp @@ -136,4 +136,70 @@ namespace chunkmanager }*/ } + void blockpick(bool place){ + // cast a ray from the camera in the direction pointed by the camera itself + glm::vec3 pos = glm::vec3(theCamera.getAtomicPosX(), theCamera.getAtomicPosY(), + theCamera.getAtomicPosZ()); + for(float t = 0.0; t <= 10.0; t += 0.5){ + // traverse the ray a block at the time + pos = theCamera.getPos() + t * theCamera.getFront(); + + // get which chunk and block the ray is at + int px = ((int)(pos.x))/CHUNK_SIZE; + int py = ((int)(pos.y))/CHUNK_SIZE; + int pz = ((int)(pos.z))/CHUNK_SIZE; + int bx = pos.x - px*CHUNK_SIZE; + int by = pos.y - py*CHUNK_SIZE; + int bz = pos.z - pz*CHUNK_SIZE; + + // exit early if the position is invalid or the chunk does not exist + if(px < 0 || py < 0 || pz < 0 || px >= 1024 || py >= 1024 || pz >= 1024) return; + + ChunkTable::accessor a; + if(!chunks.find(a, calculateIndex(px, py, pz))) return; + Chunk::Chunk* c = a->second; + if(!c->getState(Chunk::CHUNK_STATE_GENERATED) || c->getState(Chunk::CHUNK_STATE_EMPTY)) continue; + + Block b = c->getBlock(bx, by, bz); + + a.release(); + // if the block is non empty + if(b != Block::AIR){ + + // if placing a new block + if(place){ + // Go half a block backwards on the ray, to check the block where the ray was + // coming from + // Doing this and not using normal adds the unexpected (and unwanted) ability to + // place blocks diagonally, without faces colliding with the block that has + // been clicked + pos -= theCamera.getFront()*0.5f; + + int px1 = ((int)(pos.x))/CHUNK_SIZE; + int py1 = ((int)(pos.y))/CHUNK_SIZE; + int pz1 = ((int)(pos.z))/CHUNK_SIZE; + int bx1 = pos.x - px1*CHUNK_SIZE; + int by1 = pos.y - py1*CHUNK_SIZE; + int bz1 = pos.z - pz1*CHUNK_SIZE; + + // exit early if the position is invalid or the chunk does not exist + if(px1 < 0 || py1 < 0 || pz1 < 0 || px1 >= 1024 || py1 >= 1024 || pz1 >= 1024) return; + ChunkTable::accessor a1; + if(!chunks.find(a1, calculateIndex(px1, py1, pz1))) return; + Chunk::Chunk* c1 = a1->second; + // place the new block (only stone for now) + c1->setBlock( Block::STONE, bx1, by1, bz1); + + // mark the mesh of the chunk the be updated + c1->setState(Chunk::CHUNK_STATE_MESHED, false); + }else{ + // replace the current block with air to remove it + c->setBlock( Block::AIR, bx, by, bz); + + c->setState(Chunk::CHUNK_STATE_MESHED, false); + } + break; + } + } + } }; diff --git a/src/chunkmesher.cpp b/src/chunkmesher.cpp index b787d73..000111a 100755 --- a/src/chunkmesher.cpp +++ b/src/chunkmesher.cpp @@ -36,7 +36,7 @@ void mesh(Chunk::Chunk* chunk) */ // Cleanup previous data - chunk->numVertices = 0; + mesh_data->numVertices = 0; mesh_data->chunk = chunk; mesh_data->vertices.clear(); mesh_data->indices.clear(); @@ -202,7 +202,7 @@ void mesh(Chunk::Chunk* chunk) void sendtogpu(MeshData* mesh_data) { - if (mesh_data->chunk->numVertices > 0) + if (mesh_data->numVertices > 0) { if(mesh_data->chunk->VAO == 0) mesh_data->chunk->createBuffers(); @@ -234,7 +234,7 @@ void sendtogpu(MeshData* mesh_data) glBindVertexArray(0); // save the number of indices of the mesh, it is needed later for drawing - mesh_data->chunk->numVertices = (GLuint)(mesh_data->indices.size()); + mesh_data->chunk->numTriangles = (GLuint)(mesh_data->indices.size()); // once data has been sent to the GPU, it can be cleared from system RAM mesh_data->vertices.clear(); @@ -330,22 +330,22 @@ void quad(MeshData* mesh_data, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec if (backFace) { - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 2); - mesh_data->indices.push_back(mesh_data->chunk->numVertices); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 1); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 1); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 3); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 2); + mesh_data->indices.push_back(mesh_data->numVertices + 2); + mesh_data->indices.push_back(mesh_data->numVertices); + mesh_data->indices.push_back(mesh_data->numVertices + 1); + mesh_data->indices.push_back(mesh_data->numVertices + 1); + mesh_data->indices.push_back(mesh_data->numVertices + 3); + mesh_data->indices.push_back(mesh_data->numVertices + 2); } else { - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 2); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 3); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 1); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 1); - mesh_data->indices.push_back(mesh_data->chunk->numVertices); - mesh_data->indices.push_back(mesh_data->chunk->numVertices + 2); + mesh_data->indices.push_back(mesh_data->numVertices + 2); + mesh_data->indices.push_back(mesh_data->numVertices + 3); + mesh_data->indices.push_back(mesh_data->numVertices + 1); + mesh_data->indices.push_back(mesh_data->numVertices + 1); + mesh_data->indices.push_back(mesh_data->numVertices); + mesh_data->indices.push_back(mesh_data->numVertices + 2); } - mesh_data->chunk->numVertices += 4; + mesh_data->numVertices += 4; } }; diff --git a/src/main.cpp b/src/main.cpp index a8df144..90afc63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,13 +129,13 @@ void processInput(GLFWwindow *window) glfwSetWindowShouldClose(window, true); if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS && !blockpick){ - //chunkmanager::blockpick(false); + chunkmanager::blockpick(false); blockpick=true; lastBlockPick=glfwGetTime(); } if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS && !blockpick){ - //chunkmanager::blockpick(true); + chunkmanager::blockpick(true); blockpick=true; lastBlockPick=glfwGetTime(); } diff --git a/src/renderer.cpp b/src/renderer.cpp index 84fb7a2..290bbe3 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -62,8 +62,6 @@ namespace renderer{ } for(auto& c : chunks_torender){ - if(! (c->getState(Chunk::CHUNK_STATE_MESHED))) continue; - float dist = glm::distance(c->getPosition(), cameraChunkPos); if(dist <= static_cast(RENDER_DISTANCE)){ if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) continue; @@ -95,7 +93,7 @@ namespace renderer{ if (!out) { - if(c->numVertices > 0) + if(c->numTriangles > 0) { // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode theShader->setMat4("model", model); @@ -103,7 +101,7 @@ namespace renderer{ theShader->setMat4("projection", theCamera.getProjection()); glBindVertexArray(c->VAO); - glDrawElements(GL_TRIANGLES, c->numVertices , GL_UNSIGNED_INT, 0); + glDrawElements(GL_TRIANGLES, c->numTriangles , GL_UNSIGNED_INT, 0); glBindVertexArray(0); } }