Add epsilon tunable to collision checks. Add line-point collision check logic

This commit is contained in:
rexy712 2020-12-01 12:19:16 -08:00
parent 478b82582b
commit fd282607ae
4 changed files with 137 additions and 86 deletions

View File

@ -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<typename Derived>
bool collidable<Derived>::check_collision(const collidable_iface& c)const{
collision_visitor<Derived> vis(static_cast<const Derived&>(*this));
bool collidable<Derived>::check_collision(const collidable_iface& c, float epsilon)const{
collision_visitor<Derived> vis(static_cast<const Derived&>(*this), epsilon);
c.accept_visitor(vis);
return vis.result();
}
@ -113,27 +115,28 @@ namespace egn{
}
template<typename T>
constexpr collision_visitor<T>::collision_visitor(const T& l):
m_l(l){}
constexpr collision_visitor<T>::collision_visitor(const T& l, float epsilon):
m_l(l),
m_epsilon(epsilon){}
template<typename T>
void collision_visitor<T>::visit(const aabb& a){
m_result = check_collision(m_l, a);
m_result = check_collision(m_l, a, m_epsilon);
}
template<typename T>
void collision_visitor<T>::visit(const aabs& a){
m_result = check_collision(m_l, a);
m_result = check_collision(m_l, a, m_epsilon);
}
template<typename T>
void collision_visitor<T>::visit(const line& a){
m_result = check_collision(m_l, a);
m_result = check_collision(m_l, a, m_epsilon);
}
template<typename T>
void collision_visitor<T>::visit(const plane& a){
m_result = check_collision(m_l, a);
m_result = check_collision(m_l, a, m_epsilon);
}
template<typename T>
void collision_visitor<T>::visit(const point& a){
m_result = check_collision(m_l, a);
m_result = check_collision(m_l, a, m_epsilon);
}
template<typename T>
constexpr bool collision_visitor<T>::result()const{

View File

@ -243,6 +243,13 @@ namespace math{
template<typename T, typename U, size_t C, size_t R>
constexpr auto operator-(const matrix<T,R,C>& left);
template<typename T, size_t R, size_t C>
constexpr auto abs(const matrix_base<T,R,C>& left);
template<typename T, typename U, typename V, size_t R, size_t C>
constexpr bool fuzzy_eq(const matrix_base<T,R,C>& left, const matrix_base<U,R,C>& right, const V& epsilon);
template<typename T, typename U, typename V, size_t R, size_t C>
constexpr bool fuzzy_neq(const matrix_base<T,R,C>& left, const matrix_base<U,R,C>& right, const V& epsilon);
//Arithmetic assignment operators
template<typename T, typename U, size_t R>
constexpr decltype(auto) operator*=(matrix<T,R,R>& left, const matrix<U,R,R>& right);

View File

@ -20,7 +20,7 @@
#define REXY_MAT_TPP
#include <cstdlib> //size_t
#include <cmath> //sin, cos
#include <cmath> //sin, cos, abs
#include <type_traits> //decay_t, declval
#include "detail/matrix.hpp"
#include "quat.hpp"
@ -343,7 +343,26 @@ namespace math{
}
return res;
}
template<typename T, size_t R, size_t C>
constexpr auto abs(const matrix_base<T,R,C>& left){
matrix<T,R,C> res(no_initialize);
for(size_t i = 0; i < left.size(); ++i){
res.get(i) = std::abs(left.get(i));
}
return res;
}
template<typename T, typename U, typename V, size_t R, size_t C>
constexpr bool fuzzy_eq(const matrix_base<T,R,C>& left, const matrix_base<U,R,C>& 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<typename T, typename U, typename V, size_t R, size_t C>
constexpr bool fuzzy_neq(const matrix_base<T,R,C>& left, const matrix_base<U,R,C>& right, const V& epsilon){
return !fuzzy_eq(left, right, epsilon);
}
template<typename T, typename U, size_t R>
constexpr decltype(auto) operator*=(matrix<T,R,R>& left, const matrix<U,R,R>& right){

View File

@ -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<float> ab = (l.point2 - l.point1);
math::vec3<float> ac = (r - l.point1);
//check if the point and line are colinear
if(math::fuzzy_neq(math::cross(ab, ac), math::vec3<float>(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);
}
}