orient_outward_ao.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "orient_outward_ao.h"
  2. #include "per_face_normals.h"
  3. #include "barycenter.h"
  4. #include "doublearea.h"
  5. #include "matlab_format.h"
  6. #include "embree/ambient_occlusion.h"
  7. #include <iostream>
  8. #include <random>
  9. template <
  10. typename DerivedV,
  11. typename DerivedF,
  12. typename DerivedC,
  13. typename DerivedFF,
  14. typename DerivedI>
  15. IGL_INLINE void igl::orient_outward_ao(
  16. const Eigen::PlainObjectBase<DerivedV> & V,
  17. const Eigen::PlainObjectBase<DerivedF> & F,
  18. const Eigen::PlainObjectBase<DerivedC> & C,
  19. const igl::EmbreeIntersector<PointMatrixType,FaceMatrixType,RowVector3> & ei,
  20. const int num_samples,
  21. Eigen::PlainObjectBase<DerivedFF> & FF,
  22. Eigen::PlainObjectBase<DerivedI> & I)
  23. {
  24. using namespace Eigen;
  25. using namespace std;
  26. assert(C.rows() == F.rows());
  27. assert(F.cols() == 3);
  28. assert(V.cols() == 3);
  29. // number of faces
  30. const int m = F.rows();
  31. // number of patches
  32. const int num_cc = C.maxCoeff()+1;
  33. I.resize(num_cc);
  34. if(&FF != &F)
  35. {
  36. FF = F;
  37. }
  38. PlainObjectBase<DerivedV> N;
  39. Matrix<typename DerivedV::Scalar,Dynamic,1> A;
  40. per_face_normals(V,F,N);
  41. doublearea(V,F,A);
  42. double minarea = A.minCoeff();
  43. mt19937 engine;
  44. engine.seed(time(0));
  45. vector<int> ddist_probability(m);
  46. for (int f = 0; f < m; ++f)
  47. ddist_probability[f] = static_cast<int>(A(f) * 100. / minarea);
  48. discrete_distribution<int> ddist(dist_probability.begin(), dist_probability.end());
  49. uniform_real_distribution<double> rdist;
  50. VectorXi face_occluded_front(m, 0);
  51. VectorXi face_occluded_back (m, 0);
  52. #pragma omp parallel for
  53. for (int i = 0; i < num_samples; ++i) {
  54. int f = dist(engine); // select face with probability proportional to face area
  55. double t0 = rdist(engine);
  56. double t1 = rdist(engine);
  57. double t2 = rdist(engine);
  58. double t_sum = t0 + t1 + t2;
  59. t0 /= t_sum;
  60. t1 /= t_sum;
  61. t2 /= t_sum;
  62. RowVector3d p = t0 * V.row(F(f,0)) + t1 * V.row(F(f,1)) + t1 * V.row(F(f,2));
  63. RowVector3d n = N.row(f);
  64. bool is_backside = rdist(engine) < 0.5;
  65. if (is_backside)
  66. n *= -1;
  67. Matrix<typename DerivedV::Scalar,Dynamic,1> S;
  68. ambient_occlusion(ei, p, n, 1, S);
  69. }
  70. // take area weighted average
  71. for(int c = 0;c<num_cc;c++)
  72. {
  73. //dot(c) /= (typename DerivedV::Scalar) totA(c);
  74. //if(dot(c) < 0)
  75. bool b = true;
  76. I(c) = b;
  77. }
  78. // flip according to I
  79. for(int f = 0;f<m;f++)
  80. {
  81. if(I(C(f)))
  82. {
  83. FF.row(f) = FF.row(f).reverse().eval();
  84. }
  85. }
  86. }
  87. #ifndef IGL_HEADER_ONLY
  88. // Explicit template specialization
  89. template void igl::orient_outward_ao<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -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<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  90. #endif