main.cpp 3.1 KB

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