robust ray box intersect (#2244) [ci skip]

* nan-proof min/max

* templates
This commit is contained in:
Alec Jacobson
2023-08-22 14:28:34 -04:00
committed by GitHub
parent 00100b60db
commit 10e95bb93b
5 changed files with 82 additions and 17 deletions
+4
View File
@@ -1025,6 +1025,10 @@ namespace igl
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template bool igl::AABB<Eigen::Matrix<float, -1, -1, 0, -1, -1>, 3>::intersect_ray<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&) const;
// generated by autoexplicit.sh
template void igl::AABB<Eigen::Matrix<float, -1, -1, 0, -1, -1>, 3>::init<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
// generated by autoexplicit.sh
template void igl::AABB<Eigen::Matrix<double, -1, 3, 1, -1, 3>, 3>::squared_distance<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&) const;
// generated by autoexplicit.sh
template void igl::AABB<Eigen::Matrix<double, -1, 3, 1, -1, 3>, 3>::init<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+2
View File
@@ -34,6 +34,8 @@ IGL_INLINE void igl::barycenter(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::barycenter<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
// generated by autoexplicit.sh
template void igl::barycenter<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
template void igl::barycenter<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
template void igl::barycenter<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+22 -17
View File
@@ -7,6 +7,7 @@
// obtain one at http://mozilla.org/MPL/2.0/.
#include "ray_box_intersect.h"
#include <array>
#include <igl/matlab_format.h>
template <
typename Derivedsource,
@@ -105,37 +106,39 @@ IGL_INLINE bool igl::ray_box_intersect(
// http://people.csail.mit.edu/amy/papers/box-jgt.pdf
// "An Efficient and Robust RayBox Intersection Algorithm"
Scalar tymin, tymax, tzmin, tzmax;
std::array<RowVector3S, 2> bounds = {box.min(),box.max()};
std::array<RowVector3S, 2> bounds = {box.min().array(),box.max().array()};
tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0);
tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0);
tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1);
tymax = (bounds[1-sign[1]](1) - origin(1)) * inv_dir(1);
// NaN-safe min and max
const auto berger_perrin_min = [&](
const Scalar a,
const Scalar b) -> Scalar
{
return (a < b) ? a : b;
};
const auto berger_perrin_max = [&](
const Scalar a,
const Scalar b) -> Scalar
{
return (a > b) ? a : b;
};
if ( (tmin > tymax) || (tymin > tmax) )
{
return false;
}
if (tymin > tmin)
{
tmin = tymin;
}
if (tymax < tmax)
{
tmax = tymax;
}
tmin = berger_perrin_max(tmin,tymin);
tmax = berger_perrin_min(tmax,tymax);
tzmin = (bounds[sign[2]](2) - origin(2)) * inv_dir(2);
tzmax = (bounds[1-sign[2]](2) - origin(2)) * inv_dir(2);
if ( (tmin > tzmax) || (tzmin > tmax) )
{
return false;
}
if (tzmin > tmin)
{
tmin = tzmin;
}
if (tzmax < tmax)
{
tmax = tzmax;
}
tmin = berger_perrin_max(tmin,tzmin);
tmax = berger_perrin_min(tmax,tzmax);
if(!( (tmin < t1) && (tmax > t0) ))
{
return false;
@@ -146,5 +149,7 @@ IGL_INLINE bool igl::ray_box_intersect(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template bool igl::ray_box_intersect<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float>(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<float, 3> const&, float const&, float const&, float&, float&);
template bool igl::ray_box_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<double, 3> const&, double const&, double const&, double&, double&);
#endif
+4
View File
@@ -119,6 +119,10 @@ IGL_INLINE bool ray_mesh_intersect(
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
// generated by autoexplicit.sh
template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
// generated by autoexplicit.sh
template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::Hit&);
+50
View File
@@ -1,5 +1,6 @@
#include <test_common.h>
#include <igl/ray_mesh_intersect.h>
#include <igl/AABB.h>
TEST_CASE("ray_mesh_intersect: one_triangle", "[igl]")
{
@@ -23,3 +24,52 @@ TEST_CASE("ray_mesh_intersect: one_triangle", "[igl]")
REQUIRE(hits.size() == 1);
REQUIRE(hits.front().t == Approx(1.0));
}
TEST_CASE("ray_mesh_intersect: corner-case", "[igl]")
{
// . //
// /|\ //
// / | \ //
// / | \ //
// / | \ //
// .----x----. //
// \ | / //
// \ | / //
// \ | / //
// \|/ //
// . //
Eigen::MatrixXf vertices(5, 3);
vertices <<
-1., 0., 0.,
0., 1., 0.,
1., 0., 0.,
0., -1., 0.,
0., 0., 0.;
Eigen::MatrixXi faces(4, 3);
faces <<
0, 1, 4,
1, 2, 4,
2, 3, 4,
3, 0, 4;
igl::AABB<Eigen::MatrixXf, 3> mesh_bvh;
mesh_bvh.init(vertices, faces);
for (float eps: {1e-5f, 0.f})
{
Eigen::Vector3f origin(eps, eps, 1.f + eps);
Eigen::Vector3f direction(0.f, 0.f, -1.f);
std::vector<igl::Hit> hits, hits_bvh;
bool is_hit = igl::ray_mesh_intersect(origin, direction, vertices, faces, hits);
bool is_hit_bvh = mesh_bvh.intersect_ray(vertices, faces, origin, direction, hits_bvh);
REQUIRE (is_hit);
REQUIRE (is_hit == is_hit_bvh);
REQUIRE (hits.size() == hits_bvh.size());
}
}