Skip to content

Commit a15daa2

Browse files
cdtwiggfacebook-github-bot
authored andcommitted
Switch SkinnedLocatorTriangleError to use MeshState (#713)
Summary: As title. Reviewed By: cstollmeta Differential Revision: D84999391
1 parent 5590e00 commit a15daa2

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>
@@ -160,63 +158,60 @@ std::array<Eigen::Matrix3<T>, 3> compute_d_targetPos_d_vertexPos(
160158
template <typename T>
161159
double SkinnedLocatorTriangleErrorFunctionT<T>::getError(
162160
const ModelParametersT<T>& modelParameters,
163-
const SkeletonStateT<T>& /*state*/,
164-
const MeshStateT<T>& /* meshState */) {
161+
const SkeletonStateT<T>& /* state */,
162+
const MeshStateT<T>& meshState) {
165163
MT_PROFILE_FUNCTION();
166164

167-
updateMeshes(modelParameters);
165+
MT_CHECK_NOTNULL(meshState.restMesh_);
168166

169-
// loop over all constraints and calculate the error
170167
double error = 0.0;
171168

172169
if (constraintType_ == VertexConstraintType::Position) {
173-
for (size_t i = 0; i < constraints_.size(); ++i) {
174-
const SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
175-
170+
for (const auto& constr : constraints_) {
176171
// Get the skinned locator position
177172
const Eigen::Vector3<T> locatorRestPos =
178173
getLocatorRestPosition(modelParameters, constr.locatorIndex);
179174

180175
// Get the target position on the triangle
181-
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*this->restMesh_, constr);
176+
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*meshState.restMesh_, constr);
182177

183178
// Calculate position error
184179
const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
185180
error += constr.weight * diff.squaredNorm();
186181
}
187-
} else if (constraintType_ == VertexConstraintType::Plane) {
188-
for (size_t i = 0; i < constraints_.size(); ++i) {
189-
const SkinnedLocatorTriangleConstraintT<T>& constr = constraints_[i];
190-
182+
} else {
183+
MT_CHECK(constraintType_ == VertexConstraintType::Plane);
184+
for (const auto& constr : constraints_) {
191185
// Get the skinned locator position
192186
const Eigen::Vector3<T> locatorRestPos =
193187
getLocatorRestPosition(modelParameters, constr.locatorIndex);
194188

195189
// Get the target position and normal
196-
const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->restMesh_, constr);
190+
const Eigen::Vector3<T> targetNormal =
191+
computeTargetTriangleNormal(*meshState.restMesh_, constr);
197192
const Eigen::Vector3<T> tgtPoint =
198-
computeTargetBaryPosition(*this->restMesh_, constr) + constr.depth * targetNormal;
193+
computeTargetBaryPosition(*meshState.restMesh_, constr) + constr.depth * targetNormal;
199194
// Calculate plane error (projection onto normal)
200195
const T dist = targetNormal.dot(locatorRestPos - tgtPoint);
201196
error += constr.weight * dist * dist;
202197
}
203198
}
204199

205-
// return error
206200
return error * this->weight_;
207201
}
208202

209203
template <typename T>
210204
double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
211205
const ModelParametersT<T>& modelParameters,
206+
const MeshStateT<T>& meshState,
212207
const SkinnedLocatorTriangleConstraintT<T>& constr,
213208
Eigen::Ref<Eigen::VectorX<T>> gradient) const {
214209
// Get the skinned locator position
215210
const Eigen::Vector3<T> locatorRestPos =
216211
getLocatorRestPosition(modelParameters, constr.locatorIndex);
217212

218213
// Get the target position on the triangle
219-
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*this->restMesh_, constr);
214+
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*meshState.restMesh_, constr);
220215

221216
// Calculate position error
222217
const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -226,7 +221,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
226221

227222
// Get the derivative of the target position with respect to the triangle vertices
228223
const auto d_targetPos_d_tgtTriVertexPos =
229-
compute_d_targetPos_d_vertexPos(constr, *this->restMesh_);
224+
compute_d_targetPos_d_vertexPos(constr, *meshState.restMesh_);
230225

231226
// Apply gradient for locator parameter if it exists
232227
int paramIndex = getSkinnedLocatorParameterIndex(constr.locatorIndex);
@@ -270,16 +265,17 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionGradient(
270265
template <typename T>
271266
double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
272267
const ModelParametersT<T>& modelParameters,
268+
const MeshStateT<T>& meshState,
273269
const SkinnedLocatorTriangleConstraintT<T>& constr,
274270
Eigen::Ref<Eigen::VectorX<T>> gradient) const {
275271
// Get the skinned locator position
276272
const Eigen::Vector3<T> locatorRestPos =
277273
getLocatorRestPosition(modelParameters, constr.locatorIndex);
278274

279275
// Get the target position and normal
280-
const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->restMesh_, constr);
276+
const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*meshState.restMesh_, constr);
281277
const Eigen::Vector3<T> tgtPoint =
282-
computeTargetBaryPosition(*this->restMesh_, constr) + constr.depth * targetNormal;
278+
computeTargetBaryPosition(*meshState.restMesh_, constr) + constr.depth * targetNormal;
283279

284280
// Calculate plane error (projection onto normal)
285281
const Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -288,9 +284,9 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
288284

289285
// Get the derivative of the target position with respect to the triangle vertices
290286
const auto d_targetPos_d_tgtTriVertexPos =
291-
compute_d_targetPos_d_vertexPos(constr, *this->restMesh_);
287+
compute_d_targetPos_d_vertexPos(constr, *meshState.restMesh_);
292288
const auto d_targetNormal_d_tgtTriVertexPos =
293-
compute_d_targetNormal_d_vertexPos(constr, *this->restMesh_);
289+
compute_d_targetNormal_d_vertexPos(constr, *meshState.restMesh_);
294290

295291
// Apply gradient for locator parameter if it exists
296292
int paramIndex = getSkinnedLocatorParameterIndex(constr.locatorIndex);
@@ -334,6 +330,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneGradient(
334330
template <typename T>
335331
double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
336332
const ModelParametersT<T>& modelParameters,
333+
const MeshStateT<T>& meshState,
337334
const SkinnedLocatorTriangleConstraintT<T>& constr,
338335
Ref<Eigen::MatrixX<T>> jac,
339336
Ref<Eigen::VectorX<T>> res) const {
@@ -342,7 +339,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
342339
getLocatorRestPosition(modelParameters, constr.locatorIndex);
343340

344341
// Get the target position on the triangle
345-
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*this->restMesh_, constr);
342+
const Eigen::Vector3<T> tgtPoint = computeTargetPosition(*meshState.restMesh_, constr);
346343

347344
// Calculate position error
348345
const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
@@ -353,7 +350,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
353350

354351
// Get the derivative of the target position with respect to the triangle vertices
355352
const auto d_targetPos_d_tgtTriVertexPos =
356-
compute_d_targetPos_d_vertexPos(constr, *this->restMesh_);
353+
compute_d_targetPos_d_vertexPos(constr, *meshState.restMesh_);
357354

358355
// Apply Jacobian for locator parameter if it exists
359356
int paramIndex = getSkinnedLocatorParameterIndex(constr.locatorIndex);
@@ -395,6 +392,7 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePositionJacobian(
395392
template <typename T>
396393
double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
397394
const ModelParametersT<T>& modelParameters,
395+
const MeshStateT<T>& meshState,
398396
const SkinnedLocatorTriangleConstraintT<T>& constr,
399397
Ref<Eigen::MatrixX<T>> jac,
400398
T& res) const {
@@ -403,23 +401,22 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
403401
getLocatorRestPosition(modelParameters, constr.locatorIndex);
404402

405403
// Get the target position and normal
406-
const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*this->restMesh_, constr);
404+
const Eigen::Vector3<T> targetNormal = computeTargetTriangleNormal(*meshState.restMesh_, constr);
407405
const Eigen::Vector3<T> tgtPoint =
408-
computeTargetBaryPosition(*this->restMesh_, constr) + constr.depth * targetNormal;
406+
computeTargetBaryPosition(*meshState.restMesh_, constr) + constr.depth * targetNormal;
409407

410408
// Calculate plane error (projection onto normal)
411409
const Eigen::Vector3<T> diff = locatorRestPos - tgtPoint;
412410
const T dist = targetNormal.dot(diff);
413411

414-
// Set residual
415412
const T wgt = std::sqrt(constr.weight * this->weight_);
416413
res = wgt * dist;
417414

418415
// Get the derivative of the target position with respect to the triangle vertices
419416
const auto d_targetPos_d_tgtTriVertexPos =
420-
compute_d_targetPos_d_vertexPos(constr, *this->restMesh_);
417+
compute_d_targetPos_d_vertexPos(constr, *meshState.restMesh_);
421418
const auto d_targetNormal_d_tgtTriVertexPos =
422-
compute_d_targetNormal_d_vertexPos(constr, *this->restMesh_);
419+
compute_d_targetNormal_d_vertexPos(constr, *meshState.restMesh_);
423420

424421
// Apply Jacobian for locator parameter if it exists
425422
int paramIndex = getSkinnedLocatorParameterIndex(constr.locatorIndex);
@@ -462,58 +459,68 @@ double SkinnedLocatorTriangleErrorFunctionT<T>::calculatePlaneJacobian(
462459
template <typename T>
463460
double SkinnedLocatorTriangleErrorFunctionT<T>::getGradient(
464461
const ModelParametersT<T>& modelParameters,
465-
const SkeletonStateT<T>& /*state*/,
466-
const MeshStateT<T>& /* meshState */,
462+
const SkeletonStateT<T>& /* state */,
463+
const MeshStateT<T>& meshState,
467464
Eigen::Ref<Eigen::VectorX<T>> gradient) {
468-
updateMeshes(modelParameters);
465+
MT_CHECK_NOTNULL(meshState.restMesh_);
469466

470-
double error = 0.0;
467+
double error = 0;
471468

472-
for (const auto& constraint : constraints_) {
473-
if (constraintType_ == VertexConstraintType::Position) {
474-
error += calculatePositionGradient(modelParameters, constraint, gradient);
475-
} else if (constraintType_ == VertexConstraintType::Plane) {
476-
error += calculatePlaneGradient(modelParameters, constraint, gradient);
469+
if (constraintType_ == VertexConstraintType::Position) {
470+
for (size_t iCons = 0; iCons < constraints_.size(); ++iCons) {
471+
error += calculatePositionGradient(modelParameters, meshState, constraints_[iCons], gradient);
472+
}
473+
} else {
474+
MT_CHECK(constraintType_ == VertexConstraintType::Plane);
475+
for (size_t iCons = 0; iCons < constraints_.size(); ++iCons) {
476+
error += calculatePlaneGradient(modelParameters, meshState, constraints_[iCons], gradient);
477477
}
478478
}
479479

480-
return error * this->weight_;
480+
return this->weight_ * error;
481481
}
482482

483483
template <typename T>
484484
double SkinnedLocatorTriangleErrorFunctionT<T>::getJacobian(
485485
const ModelParametersT<T>& modelParameters,
486-
const SkeletonStateT<T>& /*state*/,
487-
const MeshStateT<T>& /* meshState */,
486+
const SkeletonStateT<T>& /* state */,
487+
const MeshStateT<T>& meshState,
488488
Eigen::Ref<Eigen::MatrixX<T>> jacobian,
489489
Eigen::Ref<Eigen::VectorX<T>> residual,
490490
int& usedRows) {
491491
MT_CHECK(
492492
jacobian.cols() == static_cast<Eigen::Index>(this->parameterTransform_.transform.cols()));
493+
MT_CHECK(jacobian.rows() >= (Eigen::Index)(1 * constraints_.size()));
494+
MT_CHECK(residual.rows() >= (Eigen::Index)(1 * constraints_.size()));
493495

494-
updateMeshes(modelParameters);
496+
MT_CHECK(
497+
meshState.restMesh_, "MeshState must have rest mesh for SkinnedLocatorTriangleErrorFunction");
495498

496-
double error = 0.0;
497-
usedRows = 0;
499+
double error = 0;
498500

499-
for (size_t iCons = 0; iCons < constraints_.size(); ++iCons) {
500-
if (constraintType_ == VertexConstraintType::Position) {
501+
if (constraintType_ == VertexConstraintType::Position) {
502+
for (size_t i = 0; i < constraints_.size(); ++i) {
501503
error += calculatePositionJacobian(
502504
modelParameters,
503-
constraints_[iCons],
504-
jacobian.block(usedRows, 0, 3, modelParameters.size()),
505-
residual.middleRows(usedRows, 3));
506-
usedRows += 3;
507-
} else if (constraintType_ == VertexConstraintType::Plane) {
508-
T res;
505+
meshState,
506+
constraints_[i],
507+
jacobian.block(3 * i, 0, 3, modelParameters.size()),
508+
residual.middleRows(3 * i, 3));
509+
}
510+
usedRows = 3 * constraints_.size();
511+
} else {
512+
MT_CHECK(constraintType_ == VertexConstraintType::Plane);
513+
for (size_t i = 0; i < constraints_.size(); ++i) {
514+
T residualValue;
509515
error += calculatePlaneJacobian(
510516
modelParameters,
511-
constraints_[iCons],
512-
jacobian.block(usedRows, 0, 1, modelParameters.size()),
513-
res);
514-
residual[usedRows] = res;
515-
usedRows += 1;
517+
meshState,
518+
constraints_[i],
519+
jacobian.block(i, 0, 1, modelParameters.size()),
520+
residualValue);
521+
residual(i) = residualValue;
516522
}
523+
usedRows = constraints_.size();
517524
}
518525

519526
return error;
@@ -529,42 +536,8 @@ size_t SkinnedLocatorTriangleErrorFunctionT<T>::getJacobianSize() const {
529536
return 0;
530537
}
531538

532-
template <typename T>
533-
void SkinnedLocatorTriangleErrorFunctionT<T>::updateMeshes(
534-
const ModelParametersT<T>& modelParameters) {
535-
MT_PROFILE_FUNCTION();
536-
537-
bool doUpdateNormals = false;
538-
if (this->character_.blendShape) {
539-
const BlendWeightsT<T> blendWeights =
540-
extractBlendWeights(this->parameterTransform_, modelParameters);
541-
this->character_.blendShape->computeShape(blendWeights, this->restMesh_->vertices);
542-
doUpdateNormals = true;
543-
}
544-
if (this->character_.faceExpressionBlendShape) {
545-
if (!this->character_.blendShape) {
546-
// Set restMesh back to neutral, removing potential previous expressions.
547-
// Note that if the character comes with (shape) blendShape, the previous if block already
548-
// takes care of this step.
549-
Eigen::Map<Eigen::VectorX<T>> outputVec(
550-
&this->restMesh_->vertices[0][0], this->restMesh_->vertices.size() * 3);
551-
const Eigen::Map<Eigen::VectorX<T>> baseVec(
552-
&this->neutralMesh_->vertices[0][0], this->neutralMesh_->vertices.size() * 3);
553-
outputVec = baseVec.template cast<T>();
554-
}
555-
const BlendWeightsT<T> faceExpressionBlendWeights =
556-
extractFaceExpressionBlendWeights(this->parameterTransform_, modelParameters);
557-
this->character_.faceExpressionBlendShape->applyDeltas(
558-
faceExpressionBlendWeights, this->restMesh_->vertices);
559-
doUpdateNormals = true;
560-
}
561-
if (doUpdateNormals) {
562-
this->restMesh_->updateNormals();
563-
}
564-
}
539+
} // namespace momentum
565540

566541
// Explicit template instantiations
567-
template class SkinnedLocatorTriangleErrorFunctionT<float>;
568-
template class SkinnedLocatorTriangleErrorFunctionT<double>;
569-
570-
} // namespace momentum
542+
template class momentum::SkinnedLocatorTriangleErrorFunctionT<float>;
543+
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)