geom/ray: make ray intersections more robust
This commit is contained in:
parent
3e5c89f643
commit
c33a679e81
18
geom/ray.hpp
18
geom/ray.hpp
@ -90,8 +90,13 @@ namespace util::geom {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// returns the distance along a ray to an aabb
|
// returns the distance along a ray to an aabb
|
||||||
//
|
//
|
||||||
// the return value may be negative if the plane lies behind the ray.
|
// the distance will never be negative
|
||||||
// the return value may be infinity in the case the ray and plane are parallel
|
//
|
||||||
|
// the origin point of the ray does not provoke an intersection, so the
|
||||||
|
// returned distances _should_ always be strictly positive.
|
||||||
|
//
|
||||||
|
// if a forward intersection cannot be found then 'infinity' is returned
|
||||||
|
// instead.
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
constexpr T
|
constexpr T
|
||||||
distance (const ray<S,T> r, const aabb<S,T> b)
|
distance (const ray<S,T> r, const aabb<S,T> b)
|
||||||
@ -105,12 +110,17 @@ namespace util::geom {
|
|||||||
const auto tmax = min (max (t1, t2));
|
const auto tmax = min (max (t1, t2));
|
||||||
|
|
||||||
// did not intersect
|
// did not intersect
|
||||||
if (tmin > tmax)
|
if (tmin >= tmax)
|
||||||
return std::numeric_limits<T>::infinity ();
|
return std::numeric_limits<T>::infinity ();
|
||||||
|
|
||||||
// closest is behind us
|
// closest is behind us
|
||||||
if (tmin < 0)
|
if (tmin <= 0) {
|
||||||
|
if (tmax <= 0) {
|
||||||
|
return std::numeric_limits<T>::infinity ();
|
||||||
|
} else {
|
||||||
return tmax;
|
return tmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// closest is in front of us
|
// closest is in front of us
|
||||||
return tmin;
|
return tmin;
|
||||||
|
@ -12,7 +12,7 @@ main (int, char**)
|
|||||||
util::TAP::logger tap;
|
util::TAP::logger tap;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
const auto upright = normalised (util::vector2f {1});
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
util::point2f lo;
|
util::point2f lo;
|
||||||
@ -25,12 +25,24 @@ main (int, char**)
|
|||||||
|
|
||||||
const char *message;
|
const char *message;
|
||||||
} const TESTS[] {
|
} const TESTS[] {
|
||||||
|
{
|
||||||
|
{ 0, 0 }, { 1, 1 },
|
||||||
|
{ 0, 0 }, upright,
|
||||||
|
std::sqrt (2.f),
|
||||||
|
"ray on aabb corner, pointing to opposite corner",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ 0, 0 }, { 1, 1 },
|
||||||
|
{ 0, 1 }, upright,
|
||||||
|
INFINITY,
|
||||||
|
"ray on aabb implied corner, pointing away",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
{ 1, 1 }, { 9, 9 },
|
{ 1, 1 }, { 9, 9 },
|
||||||
{ 2, 2 }, { 1/std::sqrt (2.f), 1/std::sqrt (2.f) },
|
{ 2, 2 }, upright,
|
||||||
std::sqrt (7.f * 7 * 2),
|
std::sqrt (7.f * 7 * 2),
|
||||||
"ray doesn't give negative distance to closest edge"
|
"ray inside aabb, close to one corner and pointing to far corner",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto const &t: TESTS) {
|
for (auto const &t: TESTS) {
|
||||||
|
@ -20,34 +20,6 @@ test_intersect_plane (util::TAP::logger &tap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
test_intersect_aabb (util::TAP::logger &tap)
|
|
||||||
{
|
|
||||||
using util::geom::aabb2f;
|
|
||||||
|
|
||||||
// trivial case: unit aabb at origin, ray from (0.5,-0.5) upwards
|
|
||||||
const aabb2f box {
|
|
||||||
{ 0.f, 0.f },
|
|
||||||
{ 1.f, 1.f }
|
|
||||||
};
|
|
||||||
|
|
||||||
const ray2f forward {
|
|
||||||
util::point2f { 0.5f, -0.5f },
|
|
||||||
util::vector2f { 0.0f, 1.0f }
|
|
||||||
};
|
|
||||||
|
|
||||||
tap.expect_eq (distance (forward, box), 0.5f, "ray-aabb intersect");
|
|
||||||
|
|
||||||
const ray2f behind {
|
|
||||||
util::point2f { 0.5f, 2.0f },
|
|
||||||
util::vector2f { 0.0f, 1.0f }
|
|
||||||
};
|
|
||||||
|
|
||||||
tap.expect_eq (distance (behind, box), -1.f, "ray-aabb intersect behind");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
@ -55,7 +27,6 @@ main (void)
|
|||||||
util::TAP::logger tap;
|
util::TAP::logger tap;
|
||||||
|
|
||||||
test_intersect_plane (tap);
|
test_intersect_plane (tap);
|
||||||
test_intersect_aabb (tap);
|
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user