Skip to content

Commit 22cbf41

Browse files
cdtwiggmeta-codesync[bot]
authored andcommitted
Switch SkinnedLocatorTriangleError to use MeshState (#713)
Summary: Pull Request resolved: #713 As title. Reviewed By: cstollmeta Differential Revision: D84999391
1 parent 203b70e commit 22cbf41

File tree

3 files changed

+76
-100
lines changed

3 files changed

+76
-100
lines changed

momentum/character_solver/skinned_locator_triangle_error_function.cpp

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

4139
template <typename T>
@@ -161,63 +159,60 @@ std::array<Eigen::Matrix3<T>, 3> compute_d_targetPos_d_vertexPos(
161159
template <typename T>
162160
double 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

210204
template <typename T>
211205
double 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(
271266
template <typename T>
272267
double 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(
335331
template <typename T>
336332
double 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(
396393
template <typename T>
397394
double 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(
463460
template <typename T>
464461
double 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

484484
template <typename T>
485485
double 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>;

momentum/character_solver/skinned_locator_triangle_error_function.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,23 +109,27 @@ class SkinnedLocatorTriangleErrorFunctionT : public SkeletonErrorFunctionT<T> {
109109

110110
double calculatePositionJacobian(
111111
const ModelParametersT<T>& modelParameters,
112+
const MeshStateT<T>& meshState,
112113
const SkinnedLocatorTriangleConstraintT<T>& constr,
113114
Ref<Eigen::MatrixX<T>> jac,
114115
Ref<Eigen::VectorX<T>> res) const;
115116

116117
double calculatePlaneJacobian(
117118
const ModelParametersT<T>& modelParameters,
119+
const MeshStateT<T>& meshState,
118120
const SkinnedLocatorTriangleConstraintT<T>& constr,
119121
Ref<Eigen::MatrixX<T>> jac,
120122
T& res) const;
121123

122124
double calculatePositionGradient(
123125
const ModelParametersT<T>& modelParameters,
126+
const MeshStateT<T>& meshState,
124127
const SkinnedLocatorTriangleConstraintT<T>& constr,
125128
Eigen::Ref<Eigen::VectorX<T>> gradient) const;
126129

127130
double calculatePlaneGradient(
128131
const ModelParametersT<T>& modelParameters,
132+
const MeshStateT<T>& meshState,
129133
const SkinnedLocatorTriangleConstraintT<T>& constr,
130134
Eigen::Ref<Eigen::VectorX<T>> gradient) const;
131135

@@ -136,11 +140,7 @@ class SkinnedLocatorTriangleErrorFunctionT : public SkeletonErrorFunctionT<T> {
136140

137141
std::vector<SkinnedLocatorTriangleConstraintT<T>> constraints_;
138142

139-
std::unique_ptr<MeshT<T>> neutralMesh_; // Rest mesh without facial expression basis
140-
std::unique_ptr<MeshT<T>> restMesh_; // Rest positions after shape basis is applied
141-
142143
const VertexConstraintType constraintType_;
143-
void updateMeshes(const ModelParametersT<T>& modelParameters);
144144
};
145145

146146
} // namespace momentum

0 commit comments

Comments
 (0)