#include "orient_outward_ao.h" #include "../per_face_normals.h" #include "../barycenter.h" #include "../doublearea.h" #include "../matlab_format.h" #include "ambient_occlusion.h" #include "EmbreeIntersector.h" #include #include template < typename DerivedV, typename DerivedF, typename DerivedC, typename PointMatrixType, typename FaceMatrixType, typename RowVector3, typename DerivedFF, typename DerivedI> IGL_INLINE void igl::orient_outward_ao( const Eigen::PlainObjectBase & V, const Eigen::PlainObjectBase & F, const Eigen::PlainObjectBase & C, const igl::EmbreeIntersector & ei, const int num_samples, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & I) { using namespace Eigen; using namespace std; assert(C.rows() == F.rows()); assert(F.cols() == 3); assert(V.cols() == 3); // number of faces const int m = F.rows(); // number of patches const int num_cc = C.maxCoeff()+1; I.resize(num_cc); if(&FF != &F) { FF = F; } PlainObjectBase N; Matrix A; per_face_normals(V,F,N); doublearea(V,F,A); double minarea = A.minCoeff(); mt19937 engine; engine.seed(time(0)); Matrix A_int = (A * 100.0 / minarea).template cast(); auto ddist_func = [&] (double i) { return A_int(static_cast(i)); }; discrete_distribution ddist(m, 0, m, ddist_func); // simple ctor of (Iter, Iter) not provided by the stupid VC11 impl... uniform_real_distribution rdist; Matrix C_occlude_count; // +1 when front ray is occluded, -1 when back ray is occluded C_occlude_count.setZero(m, 1); //#pragma omp parallel for for (int i = 0; i < num_samples; ++i) { int f = ddist(engine); // select face with probability proportional to face area double t0 = rdist(engine); double t1 = rdist(engine); double t2 = rdist(engine); double t_sum = t0 + t1 + t2; t0 /= t_sum; t1 /= t_sum; t2 /= t_sum; RowVector3d p = t0 * V.row(F(f,0)) + t1 * V.row(F(f,1)) + t1 * V.row(F(f,2)); RowVector3d n = N.row(f); bool is_backside = rdist(engine) < 0.5; if (is_backside) { n *= -1; } Matrix S; ambient_occlusion(ei, p, n, 1, S); if (S(0) > 0) { C_occlude_count(C(f)) += is_backside ? -1 : 1; } } for(int c = 0;c 0; } // flip according to I for(int f = 0;f IGL_INLINE void igl::orient_outward_ao( const Eigen::PlainObjectBase & V, const Eigen::PlainObjectBase & F, const Eigen::PlainObjectBase & C, const int num_samples, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & I) { using namespace igl; using namespace Eigen; EmbreeIntersector< PlainObjectBase, PlainObjectBase, Matrix > ei(V,F); return orient_outward_ao(V, F, C, ei, num_samples, FF, I); } #ifndef IGL_HEADER_ONLY // Explicit template specialization template void igl::orient_outward_ao, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif