From 6113886117d0dc9cde9313bea70d0f709a47a8fb Mon Sep 17 00:00:00 2001 From: EmaMaker Date: Fri, 26 May 2023 22:41:18 +0200 Subject: [PATCH 1/2] multithreaded blockpicking --- src/chunkmanager.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 4 +-- 2 files changed, 68 insertions(+), 2 deletions(-) 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/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(); } -- 2.40.1 From 105fff00299ccf0115eedb091c4eceb9cbd0dbdd Mon Sep 17 00:00:00 2001 From: EmaMaker Date: Fri, 26 May 2023 23:05:29 +0200 Subject: [PATCH 2/2] write number of triangles to Chunk only when sending to GPU previously the current number of vertices was stored in the chunk, and the same variable got later reused for the number of triangles. This modification increases clarity and avoid glitches when blockpicking --- include/chunk.hpp | 2 +- include/chunkmesher.hpp | 2 ++ src/chunkmesher.cpp | 32 ++++++++++++++++---------------- src/renderer.cpp | 6 ++---- 4 files changed, 21 insertions(+), 21 deletions(-) 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/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/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); } } -- 2.40.1