main.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <igl/readOBJ.h>
  2. #include <igl/cotmatrix.h>
  3. #include <igl/massmatrix.h>
  4. #include <igl/edges.h>
  5. #include <igl/find.h>
  6. #include <igl/min_quad_with_fixed.h>
  7. #include <igl/polygons_to_triangles.h>
  8. #include <igl/opengl/glfw/Viewer.h>
  9. #include <iostream>
  10. int main(int argc, char *argv[])
  11. {
  12. using namespace Eigen;
  13. using namespace std;
  14. // Load a mesh in OBJ format
  15. Eigen::MatrixXd OV,V;
  16. Eigen::VectorXi I,C;
  17. igl::readOBJ(
  18. argc<=1?TUTORIAL_SHARED_PATH "/cylinder.obj" :argv[1],V,I,C);
  19. // center
  20. V.rowwise() -= V.colwise().mean();
  21. OV = V;
  22. // Convert polygon representation to triangles
  23. Eigen::MatrixXi F;
  24. Eigen::VectorXi J;
  25. igl::polygons_to_triangles(I,C,F,J);
  26. Eigen::SparseMatrix<double> pL,pM,pP;
  27. igl::cotmatrix(V,I,C,pL,pM,pP);
  28. Eigen::SparseMatrix<double> tL,tM;
  29. igl::cotmatrix(V,F,tL);
  30. igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_DEFAULT,tM);
  31. const double bbd = (V.colwise().maxCoeff()- V.colwise().minCoeff()).norm();
  32. igl::opengl::glfw::Viewer vr;
  33. vr.data_list[0].set_mesh(V,F);
  34. vr.append_mesh();
  35. vr.selected_data_index = 0;
  36. vr.data_list[0].set_face_based(true);
  37. Eigen::MatrixXi E;
  38. igl::edges(I,C,E);
  39. bool show_edges = true;
  40. bool use_poly = true;
  41. Eigen::MatrixXd pHN;
  42. Eigen::MatrixXd tHN;
  43. const auto update = [&]()
  44. {
  45. // why does windows need this Eigen::VectorXd(...) ?
  46. pHN = (pL*V).array().colwise() / Eigen::VectorXd(pM.diagonal()).array();
  47. tHN = (tL*V).array().colwise() / Eigen::VectorXd(tM.diagonal()).array();
  48. pHN *= 1.0/pHN.rowwise().norm().maxCoeff();
  49. tHN *= 1.0/tHN.rowwise().norm().maxCoeff();
  50. const auto was_face_based = vr.data_list[0].face_based;
  51. Eigen::MatrixXd QV(V.rows()*2,3);
  52. QV.topRows(V.rows()) = V;
  53. if(use_poly)
  54. {
  55. printf("using polygon Laplacian\n");
  56. QV.bottomRows(V.rows()) = V-pHN;
  57. }else
  58. {
  59. printf("using triangle Laplacian\n");
  60. QV.bottomRows(V.rows()) = V-tHN;
  61. }
  62. Eigen::MatrixXi QE(V.rows(),2);
  63. for(int i = 0;i<V.rows();i++){ QE(i,0)=i;QE(i,1)=i+V.rows();}
  64. vr.data_list[1].set_edges(QV,QE,Eigen::RowVector3d(1,1,1));
  65. if(use_poly)
  66. {
  67. vr.data_list[0].show_lines = false;
  68. if(show_edges)
  69. {
  70. vr.data_list[0].set_edges(V,E,Eigen::RowVector3d(0,0,0));
  71. }else
  72. {
  73. vr.data_list[0].clear_edges();
  74. }
  75. }else
  76. {
  77. vr.data_list[0].clear_edges();
  78. vr.data_list[0].show_lines = show_edges;
  79. }
  80. vr.data_list[0].set_face_based(was_face_based);
  81. };
  82. const double original_area = pM.diagonal().sum();
  83. const auto recompute_M = [&]()
  84. {
  85. Eigen::SparseMatrix<double> _1,_2;
  86. igl::cotmatrix(V,I,C,_1,pM,_2);
  87. igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_DEFAULT,tM);
  88. V *= sqrt(original_area / pM.diagonal().sum());
  89. };
  90. const auto cmcf_step = [&]()
  91. {
  92. const Eigen::SparseMatrix<double> S =
  93. use_poly? ((pM) - 0.05*(pL)): ((tM) - 0.05*(tL));
  94. const Eigen::MatrixXd rhs = use_poly? pM*V : tM*V;
  95. Eigen::SimplicialLLT<Eigen::SparseMatrix<double > > solver(S);
  96. assert(solver.info() == Eigen::Success);
  97. V = solver.solve(rhs).eval();
  98. // recompute just mass matrices
  99. recompute_M();
  100. // center
  101. V.rowwise() -= V.colwise().mean();
  102. vr.data_list[0].set_vertices(V);
  103. vr.data_list[0].compute_normals();
  104. update();
  105. };
  106. vr.callback_key_pressed = [&](decltype(vr) &,unsigned int key, int mod)
  107. {
  108. switch(key)
  109. {
  110. case ' ': cmcf_step(); return true;
  111. case 'R': case 'r': V=OV;recompute_M();vr.data_list[0].set_vertices(V);vr.data_list[0].compute_normals(); update();return true;
  112. case 'P': case 'p': use_poly=!use_poly; update();return true;
  113. case 'L': case 'l': show_edges=!show_edges; update();return true;
  114. }
  115. return false;
  116. };
  117. update();
  118. vr.launch();
  119. }