ambient_occlusion.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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;
  70. ei.init(V,F);
  71. ambient_occlusion(ei,P,N,num_samples,S);
  72. }
  73. #ifndef IGL_HEADER_ONLY
  74. // Explicit template instanciation
  75. 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> >&);
  76. 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> >&);
  77. 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> >&);
  78. #endif