From d80408303a2e7fb2722d117045ca8fa28e69b4f4 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 7 Jun 2021 14:12:41 +0200 Subject: [PATCH] Yet more tidying --- modules/autonavigation/CMakeLists.txt | 2 - .../curves/zoomoutoverviewcurve.cpp | 7 +- modules/autonavigation/helperfunctions.cpp | 40 ++++--- modules/autonavigation/helperfunctions.h | 2 + modules/autonavigation/path.cpp | 94 ++++++++++------ modules/autonavigation/path.h | 5 +- .../autonavigation/rotationinterpolator.cpp | 104 ------------------ modules/autonavigation/rotationinterpolator.h | 68 ------------ 8 files changed, 96 insertions(+), 226 deletions(-) delete mode 100644 modules/autonavigation/rotationinterpolator.cpp delete mode 100644 modules/autonavigation/rotationinterpolator.h diff --git a/modules/autonavigation/CMakeLists.txt b/modules/autonavigation/CMakeLists.txt index 5a6ce3719a..cf12ac93c7 100644 --- a/modules/autonavigation/CMakeLists.txt +++ b/modules/autonavigation/CMakeLists.txt @@ -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 diff --git a/modules/autonavigation/curves/zoomoutoverviewcurve.cpp b/modules/autonavigation/curves/zoomoutoverviewcurve.cpp index e3f9a71056..a3de584f13 100644 --- a/modules/autonavigation/curves/zoomoutoverviewcurve.cpp +++ b/modules/autonavigation/curves/zoomoutoverviewcurve.cpp @@ -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(); diff --git a/modules/autonavigation/helperfunctions.cpp b/modules/autonavigation/helperfunctions.cpp index bcd2d348b4..af555afd29 100644 --- a/modules/autonavigation/helperfunctions.cpp +++ b/modules/autonavigation/helperfunctions.cpp @@ -24,6 +24,7 @@ #include #include +#include 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 f) { - double h = (t1 - t0) / static_cast(n); + const double h = (t1 - t0) / static_cast(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& points, const std::vector& 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(); diff --git a/modules/autonavigation/helperfunctions.h b/modules/autonavigation/helperfunctions.h index 94ee236515..714ce67b86 100644 --- a/modules/autonavigation/helperfunctions.h +++ b/modules/autonavigation/helperfunctions.h @@ -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 diff --git a/modules/autonavigation/path.cpp b/modules/autonavigation/path.cpp index 8fe092b018..8449948310 100644 --- a/modules/autonavigation/path.cpp +++ b/modules/autonavigation/path.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include 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(_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!"); 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(); - _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 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(); 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 diff --git a/modules/autonavigation/path.h b/modules/autonavigation/path.h index 2c03b0a77f..fb9094bbc6 100644 --- a/modules/autonavigation/path.h +++ b/modules/autonavigation/path.h @@ -26,11 +26,8 @@ #define __OPENSPACE_MODULE___PATHSEGMENT___H__ #include -#include #include #include -#include -#include 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; std::unique_ptr _curve; // Playback variables diff --git a/modules/autonavigation/rotationinterpolator.cpp b/modules/autonavigation/rotationinterpolator.cpp deleted file mode 100644 index ff718df38f..0000000000 --- a/modules/autonavigation/rotationinterpolator.cpp +++ /dev/null @@ -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 - -#include -#include -#include -#include -#include - -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 diff --git a/modules/autonavigation/rotationinterpolator.h b/modules/autonavigation/rotationinterpolator.h deleted file mode 100644 index d85f4a4fcb..0000000000 --- a/modules/autonavigation/rotationinterpolator.h +++ /dev/null @@ -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 - -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__