Skip to content

Commit

Permalink
Stub out necessary interface changes for new ModelWarperConfiguration…
Browse files Browse the repository at this point in the history
… design (#894 #891 #889)
  • Loading branch information
adamkewley committed Jul 3, 2024
1 parent daefd8f commit d1c144e
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/OpenSimCreator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ add_library(OpenSimCreator STATIC
Utils/SimTKHelpers.h
Utils/TPS3D.cpp
Utils/TPS3D.h
)
)

# OpenSimCreatorConfig.h
#
Expand Down
4 changes: 2 additions & 2 deletions src/OpenSimCreator/Documents/ModelWarper/IValidateable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

using namespace osc::mow;

ValidationCheckState osc::mow::IValidateable::implState() const
ValidationCheckState osc::mow::IValidateable::implState(const WarpableModel& root) const
{
ValidationCheckState worst = ValidationCheckState::Ok;
for (const auto& c : validate()) {
for (const auto& c : validate(root)) {
worst = max(worst, c.state());
if (worst == ValidationCheckState::Error) {
break;
Expand Down
15 changes: 10 additions & 5 deletions src/OpenSimCreator/Documents/ModelWarper/IValidateable.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

#include <vector>

namespace osc::mow { class WarpableModel; }

namespace osc::mow
{
// an interface to an object that can be runtime-validated
// an interface to an object that can be runtime-validated against the
// root document
class IValidateable {
protected:
IValidateable() = default;
Expand All @@ -19,10 +22,12 @@ namespace osc::mow
friend bool operator==(const IValidateable&, const IValidateable&) = default;
public:
virtual ~IValidateable() noexcept = default;
std::vector<ValidationCheckResult> validate() const { return implValidate(); }
ValidationCheckState state() const { return implState(); }
std::vector<ValidationCheckResult> validate(const WarpableModel& root) const { return implValidate(root); }
ValidationCheckState state(const WarpableModel& root) const { return implState(root); }

private:
virtual std::vector<ValidationCheckResult> implValidate() const { return {}; }
virtual ValidationCheckState implState() const; // by default, gets the least-valid entry returned by `validate()`
virtual std::vector<ValidationCheckResult> implValidate(const WarpableModel&) const { return {}; }
// by default, gets the least-valid entry returned by `validate()`
virtual ValidationCheckState implState(const WarpableModel&) const;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ std::vector<WarpDetail> osc::mow::IdentityFrameWarperFactory::implWarpDetails()
return {};
}

std::vector<ValidationCheckResult> osc::mow::IdentityFrameWarperFactory::implValidate() const
std::vector<ValidationCheckResult> osc::mow::IdentityFrameWarperFactory::implValidate(const WarpableModel&) const
{
return {
ValidationCheckResult{"this is an identity warp (i.e. it ignores warping this frame altogether)", ValidationCheckState::Warning},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace osc::mow
private:
std::unique_ptr<IFrameWarperFactory> implClone() const override;
std::vector<WarpDetail> implWarpDetails() const override;
std::vector<ValidationCheckResult> implValidate() const override;
std::vector<ValidationCheckResult> implValidate(const WarpableModel&) const override;
std::unique_ptr<IFrameWarper> implTryCreateFrameWarper(const WarpableModel&) const override;
};
}
142 changes: 139 additions & 3 deletions src/OpenSimCreator/Documents/ModelWarper/ModelWarperConfiguration.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#include <OpenSimCreator/Documents/ModelWarper/ICloneable.h>
#include <OpenSimCreator/Documents/ModelWarper/IValidateable.h>
#include <OpenSimCreator/Documents/ModelWarper/IWarpDetailProvider.h>

#include <OpenSim/Common/Component.h>
#include <OpenSim/Simulation/Model/PhysicalOffsetFrame.h>
#include <OpenSim/Simulation/Model/Station.h>
Expand Down Expand Up @@ -43,9 +47,46 @@ namespace osc::mow
State _state = State::None;
};

// an abstract interface to something that is capable of warping one specific component in
// the model
//
// a `ComponentWarpingStrategy` produces this after matching the component, validating it against,
// the rest of the model, etc.
class IComponentWarper {
protected:
IComponentWarper() = default;
IComponentWarper(const IComponentWarper&) = default;
IComponentWarper(IComponentWarper&&) noexcept = default;
IComponentWarper& operator=(const IComponentWarper&) = default;
IComponentWarper& operator=(IComponentWarper&&) noexcept = default;
public:
virtual ~IComponentWarper() noexcept = default;

void warpInPlace(const WarpableModel& model, const OpenSim::Component& source, OpenSim::Component& targetCopy)
{
implWarpInPlace(model, source, targetCopy);
}
private:
virtual void implWarpInPlace(const WarpableModel&, const OpenSim::Component& source, OpenSim::Component& targetCopy) = 0;
};

// concrete implementation of an `IComponentWarper` that does nothing
//
// (handy as a stand-in during development)
class IdentityComponentWarper : public IComponentWarper {
private:
void implWarpInPlace(const WarpableModel&, const OpenSim::Component&, OpenSim::Component&) override
{}
};

// abstract interface to a component that is capable of warping `n` other
// components (`StrategyTargets`) during a model warp
class ComponentWarpingStrategy : public OpenSim::Component {
class ComponentWarpingStrategy :
public OpenSim::Component,
public ICloneable<ComponentWarpingStrategy>,
public IWarpDetailProvider,
public IValidateable {

OpenSim_DECLARE_ABSTRACT_OBJECT(ComponentWarpingStrategy, OpenSim::Component);
public:
OpenSim_DECLARE_LIST_PROPERTY(StrategyTargets, std::string, "a sequence of strategy target strings that this strategy applies to");
Expand Down Expand Up @@ -91,24 +132,30 @@ namespace osc::mow
}
return best;
}

std::unique_ptr<IComponentWarper> createWarper(const WarpableModel& model, const OpenSim::Component& component)
{
return implCreateWarper(model, component);
}
private:
virtual const std::type_info& implGetTargetComponentTypeInfo() const = 0;
virtual bool implIsMatchForComponentType(const OpenSim::Component&) const = 0;
virtual std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) = 0;

void extendFinalizeFromProperties() override
{
assertStrategyTargetsNotEmpty();
assertStrategyTargetsAreUnique();
}

void assertStrategyTargetsNotEmpty()
void assertStrategyTargetsNotEmpty() const
{
if (getProperty_StrategyTargets().empty()) {
OPENSIM_THROW_FRMOBJ(OpenSim::Exception, "The <StrategyTargets> property of this component must be populated with at least one entry");
}
}

void assertStrategyTargetsAreUnique()
void assertStrategyTargetsAreUnique() const
{
const int numStrategyTargets = getProperty_StrategyTargets().size();
std::unordered_set<std::string_view> uniqueStrategyTargets;
Expand Down Expand Up @@ -158,20 +205,64 @@ namespace osc::mow
public:
// PointSources
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<ThinPlateSplineOnlyTranslationOffsetFrameWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// concrete implementation of an `OffsetFrameWarpingStrategy` in which the
// implementation should produce a halting error rather than continuing with
// the model warp
class ProduceErrorOffsetFrameWarpingStrategy final : public OffsetFrameWarpingStrategy {
OpenSim_DECLARE_CONCRETE_OBJECT(ProduceErrorOffsetFrameWarpingStrategy, OffsetFrameWarpingStrategy);
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<ProduceErrorOffsetFrameWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// concrete implementation of an `OffsetFrameWarpingStrategy` in which the implementation
// simply copies the `translation` and `rotation` of the source `OpenSim::PhysicalOffsetFrame` to
// the destination model with no modifications
class IdentityOffsetFrameWarpingStrategy final : public OffsetFrameWarpingStrategy {
OpenSim_DECLARE_CONCRETE_OBJECT(IdentityOffsetFrameWarpingStrategy, OffsetFrameWarpingStrategy);
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<IdentityOffsetFrameWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// abstract interface to a component that is capable of warping `n`
Expand All @@ -185,18 +276,63 @@ namespace osc::mow
class ThinPlateSplineStationWarpingStrategy final : public StationWarpingStrategy {
OpenSim_DECLARE_CONCRETE_OBJECT(ThinPlateSplineStationWarpingStrategy, StationWarpingStrategy);
// MeshSources
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<ThinPlateSplineStationWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// concrete implementation of a `StationWarpingStrategy` in which the implementation should
// produce a halting error rather than continuing with the model warp
class ProduceErrorStationWarpingStrategy final : public StationWarpingStrategy {
OpenSim_DECLARE_CONCRETE_OBJECT(ProduceErrorStationWarpingStrategy, StationWarpingStrategy);
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<ProduceErrorStationWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// concrete implementation of a `StationWarpingStrategy` in which the implementation should
// just copy the station's postion (+parent) without any modification
class IdentityStationWarpingStrategy final : public StationWarpingStrategy {
OpenSim_DECLARE_CONCRETE_OBJECT(IdentityStationWarpingStrategy, StationWarpingStrategy);
private:
std::unique_ptr<ComponentWarpingStrategy> implClone() const override
{
return std::make_unique<IdentityStationWarpingStrategy>(*this);
}

std::vector<WarpDetail> implWarpDetails() const override
{
return {};
}

std::unique_ptr<IComponentWarper> implCreateWarper(const WarpableModel&, const OpenSim::Component&) override
{
return std::make_unique<IdentityComponentWarper>();
}
};

// top-level model warping configuration file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ std::vector<WarpDetail> osc::mow::StationDefinedFrameWarperFactory::implWarpDeta
return {};
}

std::vector<ValidationCheckResult> osc::mow::StationDefinedFrameWarperFactory::implValidate() const
std::vector<ValidationCheckResult> osc::mow::StationDefinedFrameWarperFactory::implValidate(const WarpableModel&) const
{
return {
ValidationCheckResult{"this frame is automatically warped when the model warper warps all stations in the model", ValidationCheckState::Ok},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace osc::mow
private:
std::unique_ptr<IFrameWarperFactory> implClone() const override;
std::vector<WarpDetail> implWarpDetails() const override;
std::vector<ValidationCheckResult> implValidate() const override;
std::vector<ValidationCheckResult> implValidate(const WarpableModel&) const override;
std::unique_ptr<IFrameWarper> implTryCreateFrameWarper(const WarpableModel&) const override;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ std::vector<WarpDetail> osc::mow::TPSLandmarkPairWarperFactory::implWarpDetails(
return rv;
}

std::vector<ValidationCheckResult> osc::mow::TPSLandmarkPairWarperFactory::implValidate() const
std::vector<ValidationCheckResult> osc::mow::TPSLandmarkPairWarperFactory::implValidate(const WarpableModel&) const
{
std::vector<ValidationCheckResult> rv;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ namespace osc::mow
private:
std::unique_ptr<IPointWarperFactory> implClone() const override;
std::vector<WarpDetail> implWarpDetails() const override;
std::vector<ValidationCheckResult> implValidate() const override;
std::vector<ValidationCheckResult> implValidate(const WarpableModel&) const override;
std::unique_ptr<IPointWarper> implTryCreatePointWarper(const WarpableModel&) const override;

std::filesystem::path m_SourceMeshAbsoluteFilepath;
Expand Down
8 changes: 4 additions & 4 deletions src/OpenSimCreator/Documents/ModelWarper/WarpableModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ std::vector<WarpDetail> osc::mow::WarpableModel::details(const OpenSim::Mesh& me
std::vector<ValidationCheckResult> osc::mow::WarpableModel::validate(const OpenSim::Mesh& mesh) const
{
if (const IPointWarperFactory* p = m_MeshWarpLookup->find(GetAbsolutePathString(mesh))) {
return p->validate();
return p->validate(*this);
}
else {
return {ValidationCheckResult{"no mesh warp pairing found: this is probably an implementation error (try reloading?)", ValidationCheckState::Error}};
Expand All @@ -72,7 +72,7 @@ std::vector<ValidationCheckResult> osc::mow::WarpableModel::validate(const OpenS
ValidationCheckState osc::mow::WarpableModel::state(const OpenSim::Mesh& mesh) const
{
const IPointWarperFactory* p = m_MeshWarpLookup->find(GetAbsolutePathString(mesh));
return p ? p->state() : ValidationCheckState::Error;
return p ? p->state(*this) : ValidationCheckState::Error;
}

const IPointWarperFactory* osc::mow::WarpableModel::findMeshWarp(const OpenSim::Mesh& mesh) const
Expand All @@ -91,7 +91,7 @@ std::vector<WarpDetail> osc::mow::WarpableModel::details(const OpenSim::Physical
std::vector<ValidationCheckResult> osc::mow::WarpableModel::validate(const OpenSim::PhysicalOffsetFrame& pof) const
{
if (const IFrameWarperFactory* p = m_FrameWarpLookup->find(GetAbsolutePathString(pof))) {
return p->validate();
return p->validate(*this);
}
else {
return {ValidationCheckResult{"no frame warp method found: this is probably an implementation error (try reloading?)", ValidationCheckState::Error}};
Expand All @@ -102,7 +102,7 @@ ValidationCheckState osc::mow::WarpableModel::state(
const OpenSim::PhysicalOffsetFrame& pof) const
{
const IFrameWarperFactory* p = m_FrameWarpLookup->find(GetAbsolutePathString(pof));
return p ? p->state() : ValidationCheckState::Error;
return p ? p->state(*this) : ValidationCheckState::Error;
}

ValidationCheckState osc::mow::WarpableModel::state() const
Expand Down

0 comments on commit d1c144e

Please sign in to comment.