Yet more tidying

This commit is contained in:
Emma Broman
2021-06-07 14:12:41 +02:00
parent 50397cdafe
commit d80408303a
8 changed files with 96 additions and 226 deletions

View File

@@ -32,7 +32,6 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/path.h
${CMAKE_CURRENT_SOURCE_DIR}/pathcurve.h
${CMAKE_CURRENT_SOURCE_DIR}/pathinstruction.h
${CMAKE_CURRENT_SOURCE_DIR}/rotationinterpolator.h
${CMAKE_CURRENT_SOURCE_DIR}/speedfunction.h
${CMAKE_CURRENT_SOURCE_DIR}/waypoint.h
${CMAKE_CURRENT_SOURCE_DIR}/curves/avoidcollisioncurve.h
@@ -49,7 +48,6 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/path.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pathcurve.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pathinstruction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotationinterpolator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/speedfunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/waypoint.cpp
${CMAKE_CURRENT_SOURCE_DIR}/curves/avoidcollisioncurve.cpp

View File

@@ -38,7 +38,6 @@
namespace {
constexpr const char* _loggerCat = "ZoomOutOverviewCurve";
} // namespace
namespace openspace::autonavigation {
@@ -48,9 +47,9 @@ ZoomOutOverviewCurve::ZoomOutOverviewCurve(const Waypoint& start, const Waypoint
const double startNodeRadius = start.nodeDetails.validBoundingSphere;
const double endNodeRadius = end.nodeDetails.validBoundingSphere;
const double endsTangetLengthFactor = 2.0;
const double startTangentLength = endsTangetLengthFactor * startNodeRadius;
const double endTangentLength = endsTangetLengthFactor * endNodeRadius;
const double endTangentsLengthFactor = 2.0;
const double startTangentLength = endTangentsLengthFactor * startNodeRadius;
const double endTangentLength = endTangentsLengthFactor * endNodeRadius;
const glm::dvec3 startNodePos = start.node()->worldPosition();
const glm::dvec3 endNodePos = end.node()->worldPosition();

View File

@@ -24,6 +24,7 @@
#include <modules/autonavigation/helperfunctions.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/easing.h>
namespace {
constexpr const char* _loggerCat = "Helpers";
@@ -79,7 +80,7 @@ namespace openspace::autonavigation::helpers {
}
else {
// only care about the first intersection point if we have two
double t = (-b - std::sqrt(intersectionTest)) / (2.0 *a);
const double t = (-b - std::sqrt(intersectionTest)) / (2.0 *a);
if (t <= Epsilon || t >= abs(1.0 - Epsilon)) return false;
@@ -89,20 +90,18 @@ namespace openspace::autonavigation::helpers {
}
bool isPointInsideSphere(const glm::dvec3& p, const glm::dvec3& c, double r) {
glm::dvec3 v = c - p;
long double squaredDistance = v.x * v.x + v.y * v.y + v.z * v.z;
long double squaredRadius = r * r;
if (squaredDistance <= squaredRadius) {
return true;
}
return false;
const glm::dvec3 v = c - p;
const long double squaredDistance = v.x * v.x + v.y * v.y + v.z * v.z;
const long double squaredRadius = r * r;
return (squaredDistance <= squaredRadius);
}
double simpsonsRule(double t0, double t1, int n, std::function<double(double)> f) {
double h = (t1 - t0) / static_cast<double>(n);
const double h = (t1 - t0) / static_cast<double>(n);
const double endpoints = f(t0) + f(t1);
double times4 = 0.0;
double times2 = 0.0;
double endpoints = f(t0) + f(t1);
// weight 4
for (int i = 1; i < n; i += 2) {
@@ -154,6 +153,12 @@ namespace openspace::autonavigation::helpers {
namespace openspace::autonavigation::interpolation {
glm::dquat easedSlerp(const glm::dquat q1, const glm::dquat q2, double t) {
double tScaled = helpers::shiftAndScale(t, 0.1, 0.9);
tScaled = ghoul::sineEaseInOut(tScaled);
return glm::slerp(q1, q2, tScaled);
}
// Based on implementation by Mika Rantanen
// https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
glm::dvec3 catmullRom(double t, const glm::dvec3& p0, const glm::dvec3& p1,
@@ -225,10 +230,19 @@ namespace openspace::autonavigation::interpolation {
glm::dvec3 piecewiseCubicBezier(double t, const std::vector<glm::dvec3>& points,
const std::vector<double>& tKnots)
{
ghoul_assert(points.size() > 4, "Minimum of four control points needed for interpolation!");
ghoul_assert((points.size() - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!");
ghoul_assert(
points.size() > 4,
"Minimum of four control points needed for interpolation"
);
ghoul_assert(
(points.size() - 1) % 3 == 0,
"A vector containing 3n + 1 control points must be provided"
);
int nrSegments = (points.size() - 1) / 3;
ghoul_assert(nrSegments == (tKnots.size() - 1), "Number of interval times must match number of segments");
ghoul_assert(
rSegments == (tKnots.size() - 1),
"Number of interval times must match number of segments"
);
if (t <= 0.0) return points.front();
if (t >= 1.0) return points.back();

View File

@@ -55,6 +55,8 @@ namespace openspace::autonavigation::helpers {
namespace openspace::autonavigation::interpolation {
glm::dquat easedSlerp(const glm::dquat q1, const glm::dquat q2, double t);
// TODO: make all these into template functions.
// Alternatively, add cubicBezier interpolation in ghoul and only use
// ghoul's interpolator methods

View File

@@ -27,7 +27,6 @@
#include <modules/autonavigation/autonavigationmodule.h>
#include <modules/autonavigation/helperfunctions.h>
#include <modules/autonavigation/pathcurve.h>
#include <modules/autonavigation/rotationinterpolator.h>
#include <modules/autonavigation/speedfunction.h>
#include <modules/autonavigation/curves/avoidcollisioncurve.h>
#include <modules/autonavigation/curves/zoomoutoverviewcurve.h>
@@ -35,6 +34,7 @@
#include <openspace/engine/moduleengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/interpolator.h>
namespace {
constexpr const char* _loggerCat = "Path";
@@ -49,45 +49,27 @@ Path::Path(Waypoint start, Waypoint end, CurveType type,
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!");
throw ghoul::MissingCaseException();
return;
}
_speedFunction = SpeedFunction(SpeedFunction::Type::DampenedQuintic);
if (duration.has_value()) {
_duration = duration.value();
}
else {
_duration = std::log(pathLength());
const auto defaultDuration = [](double pathlength) {
auto module = global::moduleEngine->module<AutoNavigationModule>();
_duration /= module->AutoNavigationHandler().speedScale();
}
const double speedScale = module->AutoNavigationHandler().speedScale();
return std::log(pathlength) / speedScale;
};
_duration = duration.value_or(defaultDuration(pathLength()));
}
Waypoint Path::startPoint() const { return _start; }
@@ -103,11 +85,6 @@ std::vector<glm::dvec3> Path::controlPoints() const {
}
CameraPose Path::traversePath(double dt) {
if (!_curve || !_rotationInterpolator) {
// TODO: handle better (abort path somehow)
return _start.pose;
}
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
AutoNavigationHandler& handler = module->AutoNavigationHandler();
const int nSteps = handler.integrationResolutionPerFrame();
@@ -142,8 +119,63 @@ CameraPose Path::interpolatedPose(double distance) const {
double u = distance / pathLength();
CameraPose cs;
cs.position = _curve->positionAt(u);
cs.rotation = _rotationInterpolator->interpolate(u);
cs.rotation = interpolateRotation(u);
return cs;
}
glm::dquat Path::interpolateRotation(double u) const {
switch (_curveType) {
case CurveType::AvoidCollision:
case CurveType::Linear:
return interpolation::easedSlerp(_start.rotation(), _end.rotation(), u);
case CurveType::ZoomOutOverview:
{
const double u1 = 0.2;
const double u2 = 0.8;
const glm::dvec3 startPos = _curve->positionAt(0.0);
const glm::dvec3 endPos = _curve->positionAt(1.0);
const glm::dvec3 startNodePos = _start.node()->worldPosition();
const glm::dvec3 endNodePos = _end.node()->worldPosition();
glm::dvec3 lookAtPos;
if (u < u1) {
// Compute a position in front of the camera at the start orientation
const double inFrontDistance = glm::distance(startPos, startNodePos);
const glm::dvec3 viewDir = helpers::viewDirection(_start.rotation());
const glm::dvec3 inFrontOfStart = startPos + inFrontDistance * viewDir;
double uScaled = ghoul::cubicEaseInOut(u / u1);
lookAtPos =
ghoul::interpolateLinear(uScaled, inFrontOfStart, startNodePos);
}
else if (u <= u2) {
double uScaled = ghoul::cubicEaseInOut((u - u1) / (u2 - u1));
lookAtPos = ghoul::interpolateLinear(uScaled, startNodePos, endNodePos);
}
else if (u2 < u) {
// Compute a position in front of the camera at the end orientation
const double inFrontDistance = glm::distance(endPos, endNodePos);
const glm::dvec3 viewDir = helpers::viewDirection(_end.rotation());
const glm::dvec3 inFrontOfEnd = endPos + inFrontDistance * viewDir;
double uScaled = ghoul::cubicEaseInOut((u - u2) / (1.0 - u2));
lookAtPos = ghoul::interpolateLinear(uScaled, endNodePos, inFrontOfEnd);
}
// Handle up vector separately
glm::dvec3 startUp = _start.rotation() * glm::dvec3(0.0, 1.0, 0.0);
glm::dvec3 endUp = _end.rotation() * glm::dvec3(0.0, 1.0, 0.0);
double uUp = helpers::shiftAndScale(u, u1, u2);
uUp = ghoul::sineEaseInOut(uUp);
glm::dvec3 up = ghoul::interpolateLinear(uUp, startUp, endUp);
return helpers::lookAtQuaternion(_curve->positionAt(u), lookAtPos, up);
}
default:
throw ghoul::MissingCaseException();
}
}
} // namespace openspace::autonavigation

View File

@@ -26,11 +26,8 @@
#define __OPENSPACE_MODULE___PATHSEGMENT___H__
#include <modules/autonavigation/pathcurve.h>
#include <modules/autonavigation/rotationinterpolator.h>
#include <modules/autonavigation/speedfunction.h>
#include <modules/autonavigation/waypoint.h>
#include <ghoul/glm.h>
#include <vector>
namespace openspace::autonavigation {
@@ -56,6 +53,7 @@ public:
private:
double speedAtTime(double time) const;
glm::dquat interpolateRotation(double u) const;
Waypoint _start;
Waypoint _end;
@@ -63,7 +61,6 @@ private:
CurveType _curveType;
SpeedFunction _speedFunction;
std::unique_ptr<RotationInterpolator> _rotationInterpolator;
std::unique_ptr<PathCurve> _curve;
// Playback variables

View File

@@ -1,104 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/autonavigation/rotationinterpolator.h>
#include <modules/autonavigation/helperfunctions.h>
#include <modules/autonavigation/pathcurve.h>
#include <modules/autonavigation/waypoint.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/interpolator.h>
namespace {
constexpr const char* _loggerCat = "RotationInterpolator";
} // namespace
namespace openspace::autonavigation {
RotationInterpolator::RotationInterpolator(const glm::dquat start, const glm::dquat end)
: _start(start), _end(end)
{}
EasedSlerpInterpolator::EasedSlerpInterpolator(glm::dquat start, glm::dquat end)
: RotationInterpolator(start, end)
{}
glm::dquat EasedSlerpInterpolator::interpolate(double u) {
double uScaled = helpers::shiftAndScale(u, 0.1, 0.9);
uScaled = ghoul::sineEaseInOut(uScaled);
return glm::slerp(_start, _end, uScaled);
}
LookAtInterpolator::LookAtInterpolator(glm::dquat start, glm::dquat end,
glm::dvec3 startLookAtPos,
glm::dvec3 endLookAtPos,
PathCurve* path)
: RotationInterpolator(start, end),
_startLookAtPos(startLookAtPos),
_endLookAtPos(endLookAtPos),
_path(path)
{}
// Turn towards start node, turn towards end node, then turn to end view
glm::dquat LookAtInterpolator::interpolate(double u) {
//TODO: base on curve position?
const double u1 = 0.2;
const double u2 = 0.8;
const glm::dvec3 startPosition = _path->positionAt(0.0);
const glm::dvec3 endPosition = _path->positionAt(1.0);
glm::dvec3 lookAtPos;
if (u < u1) {
const glm::dvec3 startViewDir = helpers::viewDirection(_start);
const double startViewDist = glm::length(startPosition - _startLookAtPos);
const glm::dvec3 startViewPos = startPosition + startViewDist * startViewDir;
double uNew = ghoul::cubicEaseInOut(u / u1);
lookAtPos = ghoul::interpolateLinear(uNew, startViewPos, _startLookAtPos);
}
else if (u <= u2) {
double uNew = ghoul::cubicEaseInOut((u - u1) / (u2 - u1));
lookAtPos = ghoul::interpolateLinear(uNew, _startLookAtPos, _endLookAtPos);
}
else if (u2 < u) {
const glm::dvec3 endViewDir = helpers::viewDirection(_end);
const double endViewDist = glm::length(endPosition - _endLookAtPos);
const glm::dvec3 endViewPos = endPosition + endViewDist * endViewDir;
double uNew = ghoul::cubicEaseInOut((u - u2) / (1.0 - u2));
lookAtPos = ghoul::interpolateLinear(uNew, _endLookAtPos, endViewPos);
}
// Handle up vector separately
glm::dvec3 startUp = _start * glm::dvec3(0.0, 1.0, 0.0);
glm::dvec3 endUp = _end * glm::dvec3(0.0, 1.0, 0.0);
double uUp = helpers::shiftAndScale(u, u1, u2);
uUp = ghoul::sineEaseInOut(uUp);
glm::dvec3 up = ghoul::interpolateLinear(uUp, startUp, endUp);
return helpers::lookAtQuaternion(_path->positionAt(u), lookAtPos, up);
}
} // namespace openspace::autonavigation

View File

@@ -1,68 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_AUTONAVIGATION___ROTATIONINTERPOLATOR___H__
#define __OPENSPACE_MODULE_AUTONAVIGATION___ROTATIONINTERPOLATOR___H__
#include <ghoul/glm.h>
namespace openspace::autonavigation {
class PathCurve;
class RotationInterpolator {
public:
RotationInterpolator() = default;
RotationInterpolator(glm::dquat start, glm::dquat end);
virtual glm::dquat interpolate(double u) = 0;
protected:
glm::dquat _start;
glm::dquat _end;
};
class EasedSlerpInterpolator : public RotationInterpolator {
public:
EasedSlerpInterpolator(glm::dquat start, glm::dquat end);
glm::dquat interpolate(double u);
};
// Interpolates a look at position for the camera, and takes the start and end rotation
// into account
class LookAtInterpolator : public RotationInterpolator {
public:
LookAtInterpolator(glm::dquat start, glm::dquat end, glm::dvec3 startLookAtPos,
glm::dvec3 endLookAtPos, PathCurve* path);
glm::dquat interpolate(double u);
private:
glm::dvec3 _startLookAtPos;
glm::dvec3 _endLookAtPos;
PathCurve* _path = nullptr;
};
} // namespace openspace::autonavigation
#endif // __OPENSPACE_MODULE_AUTONAVIGATION___ROTATIONINTERPOLATOR___H__