geom/ray: make ray intersections more robust
This commit is contained in:
parent
3e5c89f643
commit
c33a679e81
20
geom/ray.hpp
20
geom/ray.hpp
@ -90,8 +90,13 @@ namespace util::geom {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// returns the distance along a ray to an aabb
|
||||
//
|
||||
// the return value may be negative if the plane lies behind the ray.
|
||||
// the return value may be infinity in the case the ray and plane are parallel
|
||||
// the distance will never be negative
|
||||
//
|
||||
// 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>
|
||||
constexpr T
|
||||
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));
|
||||
|
||||
// did not intersect
|
||||
if (tmin > tmax)
|
||||
if (tmin >= tmax)
|
||||
return std::numeric_limits<T>::infinity ();
|
||||
|
||||
// closest is behind us
|
||||
if (tmin < 0)
|
||||
return tmax;
|
||||
if (tmin <= 0) {
|
||||
if (tmax <= 0) {
|
||||
return std::numeric_limits<T>::infinity ();
|
||||
} else {
|
||||
return tmax;
|
||||
}
|
||||
}
|
||||
|
||||
// closest is in front of us
|
||||
return tmin;
|
||||
|
@ -12,7 +12,7 @@ main (int, char**)
|
||||
util::TAP::logger tap;
|
||||
|
||||
{
|
||||
|
||||
const auto upright = normalised (util::vector2f {1});
|
||||
|
||||
static struct {
|
||||
util::point2f lo;
|
||||
@ -25,12 +25,24 @@ main (int, char**)
|
||||
|
||||
const char *message;
|
||||
} 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 },
|
||||
{ 2, 2 }, { 1/std::sqrt (2.f), 1/std::sqrt (2.f) },
|
||||
{ 2, 2 }, upright,
|
||||
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) {
|
||||
|
@ -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
|
||||
main (void)
|
||||
@ -55,7 +27,6 @@ main (void)
|
||||
util::TAP::logger tap;
|
||||
|
||||
test_intersect_plane (tap);
|
||||
test_intersect_aabb (tap);
|
||||
|
||||
return tap.status ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user