Simplify speed function a bit (less object oriented)

This commit is contained in:
Emma Broman
2021-06-04 15:55:50 +02:00
parent 81b5821d0e
commit 7f9d8b8da6
4 changed files with 66 additions and 90 deletions

View File

@@ -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<glm::dvec3> 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<AvoidCollisionCurve>(_start, _end);
_rotationInterpolator = std::make_unique<EasedSlerpInterpolator>(
_start.rotation(),
_end.rotation()
);
_speedFunction = std::make_unique<QuinticDampenedSpeed>();
break;
case CurveType::Linear:
_curve = std::make_unique<LinearCurve>(_start, _end);
_rotationInterpolator = std::make_unique<EasedSlerpInterpolator>(
_start.rotation(),
_end.rotation()
);
_speedFunction = std::make_unique<QuinticDampenedSpeed>();
break;
case CurveType::ZoomOutOverview:
_curve = std::make_unique<ZoomOutOverviewCurve>(_start, _end);
_rotationInterpolator = std::make_unique<LookAtInterpolator>(
_start.rotation(),
_end.rotation(),
_start.node()->worldPosition(),
_end.node()->worldPosition(),
_curve.get()
);
_speedFunction = std::make_unique<QuinticDampenedSpeed>();
break;
default:
LERROR("Could not create curve. Type does not exist!");
return;
switch (_curveType) {
case CurveType::AvoidCollision:
_curve = std::make_unique<AvoidCollisionCurve>(_start, _end);
_rotationInterpolator = std::make_unique<EasedSlerpInterpolator>(
_start.rotation(),
_end.rotation()
);
break;
case CurveType::Linear:
_curve = std::make_unique<LinearCurve>(_start, _end);
_rotationInterpolator = std::make_unique<EasedSlerpInterpolator>(
_start.rotation(),
_end.rotation()
);
break;
case CurveType::ZoomOutOverview:
_curve = std::make_unique<ZoomOutOverviewCurve>(_start, _end);
_rotationInterpolator = std::make_unique<LookAtInterpolator>(
_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;
}

View File

@@ -65,7 +65,7 @@ private:
double _duration;
CurveType _curveType;
std::unique_ptr<SpeedFunction> _speedFunction;
SpeedFunction _speedFunction;
std::unique_ptr<RotationInterpolator> _rotationInterpolator;
std::unique_ptr<PathCurve> _curve;

View File

@@ -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;
}

View File

@@ -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