ambient_occlusion.cpp 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "ambient_occlusion.h"
  2. #include "EmbreeIntersector.h"
  3. #include <igl/random_dir.h>
  4. #include <igl/EPS.h>
  5. template <
  6. typename Scalar,
  7. typename Index,
  8. typename DerivedP,
  9. typename DerivedN,
  10. typename DerivedS >
  11. void igl::ambient_occlusion(
  12. const igl::EmbreeIntersector<Scalar,Index> & ei,
  13. const Eigen::PlainObjectBase<DerivedP> & P,
  14. const Eigen::PlainObjectBase<DerivedN> & N,
  15. const int num_samples,
  16. Eigen::PlainObjectBase<DerivedS> & S)
  17. {
  18. using namespace Eigen;
  19. using namespace igl;
  20. const int n = P.rows();
  21. // Resize output
  22. S.resize(n,1);
  23. // Embree seems to be parallel when constructing but not when tracing rays
  24. #pragma omp parallel for
  25. // loop over mesh vertices
  26. for(int p = 0;p<n;p++)
  27. {
  28. const Vector3d origin = P.row(p);
  29. const Vector3d normal = N.row(p);
  30. int num_hits = 0;
  31. MatrixXd D = random_dir_stratified(num_samples);
  32. for(int s = 0;s<num_samples;s++)
  33. {
  34. //Vector3d d = random_dir();
  35. Vector3d d = D.row(s);
  36. if(d.dot(normal) < 0)
  37. {
  38. // reverse ray
  39. d *= -1;
  40. }
  41. igl::Hit hit;
  42. const float tnear = 1e-4f;
  43. if(ei.intersectRay(origin,d,hit,tnear))
  44. {
  45. num_hits++;
  46. }
  47. }
  48. S(p) = (double)num_hits/(double)num_samples;
  49. }
  50. }
  51. template <
  52. typename DerivedV,
  53. typename DerivedF,
  54. typename DerivedP,
  55. typename DerivedN,
  56. typename DerivedS >
  57. void igl::ambient_occlusion(
  58. const Eigen::PlainObjectBase<DerivedV> & V,
  59. const Eigen::PlainObjectBase<DerivedF> & F,
  60. const Eigen::PlainObjectBase<DerivedP> & P,
  61. const Eigen::PlainObjectBase<DerivedN> & N,
  62. const int num_samples,
  63. Eigen::PlainObjectBase<DerivedS> & S)
  64. {
  65. using namespace igl;
  66. using namespace Eigen;
  67. EmbreeIntersector<
  68. typename DerivedV::Scalar,
  69. typename DerivedF::Scalar > * ei = new EmbreeIntersector<
  70. typename DerivedV::Scalar,
  71. typename DerivedF::Scalar >(V,F);
  72. ambient_occlusion(*ei,P,N,num_samples,S);
  73. delete ei;
  74. }
  75. #ifndef IGL_HEADER_ONLY
  76. // Explicit template instanciation
  77. template void igl::ambient_occlusion<double, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::EmbreeIntersector<double, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  78. template void igl::ambient_occlusion<double, int, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::EmbreeIntersector<double, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  79. template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  80. #endif