summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/GameState.cpp4
-rw-r--r--src/World.cpp93
-rw-r--r--src/World.hpp8
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);