main.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. #include "tutorial_shared_path.h"
  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. if(!collapse_edge(shortest_edge_and_midpoint,V,F,E,EMAP,EF,EI,Q,EQ,C))
  82. {
  83. break;
  84. }
  85. something_collapsed = true;
  86. num_collapsed++;
  87. }
  88. if(something_collapsed)
  89. {
  90. viewer.data().clear();
  91. viewer.data().set_mesh(V,F);
  92. viewer.data().set_face_based(true);
  93. }
  94. }
  95. return false;
  96. };
  97. const auto &key_down =
  98. [&](igl::opengl::glfw::Viewer &viewer,unsigned char key,int mod)->bool
  99. {
  100. switch(key)
  101. {
  102. case ' ':
  103. viewer.core().is_animating ^= 1;
  104. break;
  105. case 'R':
  106. case 'r':
  107. reset();
  108. break;
  109. default:
  110. return false;
  111. }
  112. return true;
  113. };
  114. reset();
  115. viewer.core().background_color.setConstant(1);
  116. viewer.core().is_animating = true;
  117. viewer.callback_key_down = key_down;
  118. viewer.callback_pre_draw = pre_draw;
  119. return viewer.launch();
  120. }