main.cpp 2.5 KB

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