main.cpp 4.5 KB

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