diff --git a/modules/autonavigation/path.cpp b/modules/autonavigation/path.cpp index 7089a979c0..9ca49d3ee5 100644 --- a/modules/autonavigation/path.cpp +++ b/modules/autonavigation/path.cpp @@ -49,6 +49,8 @@ Path::Path(Waypoint start, Waypoint end, CurveType type, { initializePath(); + _speedFunction = SpeedFunction(SpeedFunction::Type::DampenedQuintic); + if (duration.has_value()) { _duration = duration.value(); } @@ -79,7 +81,7 @@ const std::vector Path::controlPoints() const { } CameraPose Path::traversePath(double dt) { - if (!_curve || !_rotationInterpolator || !_speedFunction) { + if (!_curve || !_rotationInterpolator) { // TODO: handle better (abort path somehow) return _start.pose; } @@ -111,7 +113,7 @@ bool Path::hasReachedEnd() const { } double Path::speedAtTime(double time) const { - return _speedFunction->scaledValue(time, _duration, pathLength()); + return _speedFunction.scaledValue(time, _duration, pathLength()); } CameraPose Path::interpolatedPose(double distance) const { @@ -125,44 +127,37 @@ CameraPose Path::interpolatedPose(double distance) const { void Path::initializePath() { _curve.reset(); - switch (_curveType) - { - case CurveType::AvoidCollision: - _curve = std::make_unique(_start, _end); - _rotationInterpolator = std::make_unique( - _start.rotation(), - _end.rotation() - ); - _speedFunction = std::make_unique(); - break; - - case CurveType::Linear: - _curve = std::make_unique(_start, _end); - _rotationInterpolator = std::make_unique( - _start.rotation(), - _end.rotation() - ); - _speedFunction = std::make_unique(); - break; - - case CurveType::ZoomOutOverview: - _curve = std::make_unique(_start, _end); - _rotationInterpolator = std::make_unique( - _start.rotation(), - _end.rotation(), - _start.node()->worldPosition(), - _end.node()->worldPosition(), - _curve.get() - ); - _speedFunction = std::make_unique(); - break; - - default: - LERROR("Could not create curve. Type does not exist!"); - return; + switch (_curveType) { + case CurveType::AvoidCollision: + _curve = std::make_unique(_start, _end); + _rotationInterpolator = std::make_unique( + _start.rotation(), + _end.rotation() + ); + break; + case CurveType::Linear: + _curve = std::make_unique(_start, _end); + _rotationInterpolator = std::make_unique( + _start.rotation(), + _end.rotation() + ); + break; + case CurveType::ZoomOutOverview: + _curve = std::make_unique(_start, _end); + _rotationInterpolator = std::make_unique( + _start.rotation(), + _end.rotation(), + _start.node()->worldPosition(), + _end.node()->worldPosition(), + _curve.get() + ); + break; + default: + LERROR("Could not create curve. Type does not exist!"); + return; } - if (!_curve || !_rotationInterpolator || !_speedFunction) { + if (!_curve || !_rotationInterpolator) { LERROR("Curve type has not been properly initialized."); return; } diff --git a/modules/autonavigation/path.h b/modules/autonavigation/path.h index 7eb18a5cf7..f02a9ac446 100644 --- a/modules/autonavigation/path.h +++ b/modules/autonavigation/path.h @@ -65,7 +65,7 @@ private: double _duration; CurveType _curveType; - std::unique_ptr _speedFunction; + SpeedFunction _speedFunction; std::unique_ptr _rotationInterpolator; std::unique_ptr _curve; diff --git a/modules/autonavigation/speedfunction.cpp b/modules/autonavigation/speedfunction.cpp index 614ccd2e71..9144a46aef 100644 --- a/modules/autonavigation/speedfunction.cpp +++ b/modules/autonavigation/speedfunction.cpp @@ -35,6 +35,10 @@ namespace { namespace openspace::autonavigation { +SpeedFunction::SpeedFunction(Type type) : _type(type) { + initializeIntegratedSum(); +} + SpeedFunction::~SpeedFunction() {} /* @@ -49,7 +53,7 @@ double SpeedFunction::scaledValue(double time, double duration, double pathLengt return (pathLength * this->value(t)) / (duration * _integratedSum); } -void SpeedFunction::initIntegratedSum() { +void SpeedFunction::initializeIntegratedSum() { const int steps = 100; _integratedSum = helpers::simpsonsRule( 0.0, @@ -59,54 +63,36 @@ void SpeedFunction::initIntegratedSum() { ); } -SexticDampenedSpeed::SexticDampenedSpeed() { - initIntegratedSum(); -} - -double SexticDampenedSpeed::value(double t) const { +double SpeedFunction::value(double t) const { ghoul_assert(t >= 0.0 && t <= 1.0, "Variable t out of range [0,1]"); const double tPeak = 0.5; double speed = 0.0; - // accelerate + auto applyEasingFunction = [this](double tScaled) { + switch (_type) { + case Type::DampenedQuintic: + return ghoul::cubicEaseInOut(ghoul::quadraticEaseInOut(tScaled)); + break; + case Type::DampenedSextic: + return ghoul::cubicEaseInOut(ghoul::cubicEaseInOut(tScaled)); + default: + throw ghoul::MissingCaseException(); + } + }; + + // Accelerate if (t <= tPeak) { double tScaled = t / tPeak; - speed = ghoul::cubicEaseInOut(ghoul::cubicEaseInOut(tScaled)); + speed = applyEasingFunction(tScaled); } - // deaccelerate + // Deccelerate else if (t <= 1.0) { double tScaled = (t - tPeak) / (1.0 - tPeak); - speed = 1.0 - ghoul::cubicEaseInOut(ghoul::cubicEaseInOut(tScaled)); + speed = 1.0 - applyEasingFunction(tScaled); } - // avoid zero speed - speed += 0.00001; // TODO: Minimal speed should depend on size of visible object/node - return speed; -} - -QuinticDampenedSpeed::QuinticDampenedSpeed() { - initIntegratedSum(); -} - -double QuinticDampenedSpeed::value(double t) const { - ghoul_assert(t >= 0.0 && t <= 1.0, "Variable t out of range [0,1]"); - - const double tPeak = 0.5; - double speed = 0.0; - - // accelerate - if (t <= tPeak) { - double tScaled = t / tPeak; - speed = ghoul::cubicEaseInOut(ghoul::quadraticEaseInOut(tScaled)); - } - // deaccelerate - else if (t <= 1.0) { - double tScaled = (t - tPeak) / (1.0 - tPeak); - speed = 1.0 - ghoul::cubicEaseInOut(ghoul::quadraticEaseInOut(tScaled)); - } - - // avoid zero speed + // Avoid zero speed speed += 0.00001; // TODO: Minimal speed should depend on size of visible object/node return speed; } diff --git a/modules/autonavigation/speedfunction.h b/modules/autonavigation/speedfunction.h index dc699855ab..1d1f0c57e0 100644 --- a/modules/autonavigation/speedfunction.h +++ b/modules/autonavigation/speedfunction.h @@ -30,32 +30,27 @@ namespace openspace::autonavigation { // The speed function describing the shape of the speed curve. Values in [0,1]. class SpeedFunction { public: - SpeedFunction() = default; + enum class Type { + DampenedQuintic, + DampenedSextic + }; + + SpeedFunction(Type type = Type::DampenedQuintic); virtual ~SpeedFunction(); double scaledValue(double time, double duration, double pathLength) const; - virtual double value(double t) const = 0; + virtual double value(double t) const; protected: // must be called by each subclass after initialization - void initIntegratedSum(); + void initializeIntegratedSum(); // store the sum of the function over the duration of the segment, // so we don't need to recompue it every time we access the speed double _integratedSum = 0.0; -}; -class SexticDampenedSpeed : public SpeedFunction { -public: - SexticDampenedSpeed(); - double value(double t) const override; -}; - -class QuinticDampenedSpeed : public SpeedFunction { -public: - QuinticDampenedSpeed(); - double value(double t) const override; + Type _type; }; } // namespace openspace::autonavigation