main.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include <igl/barycenter.h>
  2. #include <igl/cotmatrix.h>
  3. #include <igl/doublearea.h>
  4. #include <igl/grad.h>
  5. #include <igl/jet.h>
  6. #include <igl/massmatrix.h>
  7. #include <igl/per_vertex_normals.h>
  8. #include <igl/readDMAT.h>
  9. #include <igl/readOFF.h>
  10. #include <igl/repdiag.h>
  11. #include <igl/viewer/Viewer.h>
  12. #include <iostream>
  13. #include "tutorial_shared_path.h"
  14. Eigen::MatrixXd V,U;
  15. Eigen::MatrixXi F;
  16. Eigen::SparseMatrix<double> L;
  17. igl::viewer::Viewer viewer;
  18. int main(int argc, char *argv[])
  19. {
  20. using namespace Eigen;
  21. using namespace std;
  22. // Load a mesh in OFF format
  23. igl::readOFF(TUTORIAL_SHARED_PATH "/cow.off", V, F);
  24. // Compute Laplace-Beltrami operator: #V by #V
  25. igl::cotmatrix(V,F,L);
  26. // Alternative construction of same Laplacian
  27. SparseMatrix<double> G,K;
  28. // Gradient/Divergence
  29. igl::grad(V,F,G);
  30. // Diagonal per-triangle "mass matrix"
  31. VectorXd dblA;
  32. igl::doublearea(V,F,dblA);
  33. // Place areas along diagonal #dim times
  34. const auto & T = 1.*(dblA.replicate(3,1)*0.5).asDiagonal();
  35. // Laplacian K built as discrete divergence of gradient or equivalently
  36. // discrete Dirichelet energy Hessian
  37. K = -G.transpose() * T * G;
  38. cout<<"|K-L|: "<<(K-L).norm()<<endl;
  39. const auto &key_down = [](igl::viewer::Viewer &viewer,unsigned char key,int mod)->bool
  40. {
  41. switch(key)
  42. {
  43. case 'r':
  44. case 'R':
  45. U = V;
  46. break;
  47. case ' ':
  48. {
  49. // Recompute just mass matrix on each step
  50. SparseMatrix<double> M;
  51. igl::massmatrix(U,F,igl::MASSMATRIX_TYPE_BARYCENTRIC,M);
  52. // Solve (M-delta*L) U = M*U
  53. const auto & S = (M - 0.001*L);
  54. Eigen::SimplicialLLT<Eigen::SparseMatrix<double > > solver(S);
  55. assert(solver.info() == Eigen::Success);
  56. U = solver.solve(M*U).eval();
  57. // Compute centroid and subtract (also important for numerics)
  58. VectorXd dblA;
  59. igl::doublearea(U,F,dblA);
  60. double area = 0.5*dblA.sum();
  61. MatrixXd BC;
  62. igl::barycenter(U,F,BC);
  63. RowVector3d centroid(0,0,0);
  64. for(int i = 0;i<BC.rows();i++)
  65. {
  66. centroid += 0.5*dblA(i)/area*BC.row(i);
  67. }
  68. U.rowwise() -= centroid;
  69. // Normalize to unit surface area (important for numerics)
  70. U.array() /= sqrt(area);
  71. break;
  72. }
  73. default:
  74. return false;
  75. }
  76. // Send new positions, update normals, recenter
  77. viewer.data.set_vertices(U);
  78. viewer.data.compute_normals();
  79. viewer.core.align_camera_center(U,F);
  80. return true;
  81. };
  82. // Use original normals as pseudo-colors
  83. MatrixXd N;
  84. igl::per_vertex_normals(V,F,N);
  85. MatrixXd C = N.rowwise().normalized().array()*0.5+0.5;
  86. // Initialize smoothing with base mesh
  87. U = V;
  88. viewer.data.set_mesh(U, F);
  89. viewer.data.set_colors(C);
  90. viewer.callback_key_down = key_down;
  91. cout<<"Press [space] to smooth."<<endl;;
  92. cout<<"Press [r] to reset."<<endl;;
  93. return viewer.launch();
  94. }