diff --git a/include/engine/collision.hpp b/include/engine/collision.hpp index d023517..8d6b478 100644 --- a/include/engine/collision.hpp +++ b/include/engine/collision.hpp @@ -21,12 +21,14 @@ namespace egn{ + static constexpr float default_collision_epsilon = 1.0e-10f; + class collidable_visitor; class collidable_iface { public: - virtual bool check_collision(const collidable_iface& c)const = 0; + virtual bool check_collision(const collidable_iface& c, float epsilon)const = 0; virtual void accept_visitor(collidable_visitor& v)const = 0; }; @@ -34,7 +36,7 @@ namespace egn{ class collidable : public collidable_iface { public: - bool check_collision(const collidable_iface& c)const override final; + bool check_collision(const collidable_iface& c, float epsilon = default_collision_epsilon)const override final; private: void accept_visitor(collidable_visitor& v)const override final; }; @@ -61,9 +63,10 @@ namespace egn{ { private: const T& m_l; + float m_epsilon; bool m_result = false; public: - constexpr explicit collision_visitor(const T& l); + constexpr explicit collision_visitor(const T& l, float epsilon); void visit(const aabb& a)override; void visit(const aabs& a)override; void visit(const line& a)override; @@ -72,38 +75,37 @@ namespace egn{ constexpr bool result()const; }; - - bool check_collision(const collidable_iface& l, const collidable_iface& r); - bool check_collision(const aabb& l, const aabb& r); - bool check_collision(const aabb& l, const aabs& r); - bool check_collision(const aabb& l, const line& r); - bool check_collision(const aabb& l, const plane& r); - bool check_collision(const aabb& l, const point& r); - bool check_collision(const aabs& l, const aabs& r); - bool check_collision(const aabs& l, const aabb& r); - bool check_collision(const aabs& l, const line& r); - bool check_collision(const aabs& l, const plane& r); - bool check_collision(const aabs& l, const point& r); - bool check_collision(const line& l, const line& r); - bool check_collision(const line& l, const aabb& r); - bool check_collision(const line& l, const aabs& r); - bool check_collision(const line& l, const plane& r); - bool check_collision(const line& l, const point& r); - bool check_collision(const plane& l, const plane& r); - bool check_collision(const plane& l, const aabb& r); - bool check_collision(const plane& l, const aabs& r); - bool check_collision(const plane& l, const line& r); - bool check_collision(const plane& l, const point& r); - bool check_collision(const point& l, const point& r); - bool check_collision(const point& l, const aabb& r); - bool check_collision(const point& l, const aabs& r); - bool check_collision(const point& l, const line& r); - bool check_collision(const point& l, const plane& r); + bool check_collision(const collidable_iface& l, const collidable_iface& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabb& l, const aabb& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabb& l, const aabs& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabb& l, const line& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabb& l, const plane& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabb& l, const point& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabs& l, const aabs& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabs& l, const aabb& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabs& l, const line& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabs& l, const plane& r, float epsilon = default_collision_epsilon); + bool check_collision(const aabs& l, const point& r, float epsilon = default_collision_epsilon); + bool check_collision(const line& l, const line& r, float epsilon = default_collision_epsilon); + bool check_collision(const line& l, const aabb& r, float epsilon = default_collision_epsilon); + bool check_collision(const line& l, const aabs& r, float epsilon = default_collision_epsilon); + bool check_collision(const line& l, const plane& r, float epsilon = default_collision_epsilon); + bool check_collision(const line& l, const point& r, float epsilon = default_collision_epsilon); + bool check_collision(const plane& l, const plane& r, float epsilon = default_collision_epsilon); + bool check_collision(const plane& l, const aabb& r, float epsilon = default_collision_epsilon); + bool check_collision(const plane& l, const aabs& r, float epsilon = default_collision_epsilon); + bool check_collision(const plane& l, const line& r, float epsilon = default_collision_epsilon); + bool check_collision(const plane& l, const point& r, float epsilon = default_collision_epsilon); + bool check_collision(const point& l, const point& r, float epsilon = default_collision_epsilon); + bool check_collision(const point& l, const aabb& r, float epsilon = default_collision_epsilon); + bool check_collision(const point& l, const aabs& r, float epsilon = default_collision_epsilon); + bool check_collision(const point& l, const line& r, float epsilon = default_collision_epsilon); + bool check_collision(const point& l, const plane& r, float epsilon = default_collision_epsilon); template - bool collidable::check_collision(const collidable_iface& c)const{ - collision_visitor vis(static_cast(*this)); + bool collidable::check_collision(const collidable_iface& c, float epsilon)const{ + collision_visitor vis(static_cast(*this), epsilon); c.accept_visitor(vis); return vis.result(); } @@ -113,27 +115,28 @@ namespace egn{ } template - constexpr collision_visitor::collision_visitor(const T& l): - m_l(l){} + constexpr collision_visitor::collision_visitor(const T& l, float epsilon): + m_l(l), + m_epsilon(epsilon){} template void collision_visitor::visit(const aabb& a){ - m_result = check_collision(m_l, a); + m_result = check_collision(m_l, a, m_epsilon); } template void collision_visitor::visit(const aabs& a){ - m_result = check_collision(m_l, a); + m_result = check_collision(m_l, a, m_epsilon); } template void collision_visitor::visit(const line& a){ - m_result = check_collision(m_l, a); + m_result = check_collision(m_l, a, m_epsilon); } template void collision_visitor::visit(const plane& a){ - m_result = check_collision(m_l, a); + m_result = check_collision(m_l, a, m_epsilon); } template void collision_visitor::visit(const point& a){ - m_result = check_collision(m_l, a); + m_result = check_collision(m_l, a, m_epsilon); } template constexpr bool collision_visitor::result()const{ diff --git a/include/math/mat.hpp b/include/math/mat.hpp index a3beec7..ef497b4 100644 --- a/include/math/mat.hpp +++ b/include/math/mat.hpp @@ -243,6 +243,13 @@ namespace math{ template constexpr auto operator-(const matrix& left); + template + constexpr auto abs(const matrix_base& left); + template + constexpr bool fuzzy_eq(const matrix_base& left, const matrix_base& right, const V& epsilon); + template + constexpr bool fuzzy_neq(const matrix_base& left, const matrix_base& right, const V& epsilon); + //Arithmetic assignment operators template constexpr decltype(auto) operator*=(matrix& left, const matrix& right); diff --git a/include/math/mat.tpp b/include/math/mat.tpp index 12406c8..b7b0055 100644 --- a/include/math/mat.tpp +++ b/include/math/mat.tpp @@ -20,7 +20,7 @@ #define REXY_MAT_TPP #include //size_t -#include //sin, cos +#include //sin, cos, abs #include //decay_t, declval #include "detail/matrix.hpp" #include "quat.hpp" @@ -343,7 +343,26 @@ namespace math{ } return res; } - + template + constexpr auto abs(const matrix_base& left){ + matrix res(no_initialize); + for(size_t i = 0; i < left.size(); ++i){ + res.get(i) = std::abs(left.get(i)); + } + return res; + } + template + constexpr bool fuzzy_eq(const matrix_base& left, const matrix_base& right, const V& epsilon){ + for(size_t i = 0;i < left.size();++i){ + if(std::abs(left.get(i) - right.get(i)) > epsilon) + return false; + } + return true; + } + template + constexpr bool fuzzy_neq(const matrix_base& left, const matrix_base& right, const V& epsilon){ + return !fuzzy_eq(left, right, epsilon); + } template constexpr decltype(auto) operator*=(matrix& left, const matrix& right){ diff --git a/src/engine/collision.cpp b/src/engine/collision.cpp index 6b33214..6fbc398 100644 --- a/src/engine/collision.cpp +++ b/src/engine/collision.cpp @@ -21,111 +21,133 @@ namespace egn{ - bool check_collision(const collidable_iface& l, const collidable_iface& r){ - return l.check_collision(r); + bool check_collision(const collidable_iface& l, const collidable_iface& r, float epsilon){ + return l.check_collision(r, epsilon); } - bool check_collision(const aabb& l, const aabb& r){ + bool check_collision(const aabb& l, const aabb& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabb& l, const aabs& r){ + bool check_collision(const aabb& l, const aabs& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabb& l, const line& r){ + bool check_collision(const aabb& l, const line& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabb& l, const plane& r){ + bool check_collision(const aabb& l, const plane& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabb& l, const point& r){ + bool check_collision(const aabb& l, const point& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabs& l, const aabs& r){ + bool check_collision(const aabs& l, const aabs& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabs& l, const aabb& r){ - return check_collision(r, l); + bool check_collision(const aabs& l, const aabb& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const aabs& l, const line& r){ + bool check_collision(const aabs& l, const line& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabs& l, const plane& r){ + bool check_collision(const aabs& l, const plane& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const aabs& l, const point& r){ + bool check_collision(const aabs& l, const point& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const line& l, const line& r){ + bool check_collision(const line& l, const line& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const line& l, const aabs& r){ - return check_collision(r, l); + bool check_collision(const line& l, const aabs& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const line& l, const aabb& r){ - return check_collision(r, l); + bool check_collision(const line& l, const aabb& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const line& l, const plane& r){ + bool check_collision(const line& l, const plane& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const line& l, const point& r){ + bool check_collision(const line& l, const point& r, float epsilon){ + math::vec3 ab = (l.point2 - l.point1); + math::vec3 ac = (r - l.point1); + + //check if the point and line are colinear + if(math::fuzzy_neq(math::cross(ab, ac), math::vec3(math::zero_initialize), epsilon)) + return false; + + //check if the point is between the endpoints of the line segment + float value = (ab * ac) / (ab * ab); + if(value >= (0.0f - epsilon) && value <= (1.0f + epsilon)) + return true; + return false; + } + bool check_collision(const plane& l, const plane& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const plane& l, const plane& r){ + bool check_collision(const plane& l, const aabb& r, float epsilon){ + return check_collision(r, l, epsilon); + } + bool check_collision(const plane& l, const aabs& r, float epsilon){ + return check_collision(r, l, epsilon); + } + bool check_collision(const plane& l, const line& r, float epsilon){ + return check_collision(r, l, epsilon); + } + bool check_collision(const plane& l, const point& r, float epsilon){ (void)l; (void)r; + (void)epsilon; return false; } - bool check_collision(const plane& l, const aabb& r){ - return check_collision(r, l); + bool check_collision(const point& l, const point& r, float epsilon){ + return math::fuzzy_eq(l, r, epsilon); } - bool check_collision(const plane& l, const aabs& r){ - return check_collision(r, l); + bool check_collision(const point& l, const aabb& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const plane& l, const line& r){ - return check_collision(r, l); + bool check_collision(const point& l, const aabs& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const plane& l, const point& r){ - (void)l; - (void)r; - return false; + bool check_collision(const point& l, const line& r, float epsilon){ + return check_collision(r, l, epsilon); } - bool check_collision(const point& l, const point& r){ - return (l == r); - } - bool check_collision(const point& l, const aabb& r){ - return check_collision(r, l); - } - bool check_collision(const point& l, const aabs& r){ - return check_collision(r, l); - } - bool check_collision(const point& l, const line& r){ - return check_collision(r, l); - } - bool check_collision(const point& l, const plane& r){ - return check_collision(r, l); + bool check_collision(const point& l, const plane& r, float epsilon){ + return check_collision(r, l, epsilon); } }