reorient_facets_raycast.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "reorient_facets_raycast.h"
  9. #include "../per_face_normals.h"
  10. #include "../doublearea.h"
  11. #include "../random_dir.h"
  12. #include "../boost/bfs_orient.h"
  13. #include "orient_outward_ao.h"
  14. #include "EmbreeIntersector.h"
  15. #include <iostream>
  16. #include <random>
  17. #include <ctime>
  18. #include <limits>
  19. template <
  20. typename DerivedV,
  21. typename DerivedF,
  22. typename DerivedI>
  23. IGL_INLINE void igl::reorient_facets_raycast(
  24. const Eigen::PlainObjectBase<DerivedV> & V,
  25. const Eigen::PlainObjectBase<DerivedF> & F,
  26. int num_rays,
  27. bool is_verbose,
  28. Eigen::PlainObjectBase<DerivedI> & I)
  29. {
  30. using namespace Eigen;
  31. using namespace std;
  32. assert(F.cols() == 3);
  33. assert(V.cols() == 3);
  34. // number of faces
  35. const int m = F.rows();
  36. if (is_verbose) cout << "extracting patches... ";
  37. VectorXi C;
  38. MatrixXi FF = F;
  39. bfs_orient(F,FF,C);
  40. // number of patches
  41. const int num_cc = C.maxCoeff()+1;
  42. // Init Embree
  43. EmbreeIntersector ei;
  44. ei.init(V.template cast<float>(),FF);
  45. // face normal
  46. MatrixXd N;
  47. per_face_normals(V,FF,N);
  48. // face area
  49. Matrix<typename DerivedV::Scalar,Dynamic,1> A;
  50. doublearea(V,FF,A);
  51. double area_min = numeric_limits<double>::max();
  52. for (int f = 0; f < m; ++f)
  53. {
  54. area_min = A(f) != 0 && A(f) < area_min ? A(f) : area_min;
  55. }
  56. double area_total = A.sum();
  57. // determine number of rays per component according to its area
  58. VectorXd area_per_component;
  59. area_per_component.setZero(num_cc);
  60. for (int f = 0; f < m; ++f)
  61. {
  62. area_per_component(C(f)) += A(f);
  63. }
  64. VectorXi num_rays_per_component(num_cc);
  65. num_rays_per_component.fill(100); // Minimum number of rays per component (predefined)
  66. for (int c = 0; c < num_cc; ++c)
  67. {
  68. num_rays_per_component(c) += static_cast<int>(num_rays * area_per_component(c) / area_total);
  69. }
  70. // generate all the rays
  71. if (is_verbose) cout << "generating rays... ";
  72. uniform_real_distribution<float> rdist;
  73. mt19937 prng;
  74. prng.seed(time(nullptr));
  75. vector<int > ray_face;
  76. vector<Vector3f> ray_ori;
  77. vector<Vector3f> ray_dir;
  78. ray_face.reserve(num_rays);
  79. ray_ori .reserve(num_rays);
  80. ray_dir .reserve(num_rays);
  81. for (int c = 0; c < num_cc; ++c)
  82. {
  83. if (area_per_component[c] == 0)
  84. {
  85. continue;
  86. }
  87. vector<int> CF; // set of faces per component
  88. vector<unsigned long long> CF_area;
  89. for (int f = 0; f < m; ++f)
  90. {
  91. if (C(f)==c)
  92. {
  93. CF.push_back(f);
  94. CF_area.push_back(static_cast<unsigned long long>(100 * A(f) / area_min));
  95. }
  96. }
  97. // discrete distribution for random selection of faces with probability proportional to their areas
  98. auto ddist_func = [&] (double i) { return CF_area[static_cast<int>(i)]; };
  99. discrete_distribution<int> ddist(CF.size(), 0, CF.size(), ddist_func); // simple ctor of (Iter, Iter) not provided by the stupid VC11 impl...
  100. for (int i = 0; i < num_rays_per_component[c]; ++i)
  101. {
  102. int f = CF[ddist(prng)]; // select face with probability proportional to face area
  103. float s = rdist(prng); // random barycentric coordinate (reference: Generating Random Points in Triangles [Turk, Graphics Gems I 1990])
  104. float t = rdist(prng);
  105. float sqrt_t = sqrtf(t);
  106. float a = 1 - sqrt_t;
  107. float b = (1 - s) * sqrt_t;
  108. float c = s * sqrt_t;
  109. Vector3f p = a * V.row(FF(f,0)).template cast<float>().eval() // be careful with the index!!!
  110. + b * V.row(FF(f,1)).template cast<float>().eval()
  111. + c * V.row(FF(f,2)).template cast<float>().eval();
  112. Vector3f n = N.row(f).cast<float>();
  113. // random direction in hemisphere around n (avoid too grazing angle)
  114. Vector3f d;
  115. while (true) {
  116. d = random_dir().cast<float>();
  117. float ndotd = n.dot(d);
  118. if (fabsf(ndotd) < 0.1f)
  119. {
  120. continue;
  121. }
  122. if (ndotd < 0)
  123. {
  124. d *= -1.0f;
  125. }
  126. break;
  127. }
  128. ray_face.push_back(f);
  129. ray_ori .push_back(p);
  130. ray_dir .push_back(d);
  131. }
  132. }
  133. // per component voting: first=front, second=back
  134. vector<pair<float, float>> C_vote_distance(num_cc, make_pair(0, 0)); // sum of distance between ray origin and intersection
  135. vector<pair<int , int >> C_vote_infinity(num_cc, make_pair(0, 0)); // number of rays reaching infinity
  136. if (is_verbose) cout << "shooting rays... ";
  137. #pragma omp parallel for
  138. for (int i = 0; i < (int)ray_face.size(); ++i)
  139. {
  140. int f = ray_face[i];
  141. Vector3f o = ray_ori [i];
  142. Vector3f d = ray_dir [i];
  143. int c = C(f);
  144. // shoot ray toward front & back
  145. vector<Hit> hits_front;
  146. vector<Hit> hits_back;
  147. int num_rays_front;
  148. int num_rays_back;
  149. ei.intersectRay(o, d, hits_front, num_rays_front);
  150. ei.intersectRay(o, -d, hits_back , num_rays_back );
  151. if (!hits_front.empty() && hits_front[0].id == f) hits_front.erase(hits_front.begin());
  152. if (!hits_back .empty() && hits_back [0].id == f) hits_back .erase(hits_back .begin());
  153. if (hits_front.empty())
  154. {
  155. #pragma omp atomic
  156. C_vote_infinity[c].first++;
  157. } else {
  158. #pragma omp atomic
  159. C_vote_distance[c].first += hits_front[0].t;
  160. }
  161. if (hits_back.empty())
  162. {
  163. #pragma omp atomic
  164. C_vote_infinity[c].second++;
  165. } else {
  166. #pragma omp atomic
  167. C_vote_distance[c].second += hits_back[0].t;
  168. }
  169. }
  170. I.resize(m);
  171. for(int f = 0; f < m; ++f)
  172. {
  173. int c = C(f);
  174. I(f) = (C_vote_infinity[c].first == C_vote_infinity[c].second && C_vote_distance[c].first < C_vote_distance[c].second) ||
  175. C_vote_infinity[c].first < C_vote_infinity[c].second
  176. ? 1 : 0;
  177. }
  178. if (is_verbose) cout << "done!" << endl;
  179. }
  180. #ifndef IGL_HEADER_ONLY
  181. // Explicit template specialization
  182. #endif