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>
@@ -161,63 +159,60 @@ std::array<Eigen::Matrix3<T>, 3> compute_d_targetPos_d_vertexPos(
161159template <typename T>
162160double SkinnedLocatorTriangleErrorFunctionT<T>::getError(
163161 const ModelParametersT<T>& modelParameters,
164- const SkeletonStateT<T>& /* state*/ ,
165- const MeshStateT<T>& /* meshState */ ) {
162+ const SkeletonStateT<T>& /* state */ ,
163+ const MeshStateT<T>& meshState) {
166164 MT_PROFILE_FUNCTION ();
167165
168- updateMeshes (modelParameters );
166+ MT_CHECK_NOTNULL (meshState. restMesh_ );
169167
170- // loop over all constraints and calculate the error
171168 double error = 0.0 ;
172169
173170 if (constraintType_ == VertexConstraintType::Position) {
174- for (size_t i = 0 ; i < constraints_.size (); ++i) {
175- const SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
176-
171+ for (const auto & constr : constraints_) {
177172 // Get the skinned locator position
178173 const Eigen::Vector3<T> locatorRestPos =
179174 getLocatorRestPosition (modelParameters, constr.locatorIndex );
180175
181176 // Get the target position on the triangle
182- const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
177+ const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
183178
184179 // Calculate position error
185180 const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
186181 error += constr.weight * diff.squaredNorm ();
187182 }
188- } else if (constraintType_ == VertexConstraintType::Plane) {
189- for (size_t i = 0 ; i < constraints_.size (); ++i) {
190- const SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
191-
183+ } else {
184+ MT_CHECK (constraintType_ == VertexConstraintType::Plane);
185+ for (const auto & constr : constraints_) {
192186 // Get the skinned locator position
193187 const Eigen::Vector3<T> locatorRestPos =
194188 getLocatorRestPosition (modelParameters, constr.locatorIndex );
195189
196190 // Get the target position and normal
197- const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this ->restMesh_ , constr);
191+ const Eigen::Vector3<T> targetNormal =
192+ computeTargetTriangleNormal (*meshState.restMesh_ , constr);
198193 const Eigen::Vector3<T> tgtPoint =
199- computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth * targetNormal;
194+ computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth * targetNormal;
200195 // Calculate plane error (projection onto normal)
201196 const T dist = targetNormal.dot (locatorRestPos - tgtPoint);
202197 error += constr.weight * dist * dist;
203198 }
204199 }
205200
206- // return error
207201 return error * this ->weight_ ;
208202}
209203
210204template <typename T>
211205double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
212206 const ModelParametersT<T>& modelParameters,
207+ const MeshStateT<T>& meshState,
213208 const SkinnedLocatorTriangleConstraintT<T>& constr,
214209 Eigen::Ref<Eigen::VectorX<T>> gradient) const {
215210 // Get the skinned locator position
216211 const Eigen::Vector3<T> locatorRestPos =
217212 getLocatorRestPosition (modelParameters, constr.locatorIndex );
218213
219214 // Get the target position on the triangle
220- const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
215+ const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
221216
222217 // Calculate position error
223218 const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -227,7 +222,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
227222
228223 // Get the derivative of the target position with respect to the triangle vertices
229224 const auto d_targetPos_d_tgtTriVertexPos =
230- compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
225+ compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
231226
232227 // Apply gradient for locator parameter if it exists
233228 int paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -271,16 +266,17 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
271266template <typename T>
272267double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
273268 const ModelParametersT<T>& modelParameters,
269+ const MeshStateT<T>& meshState,
274270 const SkinnedLocatorTriangleConstraintT<T>& constr,
275271 Eigen::Ref<Eigen::VectorX<T>> gradient) const {
276272 // Get the skinned locator position
277273 const Eigen::Vector3<T> locatorRestPos =
278274 getLocatorRestPosition (modelParameters, constr.locatorIndex );
279275
280276 // Get the target position and normal
281- const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this -> restMesh_ , constr);
277+ const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*meshState. restMesh_ , constr);
282278 const Eigen::Vector3<T> tgtPoint =
283- computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth * targetNormal;
279+ computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth * targetNormal;
284280
285281 // Calculate plane error (projection onto normal)
286282 const Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -289,9 +285,9 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
289285
290286 // Get the derivative of the target position with respect to the triangle vertices
291287 const auto d_targetPos_d_tgtTriVertexPos =
292- compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
288+ compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
293289 const auto d_targetNormal_d_tgtTriVertexPos =
294- compute_d_targetNormal_d_vertexPos (constr, *this -> restMesh_ );
290+ compute_d_targetNormal_d_vertexPos (constr, *meshState. restMesh_ );
295291
296292 // Apply gradient for locator parameter if it exists
297293 int paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -335,6 +331,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
335331template <typename T>
336332double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
337333 const ModelParametersT<T>& modelParameters,
334+ const MeshStateT<T>& meshState,
338335 const SkinnedLocatorTriangleConstraintT<T>& constr,
339336 Ref<Eigen::MatrixX<T>> jac,
340337 Ref<Eigen::VectorX<T>> res) const {
@@ -343,7 +340,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
343340 getLocatorRestPosition (modelParameters, constr.locatorIndex );
344341
345342 // Get the target position on the triangle
346- const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*this -> restMesh_ , constr);
343+ const Eigen::Vector3<T> tgtPoint = computeTargetPosition (*meshState. restMesh_ , constr);
347344
348345 // Calculate position error
349346 const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -354,7 +351,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
354351
355352 // Get the derivative of the target position with respect to the triangle vertices
356353 const auto d_targetPos_d_tgtTriVertexPos =
357- compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
354+ compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
358355
359356 // Apply Jacobian for locator parameter if it exists
360357 int paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -396,6 +393,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
396393template <typename T>
397394double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
398395 const ModelParametersT<T>& modelParameters,
396+ const MeshStateT<T>& meshState,
399397 const SkinnedLocatorTriangleConstraintT<T>& constr,
400398 Ref<Eigen::MatrixX<T>> jac,
401399 T& res) const {
@@ -404,23 +402,22 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
404402 getLocatorRestPosition (modelParameters, constr.locatorIndex );
405403
406404 // Get the target position and normal
407- const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*this -> restMesh_ , constr);
405+ const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal (*meshState. restMesh_ , constr);
408406 const Eigen::Vector3<T> tgtPoint =
409- computeTargetBaryPosition (*this -> restMesh_ , constr) + constr.depth * targetNormal;
407+ computeTargetBaryPosition (*meshState. restMesh_ , constr) + constr.depth * targetNormal;
410408
411409 // Calculate plane error (projection onto normal)
412410 const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
413411 const T dist = targetNormal.dot (diff);
414412
415- // Set residual
416413 const T wgt = std::sqrt (constr.weight * this ->weight_ );
417414 res = wgt * dist;
418415
419416 // Get the derivative of the target position with respect to the triangle vertices
420417 const auto d_targetPos_d_tgtTriVertexPos =
421- compute_d_targetPos_d_vertexPos (constr, *this -> restMesh_ );
418+ compute_d_targetPos_d_vertexPos (constr, *meshState. restMesh_ );
422419 const auto d_targetNormal_d_tgtTriVertexPos =
423- compute_d_targetNormal_d_vertexPos (constr, *this -> restMesh_ );
420+ compute_d_targetNormal_d_vertexPos (constr, *meshState. restMesh_ );
424421
425422 // Apply Jacobian for locator parameter if it exists
426423 int paramIndex = getSkinnedLocatorParameterIndex (constr.locatorIndex );
@@ -463,58 +460,68 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
463460template <typename T>
464461double SkinnedLocatorTriangleErrorFunctionT<T>::getGradient(
465462 const ModelParametersT<T>& modelParameters,
466- const SkeletonStateT<T>& /* state*/ ,
467- const MeshStateT<T>& /* meshState */ ,
463+ const SkeletonStateT<T>& /* state */ ,
464+ const MeshStateT<T>& meshState,
468465 Eigen::Ref<Eigen::VectorX<T>> gradient) {
469- updateMeshes (modelParameters );
466+ MT_CHECK_NOTNULL (meshState. restMesh_ );
470467
471- double error = 0.0 ;
468+ double error = 0 ;
472469
473- for (const auto & constraint : constraints_) {
474- if (constraintType_ == VertexConstraintType::Position) {
475- error += calculatePositionGradient (modelParameters, constraint, gradient);
476- } else if (constraintType_ == VertexConstraintType::Plane) {
477- error += calculatePlaneGradient (modelParameters, constraint, gradient);
470+ if (constraintType_ == VertexConstraintType::Position) {
471+ for (size_t iCons = 0 ; iCons < constraints_.size (); ++iCons) {
472+ error += calculatePositionGradient (modelParameters, meshState, constraints_[iCons], gradient);
473+ }
474+ } else {
475+ MT_CHECK (constraintType_ == VertexConstraintType::Plane);
476+ for (size_t iCons = 0 ; iCons < constraints_.size (); ++iCons) {
477+ error += calculatePlaneGradient (modelParameters, meshState, constraints_[iCons], gradient);
478478 }
479479 }
480480
481- return error * this ->weight_ ;
481+ return this ->weight_ * error ;
482482}
483483
484484template <typename T>
485485double SkinnedLocatorTriangleErrorFunctionT<T>::getJacobian(
486486 const ModelParametersT<T>& modelParameters,
487- const SkeletonStateT<T>& /* state*/ ,
488- const MeshStateT<T>& /* meshState */ ,
487+ const SkeletonStateT<T>& /* state */ ,
488+ const MeshStateT<T>& meshState,
489489 Eigen::Ref<Eigen::MatrixX<T>> jacobian,
490490 Eigen::Ref<Eigen::VectorX<T>> residual,
491491 int & usedRows) {
492492 MT_CHECK (
493493 jacobian.cols () == static_cast <Eigen::Index>(this ->parameterTransform_ .transform .cols ()));
494+ MT_CHECK (jacobian.rows () >= (Eigen::Index)(1 * constraints_.size ()));
495+ MT_CHECK (residual.rows () >= (Eigen::Index)(1 * constraints_.size ()));
494496
495- updateMeshes (modelParameters);
497+ MT_CHECK (
498+ meshState.restMesh_ , " MeshState must have rest mesh for SkinnedLocatorTriangleErrorFunction" );
496499
497- double error = 0.0 ;
498- usedRows = 0 ;
500+ double error = 0 ;
499501
500- for ( size_t iCons = 0 ; iCons < constraints_. size (); ++iCons ) {
501- if (constraintType_ == VertexConstraintType::Position ) {
502+ if (constraintType_ == VertexConstraintType::Position ) {
503+ for ( size_t i = 0 ; i < constraints_. size (); ++i ) {
502504 error += calculatePositionJacobian (
503505 modelParameters,
504- constraints_[iCons],
505- jacobian.block (usedRows, 0 , 3 , modelParameters.size ()),
506- residual.middleRows (usedRows, 3 ));
507- usedRows += 3 ;
508- } else if (constraintType_ == VertexConstraintType::Plane) {
509- T res;
506+ meshState,
507+ constraints_[i],
508+ jacobian.block (3 * i, 0 , 3 , modelParameters.size ()),
509+ residual.middleRows (3 * i, 3 ));
510+ }
511+ usedRows = 3 * constraints_.size ();
512+ } else {
513+ MT_CHECK (constraintType_ == VertexConstraintType::Plane);
514+ for (size_t i = 0 ; i < constraints_.size (); ++i) {
515+ T residualValue;
510516 error += calculatePlaneJacobian (
511517 modelParameters,
512- constraints_[iCons] ,
513- jacobian. block (usedRows, 0 , 1 , modelParameters. size ()) ,
514- res);
515- residual[usedRows] = res ;
516- usedRows += 1 ;
518+ meshState ,
519+ constraints_[i] ,
520+ jacobian. block (i, 0 , 1 , modelParameters. size ()),
521+ residualValue) ;
522+ residual (i) = residualValue ;
517523 }
524+ usedRows = constraints_.size ();
518525 }
519526
520527 return error;
@@ -530,42 +537,8 @@ size_t SkinnedLocatorTriangleErrorFunctionT<T>::getJacobianSize() const {
530537 return 0 ;
531538}
532539
533- template <typename T>
534- void SkinnedLocatorTriangleErrorFunctionT<T>::updateMeshes(
535- const ModelParametersT<T>& modelParameters) {
536- MT_PROFILE_FUNCTION ();
537-
538- bool doUpdateNormals = false ;
539- if (this ->character_ .blendShape ) {
540- const BlendWeightsT<T> blendWeights =
541- extractBlendWeights (this ->parameterTransform_ , modelParameters);
542- this ->character_ .blendShape ->computeShape (blendWeights, this ->restMesh_ ->vertices );
543- doUpdateNormals = true ;
544- }
545- if (this ->character_ .faceExpressionBlendShape ) {
546- if (!this ->character_ .blendShape ) {
547- // Set restMesh back to neutral, removing potential previous expressions.
548- // Note that if the character comes with (shape) blendShape, the previous if block already
549- // takes care of this step.
550- Eigen::Map<Eigen::VectorX<T>> outputVec (
551- &this ->restMesh_ ->vertices [0 ][0 ], this ->restMesh_ ->vertices .size () * 3 );
552- const Eigen::Map<Eigen::VectorX<T>> baseVec (
553- &this ->neutralMesh_ ->vertices [0 ][0 ], this ->neutralMesh_ ->vertices .size () * 3 );
554- outputVec = baseVec.template cast <T>();
555- }
556- const BlendWeightsT<T> faceExpressionBlendWeights =
557- extractFaceExpressionBlendWeights (this ->parameterTransform_ , modelParameters);
558- this ->character_ .faceExpressionBlendShape ->applyDeltas (
559- faceExpressionBlendWeights, this ->restMesh_ ->vertices );
560- doUpdateNormals = true ;
561- }
562- if (doUpdateNormals) {
563- this ->restMesh_ ->updateNormals ();
564- }
565- }
540+ } // namespace momentum
566541
567542// Explicit template instantiations
568- template class SkinnedLocatorTriangleErrorFunctionT <float >;
569- template class SkinnedLocatorTriangleErrorFunctionT <double >;
570-
571- } // namespace momentum
543+ template class momentum ::SkinnedLocatorTriangleErrorFunctionT<float >;
544+ template class momentum ::SkinnedLocatorTriangleErrorFunctionT<double >;
0 commit comments