diff options
-rw-r--r-- | src/GameState.cpp | 4 | ||||
-rw-r--r-- | src/World.cpp | 93 | ||||
-rw-r--r-- | src/World.hpp | 8 |
3 files changed, 25 insertions, 80 deletions
diff --git a/src/GameState.cpp b/src/GameState.cpp index 650cd6f..180db98 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -36,7 +36,9 @@ void GameState::Update(float deltaTime) { direction.y = sin(glm::radians(playerPitch)); direction.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - selectedBlock = world.Raycast(player->pos + player->EyeOffset, direction, distanceToSelectedBlock); + RaycastResult raycast = world.Raycast(player->pos + player->EyeOffset, direction); + selectedBlock = raycast.isHit ? raycast.hitBlock : Vector(0,0,0); + distanceToSelectedBlock = raycast.isHit ? (player->pos - raycast.hitPos).GetLength() : 0.0f; } } diff --git a/src/World.cpp b/src/World.cpp index e4c2a1b..4678964 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -135,86 +135,23 @@ const Section &World::GetSection(Vector sectionPos) { } } -Vector World::Raycast(glm::vec3 position, glm::vec3 direction, float &distance) { - auto triangle_intersection = [&] (const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &v2) -> bool { - glm::vec3 e1 = v1 - v0; - glm::vec3 e2 = v2 - v0; - - glm::vec3 pvec = glm::cross(direction, e2); - - float det = glm::dot(e1, pvec); - if (det < 1e-8 && det > -1e-8) { - return 0; - } - - float inv_det = 1 / det; - glm::vec3 tvec = position - v0; - float u = dot(tvec, pvec) * inv_det; - if (u < 0 || u > 1) { - return 0; - } - - glm::vec3 qvec = cross(tvec, e1); - float v = dot(direction, qvec) * inv_det; - if (v < 0 || u + v > 1) { - return 0; - } - return dot(e2, qvec) * inv_det; - }; - - float minDistance = 1000000; - Vector minBlock; - - for (int y = position.y-5; y<position.y+5;y++) { - for (int z = position.z-5;z<position.z+5;z++) { - for (int x = position.x-5;x<position.x+5;x++) { - if (GetBlockId(Vector(x,y,z)) == BlockId{0,0}) - continue; - - //Z- north - //Z+ south - //X+ east - //X- west - //Y+ top - //Y- bottom - glm::vec3 vNNN {x,y,z}; - glm::vec3 vNNP {x,y,z+1}; - glm::vec3 vNPN {x,y+1,z}; - glm::vec3 vNPP {x,y+1,z+1}; - glm::vec3 vPNN {x+1,y,z}; - glm::vec3 vPNP {x+1,y,z+1}; - glm::vec3 vPPN {x+1,y+1,z}; - glm::vec3 vPPP {x+1,y+1,z+1}; - - float west = triangle_intersection(vNNN,vNPN,vNPP); - float east = triangle_intersection(vPPN,vPNP,vPNN); - float north = triangle_intersection(vNPN,vPNN,vNNN); - float south = triangle_intersection(vNNP,vNPP,vPNP); - float top = triangle_intersection(vNPN,vNPP,vPPN); - float bottom = triangle_intersection(vNNN,vNNP,vPNN); - - if (west || east || north || south || top || bottom) { - float len = (Vector(position.x,position.y,position.z) - Vector(x,y,z)).GetLength(); - if (len <= minDistance) { - float we = west < east && west != 0 ? west : east; - float ns = north < south && north != 0 ? north : south; - float tb = top < bottom && top != 0 ? top : bottom; - float wens = we < ns && we != 0 ? we : ns; - minDistance = wens < tb && wens != 0? wens : tb; - minBlock = Vector(x,y,z); - } - } - } - } - } - - if (minDistance == 1000000) { - distance = 0; - return Vector(0,0,0); +RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) { + const float maxLen = 5.0; + const float step = 0.01; + glm::vec3 pos; + float len=0; + Vector blockPos = Vector(position.x,position.y,position.z); + while (GetBlockId(blockPos) == BlockId{0, 0} && len <= maxLen) { + pos = position + direction * len; + len += step; + blockPos = Vector(floor(pos.x),floor(pos.y),floor(pos.z)); } - distance = minDistance; - return minBlock; + RaycastResult result; + result.isHit = !(GetBlockId(blockPos) == BlockId{0, 0}); + result.hitPos = VectorF(pos.x,pos.y,pos.z); + result.hitBlock = blockPos; + return result; } void World::UpdatePhysics(float delta) diff --git a/src/World.hpp b/src/World.hpp index 50dfa31..2c80b31 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -19,6 +19,12 @@ class PacketMultiBlockChange; class PacketUnloadChunk; class StreamInput; +struct RaycastResult { + bool isHit; + Vector hitBlock; + VectorF hitPos; +}; + class World { int dimension = 0; @@ -55,7 +61,7 @@ public: const Section &GetSection(Vector sectionPos); - Vector Raycast(glm::vec3 position, glm::vec3 direction, float &distance); + RaycastResult Raycast(glm::vec3 position, glm::vec3 direction); void UpdatePhysics(float delta); |