main.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include <igl/opengl/glfw/Viewer.h>
  2. #include <igl/read_triangle_mesh.h>
  3. #include <igl/predicates/find_self_intersections.h>
  4. #include <igl/unique.h>
  5. #include <igl/remove_unreferenced.h>
  6. #include <igl/get_seconds.h>
  7. #include <igl/AABB.h>
  8. #include <igl/writePLY.h>
  9. #include <igl/intersection_blocking_collapse_edge_callbacks.h>
  10. #include <igl/qslim_optimal_collapse_edge_callbacks.h>
  11. #include <igl/per_vertex_point_to_plane_quadrics.h>
  12. #include <igl/STR.h>
  13. #include <igl/connect_boundary_to_infinity.h>
  14. #include <igl/decimate.h>
  15. #include <igl/max_faces_stopping_condition.h>
  16. #include <igl/point_simplex_squared_distance.h>
  17. #include <igl/edge_flaps.h>
  18. #include <igl/decimate_callback_types.h>
  19. #include <igl/find.h>
  20. int main(int argc, char *argv[])
  21. {
  22. IGL_TICTOC_LAMBDA;
  23. Eigen::MatrixXd V,V0;
  24. Eigen::MatrixXi F,F0;
  25. igl::read_triangle_mesh(
  26. argc<=1 ? TUTORIAL_SHARED_PATH "/octopus-low.mesh" :
  27. argv[1],V,F);
  28. V0 = V;F0 = F;
  29. ///////////////////////////////////////////////////////////
  30. /// Before collapsing starts
  31. ///////////////////////////////////////////////////////////
  32. tictoc();
  33. igl::AABB<Eigen::MatrixXd, 3> * tree = new igl::AABB<Eigen::MatrixXd, 3>();
  34. tree->init(V,F);
  35. printf("tree->init: %g\n",tictoc());
  36. tree->validate();
  37. const int target_m = F.rows() * 0.1 + 1;
  38. Eigen::MatrixXd dV[2];
  39. Eigen::MatrixXd dC[2];
  40. Eigen::MatrixXi dF[2];
  41. Eigen::RowVector3d gray(0.9,0.9,0.9);
  42. for(auto pass : {0,1})
  43. {
  44. Eigen::MatrixXd VO;
  45. Eigen::MatrixXi FO;
  46. igl::connect_boundary_to_infinity(V,F,VO,FO);
  47. Eigen::VectorXi EMAP;
  48. Eigen::MatrixXi E,EF,EI;
  49. igl::edge_flaps(FO,E,EMAP,EF,EI);
  50. igl::decimate_cost_and_placement_callback cost_and_placement;
  51. igl::decimate_pre_collapse_callback pre_collapse;
  52. igl::decimate_post_collapse_callback post_collapse;
  53. // Quadrics per vertex
  54. typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
  55. std::vector<Quadric> quadrics;
  56. igl::per_vertex_point_to_plane_quadrics(VO,FO,EMAP,EF,EI,quadrics);
  57. // State variables keeping track of edge we just collapsed
  58. int v1 = -1;
  59. int v2 = -1;
  60. // Callbacks for computing and updating metric
  61. igl::qslim_optimal_collapse_edge_callbacks(
  62. E,quadrics,v1,v2, cost_and_placement, pre_collapse,post_collapse);
  63. if(pass == 1)
  64. {
  65. igl::intersection_blocking_collapse_edge_callbacks(
  66. pre_collapse, post_collapse, // These will get copied as needed
  67. tree,
  68. pre_collapse, post_collapse);
  69. }
  70. int m = F.rows();
  71. const int orig_m = m;
  72. Eigen::MatrixXd U;
  73. Eigen::MatrixXi G;
  74. Eigen::VectorXi J,I;
  75. tictoc();
  76. const bool ret = igl::decimate(
  77. VO, FO,
  78. cost_and_placement,
  79. igl::max_faces_stopping_condition(m,orig_m,target_m),
  80. pre_collapse,
  81. post_collapse,
  82. E, EMAP, EF, EI,
  83. U, G, J, I);
  84. G = G(igl::find((J.array()<orig_m).eval()), Eigen::all).eval();
  85. {
  86. Eigen::VectorXi _;
  87. igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_);
  88. }
  89. printf("qslim-%22s in %g secs\n",pass?"-intersection-blocking":"",tictoc());
  90. igl::writePLY(STR("out-"<<pass<<".ply"),U,G);
  91. dV[pass] = U;
  92. dF[pass] = G;
  93. {
  94. Eigen::VectorXi BI;
  95. {
  96. Eigen::MatrixXi IF;
  97. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  98. igl::predicates::find_self_intersections(dV[pass],dF[pass],false,IF,CP);
  99. igl::unique(IF,BI);
  100. }
  101. printf(" # self-intersections: %d\n",(int)BI.size());
  102. dC[pass] = gray.replicate(dF[pass].rows(),1);
  103. dC[pass](BI,Eigen::all) =
  104. Eigen::RowVector3d(0.95,0.15,0.15).replicate(BI.size(),1);
  105. }
  106. }
  107. tree->validate();
  108. assert(tree == tree->root());
  109. tree = tree->root();
  110. igl::opengl::glfw::Viewer vr;
  111. vr.callback_key_pressed = [&](decltype(vr) &,unsigned int key, int mod)
  112. {
  113. switch(key)
  114. {
  115. case ',':
  116. case '.':
  117. vr.data_list[vr.selected_data_index].is_visible = false;
  118. vr.selected_data_index += (key==','?-1:1) + vr.data_list.size();
  119. vr.selected_data_index %= vr.data_list.size();
  120. vr.data_list[vr.selected_data_index].is_visible = true;
  121. switch(vr.selected_data_index)
  122. {
  123. case 0:
  124. printf("Original mesh\n");
  125. break;
  126. case 1:
  127. printf("Qslim mesh\n");
  128. break;
  129. case 2:
  130. printf("Qslim mesh with intersection blocking\n");
  131. break;
  132. }
  133. return true;
  134. default:
  135. return false;
  136. }
  137. };
  138. vr.data().set_mesh(V0,F0);
  139. vr.data().show_lines = false;
  140. vr.data().set_face_based(true);
  141. vr.data().is_visible = false;
  142. vr.data().set_colors(gray);
  143. vr.append_mesh();
  144. vr.data().set_mesh(dV[0],dF[0]);
  145. vr.data().show_lines = true;
  146. vr.data().set_face_based(true);
  147. vr.data().is_visible = false;
  148. vr.data().set_colors(dC[0]);
  149. vr.append_mesh();
  150. vr.data().set_mesh(dV[1],dF[1]);
  151. vr.data().show_lines = true;
  152. vr.data().set_face_based(true);
  153. vr.data().set_colors(dC[1]);
  154. vr.launch();
  155. }