#include "ray_triangle_intersect.h" #include #include namespace { // It'd be nice to have a varadic version of this and put in the igl namespace template void assert_3_vector(const Eigen::MatrixBase& mat) { static_assert( (Derived::RowsAtCompileTime == 3 && Derived::ColsAtCompileTime == 1) || (Derived::RowsAtCompileTime == 1 && Derived::ColsAtCompileTime == 3) || (Derived::RowsAtCompileTime == Eigen::Dynamic && Derived::ColsAtCompileTime == 1) || (Derived::RowsAtCompileTime == 1 && Derived::ColsAtCompileTime == Eigen::Dynamic), "Matrix must be 3x1, 1x3, Eigen::Dynamic×1, or 1×Eigen::Dynamic."); // Add runtime check for dynamic sizes assert((mat.rows() == 3 && mat.cols() == 1) || (mat.rows() == 1 && mat.cols() == 3)); } } template < typename DerivedO, typename DerivedD, typename DerivedV0, typename DerivedV1, typename DerivedV2> IGL_INLINE bool igl::ray_triangle_intersect( const Eigen::MatrixBase & _O, const Eigen::MatrixBase & _D, const Eigen::MatrixBase & _V0, const Eigen::MatrixBase & _V1, const Eigen::MatrixBase & _V2, const typename DerivedO::Scalar epsilon, typename DerivedO::Scalar & t, typename DerivedO::Scalar & u, typename DerivedO::Scalar & v, bool & parallel) { // Eigen grossness to ensure we have compile-time 3 vectors below. assert_3_vector(_O); assert_3_vector(_D); assert_3_vector(_V0); assert_3_vector(_V1); assert_3_vector(_V2); using Scalar = typename DerivedO::Scalar; static_assert(std::is_same::value, "O and D must have the same scalar type"); static_assert(std::is_same::value, "O and V0 must have the same scalar type"); static_assert(std::is_same::value, "O and V1 must have the same scalar type"); static_assert(std::is_same::value, "O and V2 must have the same scalar type"); const auto O = _O.template head<3>(); const auto D = _D.template head<3>(); const auto V0 = _V0.template head<3>(); const auto V1 = _V1.template head<3>(); const auto V2 = _V2.template head<3>(); // This Eigen rewrite of raytri.c seems… way faster? like 8× over // intersect_triangle and 50× over intersect_triangle1,2,3. It's not clear to // me why. const auto edge1 = (V1-V0).eval(); const auto edge2 = (V2-V0).eval(); const auto pvec = D.cross(edge2).eval(); const Scalar det = edge1.dot(pvec); if( det > -epsilon && det < epsilon ) { parallel = true; return false; } parallel = false; const Scalar inv_det = 1.0 / det; const auto tvec = (O - V0).eval(); u = tvec.dot(pvec) * inv_det; if( u < 0.0-epsilon || u > 1.0+epsilon ) { return false; } const auto qvec = tvec.cross(edge1).eval(); v = D.dot(qvec) * inv_det; if( v < 0.0-epsilon || u + v > 1.0+epsilon ) { return false; } t = edge2.dot(qvec) * inv_det; return true; } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template bool igl::ray_triangle_intersect, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar&, Eigen::Matrix::Scalar&, Eigen::Matrix::Scalar&, bool&); #endif