arap_dof.h 8.9 KB

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