diff options
| -rw-r--r-- | src/Entities/Player.cpp | 28 | ||||
| -rw-r--r-- | src/Math/AABB.hpp | 6 | ||||
| -rw-r--r-- | src/Math/Functions.hpp | 7 | ||||
| -rw-r--r-- | src/Math/Ray.hpp | 2 | ||||
| -rw-r--r-- | src/Math/Vector.hpp | 9 |
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]; } |
