arap_dof.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #ifndef IGL_ARAP_ENERGY_TYPE_DOF_H
  9. #define IGL_ARAP_ENERGY_TYPE_DOF_H
  10. #include "igl_inline.h"
  11. #include <Eigen/Dense>
  12. #include <Eigen/Sparse>
  13. #include "ARAPEnergyType.h"
  14. #include <vector>
  15. /// @file arap_dof.h
  16. /// @brief "Fast Automatic Skinning Transformations" [Jacobson et al.\ 2012]
  17. ///
  18. /// Arap DOF precomputation consists of two parts the computation. The first is
  19. /// that which depends solely on the mesh (V,F), the linear blend skinning
  20. /// weights (M) and the groups G. Then there's the part that depends on the
  21. /// previous precomputation and the list of free and fixed vertices.
  22. ///
  23. ///
  24. /// #### Caller example:
  25. ///
  26. /// Once:
  27. /// arap_dof_precomputation(...)
  28. ///
  29. /// Each frame:
  30. /// while(not satisfied)
  31. /// arap_dof_update(...)
  32. /// end
  33. /// The code and variables differ from the description in Section 3 of "Fast
  34. /// Automatic Skinning Transformations" by [Jacobson et al. 2012]
  35. ///
  36. /// Here is a useful conversion table:
  37. ///
  38. /// [article] [code]
  39. /// S = \tilde{K} T S = CSM * Lsep
  40. /// S --> R S --> R --shuffled--> Rxyz
  41. /// Gamma_solve RT = Pi_1 \tilde{K} RT L_part1xyz = CSolveBlock1 * Rxyz
  42. /// Pi_1 \tilde{K} CSolveBlock1
  43. /// Peq = [T_full; P_pos]
  44. /// T_full B_eq_fix <--- L0
  45. /// P_pos B_eq
  46. /// Pi_2 * P_eq = Lpart2and3 = Lpart2 + Lpart3
  47. /// Pi_2_left T_full + Lpart3 = M_fullsolve(right) * B_eq_fix
  48. /// Pi_2_right P_pos Lpart2 = M_fullsolve(left) * B_eq
  49. /// T = [Pi_1 Pi_2] [\tilde{K}TRT P_eq] L = Lpart1 + Lpart2and3
  50. ///
  51. namespace igl
  52. {
  53. template <typename LbsMatrixType, typename SSCALAR>
  54. struct ArapDOFData;
  55. /// Precomputes the system to optimize for "Fast Automatic Skinning
  56. /// Transformations" [Jacobson et al.\ 2012] skinning degrees of freedom
  57. /// optimization using as-rigid-as-possible energy. This consists of building
  58. /// constructor matrices (to compute covariance matrices from transformations
  59. /// and to build the poisson solve right hand side from rotation matrix entries)
  60. /// and also prefactoring the poisson system.
  61. ///
  62. /// @param[in] V #V by dim list of vertex positions
  63. /// @param[in] F #F by {3|4} list of face indices
  64. /// @param[in] M #V * dim by #handles * dim * (dim+1) matrix such that
  65. /// new_V(:) = LBS(V,W,A) = reshape(M * A,size(V)), where A is a column
  66. /// vectors formed by the entries in each handle's dim by dim+1
  67. /// transformation matrix. Specifcally, A =
  68. /// reshape(permute(Astack,[3 1 2]),n*dim*(dim+1),1)
  69. /// or A = [Lxx;Lyx;Lxy;Lyy;tx;ty], and likewise for other dim
  70. /// if Astack(:,:,i) is the dim by (dim+1) transformation at handle i
  71. /// handles are ordered according to P then BE (point handles before bone
  72. /// handles)
  73. /// @param[in] G #V list of group indices (1 to k) for each vertex, such that vertex i
  74. /// is assigned to group G(i)
  75. /// @param[out] data structure containing all necessary precomputation for calling
  76. /// arap_dof_update
  77. /// @return true on success, false on error
  78. ///
  79. /// \see lbs_matrix_column
  80. ///
  81. /// \fileinfo
  82. template <typename LbsMatrixType, typename SSCALAR>
  83. IGL_INLINE bool arap_dof_precomputation(
  84. const Eigen::MatrixXd & V,
  85. const Eigen::MatrixXi & F,
  86. const LbsMatrixType & M,
  87. const Eigen::Matrix<int,Eigen::Dynamic,1> & G,
  88. ArapDOFData<LbsMatrixType, SSCALAR> & data);
  89. /// Should always be called after arap_dof_precomputation, but may be called in
  90. /// between successive calls to arap_dof_update, recomputes precomputation
  91. /// given that there are only changes in free and fixed
  92. ///
  93. /// @param[in] fixed_dim list of transformation element indices for fixed (or partailly
  94. /// fixed) handles: not necessarily the complement of 'free'
  95. /// NOTE: the constraints for fixed transformations still need to be
  96. /// present in A_eq
  97. /// @param[in] A_eq dim*#constraint_points by m*dim*(dim+1) matrix of linear equality
  98. /// constraint coefficients. Each row corresponds to a linear constraint,
  99. /// so that A_eq * L = Beq says that the linear transformation entries in
  100. /// the column L should produce the user supplied positional constraints
  101. /// for each handle in Beq. The row A_eq(i*dim+d) corresponds to the
  102. /// constrain on coordinate d of position i
  103. /// @param[out] data structure containing all necessary precomputation for calling
  104. /// arap_dof_update
  105. /// @return true on success, false on error
  106. ///
  107. /// \see lbs_matrix_column
  108. ///
  109. /// \fileinfo
  110. template <typename LbsMatrixType, typename SSCALAR>
  111. IGL_INLINE bool arap_dof_recomputation(
  112. const Eigen::Matrix<int,Eigen::Dynamic,1> & fixed_dim,
  113. const Eigen::SparseMatrix<double> & A_eq,
  114. ArapDOFData<LbsMatrixType, SSCALAR> & data);
  115. /// Optimizes the transformations attached to each weight function based on
  116. /// precomputed system.
  117. ///
  118. /// @param[in] data precomputation data struct output from arap_dof_precomputation
  119. /// @param[in] Beq dim*#constraint_points constraint values.
  120. /// @param[in] L0 #handles * dim * dim+1 list of initial guess transformation entries,
  121. /// also holds fixed transformation entries for fixed handles
  122. /// @param[in] max_iters maximum number of iterations
  123. /// @param[in] tol stopping criteria parameter. If variables (linear transformation
  124. /// matrix entries) change by less than 'tol' the optimization terminates,
  125. /// 0.75 (weak tolerance)
  126. /// 0.0 (extreme tolerance)
  127. /// @param[out] L #handles * dim * dim+1 list of final optimized transformation entries,
  128. /// allowed to be the same as L
  129. ///
  130. /// \fileinfo
  131. template <typename LbsMatrixType, typename SSCALAR>
  132. IGL_INLINE bool arap_dof_update(
  133. const ArapDOFData<LbsMatrixType,SSCALAR> & data,
  134. const Eigen::Matrix<double,Eigen::Dynamic,1> & B_eq,
  135. const Eigen::MatrixXd & L0,
  136. const int max_iters,
  137. const double tol,
  138. Eigen::MatrixXd & L
  139. );
  140. /// Structure that contains fields for all precomputed data or data that needs
  141. /// to be remembered at update
  142. ///
  143. /// \fileinfo
  144. template <typename LbsMatrixType, typename SSCALAR>
  145. struct ArapDOFData
  146. {
  147. /// Matrix with SSCALAR type
  148. typedef Eigen::Matrix<SSCALAR, Eigen::Dynamic, Eigen::Dynamic> MatrixXS;
  149. /// Type of arap energy we're solving
  150. igl::ARAPEnergyType energy;
  151. /// List of indices of fixed transformation entries
  152. Eigen::Matrix<int,Eigen::Dynamic,1> fixed_dim;
  153. /// List of precomputed covariance scatter matrices multiplied by lbs
  154. /// matrices
  155. std::vector<Eigen::MatrixXd> CSM_M;
  156. /// @private
  157. LbsMatrixType M_KG;
  158. /// Number of mesh vertices
  159. int n;
  160. /// Number of weight functions
  161. int m;
  162. /// Number of dimensions
  163. int dim;
  164. /// Effective dimensions
  165. int effective_dim;
  166. /// List of indices into C of positional constraints
  167. Eigen::Matrix<int,Eigen::Dynamic,1> interpolated;
  168. /// Mask of free variables
  169. std::vector<bool> free_mask;
  170. /// Full quadratic coefficients matrix before lagrangian (should be dense)
  171. LbsMatrixType Q;
  172. //// Solve matrix for the global step
  173. //Eigen::MatrixXd M_Solve; // TODO: remove from here
  174. /// Full solve matrix that contains also conversion from rotations to the right hand side,
  175. /// i.e., solves Poisson transformations just from rotations and positional constraints
  176. MatrixXS M_FullSolve;
  177. /// Precomputed condensed matrices (3x3 commutators folded to 1x1):
  178. MatrixXS CSM;
  179. /// @private
  180. MatrixXS CSolveBlock1;
  181. /// Print timings at each update
  182. bool print_timings;
  183. /// dynamics
  184. bool with_dynamics;
  185. // I'm hiding the extra dynamics stuff in this struct, which sort of defeats
  186. // the purpose of this function-based coding style...
  187. /// Time step
  188. double h;
  189. /// #handles * dim * dim+1 list of transformation entries from
  190. /// previous solve
  191. MatrixXS L0;
  192. //// Lm1 #handles * dim * dim+1 list of transformation entries from
  193. //// previous-previous solve
  194. //MatrixXS Lm1;
  195. /// "Velocity"
  196. MatrixXS Lvel0;
  197. /// #V by dim matrix of external forces
  198. MatrixXS fext;
  199. /// Mass_tilde: MT * Mass * M
  200. LbsMatrixType Mass_tilde;
  201. /// Force due to gravity (premultiplier)
  202. Eigen::MatrixXd fgrav;
  203. /// Direction of gravity
  204. Eigen::Vector3d grav_dir;
  205. /// Magnitude of gravity
  206. double grav_mag;
  207. /// Π1 from the paper
  208. MatrixXS Pi_1;
  209. // @private Default values
  210. ArapDOFData():
  211. energy(igl::ARAP_ENERGY_TYPE_SPOKES),
  212. with_dynamics(false),
  213. h(1),
  214. grav_dir(0,-1,0),
  215. grav_mag(0)
  216. {
  217. }
  218. };
  219. }
  220. #ifndef IGL_STATIC_LIBRARY
  221. # include "arap_dof.cpp"
  222. #endif
  223. #endif