ambient_occlusion.cpp 3.3 KB

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