summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Entities/Player.cpp28
-rw-r--r--src/Math/AABB.hpp6
-rw-r--r--src/Math/Functions.hpp7
-rw-r--r--src/Math/Ray.hpp2
-rw-r--r--src/Math/Vector.hpp9
5 files changed, 33 insertions, 19 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 01e3588..ae82e83 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1,5 +1,4 @@
 #include "Player.hpp"
-
 #include "../Common/Casts.hpp"
 #include <unordered_set>
 
@@ -17,8 +16,8 @@ void Player::update(const Time& time, GFX::Window& window, GFX::Camera& camera,
         m_on_ground = blocked_axes.y().negative;
 
         for (UInt axis = 0; axis < 3; axis++) {
-            if (blocked_axes[axis].positive) m_velocity[axis] = std::max(m_velocity[axis], 0.0);
-            if (blocked_axes[axis].negative) m_velocity[axis] = std::min(m_velocity[axis], 0.0);
+            if (blocked_axes[axis].positive) m_velocity[axis] = std::min(m_velocity[axis], 0.0);
+            if (blocked_axes[axis].negative) m_velocity[axis] = std::max(m_velocity[axis], 0.0);
         }
     }
 
@@ -78,11 +77,9 @@ Vec3 Player::walking_velocity(GFX::Window& window, const Time& time, Vec3 input_
     auto const walking_velocity = walking_direction * base_move_speed * time.delta();
 
     auto vertical_velocity = 0.0;
-    if (m_on_ground) {
-        if (window.key(GLFW_KEY_SPACE, GLFW_PRESS)) {
-            vertical_velocity = initial_jump_velocity;
-            m_on_ground = false;
-        }
+    if (m_on_ground && input_direction.y() > 0.5) {
+        vertical_velocity = initial_jump_velocity;
+        m_on_ground = false;
     } else {
         // TODO: This integration depends on frame delta.
         vertical_velocity = m_velocity.y() - gravity * time.delta();
@@ -165,13 +162,13 @@ void Player::actions(GFX::Window& window, World::World& world) {
 Player::ProcessCollisionsResult Player::process_collisions(World::World& world, Position::World from, Position::World to) {
     if (from.mostly_equal(to)) return {to, {}};
 
-    auto current_box = bounding_box_for_position(from);
+    auto const current_box = bounding_box_for_position(from);
 
     // All the blocks we could theoretically collide with.
     // NOTE: It isn't updated as new responses are applied,
     // as that would be (currently) too expensive.
     // At very high speeds, this may lead to phasing through blocks.
-    auto collision_domain = terrain_collision_domain(from, to, world);
+    auto const collision_domain = terrain_collision_domain(from, to, world);
 
     // Sort the responses first by the magnitude of the velocity until the collision,
     // and then by the distance from the entity, so that we slide along the closest block.
@@ -189,12 +186,12 @@ Player::ProcessCollisionsResult Player::process_collisions(World::World& world,
     };
     std::vector<Response> responses;
     for (UInt stuck = 0; stuck < STUCK_THRESHOLD; stuck++) {
-        auto v = to - from;
+        auto const v = to - from;
 
         for (auto possible_collision : collision_domain) {
-            auto response = current_box.collision_response(v, possible_collision);
-            auto total_velocity = response.v_to_collision + response.v_slide;
-            if (!total_velocity.mostly_equal(v)) {
+            auto const response = current_box.collision_response(v, possible_collision);
+            auto const total_velocity = response.v_to_collision + response.v_slide;
+            if (!total_velocity.mostly_equal(v) && !total_velocity.is_nan()) {
                 responses.push_back({
                     response,
                     possible_collision.center().distance_squared(from),
@@ -212,10 +209,9 @@ Player::ProcessCollisionsResult Player::process_collisions(World::World& world,
         // TODO: This applies the entire response, even though ideally we'd apply it in two parts,
         // since technically the total velocity is a diagonal of the two components.
         // This should only be a marginal issue, though.
-        auto response = responses[0].response;
+        auto const response = responses[0].response;
         to = from + response.v_to_collision + response.v_slide;
 
-
         auto check_axis = [&](Real axis_normal, BlockedAxis& axis) -> Bool {
             if (axis_normal < -0.5) { axis.negative = true; return true; }
             if (axis_normal > 0.5) { axis.positive = true; return true; }
diff --git a/src/Math/AABB.hpp b/src/Math/AABB.hpp
index b298126..bff543e 100644
--- a/src/Math/AABB.hpp
+++ b/src/Math/AABB.hpp
@@ -27,15 +27,15 @@ struct AABB {
     }
 
     Bool intersects_on_x(AABB other) const {
-        return min.x() <= other.max.x() && max.x() >= other.min.x();
+        return Math::floats_less(min.x(), other.max.x()) && Math::floats_less(other.min.x(), max.x());
     }
 
     Bool intersects_on_y(AABB other) const {
-        return min.y() <= other.max.y() && max.y() >= other.min.y();
+        return Math::floats_less(min.y(), other.max.y()) && Math::floats_less(other.min.y(), max.y());
     }
 
     Bool intersects_on_z(AABB other) const {
-        return min.z() <= other.max.z() && max.z() >= other.min.z();
+        return Math::floats_less(min.z(), other.max.z()) && Math::floats_less(other.min.z(), max.z());
     }
 
     Bool collides(AABB other) const {
diff --git a/src/Math/Functions.hpp b/src/Math/Functions.hpp
index fd99c6d..0cda6bd 100644
--- a/src/Math/Functions.hpp
+++ b/src/Math/Functions.hpp
@@ -38,9 +38,16 @@ R sign(T x) {
 
 // III. Utility functions.
 
+// Compares two floating point numbers for equality, with a given epsilon.
 template <typename T>
 Bool floats_equal(T a, T b, Real epsilon = 0.0001f) {
     return std::abs(a - b) < epsilon;
 }
 
+// Compares two floating point numbers for inequality, with a given epsilon.
+template <typename T>
+Bool floats_less(T a, T b, Real epsilon = 0.0001f) {
+    return a < b - epsilon;
+}
+
 }
\ No newline at end of file
diff --git a/src/Math/Ray.hpp b/src/Math/Ray.hpp
index db37ac2..4050a02 100644
--- a/src/Math/Ray.hpp
+++ b/src/Math/Ray.hpp
@@ -15,6 +15,8 @@ struct Ray {
     // [1]: https://gdbooks.gitbooks.io/3dcollisions/content/Chapter3/raycast_aabb.html
     // [2]: https://tavianator.com/2015/ray_box_nan.html
     RaycastResult cast(AABB box, Real max_distance = 0) const {
+        if (direction.is_zero()) return {};
+
         RaycastResult hit{ true };
 
         // `t` is the time at which the ray intersects a plane of the AABB.
diff --git a/src/Math/Vector.hpp b/src/Math/Vector.hpp
index 7d07d5c..3525e42 100644
--- a/src/Math/Vector.hpp
+++ b/src/Math/Vector.hpp
@@ -125,6 +125,15 @@ struct Vector {
         return mostly_equal(zero());
     }
 
+    Bool is_nan() const {
+        for (UInt i = 0; i < S; i++) {
+            if (std::isnan(elements[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     T operator[](USize index) const {
         return elements[index];
     }