ray_box_intersect.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "ray_box_intersect.h"
  2. #include <vector>
  3. template <
  4. typename Derivedsource,
  5. typename Deriveddir,
  6. typename Scalar>
  7. IGL_INLINE bool igl::ray_box_intersect(
  8. const Eigen::PlainObjectBase<Derivedsource> & origin,
  9. const Eigen::PlainObjectBase<Deriveddir> & dir,
  10. const Eigen::AlignedBox<Scalar,3> & box,
  11. const Scalar & t0,
  12. const Scalar & t1,
  13. Scalar & tmin,
  14. Scalar & tmax)
  15. {
  16. #ifdef false
  17. // https://github.com/RMonica/basic_next_best_view/blob/master/src/RayTracer.cpp
  18. const auto & intersectRayBox = [](
  19. const Eigen::Vector3f& rayo,
  20. const Eigen::Vector3f& rayd,
  21. const Eigen::Vector3f& bmin,
  22. const Eigen::Vector3f& bmax,
  23. float & tnear,
  24. float & tfar
  25. )->bool
  26. {
  27. Eigen::Vector3f bnear;
  28. Eigen::Vector3f bfar;
  29. // Checks for intersection testing on each direction coordinate
  30. // Computes
  31. float t1, t2;
  32. tnear = -1e+6f, tfar = 1e+6f; //, tCube;
  33. bool intersectFlag = true;
  34. for (int i = 0; i < 3; ++i) {
  35. // std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl;
  36. assert(bmin(i) <= bmax(i));
  37. if (::fabs(rayd(i)) < 1e-6) { // Ray parallel to axis i-th
  38. if (rayo(i) < bmin(i) || rayo(i) > bmax(i)) {
  39. intersectFlag = false;
  40. }
  41. }
  42. else {
  43. // Finds the nearest and the farthest vertices of the box from the ray origin
  44. if (::fabs(bmin(i) - rayo(i)) < ::fabs(bmax(i) - rayo(i))) {
  45. bnear(i) = bmin(i);
  46. bfar(i) = bmax(i);
  47. }
  48. else {
  49. bnear(i) = bmax(i);
  50. bfar(i) = bmin(i);
  51. }
  52. // std::cout << " bnear " << bnear(i) << ", bfar " << bfar(i) << std::endl;
  53. // Finds the distance parameters t1 and t2 of the two ray-box intersections:
  54. // t1 must be the closest to the ray origin rayo.
  55. t1 = (bnear(i) - rayo(i)) / rayd(i);
  56. t2 = (bfar(i) - rayo(i)) / rayd(i);
  57. if (t1 > t2) {
  58. std::swap(t1,t2);
  59. }
  60. // The two intersection values are used to saturate tnear and tfar
  61. if (t1 > tnear) {
  62. tnear = t1;
  63. }
  64. if (t2 < tfar) {
  65. tfar = t2;
  66. }
  67. // std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar
  68. // << " tnear > tfar? " << (tnear > tfar) << ", tfar < 0? " << (tfar < 0) << std::endl;
  69. if(tnear > tfar) {
  70. intersectFlag = false;
  71. }
  72. if(tfar < 0) {
  73. intersectFlag = false;
  74. }
  75. }
  76. }
  77. // Checks whether intersection occurs or not
  78. return intersectFlag;
  79. };
  80. float tmin_f, tmax_f;
  81. bool ret = intersectRayBox(
  82. origin. template cast<float>(),
  83. dir. template cast<float>(),
  84. box.min().template cast<float>(),
  85. box.max().template cast<float>(),
  86. tmin_f,
  87. tmax_f);
  88. tmin = tmin_f;
  89. tmax = tmax_f;
  90. return ret;
  91. #else
  92. using namespace Eigen;
  93. // This should be precomputed and provided as input
  94. typedef Matrix<Scalar,1,3> RowVector3S;
  95. const RowVector3S inv_dir( 1./dir(0),1./dir(1),1./dir(2));
  96. const std::vector<bool> sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0};
  97. // http://people.csail.mit.edu/amy/papers/box-jgt.pdf
  98. // "An Efficient and Robust Ray–Box Intersection Algorithm"
  99. Scalar tymin, tymax, tzmin, tzmax;
  100. std::vector<RowVector3S> bounds = {box.min(),box.max()};
  101. tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0);
  102. tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0);
  103. tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1);
  104. tymax = (bounds[1-sign[1]](1) - origin(1)) * inv_dir(1);
  105. if ( (tmin > tymax) || (tymin > tmax) )
  106. {
  107. return false;
  108. }
  109. if (tymin > tmin)
  110. {
  111. tmin = tymin;
  112. }
  113. if (tymax < tmax)
  114. {
  115. tmax = tymax;
  116. }
  117. tzmin = (bounds[sign[2]](2) - origin(2)) * inv_dir(2);
  118. tzmax = (bounds[1-sign[2]](2) - origin(2)) * inv_dir(2);
  119. if ( (tmin > tzmax) || (tzmin > tmax) )
  120. {
  121. return false;
  122. }
  123. if (tzmin > tmin)
  124. {
  125. tmin = tzmin;
  126. }
  127. if (tzmax < tmax)
  128. {
  129. tmax = tzmax;
  130. }
  131. if(!( (tmin < t1) && (tmax > t0) ))
  132. {
  133. return false;
  134. }
  135. return true;
  136. #endif
  137. }