main.cpp 3.8 KB

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