34 const OpenSim::Model& sourceModel,
35 const OpenSim::Model& resultModel,
36 const OpenSim::Mesh& sourceMesh,
37 const OpenSim::Mesh& resultMesh,
38 const OpenSim::Frame& sourceLandmarksFrame,
39 const OpenSim::Frame& resultLandmarksFrame,
41 bool compensateForFrameChanges)
47 const Transforms transforms = calculateTransforms(
50 sourceMesh.getFrame(),
51 resultMesh.getFrame(),
54 compensateForFrameChanges
60 resultModel.getWorkingState(),
65 auto vertices = resultOscMesh.
vertices();
66 for (
auto& vertex : vertices) {
67 vertex = transform_point(transforms.localToLandmarks, vertex);
69 static_assert(
alignof(
decltype(vertices.front())) ==
alignof(SimTK::fVec3));
70 static_assert(
sizeof(
decltype(vertices.front())) ==
sizeof(SimTK::fVec3));
71 auto* punned = std::launder(
reinterpret_cast<SimTK::fVec3*
>(vertices.data()));
73 for (
auto& vertex : vertices) {
74 vertex = transform_point(transforms.landmarksToLocal, vertex);
80 return std::make_unique<InMemoryMesh>(resultOscMesh);
84 const OpenSim::Model& sourceModel,
85 const OpenSim::Model& resultModel,
86 [[maybe_unused]]
const SimTK::Vec3& sourceLocation,
87 const SimTK::Vec3& resultLocation,
88 const OpenSim::Frame& sourceParentFrame,
89 const OpenSim::Frame& resultParentFrame,
90 const OpenSim::Frame& sourceLandmarksFrame,
91 const OpenSim::Frame& resultLandmarksFrame,
93 bool compensateForFrameChanges)
99 const Transforms transforms = calculateTransforms(
104 sourceLandmarksFrame,
105 resultLandmarksFrame,
106 compensateForFrameChanges
109 const auto resultLocationInLandmarkFrame = transform_point(transforms.localToLandmarks, osc::to<osc::Vector3>(resultLocation));
110 const auto warpedLocationInLandmarkFrame =
tps3d_warp_point(coefficients, osc::to<SimTK::fVec3>(resultLocationInLandmarkFrame),
static_cast<float>(tpsInputs.
blendingFactor));
111 return osc::to<SimTK::Vec3>(
osc::transform_point(transforms.landmarksToLocal, osc::to<osc::Vector3>(warpedLocationInLandmarkFrame)));
121 const SimTK::Vec<3, float> x = coefficients.
a2.normalize();
122 const SimTK::Vec<3, float> y = coefficients.
a3.normalize();
123 const SimTK::Vec<3, float> z = coefficients.
a4.normalize();
124 const SimTK::Mat33 rotationMatrix{
129 const SimTK::Rotation rotation{rotationMatrix};
130 const auto translation = osc::to<SimTK::Vec3>(coefficients.
a1);
131 return SimTK::Transform{rotation, translation};
134 void clear() { m_CoefficientCache.clear(); }
136 struct Transforms final {
141 Transforms calculateTransforms(
142 const OpenSim::Model& sourceModel,
143 const OpenSim::Model& resultModel,
144 const OpenSim::Frame& sourceFrame,
145 const OpenSim::Frame& resultFrame,
146 const OpenSim::Frame& sourceLandmarksFrame,
147 const OpenSim::Frame& resultLandmarksFrame,
148 bool compensateForFrameChanges)
const
150 const SimTK::Transform resultTransform = resultFrame.findTransformBetween(resultModel.getWorkingState(), resultLandmarksFrame);
152 if (compensateForFrameChanges) {
153 const SimTK::Transform sourceTransform = sourceFrame.findTransformBetween(sourceModel.getWorkingState(), sourceLandmarksFrame);
154 const SimTK::Transform frameWarpTransform = sourceTransform.invert() * resultTransform;
156 .localToLandmarks = osc::to<osc::Matrix4x4>(sourceTransform),
157 .landmarksToLocal = osc::to<osc::Matrix4x4>(frameWarpTransform.invert() * sourceTransform.invert()),
161 .localToLandmarks = osc::to<osc::Matrix4x4>(resultTransform),
162 .landmarksToLocal = osc::to<osc::Matrix4x4>(SimTK::Transform{resultTransform.invert()}),
167 const TPSCoefficients3D<float>& lookupTPSCoefficients(
const ThinPlateSplineCommonInputs& tpsInputs)
169 const auto [cacheEntry, inserted] = m_CoefficientCache.try_emplace(tpsInputs);
171 return cacheEntry->second;
179 TPSCoefficientSolverInputs3D<float> inputs;
180 inputs.landmarks.reserve(
osc::max(sourceLandmarks.size(), destinationLandmarks.size()));
181 TryPairingLandmarks(sourceLandmarks, destinationLandmarks, [&inputs, &tpsInputs](
const MaybeNamedLandmarkPair& p)
183 if (
auto landmark3d = p.tryGetPairedLocations()) {
184 landmark3d->source = tpsInputs.sourceLandmarksPrescale * landmark3d->source;
185 landmark3d->destination = tpsInputs.destinationLandmarksPrescale * landmark3d->destination;
186 inputs.landmarks.push_back(*landmark3d);
189 osc::log_warn(
"The landmarks {} could not be paired, might be missing in the source/destination?", p.name());
192 inputs.apply_affine_translation = tpsInputs.applyAffineTranslation;
193 inputs.apply_affine_scale = tpsInputs.applyAffineScale;
194 inputs.apply_affine_rotation = tpsInputs.applyAffineRotation;
195 inputs.apply_non_affine_warp = tpsInputs.applyNonAffineWarp;
196 inputs.warping_penalty =
static_cast<float>(tpsInputs.warpingPenalty);
201 return cacheEntry->second;
204 std::unordered_map<ThinPlateSplineCommonInputs, TPSCoefficients3D<float>> m_CoefficientCache;
SimTK::Vec3 lookupTPSWarpedRigidPoint(const OpenSim::Model &sourceModel, const OpenSim::Model &resultModel, const SimTK::Vec3 &sourceLocation, const SimTK::Vec3 &resultLocation, const OpenSim::Frame &sourceParentFrame, const OpenSim::Frame &resultParentFrame, const OpenSim::Frame &sourceLandmarksFrame, const OpenSim::Frame &resultLandmarksFrame, const ThinPlateSplineCommonInputs &tpsInputs, bool compensateForFrameChanges)
Definition scaling_cache.h:83
std::unique_ptr< InMemoryMesh > lookupTPSMeshWarp(const OpenSim::Model &sourceModel, const OpenSim::Model &resultModel, const OpenSim::Mesh &sourceMesh, const OpenSim::Mesh &resultMesh, const OpenSim::Frame &sourceLandmarksFrame, const OpenSim::Frame &resultLandmarksFrame, const ThinPlateSplineCommonInputs &tpsInputs, bool compensateForFrameChanges)
Definition scaling_cache.h:33
osc::Mesh ToOscMesh(osc::SceneCache &, const OpenSim::Model &, const SimTK::State &, const OpenSim::Mesh &, const OpenSimDecorationOptions &, float fixupScaleFactor)
constexpr auto max(Angle< Rep1, Units1 > x, Angle< Rep2, Units2 > y) -> std::common_type_t< decltype(x), decltype(y)>
Definition angle.h:300