main.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include <igl/circulation.h>
  2. #include <igl/collapse_least_cost_edge.h>
  3. #include <igl/edge_flaps.h>
  4. #include <igl/decimate.h>
  5. #include <igl/shortest_edge_and_midpoint.h>
  6. #include <igl/decimate_trivial_callbacks.h>
  7. #include <igl/parallel_for.h>
  8. #include <igl/read_triangle_mesh.h>
  9. #include <igl/opengl/glfw/Viewer.h>
  10. #include <Eigen/Core>
  11. #include <iostream>
  12. #include <set>
  13. int main(int argc, char * argv[])
  14. {
  15. using namespace std;
  16. using namespace Eigen;
  17. using namespace igl;
  18. cout<<"Usage: ./703_Decimation_bin [filename.(off|obj|ply)]"<<endl;
  19. cout<<" [space] toggle animation."<<endl;
  20. cout<<" 'r' reset."<<endl;
  21. // Load a closed manifold mesh
  22. string filename(TUTORIAL_SHARED_PATH "/fertility.off");
  23. if(argc>=2)
  24. {
  25. filename = argv[1];
  26. }
  27. MatrixXd V,OV;
  28. MatrixXi F,OF;
  29. read_triangle_mesh(filename,OV,OF);
  30. igl::opengl::glfw::Viewer viewer;
  31. // Prepare array-based edge data structures and priority queue
  32. VectorXi EMAP;
  33. MatrixXi E,EF,EI;
  34. igl::min_heap< std::tuple<double,int,int> > Q;
  35. Eigen::VectorXi EQ;
  36. // If an edge were collapsed, we'd collapse it to these points:
  37. MatrixXd C;
  38. int num_collapsed;
  39. // Function to reset original mesh and data structures
  40. const auto & reset = [&]()
  41. {
  42. F = OF;
  43. V = OV;
  44. edge_flaps(F,E,EMAP,EF,EI);
  45. C.resize(E.rows(),V.cols());
  46. VectorXd costs(E.rows());
  47. // https://stackoverflow.com/questions/2852140/priority-queue-clear-method
  48. // Q.clear();
  49. Q = {};
  50. EQ = Eigen::VectorXi::Zero(E.rows());
  51. {
  52. Eigen::VectorXd costs(E.rows());
  53. igl::parallel_for(E.rows(),[&](const int e)
  54. {
  55. double cost = e;
  56. RowVectorXd p(1,3);
  57. shortest_edge_and_midpoint(e,V,F,E,EMAP,EF,EI,cost,p);
  58. C.row(e) = p;
  59. costs(e) = cost;
  60. },10000);
  61. for(int e = 0;e<E.rows();e++)
  62. {
  63. Q.emplace(costs(e),e,0);
  64. }
  65. }
  66. num_collapsed = 0;
  67. viewer.data().clear();
  68. viewer.data().set_mesh(V,F);
  69. viewer.data().set_face_based(true);
  70. };
  71. const auto &pre_draw = [&](igl::opengl::glfw::Viewer & viewer)->bool
  72. {
  73. // If animating then collapse 10% of edges
  74. if(viewer.core().is_animating && !Q.empty())
  75. {
  76. bool something_collapsed = false;
  77. // collapse edge
  78. const int max_iter = std::ceil(0.01*Q.size());
  79. for(int j = 0;j<max_iter;j++)
  80. {
  81. igl::decimate_pre_collapse_callback always_try;
  82. igl::decimate_post_collapse_callback never_care;
  83. igl::decimate_trivial_callbacks(always_try,never_care);
  84. // Explicit template instanciations expect std::function not raw pointer
  85. // Only relevant if IGL_STATIC_LIBRARY is defined
  86. const std::function<void (int, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, double&, Eigen::Matrix<double, 1, -1, 1, 1, -1>&)> cp = shortest_edge_and_midpoint;
  87. int e,e1,e2,f1,f2;
  88. if(!collapse_least_cost_edge(
  89. cp,always_try,never_care,
  90. V,F,E,
  91. EMAP,EF,EI,
  92. Q,EQ,C,
  93. e,e1,e2,f1,f2))
  94. {
  95. break;
  96. }
  97. something_collapsed = true;
  98. num_collapsed++;
  99. }
  100. if(something_collapsed)
  101. {
  102. viewer.data().clear();
  103. viewer.data().set_mesh(V,F);
  104. viewer.data().set_face_based(true);
  105. }
  106. }
  107. return false;
  108. };
  109. const auto &key_down =
  110. [&](igl::opengl::glfw::Viewer &viewer,unsigned char key,int mod)->bool
  111. {
  112. switch(key)
  113. {
  114. case ' ':
  115. viewer.core().is_animating ^= 1;
  116. break;
  117. case 'R':
  118. case 'r':
  119. reset();
  120. break;
  121. default:
  122. return false;
  123. }
  124. return true;
  125. };
  126. reset();
  127. viewer.core().background_color.setConstant(1);
  128. viewer.core().is_animating = true;
  129. viewer.callback_key_down = key_down;
  130. viewer.callback_pre_draw = pre_draw;
  131. return viewer.launch();
  132. }