1212#include  " momentum/character/blend_shape.h" 
1313#include  " momentum/character/blend_shape_skinning.h" 
1414#include  " momentum/character/linear_skinning.h" 
15+ #include  " momentum/character/mesh_state.h" 
1516#include  " momentum/character/skeleton_state.h" 
1617#include  " momentum/character/skin_weights.h" 
1718#include  " momentum/common/checks.h" 
@@ -33,9 +34,6 @@ SkinnedLocatorTriangleErrorFunctionT<T>::SkinnedLocatorTriangleErrorFunctionT(
3334  MT_THROW_IF (
3435      type != VertexConstraintType::Position && type != VertexConstraintType::Plane,
3536      " SkinnedLocatorTriangleErrorFunction only supports Position and Plane constraint types" 
36- 
37-   this ->neutralMesh_  = std::make_unique<MeshT<T>>(character_in.mesh ->template  cast <T>());
38-   this ->restMesh_  = std::make_unique<MeshT<T>>(character_in.mesh ->template  cast <T>());
3937}
4038
4139template  <typename  T>
@@ -160,63 +158,60 @@ std::array<Eigen::Matrix3<T>, 3> compute_d_targetPos_d_vertexPos(
160158template  <typename  T>
161159double  SkinnedLocatorTriangleErrorFunctionT<T>::getError(
162160    const  ModelParametersT<T>& modelParameters,
163-     const  SkeletonStateT<T>& /* state*/ 
164-     const  MeshStateT<T>& /*   meshState  */ 
161+     const  SkeletonStateT<T>& /*   state  */ 
162+     const  MeshStateT<T>& meshState) {
165163  MT_PROFILE_FUNCTION ();
166164
167-   updateMeshes (modelParameters );
165+   MT_CHECK_NOTNULL (meshState. restMesh_ );
168166
169-   //  loop over all constraints and calculate the error
170167  double  error = 0.0 ;
171168
172169  if  (constraintType_ == VertexConstraintType::Position) {
173-     for  (size_t  i = 0 ; i < constraints_.size (); ++i) {
174-       const  SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
175- 
170+     for  (const  auto & constr : constraints_) {
176171      //  Get the skinned locator position
177172      const  Eigen::Vector3<T> locatorRestPos =
178173          getLocatorRestPosition (modelParameters, constr.locatorIndex );
179174
180175      //  Get the target position on the triangle
181-       const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
176+       const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
182177
183178      //  Calculate position error
184179      const  Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
185180      error += constr.weight  * diff.squaredNorm ();
186181    }
187-   } else  if  (constraintType_ == VertexConstraintType::Plane) {
188-     for  (size_t  i = 0 ; i < constraints_.size (); ++i) {
189-       const  SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
190- 
182+   } else  {
183+     MT_CHECK (constraintType_ == VertexConstraintType::Plane);
184+     for  (const  auto & constr : constraints_) {
191185      //  Get the skinned locator position
192186      const  Eigen::Vector3<T> locatorRestPos =
193187          getLocatorRestPosition (modelParameters, constr.locatorIndex );
194188
195189      //  Get the target position and normal
196-       const  Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this ->restMesh_ , constr);
190+       const  Eigen::Vector3<T> targetNormal =
191+           computeTargetTriangleNormal (*meshState.restMesh_ , constr);
197192      const  Eigen::Vector3<T> tgtPoint =
198-           computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth  * targetNormal;
193+           computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth  * targetNormal;
199194      //  Calculate plane error (projection onto normal)
200195      const  T dist = targetNormal.dot (locatorRestPos - tgtPoint);
201196      error += constr.weight  * dist * dist;
202197    }
203198  }
204199
205-   //  return error
206200  return  error * this ->weight_ ;
207201}
208202
209203template  <typename  T>
210204double  SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
211205    const  ModelParametersT<T>& modelParameters,
206+     const  MeshStateT<T>& meshState,
212207    const  SkinnedLocatorTriangleConstraintT<T>& constr,
213208    Eigen::Ref<Eigen::VectorX<T>> gradient) const  {
214209  //  Get the skinned locator position
215210  const  Eigen::Vector3<T> locatorRestPos =
216211      getLocatorRestPosition (modelParameters, constr.locatorIndex );
217212
218213  //  Get the target position on the triangle
219-   const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
214+   const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
220215
221216  //  Calculate position error
222217  const  Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -226,7 +221,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
226221
227222  //  Get the derivative of the target position with respect to the triangle vertices
228223  const  auto  d_targetPos_d_tgtTriVertexPos =
229-       compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
224+       compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
230225
231226  //  Apply gradient for locator parameter if it exists
232227  int  paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -270,16 +265,17 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
270265template  <typename  T>
271266double  SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
272267    const  ModelParametersT<T>& modelParameters,
268+     const  MeshStateT<T>& meshState,
273269    const  SkinnedLocatorTriangleConstraintT<T>& constr,
274270    Eigen::Ref<Eigen::VectorX<T>> gradient) const  {
275271  //  Get the skinned locator position
276272  const  Eigen::Vector3<T> locatorRestPos =
277273      getLocatorRestPosition (modelParameters, constr.locatorIndex );
278274
279275  //  Get the target position and normal
280-   const  Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this -> restMesh_ , constr);
276+   const  Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*meshState. restMesh_ , constr);
281277  const  Eigen::Vector3<T> tgtPoint =
282-       computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth  * targetNormal;
278+       computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth  * targetNormal;
283279
284280  //  Calculate plane error (projection onto normal)
285281  const  Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -288,9 +284,9 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
288284
289285  //  Get the derivative of the target position with respect to the triangle vertices
290286  const  auto  d_targetPos_d_tgtTriVertexPos =
291-       compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
287+       compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
292288  const  auto  d_targetNormal_d_tgtTriVertexPos =
293-       compute_d_targetNormal_d_vertexPos (constr, *this -> restMesh_ );
289+       compute_d_targetNormal_d_vertexPos (constr, *meshState. restMesh_ );
294290
295291  //  Apply gradient for locator parameter if it exists
296292  int  paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -334,6 +330,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
334330template  <typename  T>
335331double  SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
336332    const  ModelParametersT<T>& modelParameters,
333+     const  MeshStateT<T>& meshState,
337334    const  SkinnedLocatorTriangleConstraintT<T>& constr,
338335    Ref<Eigen::MatrixX<T>> jac,
339336    Ref<Eigen::VectorX<T>> res) const  {
@@ -342,7 +339,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
342339      getLocatorRestPosition (modelParameters, constr.locatorIndex );
343340
344341  //  Get the target position on the triangle
345-   const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
342+   const  Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
346343
347344  //  Calculate position error
348345  const  Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -353,7 +350,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
353350
354351  //  Get the derivative of the target position with respect to the triangle vertices
355352  const  auto  d_targetPos_d_tgtTriVertexPos =
356-       compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
353+       compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
357354
358355  //  Apply Jacobian for locator parameter if it exists
359356  int  paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -395,6 +392,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
395392template  <typename  T>
396393double  SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
397394    const  ModelParametersT<T>& modelParameters,
395+     const  MeshStateT<T>& meshState,
398396    const  SkinnedLocatorTriangleConstraintT<T>& constr,
399397    Ref<Eigen::MatrixX<T>> jac,
400398    T& res) const  {
@@ -403,23 +401,22 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
403401      getLocatorRestPosition (modelParameters, constr.locatorIndex );
404402
405403  //  Get the target position and normal
406-   const  Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this -> restMesh_ , constr);
404+   const  Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*meshState. restMesh_ , constr);
407405  const  Eigen::Vector3<T> tgtPoint =
408-       computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth  * targetNormal;
406+       computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth  * targetNormal;
409407
410408  //  Calculate plane error (projection onto normal)
411409  const  Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
412410  const  T dist = targetNormal.dot (diff);
413411
414-   //  Set residual
415412  const  T wgt = std::sqrt (constr.weight  * this ->weight_ );
416413  res = wgt * dist;
417414
418415  //  Get the derivative of the target position with respect to the triangle vertices
419416  const  auto  d_targetPos_d_tgtTriVertexPos =
420-       compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
417+       compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
421418  const  auto  d_targetNormal_d_tgtTriVertexPos =
422-       compute_d_targetNormal_d_vertexPos (constr, *this -> restMesh_ );
419+       compute_d_targetNormal_d_vertexPos (constr, *meshState. restMesh_ );
423420
424421  //  Apply Jacobian for locator parameter if it exists
425422  int  paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -462,58 +459,68 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
462459template  <typename  T>
463460double  SkinnedLocatorTriangleErrorFunctionT<T>::getGradient(
464461    const  ModelParametersT<T>& modelParameters,
465-     const  SkeletonStateT<T>& /* state*/ 
466-     const  MeshStateT<T>& /*   meshState  */ 
462+     const  SkeletonStateT<T>& /*   state  */ 
463+     const  MeshStateT<T>& meshState,
467464    Eigen::Ref<Eigen::VectorX<T>> gradient) {
468-   updateMeshes (modelParameters );
465+   MT_CHECK_NOTNULL (meshState. restMesh_ );
469466
470-   double  error = 0.0  ;
467+   double  error = 0 ;
471468
472-   for  (const  auto & constraint : constraints_) {
473-     if  (constraintType_ == VertexConstraintType::Position) {
474-       error += calculatePositionGradient (modelParameters, constraint, gradient);
475-     } else  if  (constraintType_ == VertexConstraintType::Plane) {
476-       error += calculatePlaneGradient (modelParameters, constraint, gradient);
469+   if  (constraintType_ == VertexConstraintType::Position) {
470+     for  (size_t  iCons = 0 ; iCons < constraints_.size (); ++iCons) {
471+       error += calculatePositionGradient (modelParameters, meshState, constraints_[iCons], gradient);
472+     }
473+   } else  {
474+     MT_CHECK (constraintType_ == VertexConstraintType::Plane);
475+     for  (size_t  iCons = 0 ; iCons < constraints_.size (); ++iCons) {
476+       error += calculatePlaneGradient (modelParameters, meshState, constraints_[iCons], gradient);
477477    }
478478  }
479479
480-   return  error *  this ->weight_ ;
480+   return  this ->weight_  * error ;
481481}
482482
483483template  <typename  T>
484484double  SkinnedLocatorTriangleErrorFunctionT<T>::getJacobian(
485485    const  ModelParametersT<T>& modelParameters,
486-     const  SkeletonStateT<T>& /* state*/ 
487-     const  MeshStateT<T>& /*   meshState  */ 
486+     const  SkeletonStateT<T>& /*   state  */ 
487+     const  MeshStateT<T>& meshState,
488488    Eigen::Ref<Eigen::MatrixX<T>> jacobian,
489489    Eigen::Ref<Eigen::VectorX<T>> residual,
490490    int & usedRows) {
491491  MT_CHECK (
492492      jacobian.cols () == static_cast <Eigen::Index>(this ->parameterTransform_ .transform .cols ()));
493+   MT_CHECK (jacobian.rows () >= (Eigen::Index)(1  * constraints_.size ()));
494+   MT_CHECK (residual.rows () >= (Eigen::Index)(1  * constraints_.size ()));
493495
494-   updateMeshes (modelParameters);
496+   MT_CHECK (
497+       meshState.restMesh_ , " MeshState must have rest mesh for SkinnedLocatorTriangleErrorFunction" 
495498
496-   double  error = 0.0 ;
497-   usedRows = 0 ;
499+   double  error = 0 ;
498500
499-   for  ( size_t  iCons =  0 ; iCons < constraints_. size (); ++iCons ) {
500-     if  (constraintType_ == VertexConstraintType::Position ) {
501+   if  (constraintType_ == VertexConstraintType::Position ) {
502+     for  ( size_t  i =  0 ; i < constraints_. size (); ++i ) {
501503      error += calculatePositionJacobian (
502504          modelParameters,
503-           constraints_[iCons],
504-           jacobian.block (usedRows, 0 , 3 , modelParameters.size ()),
505-           residual.middleRows (usedRows, 3 ));
506-       usedRows += 3 ;
507-     } else  if  (constraintType_ == VertexConstraintType::Plane) {
508-       T res;
505+           meshState,
506+           constraints_[i],
507+           jacobian.block (3  * i, 0 , 3 , modelParameters.size ()),
508+           residual.middleRows (3  * i, 3 ));
509+     }
510+     usedRows = 3  * constraints_.size ();
511+   } else  {
512+     MT_CHECK (constraintType_ == VertexConstraintType::Plane);
513+     for  (size_t  i = 0 ; i < constraints_.size (); ++i) {
514+       T residualValue;
509515      error += calculatePlaneJacobian (
510516          modelParameters,
511-           constraints_[iCons] ,
512-           jacobian. block (usedRows,  0 ,  1 , modelParameters. size ()) ,
513-           res); 
514-       residual[usedRows] = res ;
515-       usedRows +=  1 ;
517+           meshState ,
518+           constraints_[i] ,
519+           jacobian. block (i,  0 ,  1 , modelParameters. size ()), 
520+           residualValue) ;
521+       residual (i) = residualValue ;
516522    }
523+     usedRows = constraints_.size ();
517524  }
518525
519526  return  error;
@@ -529,42 +536,8 @@ size_t SkinnedLocatorTriangleErrorFunctionT<T>::getJacobianSize() const {
529536  return  0 ;
530537}
531538
532- template  <typename  T>
533- void  SkinnedLocatorTriangleErrorFunctionT<T>::updateMeshes(
534-     const  ModelParametersT<T>& modelParameters) {
535-   MT_PROFILE_FUNCTION ();
536- 
537-   bool  doUpdateNormals = false ;
538-   if  (this ->character_ .blendShape ) {
539-     const  BlendWeightsT<T> blendWeights =
540-         extractBlendWeights (this ->parameterTransform_ , modelParameters);
541-     this ->character_ .blendShape ->computeShape (blendWeights, this ->restMesh_ ->vertices );
542-     doUpdateNormals = true ;
543-   }
544-   if  (this ->character_ .faceExpressionBlendShape ) {
545-     if  (!this ->character_ .blendShape ) {
546-       //  Set restMesh back to neutral, removing potential previous expressions.
547-       //  Note that if the character comes with (shape) blendShape, the previous if block already
548-       //  takes care of this step.
549-       Eigen::Map<Eigen::VectorX<T>> outputVec (
550-           &this ->restMesh_ ->vertices [0 ][0 ], this ->restMesh_ ->vertices .size () * 3 );
551-       const  Eigen::Map<Eigen::VectorX<T>> baseVec (
552-           &this ->neutralMesh_ ->vertices [0 ][0 ], this ->neutralMesh_ ->vertices .size () * 3 );
553-       outputVec = baseVec.template  cast <T>();
554-     }
555-     const  BlendWeightsT<T> faceExpressionBlendWeights =
556-         extractFaceExpressionBlendWeights (this ->parameterTransform_ , modelParameters);
557-     this ->character_ .faceExpressionBlendShape ->applyDeltas (
558-         faceExpressionBlendWeights, this ->restMesh_ ->vertices );
559-     doUpdateNormals = true ;
560-   }
561-   if  (doUpdateNormals) {
562-     this ->restMesh_ ->updateNormals ();
563-   }
564- }
539+ } //  namespace momentum
565540
566541//  Explicit template instantiations
567- template  class  SkinnedLocatorTriangleErrorFunctionT <float >;
568- template  class  SkinnedLocatorTriangleErrorFunctionT <double >;
569- 
570- } //  namespace momentum
542+ template  class  momentum ::SkinnedLocatorTriangleErrorFunctionT<float >;
543+ template  class  momentum ::SkinnedLocatorTriangleErrorFunctionT<double >;
0 commit comments