Skip to content

Commit 569380b

Browse files
cdtwiggmeta-codesync[bot]
authored andcommitted
point_triangle error.
Differential Revision: D84999386
1 parent 5193454 commit 569380b

File tree

2 files changed

+55
-93
lines changed

2 files changed

+55
-93
lines changed

momentum/character_solver/point_triangle_vertex_error_function.cpp

Lines changed: 51 additions & 82 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"
@@ -38,9 +39,6 @@ PointTriangleVertexErrorFunctionT<T>::PointTriangleVertexErrorFunctionT(
3839
character_in.faceExpressionBlendShape && (type != VertexConstraintType::Position),
3940
"Constraint type {} not implemented yet for face. Only Position type is supported.",
4041
toString(type));
41-
this->neutralMesh_ = std::make_unique<MeshT<T>>(character_in.mesh->template cast<T>());
42-
this->restMesh_ = std::make_unique<MeshT<T>>(character_in.mesh->template cast<T>());
43-
this->posedMesh_ = std::make_unique<MeshT<T>>(character_in.mesh->template cast<T>());
4442
}
4543

4644
template <typename T>
@@ -97,10 +95,10 @@ template <typename T>
9795
double PointTriangleVertexErrorFunctionT<T>::getError(
9896
const ModelParametersT<T>& modelParameters,
9997
const SkeletonStateT<T>& state,
100-
const MeshStateT<T>& /* meshState */) {
98+
const MeshStateT<T>& meshState) {
10199
MT_PROFILE_FUNCTION();
102100

103-
updateMeshes(modelParameters, state);
101+
MT_CHECK_NOTNULL(meshState.posedMesh_);
104102

105103
// loop over all constraints and calculate the error
106104
double error = 0.0;
@@ -109,8 +107,8 @@ double PointTriangleVertexErrorFunctionT<T>::getError(
109107
for (size_t i = 0; i < constraints_.size(); ++i) {
110108
const PointTriangleVertexConstraintT<T>& constr = constraints_[i];
111109

112-
const Eigen::Vector3<T> srcPoint = this->posedMesh_->vertices[constr.srcVertexIndex];
113-
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*this->posedMesh_, constr);
110+
const Eigen::Vector3<T> srcPoint = meshState.posedMesh_->vertices[constr.srcVertexIndex];
111+
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*meshState.posedMesh_, constr);
114112
const Eigen::Vector3<T> diff = srcPoint - tgtPoint;
115113
error += constr.weight * diff.squaredNorm() * kPositionWeight;
116114
}
@@ -119,13 +117,13 @@ double PointTriangleVertexErrorFunctionT<T>::getError(
119117
for (size_t i = 0; i < constraints_.size(); ++i) {
120118
const PointTriangleVertexConstraintT<T>& constr = constraints_[i];
121119

122-
const Eigen::Vector3<T> srcPoint = this->posedMesh_->vertices[constr.srcVertexIndex];
120+
const Eigen::Vector3<T> srcPoint = meshState.posedMesh_->vertices[constr.srcVertexIndex];
123121

124-
const Eigen::Vector3<T> sourceNormal = this->posedMesh_->normals[constr.srcVertexIndex];
125-
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->posedMesh_, constr);
122+
const Eigen::Vector3<T> sourceNormal = meshState.posedMesh_->normals[constr.srcVertexIndex];
123+
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*meshState.posedMesh_, constr);
126124

127125
const Eigen::Vector3<T> tgtPoint =
128-
computeTargetBaryPosition(*this->posedMesh_, constr) + constr.depth * targetNormal;
126+
computeTargetBaryPosition(*meshState.posedMesh_, constr) + constr.depth * targetNormal;
129127

130128
if (sourceNormal.dot(targetNormal) < 0) {
131129
targetNormal *= -1;
@@ -215,18 +213,19 @@ template <typename T>
215213
double PointTriangleVertexErrorFunctionT<T>::calculatePositionGradient(
216214
const ModelParametersT<T>& modelParameters,
217215
const SkeletonStateT<T>& state,
216+
const MeshStateT<T>& meshState,
218217
const PointTriangleVertexConstraintT<T>& constr,
219218
Eigen::Ref<Eigen::VectorX<T>> gradient) const {
220-
const Eigen::Vector3<T> srcPos = this->posedMesh_->vertices[constr.srcVertexIndex];
221-
const Eigen::Vector3<T> tgtPos = computeTargetPosition(*this->posedMesh_, constr);
219+
const Eigen::Vector3<T> srcPos = meshState.posedMesh_->vertices[constr.srcVertexIndex];
220+
const Eigen::Vector3<T> tgtPos = computeTargetPosition(*meshState.posedMesh_, constr);
222221

223222
const Eigen::Vector3<T> diff = srcPos - tgtPos;
224223

225224
// calculate the difference between target and position and error
226225
const T wgt = constr.weight * 2.0f * kPositionWeight * this->weight_;
227226

228227
const auto d_targetPos_d_tgtTriVertexPos =
229-
compute_d_targetPos_d_vertexPos(constr, *this->posedMesh_);
228+
compute_d_targetPos_d_vertexPos(constr, *meshState.posedMesh_);
230229

231230
// To simplify things we'll have one loop that goes through all 3 target triangle vertices _and_
232231
// the source vertex.
@@ -240,7 +239,8 @@ double PointTriangleVertexErrorFunctionT<T>::calculatePositionGradient(
240239
? Eigen::Matrix3<T>(-d_targetPos_d_tgtTriVertexPos[iTriVert])
241240
: Eigen::Matrix3<T>::Identity();
242241

243-
SkinningWeightIteratorT<T> skinningIter(this->character_, *this->restMesh_, state, vertexIndex);
242+
SkinningWeightIteratorT<T> skinningIter(
243+
this->character_, *meshState.restMesh_, state, vertexIndex);
244244

245245
// IN handle derivatives wrt jointParameters
246246
while (!skinningIter.finished()) {
@@ -394,22 +394,23 @@ template <typename T>
394394
double PointTriangleVertexErrorFunctionT<T>::calculatePositionJacobian(
395395
const ModelParametersT<T>& modelParameters,
396396
const SkeletonStateT<T>& state,
397+
const MeshStateT<T>& meshState,
397398
const PointTriangleVertexConstraintT<T>& constr,
398399
Ref<Eigen::MatrixX<T>> jac,
399400
Ref<Eigen::VectorX<T>> res) const {
400401
// calculate the difference between target and position and error
401-
const Eigen::Vector3<T> srcPos = this->posedMesh_->vertices[constr.srcVertexIndex];
402-
const Eigen::Vector3<T> tgtPos = computeTargetPosition(*this->posedMesh_, constr);
402+
const Eigen::Vector3<T> srcPos = meshState.posedMesh_->vertices[constr.srcVertexIndex];
403+
const Eigen::Vector3<T> tgtPos = computeTargetPosition(*meshState.posedMesh_, constr);
403404

404405
// The derivative of the target position wrt the triangle vertices:
405406
// p_tgt = bary_0 * p_0 + bary_1 * p_1 + bary_2 * p_2 + depth * n
406407

407-
const Eigen::Vector3<T> diff = this->posedMesh_->vertices[constr.srcVertexIndex] - tgtPos;
408+
const Eigen::Vector3<T> diff = meshState.posedMesh_->vertices[constr.srcVertexIndex] - tgtPos;
408409

409410
const T wgt = std::sqrt(constr.weight * kPositionWeight * this->weight_);
410411

411412
const auto d_targetPos_d_tgtTriVertexPos =
412-
compute_d_targetPos_d_vertexPos(constr, *this->posedMesh_);
413+
compute_d_targetPos_d_vertexPos(constr, *meshState.posedMesh_);
413414

414415
// Verify derivative:
415416
#if 0
@@ -450,7 +451,8 @@ double PointTriangleVertexErrorFunctionT<T>::calculatePositionJacobian(
450451
? Eigen::Matrix3<T>(-d_targetPos_d_tgtTriVertexPos[iTriVert])
451452
: Eigen::Matrix3<T>::Identity();
452453

453-
SkinningWeightIteratorT<T> skinningIter(this->character_, *this->restMesh_, state, vertexIndex);
454+
SkinningWeightIteratorT<T> skinningIter(
455+
this->character_, *meshState.restMesh_, state, vertexIndex);
454456

455457
// IN handle derivatives wrt jointParameters
456458
while (!skinningIter.finished()) {
@@ -547,13 +549,14 @@ template <typename T>
547549
double PointTriangleVertexErrorFunctionT<T>::calculateNormalGradient(
548550
const ModelParametersT<T>& modelParameters,
549551
const SkeletonStateT<T>& state,
552+
const MeshStateT<T>& meshState,
550553
const PointTriangleVertexConstraintT<T>& constr,
551554
const T sourceNormalWeight,
552555
const T targetNormalWeight,
553556
Eigen::Ref<Eigen::VectorX<T>> gradient) const {
554-
const Eigen::Vector3<T> sourceNormal = posedMesh_->normals[constr.srcVertexIndex];
555-
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->posedMesh_, constr);
556-
const Eigen::Vector3<T> tgtPosition = computeTargetPosition(*this->posedMesh_, constr);
557+
const Eigen::Vector3<T> sourceNormal = meshState.posedMesh_->normals[constr.srcVertexIndex];
558+
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*meshState.posedMesh_, constr);
559+
const Eigen::Vector3<T> tgtPosition = computeTargetPosition(*meshState.posedMesh_, constr);
557560

558561
T targetNormalSign = 1;
559562
if (sourceNormal.dot(targetNormal) < 0) {
@@ -564,15 +567,16 @@ double PointTriangleVertexErrorFunctionT<T>::calculateNormalGradient(
564567
sourceNormalWeight * sourceNormal + targetNormalWeight * targetNormal;
565568

566569
// calculate the difference between target and position and error
567-
const Eigen::Vector3<T> diff = this->posedMesh_->vertices[constr.srcVertexIndex] - tgtPosition;
570+
const Eigen::Vector3<T> diff =
571+
meshState.posedMesh_->vertices[constr.srcVertexIndex] - tgtPosition;
568572
const T dist = diff.dot(normal);
569573

570574
const T wgt = constr.weight * 2.0f * kPlaneWeight * this->weight_;
571575

572576
const auto d_targetPos_d_tgtTriVertexPos =
573-
compute_d_targetPos_d_vertexPos(constr, *this->posedMesh_);
577+
compute_d_targetPos_d_vertexPos(constr, *meshState.posedMesh_);
574578
const auto d_targetNormal_d_tgtTriVertexPos =
575-
compute_d_targetNormal_d_vertexPos(constr, *this->posedMesh_);
579+
compute_d_targetNormal_d_vertexPos(constr, *meshState.posedMesh_);
576580

577581
for (int iTriVert = 0; iTriVert < 4; ++iTriVert) {
578582
const auto vertexIndex =
@@ -582,7 +586,8 @@ double PointTriangleVertexErrorFunctionT<T>::calculateNormalGradient(
582586
? Eigen::Matrix3<T>(-d_targetPos_d_tgtTriVertexPos[iTriVert])
583587
: Eigen::Matrix3<T>::Identity();
584588

585-
SkinningWeightIteratorT<T> skinningIter(this->character_, *this->restMesh_, state, vertexIndex);
589+
SkinningWeightIteratorT<T> skinningIter(
590+
this->character_, *meshState.restMesh_, state, vertexIndex);
586591

587592
// IN handle derivatives wrt jointParameters
588593
while (!skinningIter.finished()) {
@@ -681,14 +686,15 @@ template <typename T>
681686
double PointTriangleVertexErrorFunctionT<T>::calculateNormalJacobian(
682687
const ModelParametersT<T>& modelParameters,
683688
const SkeletonStateT<T>& state,
689+
const MeshStateT<T>& meshState,
684690
const PointTriangleVertexConstraintT<T>& constr,
685691
const T sourceNormalWeight,
686692
const T targetNormalWeight,
687693
Ref<Eigen::MatrixX<T>> jac,
688694
T& res) const {
689-
const Eigen::Vector3<T> sourceNormal = posedMesh_->normals[constr.srcVertexIndex];
690-
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->posedMesh_, constr);
691-
const Eigen::Vector3<T> tgtPosition = computeTargetPosition(*this->posedMesh_, constr);
695+
const Eigen::Vector3<T> sourceNormal = meshState.posedMesh_->normals[constr.srcVertexIndex];
696+
Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*meshState.posedMesh_, constr);
697+
const Eigen::Vector3<T> tgtPosition = computeTargetPosition(*meshState.posedMesh_, constr);
692698

693699
T targetNormalSign = 1;
694700
if (sourceNormal.dot(targetNormal) < 0) {
@@ -699,15 +705,16 @@ double PointTriangleVertexErrorFunctionT<T>::calculateNormalJacobian(
699705
sourceNormalWeight * sourceNormal + targetNormalWeight * targetNormal;
700706

701707
// calculate the difference between target and position and error
702-
const Eigen::Vector3<T> diff = this->posedMesh_->vertices[constr.srcVertexIndex] - tgtPosition;
708+
const Eigen::Vector3<T> diff =
709+
meshState.posedMesh_->vertices[constr.srcVertexIndex] - tgtPosition;
703710
const T dist = diff.dot(normal);
704711

705712
const T wgt = std::sqrt(constr.weight * kPositionWeight * this->weight_);
706713

707714
const auto d_targetPos_d_tgtTriVertexPos =
708-
compute_d_targetPos_d_vertexPos(constr, *this->posedMesh_);
715+
compute_d_targetPos_d_vertexPos(constr, *meshState.posedMesh_);
709716
const auto d_targetNormal_d_tgtTriVertexPos =
710-
compute_d_targetNormal_d_vertexPos(constr, *this->posedMesh_);
717+
compute_d_targetNormal_d_vertexPos(constr, *meshState.posedMesh_);
711718

712719
for (int iTriVert = 0; iTriVert < 4; ++iTriVert) {
713720
const auto vertexIndex =
@@ -717,7 +724,8 @@ double PointTriangleVertexErrorFunctionT<T>::calculateNormalJacobian(
717724
? Eigen::Matrix3<T>(-d_targetPos_d_tgtTriVertexPos[iTriVert])
718725
: Eigen::Matrix3<T>::Identity();
719726

720-
SkinningWeightIteratorT<T> skinningIter(this->character_, *this->restMesh_, state, vertexIndex);
727+
SkinningWeightIteratorT<T> skinningIter(
728+
this->character_, *meshState.restMesh_, state, vertexIndex);
721729

722730
// IN handle derivatives wrt jointParameters
723731
while (!skinningIter.finished()) {
@@ -827,15 +835,16 @@ template <typename T>
827835
double PointTriangleVertexErrorFunctionT<T>::getGradient(
828836
const ModelParametersT<T>& modelParameters,
829837
const SkeletonStateT<T>& state,
830-
const MeshStateT<T>& /* meshState */,
838+
const MeshStateT<T>& meshState,
831839
Eigen::Ref<Eigen::VectorX<T>> gradient) {
832-
updateMeshes(modelParameters, state);
840+
MT_CHECK_NOTNULL(meshState.posedMesh_);
833841

834842
double error = 0;
835843

836844
if (constraintType_ == VertexConstraintType::Position) {
837845
for (size_t iCons = 0; iCons < constraints_.size(); ++iCons) {
838-
error += calculatePositionGradient(modelParameters, state, constraints_[iCons], gradient);
846+
error += calculatePositionGradient(
847+
modelParameters, state, meshState, constraints_[iCons], gradient);
839848
}
840849
} else {
841850
T sourceNormalWeight;
@@ -846,6 +855,7 @@ double PointTriangleVertexErrorFunctionT<T>::getGradient(
846855
error += calculateNormalGradient(
847856
modelParameters,
848857
state,
858+
meshState,
849859
constraints_[iCons],
850860
sourceNormalWeight,
851861
targetNormalWeight,
@@ -860,7 +870,7 @@ template <typename T>
860870
double PointTriangleVertexErrorFunctionT<T>::getJacobian(
861871
const ModelParametersT<T>& modelParameters,
862872
const SkeletonStateT<T>& state,
863-
const MeshStateT<T>& /* meshState */,
873+
const MeshStateT<T>& meshState,
864874
Eigen::Ref<Eigen::MatrixX<T>> jacobian,
865875
Eigen::Ref<Eigen::VectorX<T>> residual,
866876
int& usedRows) {
@@ -869,7 +879,7 @@ double PointTriangleVertexErrorFunctionT<T>::getJacobian(
869879
MT_CHECK(jacobian.rows() >= (Eigen::Index)(1 * constraints_.size()));
870880
MT_CHECK(residual.rows() >= (Eigen::Index)(1 * constraints_.size()));
871881

872-
updateMeshes(modelParameters, state);
882+
MT_CHECK_NOTNULL(meshState.posedMesh_);
873883

874884
double error = 0;
875885

@@ -880,6 +890,7 @@ double PointTriangleVertexErrorFunctionT<T>::getJacobian(
880890
error += calculatePositionJacobian(
881891
modelParameters,
882892
state,
893+
meshState,
883894
constraints_[iCons],
884895
jacobian.block(3 * iCons, 0, 3, modelParameters.size()),
885896
residual.middleRows(3 * iCons, 3));
@@ -895,6 +906,7 @@ double PointTriangleVertexErrorFunctionT<T>::getJacobian(
895906
error += calculateNormalJacobian(
896907
modelParameters,
897908
state,
909+
meshState,
898910
constraints_[iCons],
899911
sourceNormalWeight,
900912
targetNormalWeight,
@@ -921,49 +933,6 @@ size_t PointTriangleVertexErrorFunctionT<T>::getJacobianSize() const {
921933
}
922934
}
923935

924-
template <typename T>
925-
void PointTriangleVertexErrorFunctionT<T>::updateMeshes(
926-
const ModelParametersT<T>& modelParameters,
927-
const SkeletonStateT<T>& state) {
928-
MT_PROFILE_FUNCTION();
929-
930-
bool doUpdateNormals = false;
931-
if (this->character_.blendShape) {
932-
const BlendWeightsT<T> blendWeights =
933-
extractBlendWeights(this->parameterTransform_, modelParameters);
934-
this->character_.blendShape->computeShape(blendWeights, this->restMesh_->vertices);
935-
doUpdateNormals = true;
936-
}
937-
if (this->character_.faceExpressionBlendShape) {
938-
if (!this->character_.blendShape) {
939-
// Set restMesh back to neutral, removing potential previous expressions.
940-
// Note that if the character comes with (shape) blendShape, the previous if block already
941-
// takes care of this step.
942-
Eigen::Map<Eigen::VectorX<T>> outputVec(
943-
&this->restMesh_->vertices[0][0], this->restMesh_->vertices.size() * 3);
944-
const Eigen::Map<Eigen::VectorX<T>> baseVec(
945-
&this->neutralMesh_->vertices[0][0], this->neutralMesh_->vertices.size() * 3);
946-
outputVec = baseVec.template cast<T>();
947-
}
948-
const BlendWeightsT<T> faceExpressionBlendWeights =
949-
extractFaceExpressionBlendWeights(this->parameterTransform_, modelParameters);
950-
this->character_.faceExpressionBlendShape->applyDeltas(
951-
faceExpressionBlendWeights, this->restMesh_->vertices);
952-
doUpdateNormals = true;
953-
}
954-
if (doUpdateNormals) {
955-
this->restMesh_->updateNormals();
956-
}
957-
958-
applySSD(
959-
cast<T>(character_.inverseBindPose),
960-
*this->character_.skinWeights,
961-
*this->restMesh_,
962-
state,
963-
*this->posedMesh_);
964-
// TODO should we call updateNormals() here too or trust the ones from skinning?
965-
}
966-
967936
template class PointTriangleVertexErrorFunctionT<float>;
968937
template class PointTriangleVertexErrorFunctionT<double>;
969938

momentum/character_solver/point_triangle_vertex_error_function.h

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,15 @@ class PointTriangleVertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
9898
double calculatePositionJacobian(
9999
const ModelParametersT<T>& modelParameters,
100100
const SkeletonStateT<T>& state,
101+
const MeshStateT<T>& meshState,
101102
const PointTriangleVertexConstraintT<T>& constr,
102103
Ref<Eigen::MatrixX<T>> jac,
103104
Ref<Eigen::VectorX<T>> res) const;
104105

105106
double calculateNormalJacobian(
106107
const ModelParametersT<T>& modelParameters,
107108
const SkeletonStateT<T>& state,
109+
const MeshStateT<T>& meshState,
108110
const PointTriangleVertexConstraintT<T>& constr,
109111
T sourceNormalWeight,
110112
T targetNormalWeight,
@@ -114,12 +116,14 @@ class PointTriangleVertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
114116
double calculatePositionGradient(
115117
const ModelParametersT<T>& modelParameters,
116118
const SkeletonStateT<T>& state,
119+
const MeshStateT<T>& meshState,
117120
const PointTriangleVertexConstraintT<T>& constr,
118121
Eigen::Ref<Eigen::VectorX<T>> gradient) const;
119122

120123
double calculateNormalGradient(
121124
const ModelParametersT<T>& modelParameters,
122125
const SkeletonStateT<T>& state,
126+
const MeshStateT<T>& meshState,
123127
const PointTriangleVertexConstraintT<T>& constr,
124128
T sourceNormalWeight,
125129
T targetNormalWeight,
@@ -131,18 +135,7 @@ class PointTriangleVertexErrorFunctionT : public SkeletonErrorFunctionT<T> {
131135

132136
std::vector<PointTriangleVertexConstraintT<T>> constraints_;
133137

134-
std::unique_ptr<MeshT<T>>
135-
neutralMesh_; // Rest mesh without facial expression basis,
136-
// used to restore the neutral shape after facial expressions are applied.
137-
// Not used with there is a shape basis.
138-
std::unique_ptr<MeshT<T>> restMesh_; // The rest positions of the mesh after shape basis
139-
// (and potentially facial expression) has been applied
140-
std::unique_ptr<MeshT<T>>
141-
posedMesh_; // The posed mesh after the skeleton transforms have been applied.
142-
143138
const VertexConstraintType constraintType_;
144-
145-
void updateMeshes(const ModelParametersT<T>& modelParameters, const SkeletonStateT<T>& state);
146139
};
147140

148141
} // namespace momentum

0 commit comments

Comments
 (0)