Skip to content

Commit f70b46f

Browse files
cdtwiggmeta-codesync[bot]
authored andcommitted
Switch VertexErrorFunction to use MeshState. (#711)
Summary: Pull Request resolved: #711 As title. Reviewed By: cstollmeta Differential Revision: D84999392 fbshipit-source-id: 4c223219b1e5d8b25e02fda61ded80d15858f79c
1 parent 7efd3da commit f70b46f

File tree

2 files changed

+33
-78
lines changed

2 files changed

+33
-78
lines changed

momentum/character_solver/vertex_error_function.cpp

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
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

5553
template <typename T>
@@ -74,10 +72,10 @@ template <typename T>
7472
double 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>
138136
double 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>
243242
double 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>
349349
double 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>
457458
double 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>
579581
double 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>
651654
double 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-
778740
template class VertexErrorFunctionT<float>;
779741
template class VertexErrorFunctionT<double>;
780742

momentum/character_solver/vertex_error_function.h

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,15 @@ class VertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
102102
double calculatePositionJacobian(
103103
const ModelParametersT<T>& modelParameters,
104104
const SkeletonStateT<T>& state,
105+
const MeshStateT<T>& meshState,
105106
const VertexConstraintT<T>& constr,
106107
Ref<Eigen::MatrixX<T>> jac,
107108
Ref<Eigen::VectorX<T>> res) const;
108109

109110
double calculateNormalJacobian(
110111
const ModelParametersT<T>& modelParameters,
111112
const SkeletonStateT<T>& state,
113+
const MeshStateT<T>& meshState,
112114
const VertexConstraintT<T>& constr,
113115
T sourceNormalWeight,
114116
T targetNormalWeight,
@@ -118,12 +120,14 @@ class VertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
118120
double calculatePositionGradient(
119121
const ModelParametersT<T>& modelParameters,
120122
const SkeletonStateT<T>& state,
123+
const MeshStateT<T>& meshState,
121124
const VertexConstraintT<T>& constr,
122125
Eigen::Ref<Eigen::VectorX<T>> gradient) const;
123126

124127
double calculateNormalGradient(
125128
const ModelParametersT<T>& modelParameters,
126129
const SkeletonStateT<T>& state,
130+
const MeshStateT<T>& meshState,
127131
const VertexConstraintT<T>& constr,
128132
T sourceNormalWeight,
129133
T targetNormalWeight,
@@ -143,20 +147,9 @@ class VertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
143147

144148
std::vector<VertexConstraintT<T>> constraints_;
145149

146-
std::unique_ptr<MeshT<T>>
147-
neutralMesh_; // Rest mesh without facial expression basis,
148-
// used to restore the neutral shape after facial expressions are applied.
149-
// Not used with there is a shape basis.
150-
std::unique_ptr<MeshT<T>> restMesh_; // The rest positions of the mesh after shape basis
151-
// (and potentially facial expression) has been applied
152-
std::unique_ptr<MeshT<T>>
153-
posedMesh_; // The posed mesh after the skeleton transforms have been applied.
154-
155150
const VertexConstraintType constraintType_;
156151

157152
uint32_t maxThreads_;
158-
159-
void updateMeshes(const ModelParametersT<T>& modelParameters, const SkeletonStateT<T>& state);
160153
};
161154

162155
} // namespace momentum

0 commit comments

Comments
 (0)