1212#include " momentum/character/blend_shape_skinning.h"
1313#include " momentum/character/character.h"
1414#include " momentum/character/linear_skinning.h"
15+ #include " momentum/character/mesh_state.h"
1516#include " momentum/character/skeleton.h"
1617#include " momentum/character/skeleton_state.h"
1718#include " momentum/character/skin_weights.h"
@@ -47,9 +48,6 @@ VertexErrorFunctionT<T>::VertexErrorFunctionT(
4748 character_in.faceExpressionBlendShape && (type != VertexConstraintType::Position),
4849 " Constraint type {} not implemented yet for face. Only Position type is supported." ,
4950 toString (type));
50- this ->neutralMesh_ = std::make_unique<MeshT<T>>(character_in.mesh ->template cast <T>());
51- this ->restMesh_ = std::make_unique<MeshT<T>>(character_in.mesh ->template cast <T>());
52- this ->posedMesh_ = std::make_unique<MeshT<T>>(character_in.mesh ->template cast <T>());
5351}
5452
5553template <typename T>
@@ -74,10 +72,10 @@ template <typename T>
7472double VertexErrorFunctionT<T>::getError(
7573 const ModelParametersT<T>& modelParameters,
7674 const SkeletonStateT<T>& state,
77- const MeshStateT<T>& /* meshState */ ) {
75+ const MeshStateT<T>& meshState) {
7876 MT_PROFILE_FUNCTION ();
7977
80- updateMeshes (modelParameters, state );
78+ MT_CHECK_NOTNULL (meshState. posedMesh_ );
8179
8280 // loop over all constraints and calculate the error
8381 double error = 0.0 ;
@@ -87,15 +85,15 @@ double VertexErrorFunctionT<T>::getError(
8785 const VertexConstraintT<T>& constr = constraints_[i];
8886
8987 const Eigen::Vector3<T> diff =
90- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
88+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
9189 error += constr.weight * diff.squaredNorm () * kPositionWeight ;
9290 }
9391 } else {
9492 const auto [sourceNormalWeight, targetNormalWeight] = computeNormalWeights ();
9593 for (size_t i = 0 ; i < constraints_.size (); ++i) {
9694 const VertexConstraintT<T>& constr = constraints_[i];
9795
98- const Eigen::Vector3<T> sourceNormal = this -> posedMesh_ ->normals [constr.vertexIndex ];
96+ const Eigen::Vector3<T> sourceNormal = meshState. posedMesh_ ->normals [constr.vertexIndex ];
9997 Eigen::Vector3<T> targetNormal = constr.targetNormal ;
10098 if (sourceNormal.dot (constr.targetNormal ) < 0 ) {
10199 targetNormal *= -1 ;
@@ -105,7 +103,7 @@ double VertexErrorFunctionT<T>::getError(
105103
106104 // calculate point->plane distance and error
107105 const Eigen::Vector3<T> diff =
108- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
106+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
109107 const T dist = normal.dot (diff);
110108 error += constr.weight * dist * dist * kPlaneWeight ;
111109 }
@@ -138,16 +136,17 @@ template <typename T>
138136double VertexErrorFunctionT<T>::calculatePositionGradient(
139137 const ModelParametersT<T>& /* modelParameters */ ,
140138 const SkeletonStateT<T>& state,
139+ const MeshStateT<T>& meshState,
141140 const VertexConstraintT<T>& constr,
142141 Eigen::Ref<Eigen::VectorX<T>> gradient) const {
143142 const Eigen::Vector3<T> diff =
144- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
143+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
145144
146145 // calculate the difference between target and position and error
147146 const T wgt = constr.weight * 2 .0f * kPositionWeight * this ->weight_ ;
148147
149148 SkinningWeightIteratorT<T> skinningIter (
150- this ->character_ , *this -> restMesh_ , state, constr.vertexIndex );
149+ this ->character_ , *meshState. restMesh_ , state, constr.vertexIndex );
151150
152151 // IN handle derivatives wrt jointParameters
153152 while (!skinningIter.finished ()) {
@@ -243,17 +242,18 @@ template <typename T>
243242double VertexErrorFunctionT<T>::calculatePositionJacobian(
244243 const ModelParametersT<T>& /* modelParameters */ ,
245244 const SkeletonStateT<T>& state,
245+ const MeshStateT<T>& meshState,
246246 const VertexConstraintT<T>& constr,
247247 Ref<Eigen::MatrixX<T>> jac,
248248 Ref<Eigen::VectorX<T>> res) const {
249249 // calculate the difference between target and position and error
250250 const Eigen::Vector3<T> diff =
251- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
251+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
252252
253253 const T wgt = std::sqrt (constr.weight * kPositionWeight * this ->weight_ );
254254
255255 SkinningWeightIteratorT<T> skinningIter (
256- this ->character_ , *this -> restMesh_ , state, constr.vertexIndex );
256+ this ->character_ , *meshState. restMesh_ , state, constr.vertexIndex );
257257
258258 // IN handle derivatives wrt jointParameters
259259 while (!skinningIter.finished ()) {
@@ -349,13 +349,14 @@ template <typename T>
349349double VertexErrorFunctionT<T>::calculateNormalGradient(
350350 const ModelParametersT<T>& /* modelParameters */ ,
351351 const SkeletonStateT<T>& state,
352+ const MeshStateT<T>& meshState,
352353 const VertexConstraintT<T>& constr,
353354 const T sourceNormalWeight,
354355 const T targetNormalWeight,
355356 Eigen::Ref<Eigen::VectorX<T>> gradient) const {
356357 const auto & skinWeights = *character_.skinWeights ;
357358
358- const Eigen::Vector3<T> sourceNormal = posedMesh_->normals [constr.vertexIndex ];
359+ const Eigen::Vector3<T> sourceNormal = meshState. posedMesh_ ->normals [constr.vertexIndex ];
359360 Eigen::Vector3<T> targetNormal = constr.targetNormal ;
360361 if (sourceNormal.dot (constr.targetNormal ) < 0 ) {
361362 targetNormal *= -1 ;
@@ -364,14 +365,14 @@ double VertexErrorFunctionT<T>::calculateNormalGradient(
364365 sourceNormalWeight * sourceNormal + targetNormalWeight * targetNormal;
365366
366367 const Eigen::Vector3<T> diff =
367- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
368+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
368369 const T dist = diff.dot (normal);
369370
370371 // calculate the difference between target and position and error
371372 const T wgt = constr.weight * 2 .0f * kPositionWeight * this ->weight_ ;
372373
373374 SkinningWeightIteratorT<T> skinningIter (
374- this ->character_ , *this -> restMesh_ , state, constr.vertexIndex );
375+ this ->character_ , *meshState. restMesh_ , state, constr.vertexIndex );
375376
376377 // IN handle derivatives wrt jointParameters
377378 while (!skinningIter.finished ()) {
@@ -457,14 +458,15 @@ template <typename T>
457458double VertexErrorFunctionT<T>::calculateNormalJacobian(
458459 const ModelParametersT<T>& /* modelParameters */ ,
459460 const SkeletonStateT<T>& state,
461+ const MeshStateT<T>& meshState,
460462 const VertexConstraintT<T>& constr,
461463 const T sourceNormalWeight,
462464 const T targetNormalWeight,
463465 Ref<Eigen::MatrixX<T>> jac,
464466 T& res) const {
465467 const auto & skinWeights = *character_.skinWeights ;
466468
467- const Eigen::Vector3<T> sourceNormal = posedMesh_->normals [constr.vertexIndex ];
469+ const Eigen::Vector3<T> sourceNormal = meshState. posedMesh_ ->normals [constr.vertexIndex ];
468470 Eigen::Vector3<T> targetNormal = constr.targetNormal ;
469471 if (sourceNormal.dot (constr.targetNormal ) < 0 ) {
470472 targetNormal *= -1 ;
@@ -474,13 +476,13 @@ double VertexErrorFunctionT<T>::calculateNormalJacobian(
474476
475477 // calculate the difference between target and position and error
476478 const Eigen::Vector3<T> diff =
477- this -> posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
479+ meshState. posedMesh_ ->vertices [constr.vertexIndex ] - constr.targetPosition ;
478480 const T dist = diff.dot (normal);
479481
480482 const T wgt = std::sqrt (constr.weight * kPlaneWeight * this ->weight_ );
481483
482484 SkinningWeightIteratorT<T> skinningIter (
483- this ->character_ , *this -> restMesh_ , state, constr.vertexIndex );
485+ this ->character_ , *meshState. restMesh_ , state, constr.vertexIndex );
484486
485487 // IN handle derivatives wrt jointParameters
486488 while (!skinningIter.finished ()) {
@@ -579,9 +581,9 @@ template <typename T>
579581double VertexErrorFunctionT<T>::getGradient(
580582 const ModelParametersT<T>& modelParameters,
581583 const SkeletonStateT<T>& state,
582- const MeshStateT<T>& /* meshState */ ,
584+ const MeshStateT<T>& meshState,
583585 Eigen::Ref<Eigen::VectorX<T>> gradient) {
584- updateMeshes (modelParameters, state );
586+ MT_CHECK_NOTNULL (meshState. posedMesh_ );
585587
586588 double error = 0 ;
587589 std::vector<std::tuple<double , VectorX<T>>> errorGradThread;
@@ -600,8 +602,8 @@ double VertexErrorFunctionT<T>::getGradient(
600602 [&](std::tuple<double , VectorX<T>>& errorGradLocal, const size_t iCons) {
601603 double & errorLocal = std::get<0 >(errorGradLocal);
602604 auto & gradLocal = std::get<1 >(errorGradLocal);
603- errorLocal +=
604- calculatePositionGradient ( modelParameters, state, constraints_[iCons], gradLocal);
605+ errorLocal += calculatePositionGradient (
606+ modelParameters, state, meshState , constraints_[iCons], gradLocal);
605607 },
606608 dispensoOptions);
607609 } else {
@@ -622,6 +624,7 @@ double VertexErrorFunctionT<T>::getGradient(
622624 errorLocal += calculateNormalGradient (
623625 modelParameters,
624626 state,
627+ meshState,
625628 constraints_[iCons],
626629 sourceNormalWeight,
627630 targetNormalWeight,
@@ -651,7 +654,7 @@ template <typename T>
651654double VertexErrorFunctionT<T>::getJacobian(
652655 const ModelParametersT<T>& modelParameters,
653656 const SkeletonStateT<T>& state,
654- const MeshStateT<T>& /* meshState */ ,
657+ const MeshStateT<T>& meshState,
655658 Eigen::Ref<Eigen::MatrixX<T>> jacobian,
656659 Eigen::Ref<Eigen::VectorX<T>> residual,
657660 int & usedRows) {
@@ -660,7 +663,7 @@ double VertexErrorFunctionT<T>::getJacobian(
660663 MT_CHECK (jacobian.rows () >= (Eigen::Index)(1 * constraints_.size ()));
661664 MT_CHECK (residual.rows () >= (Eigen::Index)(1 * constraints_.size ()));
662665
663- updateMeshes (modelParameters, state );
666+ MT_CHECK_NOTNULL (meshState. posedMesh_ );
664667
665668 double error = 0 ;
666669 std::vector<double > errorThread;
@@ -680,6 +683,7 @@ double VertexErrorFunctionT<T>::getJacobian(
680683 errorLocal += calculatePositionJacobian (
681684 modelParameters,
682685 state,
686+ meshState,
683687 constraints_[iCons],
684688 jacobian.block (3 * iCons, 0 , 3 , modelParameters.size ()),
685689 residual.middleRows (3 * iCons, 3 ));
@@ -701,6 +705,7 @@ double VertexErrorFunctionT<T>::getJacobian(
701705 errorLocal += calculateNormalJacobian (
702706 modelParameters,
703707 state,
708+ meshState,
704709 constraints_[iCons],
705710 sourceNormalWeight,
706711 targetNormalWeight,
@@ -732,49 +737,6 @@ size_t VertexErrorFunctionT<T>::getJacobianSize() const {
732737 }
733738}
734739
735- template <typename T>
736- void VertexErrorFunctionT<T>::updateMeshes(
737- const ModelParametersT<T>& modelParameters,
738- const SkeletonStateT<T>& state) {
739- MT_PROFILE_FUNCTION ();
740-
741- bool doUpdateNormals = false ;
742- if (this ->character_ .blendShape ) {
743- const BlendWeightsT<T> blendWeights =
744- extractBlendWeights (this ->parameterTransform_ , modelParameters);
745- this ->character_ .blendShape ->computeShape (blendWeights, this ->restMesh_ ->vertices );
746- doUpdateNormals = true ;
747- }
748- if (this ->character_ .faceExpressionBlendShape ) {
749- if (!this ->character_ .blendShape ) {
750- // Set restMesh back to neutral, removing potential previous expressions.
751- // Note that if the character comes with (shape) blendShape, the previous if block already
752- // takes care of this step.
753- Eigen::Map<Eigen::VectorX<T>> outputVec (
754- &this ->restMesh_ ->vertices [0 ][0 ], this ->restMesh_ ->vertices .size () * 3 );
755- const Eigen::Map<Eigen::VectorX<T>> baseVec (
756- &this ->neutralMesh_ ->vertices [0 ][0 ], this ->neutralMesh_ ->vertices .size () * 3 );
757- outputVec = baseVec.template cast <T>();
758- }
759- const BlendWeightsT<T> faceExpressionBlendWeights =
760- extractFaceExpressionBlendWeights (this ->parameterTransform_ , modelParameters);
761- this ->character_ .faceExpressionBlendShape ->applyDeltas (
762- faceExpressionBlendWeights, this ->restMesh_ ->vertices );
763- doUpdateNormals = true ;
764- }
765- if (doUpdateNormals) {
766- this ->restMesh_ ->updateNormals ();
767- }
768-
769- applySSD (
770- cast<T>(character_.inverseBindPose ),
771- *this ->character_ .skinWeights ,
772- *this ->restMesh_ ,
773- state,
774- *this ->posedMesh_ );
775- // TODO should we call updateNormals() here too or trust the ones from skinning?
776- }
777-
778740template class VertexErrorFunctionT <float >;
779741template class VertexErrorFunctionT <double >;
780742
0 commit comments