main.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <igl/directed_edge_orientations.h>
  2. #include <igl/directed_edge_parents.h>
  3. #include <igl/forward_kinematics.h>
  4. #include <igl/PI.h>
  5. #include <igl/lbs_matrix.h>
  6. #include <igl/deform_skeleton.h>
  7. #include <igl/dqs.h>
  8. #include <igl/readDMAT.h>
  9. #include <igl/readOBJ.h>
  10. #include <igl/readTGF.h>
  11. #include <igl/viewer/Viewer.h>
  12. #include <Eigen/Geometry>
  13. #include <Eigen/StdVector>
  14. #include <vector>
  15. #include <algorithm>
  16. #include <iostream>
  17. #include "tutorial_shared_path.h"
  18. typedef
  19. std::vector<Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> >
  20. RotationList;
  21. const Eigen::RowVector3d sea_green(70./255.,252./255.,167./255.);
  22. Eigen::MatrixXd V,W,C,U,M;
  23. Eigen::MatrixXi F,BE;
  24. Eigen::VectorXi P;
  25. std::vector<RotationList > poses;
  26. double anim_t = 0.0;
  27. double anim_t_dir = 0.015;
  28. bool use_dqs = false;
  29. bool recompute = true;
  30. bool pre_draw(igl::viewer::Viewer & viewer)
  31. {
  32. using namespace Eigen;
  33. using namespace std;
  34. if(recompute)
  35. {
  36. // Find pose interval
  37. const int begin = (int)floor(anim_t)%poses.size();
  38. const int end = (int)(floor(anim_t)+1)%poses.size();
  39. const double t = anim_t - floor(anim_t);
  40. // Interpolate pose and identity
  41. RotationList anim_pose(poses[begin].size());
  42. for(int e = 0;e<poses[begin].size();e++)
  43. {
  44. anim_pose[e] = poses[begin][e].slerp(t,poses[end][e]);
  45. }
  46. // Propogate relative rotations via FK to retrieve absolute transformations
  47. RotationList vQ;
  48. vector<Vector3d> vT;
  49. igl::forward_kinematics(C,BE,P,anim_pose,vQ,vT);
  50. const int dim = C.cols();
  51. MatrixXd T(BE.rows()*(dim+1),dim);
  52. for(int e = 0;e<BE.rows();e++)
  53. {
  54. Affine3d a = Affine3d::Identity();
  55. a.translate(vT[e]);
  56. a.rotate(vQ[e]);
  57. T.block(e*(dim+1),0,dim+1,dim) =
  58. a.matrix().transpose().block(0,0,dim+1,dim);
  59. }
  60. // Compute deformation via LBS as matrix multiplication
  61. if(use_dqs)
  62. {
  63. igl::dqs(V,W,vQ,vT,U);
  64. }else
  65. {
  66. U = M*T;
  67. }
  68. // Also deform skeleton edges
  69. MatrixXd CT;
  70. MatrixXi BET;
  71. igl::deform_skeleton(C,BE,T,CT,BET);
  72. viewer.data.set_vertices(U);
  73. viewer.data.set_edges(CT,BET,sea_green);
  74. viewer.data.compute_normals();
  75. if(viewer.core.is_animating)
  76. {
  77. anim_t += anim_t_dir;
  78. }
  79. else
  80. {
  81. recompute=false;
  82. }
  83. }
  84. return false;
  85. }
  86. bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
  87. {
  88. recompute = true;
  89. switch(key)
  90. {
  91. case 'D':
  92. case 'd':
  93. use_dqs = !use_dqs;
  94. return true;
  95. case ' ':
  96. viewer.core.is_animating = !viewer.core.is_animating;
  97. return true;
  98. }
  99. return false;
  100. }
  101. int main(int argc, char *argv[])
  102. {
  103. using namespace Eigen;
  104. using namespace std;
  105. igl::readOBJ(TUTORIAL_SHARED_PATH "/arm.obj",V,F);
  106. U=V;
  107. igl::readTGF(TUTORIAL_SHARED_PATH "/arm.tgf",C,BE);
  108. // retrieve parents for forward kinematics
  109. igl::directed_edge_parents(BE,P);
  110. RotationList rest_pose;
  111. igl::directed_edge_orientations(C,BE,rest_pose);
  112. poses.resize(4,RotationList(4,Quaterniond::Identity()));
  113. // poses[1] // twist
  114. const Quaterniond twist(AngleAxisd(igl::PI,Vector3d(1,0,0)));
  115. poses[1][2] = rest_pose[2]*twist*rest_pose[2].conjugate();
  116. const Quaterniond bend(AngleAxisd(-igl::PI*0.7,Vector3d(0,0,1)));
  117. poses[3][2] = rest_pose[2]*bend*rest_pose[2].conjugate();
  118. igl::readDMAT(TUTORIAL_SHARED_PATH "/arm-weights.dmat",W);
  119. igl::lbs_matrix(V,W,M);
  120. // Plot the mesh with pseudocolors
  121. igl::viewer::Viewer viewer;
  122. viewer.data.set_mesh(U, F);
  123. viewer.data.set_edges(C,BE,sea_green);
  124. viewer.core.show_lines = false;
  125. viewer.core.show_overlay_depth = false;
  126. viewer.core.line_width = 1;
  127. viewer.core.trackball_angle.normalize();
  128. viewer.callback_pre_draw = &pre_draw;
  129. viewer.callback_key_down = &key_down;
  130. viewer.core.is_animating = false;
  131. viewer.core.camera_zoom = 2.5;
  132. viewer.core.animation_max_fps = 30.;
  133. cout<<"Press [d] to toggle between LBS and DQS"<<endl<<
  134. "Press [space] to toggle animation"<<endl;
  135. viewer.launch();
  136. }