aabb-evaluation.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <libslic3r/TriangleMesh.hpp>
  5. #include <libslic3r/AABBTreeIndirect.hpp>
  6. #include <libslic3r/SLA/EigenMesh3D.hpp>
  7. #include <Shiny/Shiny.h>
  8. #ifdef _MSC_VER
  9. #pragma warning(push)
  10. #pragma warning(disable: 4244)
  11. #pragma warning(disable: 4267)
  12. #endif
  13. #include <igl/ray_mesh_intersect.h>
  14. #include <igl/point_mesh_squared_distance.h>
  15. #include <igl/remove_duplicate_vertices.h>
  16. #include <igl/signed_distance.h>
  17. #include <igl/random_dir.h>
  18. #ifdef _MSC_VER
  19. #pragma warning(pop)
  20. #endif
  21. const std::string USAGE_STR = {
  22. "Usage: aabb-evaluation stlfilename.stl"
  23. };
  24. using namespace Slic3r;
  25. void profile(const TriangleMesh &mesh)
  26. {
  27. Eigen::MatrixXd V;
  28. Eigen::MatrixXi F;
  29. Eigen::MatrixXd vertex_normals;
  30. sla::to_eigen_mesh(mesh, V, F);
  31. igl::per_vertex_normals(V, F, vertex_normals);
  32. static constexpr int num_samples = 100;
  33. const int num_vertices = std::min(10000, int(mesh.its.vertices.size()));
  34. const Eigen::MatrixXd dirs = igl::random_dir_stratified(num_samples).cast<double>();
  35. Eigen::MatrixXd occlusion_output0;
  36. {
  37. AABBTreeIndirect::Tree3f tree;
  38. {
  39. PROFILE_BLOCK(AABBIndirect_Init);
  40. tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(mesh.its.vertices, mesh.its.indices);
  41. }
  42. {
  43. PROFILE_BLOCK(EigenMesh3D_AABBIndirectF_AmbientOcclusion);
  44. occlusion_output0.resize(num_vertices, 1);
  45. for (int ivertex = 0; ivertex < num_vertices; ++ ivertex) {
  46. const Eigen::Vector3d origin = mesh.its.vertices[ivertex].template cast<double>();
  47. const Eigen::Vector3d normal = vertex_normals.row(ivertex).template cast<double>();
  48. int num_hits = 0;
  49. for (int s = 0; s < num_samples; s++) {
  50. Eigen::Vector3d d = dirs.row(s);
  51. if(d.dot(normal) < 0) {
  52. // reverse ray
  53. d *= -1;
  54. }
  55. igl::Hit hit;
  56. if (AABBTreeIndirect::intersect_ray_first_hit(mesh.its.vertices, mesh.its.indices, tree, (origin + 1e-4 * d).eval(), d, hit))
  57. ++ num_hits;
  58. }
  59. occlusion_output0(ivertex) = (double)num_hits/(double)num_samples;
  60. }
  61. }
  62. {
  63. PROFILE_BLOCK(EigenMesh3D_AABBIndirectFF_AmbientOcclusion);
  64. occlusion_output0.resize(num_vertices, 1);
  65. for (int ivertex = 0; ivertex < num_vertices; ++ ivertex) {
  66. const Eigen::Vector3d origin = mesh.its.vertices[ivertex].template cast<double>();
  67. const Eigen::Vector3d normal = vertex_normals.row(ivertex).template cast<double>();
  68. int num_hits = 0;
  69. for (int s = 0; s < num_samples; s++) {
  70. Eigen::Vector3d d = dirs.row(s);
  71. if(d.dot(normal) < 0) {
  72. // reverse ray
  73. d *= -1;
  74. }
  75. igl::Hit hit;
  76. if (AABBTreeIndirect::intersect_ray_first_hit(mesh.its.vertices, mesh.its.indices, tree,
  77. Eigen::Vector3f((origin + 1e-4 * d).template cast<float>()),
  78. Eigen::Vector3f(d.template cast<float>()), hit))
  79. ++ num_hits;
  80. }
  81. occlusion_output0(ivertex) = (double)num_hits/(double)num_samples;
  82. }
  83. }
  84. }
  85. Eigen::MatrixXd occlusion_output1;
  86. {
  87. std::vector<Vec3d> vertices;
  88. std::vector<Vec3i> triangles;
  89. for (int i = 0; i < V.rows(); ++ i)
  90. vertices.emplace_back(V.row(i).transpose());
  91. for (int i = 0; i < F.rows(); ++ i)
  92. triangles.emplace_back(F.row(i).transpose());
  93. AABBTreeIndirect::Tree3d tree;
  94. {
  95. PROFILE_BLOCK(AABBIndirectD_Init);
  96. tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(vertices, triangles);
  97. }
  98. {
  99. PROFILE_BLOCK(EigenMesh3D_AABBIndirectD_AmbientOcclusion);
  100. occlusion_output1.resize(num_vertices, 1);
  101. for (int ivertex = 0; ivertex < num_vertices; ++ ivertex) {
  102. const Eigen::Vector3d origin = V.row(ivertex).template cast<double>();
  103. const Eigen::Vector3d normal = vertex_normals.row(ivertex).template cast<double>();
  104. int num_hits = 0;
  105. for (int s = 0; s < num_samples; s++) {
  106. Eigen::Vector3d d = dirs.row(s);
  107. if(d.dot(normal) < 0) {
  108. // reverse ray
  109. d *= -1;
  110. }
  111. igl::Hit hit;
  112. if (AABBTreeIndirect::intersect_ray_first_hit(vertices, triangles, tree, Eigen::Vector3d(origin + 1e-4 * d), d, hit))
  113. ++ num_hits;
  114. }
  115. occlusion_output1(ivertex) = (double)num_hits/(double)num_samples;
  116. }
  117. }
  118. }
  119. // Build the AABB accelaration tree
  120. Eigen::MatrixXd occlusion_output2;
  121. {
  122. igl::AABB<Eigen::MatrixXd, 3> AABB;
  123. {
  124. PROFILE_BLOCK(EigenMesh3D_AABB_Init);
  125. AABB.init(V, F);
  126. }
  127. {
  128. PROFILE_BLOCK(EigenMesh3D_AABB_AmbientOcclusion);
  129. occlusion_output2.resize(num_vertices, 1);
  130. for (int ivertex = 0; ivertex < num_vertices; ++ ivertex) {
  131. const Eigen::Vector3d origin = V.row(ivertex).template cast<double>();
  132. const Eigen::Vector3d normal = vertex_normals.row(ivertex).template cast<double>();
  133. int num_hits = 0;
  134. for (int s = 0; s < num_samples; s++) {
  135. Eigen::Vector3d d = dirs.row(s);
  136. if(d.dot(normal) < 0) {
  137. // reverse ray
  138. d *= -1;
  139. }
  140. igl::Hit hit;
  141. if (AABB.intersect_ray(V, F, origin + 1e-4 * d, d, hit))
  142. ++ num_hits;
  143. }
  144. occlusion_output2(ivertex) = (double)num_hits/(double)num_samples;
  145. }
  146. }
  147. }
  148. Eigen::MatrixXd occlusion_output3;
  149. {
  150. typedef Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>> MapMatrixXfUnaligned;
  151. typedef Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>> MapMatrixXiUnaligned;
  152. igl::AABB<MapMatrixXfUnaligned, 3> AABB;
  153. auto vertices = MapMatrixXfUnaligned(mesh.its.vertices.front().data(), mesh.its.vertices.size(), 3);
  154. auto faces = MapMatrixXiUnaligned(mesh.its.indices.front().data(), mesh.its.indices.size(), 3);
  155. {
  156. PROFILE_BLOCK(EigenMesh3D_AABBf_Init);
  157. AABB.init(
  158. vertices,
  159. faces);
  160. }
  161. {
  162. PROFILE_BLOCK(EigenMesh3D_AABBf_AmbientOcclusion);
  163. occlusion_output3.resize(num_vertices, 1);
  164. for (int ivertex = 0; ivertex < num_vertices; ++ ivertex) {
  165. const Eigen::Vector3d origin = mesh.its.vertices[ivertex].template cast<double>();
  166. const Eigen::Vector3d normal = vertex_normals.row(ivertex).template cast<double>();
  167. int num_hits = 0;
  168. for (int s = 0; s < num_samples; s++) {
  169. Eigen::Vector3d d = dirs.row(s);
  170. if(d.dot(normal) < 0) {
  171. // reverse ray
  172. d *= -1;
  173. }
  174. igl::Hit hit;
  175. if (AABB.intersect_ray(vertices, faces, (origin + 1e-4 * d).eval().template cast<float>(), d.template cast<float>(), hit))
  176. ++ num_hits;
  177. }
  178. occlusion_output3(ivertex) = (double)num_hits/(double)num_samples;
  179. }
  180. }
  181. }
  182. PROFILE_UPDATE();
  183. PROFILE_OUTPUT(nullptr);
  184. }
  185. int main(const int argc, const char *argv[])
  186. {
  187. if(argc < 2) {
  188. std::cout << USAGE_STR << std::endl;
  189. return EXIT_SUCCESS;
  190. }
  191. TriangleMesh mesh;
  192. if (! mesh.ReadSTLFile(argv[1])) {
  193. std::cerr << "Error loading " << argv[1] << std::endl;
  194. return -1;
  195. }
  196. if (mesh.empty()) {
  197. std::cerr << "Error loading " << argv[1] << " . It is empty." << std::endl;
  198. return -1;
  199. }
  200. profile(mesh);
  201. return EXIT_SUCCESS;
  202. }