main.cpp 2.9 KB

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