ray_triangle_intersect.cpp 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "ray_triangle_intersect.h"
  2. #include <Eigen/Geometry>
  3. #include <type_traits>
  4. namespace
  5. {
  6. // It'd be nice to have a varadic version of this and put in the igl namespace
  7. template <typename Derived>
  8. void assert_3_vector(const Eigen::MatrixBase<Derived>& mat) {
  9. static_assert(
  10. (Derived::RowsAtCompileTime == 3 && Derived::ColsAtCompileTime == 1) ||
  11. (Derived::RowsAtCompileTime == 1 && Derived::ColsAtCompileTime == 3) ||
  12. (Derived::RowsAtCompileTime == Eigen::Dynamic && Derived::ColsAtCompileTime == 1) ||
  13. (Derived::RowsAtCompileTime == 1 && Derived::ColsAtCompileTime == Eigen::Dynamic),
  14. "Matrix must be 3x1, 1x3, Eigen::Dynamic×1, or 1×Eigen::Dynamic.");
  15. // Add runtime check for dynamic sizes
  16. assert((mat.rows() == 3 && mat.cols() == 1) ||
  17. (mat.rows() == 1 && mat.cols() == 3));
  18. }
  19. }
  20. template <
  21. typename DerivedO,
  22. typename DerivedD,
  23. typename DerivedV0,
  24. typename DerivedV1,
  25. typename DerivedV2>
  26. IGL_INLINE bool igl::ray_triangle_intersect(
  27. const Eigen::MatrixBase<DerivedO> & _O,
  28. const Eigen::MatrixBase<DerivedD> & _D,
  29. const Eigen::MatrixBase<DerivedV0> & _V0,
  30. const Eigen::MatrixBase<DerivedV1> & _V1,
  31. const Eigen::MatrixBase<DerivedV2> & _V2,
  32. const typename DerivedO::Scalar epsilon,
  33. typename DerivedO::Scalar & t,
  34. typename DerivedO::Scalar & u,
  35. typename DerivedO::Scalar & v,
  36. bool & parallel)
  37. {
  38. // Eigen grossness to ensure we have compile-time 3 vectors below.
  39. assert_3_vector(_O);
  40. assert_3_vector(_D);
  41. assert_3_vector(_V0);
  42. assert_3_vector(_V1);
  43. assert_3_vector(_V2);
  44. using Scalar = typename DerivedO::Scalar;
  45. static_assert(std::is_same<Scalar, typename DerivedD::Scalar>::value,
  46. "O and D must have the same scalar type");
  47. static_assert(std::is_same<Scalar, typename DerivedV0::Scalar>::value,
  48. "O and V0 must have the same scalar type");
  49. static_assert(std::is_same<Scalar, typename DerivedV1::Scalar>::value,
  50. "O and V1 must have the same scalar type");
  51. static_assert(std::is_same<Scalar, typename DerivedV2::Scalar>::value,
  52. "O and V2 must have the same scalar type");
  53. const auto O = _O.template head<3>();
  54. const auto D = _D.template head<3>();
  55. const auto V0 = _V0.template head<3>();
  56. const auto V1 = _V1.template head<3>();
  57. const auto V2 = _V2.template head<3>();
  58. // This Eigen rewrite of raytri.c seems… way faster? like 8× over
  59. // intersect_triangle and 50× over intersect_triangle1,2,3. It's not clear to
  60. // me why.
  61. const auto edge1 = (V1-V0).eval();
  62. const auto edge2 = (V2-V0).eval();
  63. const auto pvec = D.cross(edge2).eval();
  64. const Scalar det = edge1.dot(pvec);
  65. if( det > -epsilon && det < epsilon )
  66. {
  67. parallel = true;
  68. return false;
  69. }
  70. parallel = false;
  71. const Scalar inv_det = 1.0 / det;
  72. const auto tvec = (O - V0).eval();
  73. u = tvec.dot(pvec) * inv_det;
  74. if( u < 0.0-epsilon || u > 1.0+epsilon )
  75. {
  76. return false;
  77. }
  78. const auto qvec = tvec.cross(edge1).eval();
  79. v = D.dot(qvec) * inv_det;
  80. if( v < 0.0-epsilon || u + v > 1.0+epsilon )
  81. {
  82. return false;
  83. }
  84. t = edge2.dot(qvec) * inv_det;
  85. return true;
  86. }
  87. #ifdef IGL_STATIC_LIBRARY
  88. // Explicit template instantiation
  89. // generated by autoexplicit.sh
  90. template bool igl::ray_triangle_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3>::Scalar, Eigen::Matrix<double, 1, 3, 1, 1, 3>::Scalar&, Eigen::Matrix<double, 1, 3, 1, 1, 3>::Scalar&, Eigen::Matrix<double, 1, 3, 1, 1, 3>::Scalar&, bool&);
  91. #endif