ray_box_intersect.cpp 4.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "ray_box_intersect.h"
  9. #include <array>
  10. #include <igl/matlab_format.h>
  11. #include <igl/increment_ulp.h>
  12. template <
  13. typename Derivedsource,
  14. typename Deriveddir,
  15. typename Scalar>
  16. IGL_INLINE bool igl::ray_box_intersect(
  17. const Eigen::MatrixBase<Derivedsource> & origin,
  18. const Eigen::MatrixBase<Deriveddir> & inv_dir,
  19. const Eigen::MatrixBase<Deriveddir> & inv_dir_pad,
  20. const Eigen::AlignedBox<Scalar,3> & box,
  21. const Scalar & t0,
  22. const Scalar & t1,
  23. Scalar & tmin,
  24. Scalar & tmax)
  25. {
  26. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  27. const std::array<bool, 3> sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0};
  28. // http://people.csail.mit.edu/amy/papers/box-jgt.pdf
  29. // "An Efficient and Robust Ray–Box Intersection Algorithm"
  30. // corrected in "Robust BVH Ray Traversal" by Thiago Ize, section 3:
  31. Scalar tymin, tymax, tzmin, tzmax;
  32. std::array<RowVector3S, 2> bounds = {box.min().array(),box.max().array()};
  33. tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0);
  34. tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir_pad(0);
  35. tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1);
  36. tymax = (bounds[1-sign[1]](1) - origin(1)) * inv_dir_pad(1);
  37. // NaN-safe min and max
  38. const auto berger_perrin_min = [&](
  39. const Scalar a,
  40. const Scalar b) -> Scalar
  41. {
  42. return (a < b) ? a : b;
  43. };
  44. const auto berger_perrin_max = [&](
  45. const Scalar a,
  46. const Scalar b) -> Scalar
  47. {
  48. return (a > b) ? a : b;
  49. };
  50. if ( (tmin > tymax) || (tymin > tmax) )
  51. {
  52. return false;
  53. }
  54. tmin = berger_perrin_max(tmin, tymin);
  55. tmax = berger_perrin_min(tmax, tymax);
  56. tzmin = (bounds[sign[2]](2) - origin(2)) * inv_dir(2);
  57. tzmax = (bounds[1-sign[2]](2) - origin(2)) * inv_dir_pad(2);
  58. if ((tmin > tzmax) || (tzmin > tmax))
  59. {
  60. return false;
  61. }
  62. tmin = berger_perrin_max(tmin, tzmin);
  63. tmax = berger_perrin_min(tmax, tzmax);
  64. return ((tmin < t1) && (tmax > t0));
  65. }
  66. template <
  67. typename Derivedsource,
  68. typename Deriveddir,
  69. typename Scalar>
  70. IGL_INLINE bool igl::ray_box_intersect(
  71. const Eigen::MatrixBase<Derivedsource> & origin,
  72. const Eigen::MatrixBase<Deriveddir> & dir,
  73. const Eigen::AlignedBox<Scalar,3> & box,
  74. const Scalar & t0,
  75. const Scalar & t1,
  76. Scalar & tmin,
  77. Scalar & tmax)
  78. {
  79. // precompute the inv_dir
  80. Eigen::Matrix<Scalar, 1, 3> inv_dir = dir.cwiseInverse();
  81. // see "Robust BVH Ray Traversal" by Thiago Ize, section 3:
  82. // for why we need this
  83. Eigen::Matrix<Scalar, 1, 3> inv_dir_pad = inv_dir;
  84. igl::increment_ulp(inv_dir_pad, 2);
  85. return igl::ray_box_intersect(origin, inv_dir, inv_dir_pad, box, t0, t1, tmin, tmax);
  86. }
  87. #ifdef IGL_STATIC_LIBRARY
  88. // Explicit template instantiation
  89. // generated by autoexplicit.sh
  90. 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::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<float, 3> const&, float const&, float const&, float&, float&);
  91. 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::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<double, 3> const&, double const&, double const&, double&, double&);
  92. template bool igl::ray_box_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, float>(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1>> const&, Eigen::AlignedBox<float, 3> const&, float const&, float const&, float&, float&);
  93. 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&);
  94. 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&);
  95. #endif