main.cpp 5.0 KB

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