2
0

main.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include <igl/boundary_conditions.h>
  2. #include <igl/colon.h>
  3. #include <igl/column_to_quats.h>
  4. #include <igl/directed_edge_parents.h>
  5. #include <igl/forward_kinematics.h>
  6. #include <igl/jet.h>
  7. #include <igl/lbs_matrix.h>
  8. #include <igl/deform_skeleton.h>
  9. #include <igl/readDMAT.h>
  10. #include <igl/readMESH.h>
  11. #include <igl/readTGF.h>
  12. #include <igl/opengl/glfw/Viewer.h>
  13. #include <igl/bbw.h>
  14. #include <Eigen/Geometry>
  15. #include <Eigen/StdVector>
  16. #include <vector>
  17. #include <algorithm>
  18. #include <iostream>
  19. typedef
  20. std::vector<Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> >
  21. RotationList;
  22. const Eigen::RowVector3d sea_green(70./255.,252./255.,167./255.);
  23. int selected = 0;
  24. Eigen::MatrixXd V,W,U,C,M;
  25. Eigen::MatrixXi T,F,BE;
  26. Eigen::VectorXi P;
  27. RotationList pose;
  28. double anim_t = 1.0;
  29. double anim_t_dir = -0.03;
  30. bool pre_draw(igl::opengl::glfw::Viewer & viewer)
  31. {
  32. using namespace Eigen;
  33. using namespace std;
  34. if(viewer.core().is_animating)
  35. {
  36. // Interpolate pose and identity
  37. RotationList anim_pose(pose.size());
  38. for(int e = 0;e<pose.size();e++)
  39. {
  40. anim_pose[e] = pose[e].slerp(anim_t,Quaterniond::Identity());
  41. }
  42. // Propagate relative rotations via FK to retrieve absolute transformations
  43. RotationList vQ;
  44. vector<Vector3d> vT;
  45. igl::forward_kinematics(C,BE,P,anim_pose,vQ,vT);
  46. const int dim = C.cols();
  47. MatrixXd T(BE.rows()*(dim+1),dim);
  48. for(int e = 0;e<BE.rows();e++)
  49. {
  50. Affine3d a = Affine3d::Identity();
  51. a.translate(vT[e]);
  52. a.rotate(vQ[e]);
  53. T.block(e*(dim+1),0,dim+1,dim) =
  54. a.matrix().transpose().block(0,0,dim+1,dim);
  55. }
  56. // Compute deformation via LBS as matrix multiplication
  57. U = M*T;
  58. // Also deform skeleton edges
  59. MatrixXd CT;
  60. MatrixXi BET;
  61. igl::deform_skeleton(C,BE,T,CT,BET);
  62. viewer.data().set_vertices(U);
  63. viewer.data().set_edges(CT,BET,sea_green);
  64. viewer.data().compute_normals();
  65. anim_t += anim_t_dir;
  66. anim_t_dir *= (anim_t>=1.0 || anim_t<=0.0?-1.0:1.0);
  67. }
  68. return false;
  69. }
  70. bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
  71. {
  72. switch(key)
  73. {
  74. case ' ':
  75. viewer.core().is_animating = !viewer.core().is_animating;
  76. break;
  77. case '.':
  78. selected++;
  79. selected = std::min(std::max(selected,0),(int)W.cols()-1);
  80. viewer.data().set_data(W.col(selected));
  81. break;
  82. case ',':
  83. selected--;
  84. selected = std::min(std::max(selected,0),(int)W.cols()-1);
  85. viewer.data().set_data(W.col(selected));
  86. break;
  87. }
  88. return true;
  89. }
  90. int main(int argc, char *argv[])
  91. {
  92. using namespace Eigen;
  93. using namespace std;
  94. igl::readMESH(TUTORIAL_SHARED_PATH "/hand.mesh",V,T,F);
  95. U=V;
  96. igl::readTGF(TUTORIAL_SHARED_PATH "/hand.tgf",C,BE);
  97. // retrieve parents for forward kinematics
  98. igl::directed_edge_parents(BE,P);
  99. // Read pose as matrix of quaternions per row
  100. MatrixXd Q;
  101. igl::readDMAT(TUTORIAL_SHARED_PATH "/hand-pose.dmat",Q);
  102. igl::column_to_quats(Q,pose);
  103. assert(pose.size() == BE.rows());
  104. // List of boundary indices (aka fixed value indices into VV)
  105. VectorXi b;
  106. // List of boundary conditions of each weight function
  107. MatrixXd bc;
  108. igl::boundary_conditions(V,T,C,VectorXi(),BE,MatrixXi(),MatrixXi(),b,bc);
  109. // compute BBW weights matrix
  110. igl::BBWData bbw_data;
  111. // only a few iterations for sake of demo
  112. bbw_data.active_set_params.max_iter = 8;
  113. bbw_data.verbosity = 2;
  114. if(!igl::bbw(V,T,b,bc,bbw_data,W))
  115. {
  116. return EXIT_FAILURE;
  117. }
  118. //MatrixXd Vsurf = V.topLeftCorner(F.maxCoeff()+1,V.cols());
  119. //MatrixXd Wsurf;
  120. //if(!igl::bone_heat(Vsurf,F,C,VectorXi(),BE,MatrixXi(),Wsurf))
  121. //{
  122. // return false;
  123. //}
  124. //W.setConstant(V.rows(),Wsurf.cols(),1);
  125. //W.topLeftCorner(Wsurf.rows(),Wsurf.cols()) = Wsurf = Wsurf = Wsurf = Wsurf;
  126. // Normalize weights to sum to one
  127. W = (W.array().colwise() / W.array().rowwise().sum()).eval();
  128. // precompute linear blend skinning matrix
  129. igl::lbs_matrix(V,W,M);
  130. // Plot the mesh with pseudocolors
  131. igl::opengl::glfw::Viewer viewer;
  132. viewer.data().set_mesh(U, F);
  133. viewer.data().set_data(W.col(selected));
  134. viewer.data().set_edges(C,BE,sea_green);
  135. viewer.data().show_lines = false;
  136. viewer.data().show_overlay_depth = false;
  137. viewer.data().line_width = 1;
  138. viewer.callback_pre_draw = &pre_draw;
  139. viewer.callback_key_down = &key_down;
  140. viewer.core().is_animating = false;
  141. viewer.core().animation_max_fps = 30.;
  142. cout<<
  143. "Press '.' to show next weight function."<<endl<<
  144. "Press ',' to show previous weight function."<<endl<<
  145. "Press [space] to toggle animation."<<endl;
  146. viewer.launch();
  147. return EXIT_SUCCESS;
  148. }