From 9e566efccedb0a3e0fb887d0fd0c8e4e77f3a89b Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 8 Jun 2021 10:25:18 +0200 Subject: [PATCH] More cleanup/restructuring --- modules/autonavigation/CMakeLists.txt | 2 - modules/autonavigation/atnodenavigator.cpp | 132 ------------------ modules/autonavigation/atnodenavigator.h | 66 --------- .../autonavigation/autonavigationhandler.cpp | 111 +++++++++++---- .../autonavigation/autonavigationhandler.h | 12 +- modules/autonavigation/pathinstruction.cpp | 61 ++++---- modules/autonavigation/pathinstruction.h | 39 +++--- 7 files changed, 145 insertions(+), 278 deletions(-) delete mode 100644 modules/autonavigation/atnodenavigator.cpp delete mode 100644 modules/autonavigation/atnodenavigator.h diff --git a/modules/autonavigation/CMakeLists.txt b/modules/autonavigation/CMakeLists.txt index cf12ac93c7..f731704e93 100644 --- a/modules/autonavigation/CMakeLists.txt +++ b/modules/autonavigation/CMakeLists.txt @@ -25,7 +25,6 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/atnodenavigator.h ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.h ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.h ${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.h @@ -40,7 +39,6 @@ set(HEADER_FILES source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/atnodenavigator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule_lua.inl diff --git a/modules/autonavigation/atnodenavigator.cpp b/modules/autonavigation/atnodenavigator.cpp deleted file mode 100644 index 3753d0446a..0000000000 --- a/modules/autonavigation/atnodenavigator.cpp +++ /dev/null @@ -1,132 +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 -#include -#include -#include -#include - -namespace { - constexpr const char* _loggerCat = "AtNodeNavigator"; - - constexpr const openspace::properties::Property::PropertyInfo OrbitSpeedFactorInfo = { - "OrbitSpeedFactor", - "Orbit Speed Factor", - "Controls the speed of the orbiting around an anchor." - }; -} // namespace - -namespace openspace::autonavigation { - -AtNodeNavigator::AtNodeNavigator() - : properties::PropertyOwner({ "AtNodeNavigator" }) - , _orbitSpeedFactor(OrbitSpeedFactorInfo, 0.5, 0.0, 20.0) -{ - addProperty(_orbitSpeedFactor); - _behavior = Behavior::None; -} - -AtNodeNavigator::~AtNodeNavigator() {} // NOLINT - -AtNodeNavigator::Behavior AtNodeNavigator::behavior() const { - return _behavior; -} - -void AtNodeNavigator::setBehavior(Behavior behavior) { - _behavior = behavior; -} - -void AtNodeNavigator::updateCamera(double deltaTime) { - switch (_behavior) - { - case Behavior::Orbit: - orbitNode(deltaTime); - break; - case Behavior::None: - // Do nothing - break; - default: - LERROR("Behavior type not implemented."); - break; - } -} - -Camera* AtNodeNavigator::camera() const { - return global::navigationHandler->camera(); -} - -const SceneGraphNode* AtNodeNavigator::anchor() const { - return global::navigationHandler->anchorNode(); -} - -// Move along the right vector for the camera, while looking at the center of the node -void AtNodeNavigator::orbitNode(double deltaTime) { - ghoul_assert(anchor() != nullptr, "Node to orbit must be set!") - const glm::dvec3 prevPosition = camera()->positionVec3(); - const glm::dquat prevRotation = camera()->rotationQuaternion(); - - const glm::dvec3 up = camera()->lookUpVectorWorldSpace(); - const double speedFactor = 0.1 * _orbitSpeedFactor; - - glm::dvec3 nodeCenter = anchor()->worldPosition(); - double orbitRadius = glm::distance(prevPosition, nodeCenter); - double distanceToSurface = orbitRadius - anchor()->boundingSphere(); - double orbitSpeed = distanceToSurface * speedFactor; - - // compute a new position along the orbit - const glm::dquat lookAtNodeRotation = helpers::lookAtQuaternion( - prevPosition, - nodeCenter, - up - ); - const glm::dvec3 targetForward = lookAtNodeRotation * glm::dvec3(0.0, 0.0, -1.0); - const glm::dvec3 rightOrbitTangent = glm::normalize(glm::cross(targetForward, up)); - - glm::dvec3 newPosition = prevPosition + orbitSpeed * deltaTime * rightOrbitTangent; - - // adjust for numerical error - const glm::dvec3 nodeToNewPos = newPosition - nodeCenter; - const double nodeToPrevPosDistance = glm::distance(prevPosition, nodeCenter); - const double distanceDiff = glm::length(nodeToNewPos) - nodeToPrevPosDistance; - newPosition -= distanceDiff * glm::normalize(nodeToNewPos); - - // rotate with the orbit, but keep the relative orientation with regards to the anchor - const glm::dquat localRotation = glm::inverse(lookAtNodeRotation) * prevRotation; - const glm::dquat newLookAtRotation = - helpers::lookAtQuaternion(newPosition, nodeCenter, up); - - const glm::dquat newRotation = newLookAtRotation * localRotation; - - camera()->setPositionVec3(newPosition); - camera()->setRotation(newRotation); -} - -} // namespace openspace::autonavigation diff --git a/modules/autonavigation/atnodenavigator.h b/modules/autonavigation/atnodenavigator.h deleted file mode 100644 index 4ce227e813..0000000000 --- a/modules/autonavigation/atnodenavigator.h +++ /dev/null @@ -1,66 +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___ATNODENAVIGATOR___H__ -#define __OPENSPACE_MODULE___ATNODENAVIGATOR___H__ - -#include -#include - -namespace openspace { - class Camera; - class SceneGraphNode; -} // namespace openspace - -namespace openspace::autonavigation { - -class AtNodeNavigator : public properties::PropertyOwner { -public: - enum Behavior { - None = 0, - Orbit, - }; - - AtNodeNavigator(); - ~AtNodeNavigator(); - - Behavior behavior() const; - void setBehavior(Behavior behavior); - - void updateCamera(double deltaTime); - -private: - Camera* camera() const; - const SceneGraphNode* anchor() const; - - //Behaviors - void orbitNode(double deltaTime); - - Behavior _behavior; - properties::DoubleProperty _orbitSpeedFactor; -}; - -} // namespace openspace::autonavigation - -#endif // __OPENSPACE_MODULE___ATNODENAVIGATOR___H__ diff --git a/modules/autonavigation/autonavigationhandler.cpp b/modules/autonavigation/autonavigationhandler.cpp index ab75873f2f..dc264ce1e2 100644 --- a/modules/autonavigation/autonavigationhandler.cpp +++ b/modules/autonavigation/autonavigationhandler.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -45,27 +44,28 @@ namespace { constexpr openspace::properties::Property::PropertyInfo DefaultCurveOptionInfo = { "DefaultCurveOption", "Default Curve Option", - "The defualt curve type chosen when generating a path, if none is specified." + "The defualt curve type chosen when generating a path, if none is specified" }; constexpr openspace::properties::Property::PropertyInfo IncludeRollInfo = { "IncludeRoll", "Include Roll", - "If disabled, roll is removed from the interpolation of camera orientation." + "If disabled, roll is removed from the interpolation of camera orientation" }; - constexpr openspace::properties::Property::PropertyInfo DefaultStopBehaviorInfo = { - "DefaultStopBehavior", - "Default Stop Behavior", - "The default camera behavior that is applied when the camera reaches and stops " - "at a target." + constexpr openspace::properties::Property::PropertyInfo StopBehaviorInfo = { + "StopBehavior", + "Stop Behavior", + "A camera motion behavior that is applied when no path is being played" }; - constexpr openspace::properties::Property::PropertyInfo ApplyStopBehaviorWhenIdleInfo = { + constexpr openspace::properties::Property::PropertyInfo + ApplyStopBehaviorWhenIdleInfo = + { "ApplyStopBehaviorWhenIdle", "Apply Stop Behavior When Idle", - "If enabled, the camera is controlled using the default stop behavior even when" - "no path is playing." + "If enabled, the camera is controlled using the set stop behavior when" + "no path is playing" }; constexpr openspace::properties::Property::PropertyInfo SpeedScaleInfo = { @@ -74,6 +74,11 @@ namespace { "Scale factor that affects the default speed for a camera path." }; + constexpr openspace::properties::Property::PropertyInfo OrbitSpeedFactorInfo = { + "OrbitSpeedFactor", + "Orbit Speed Factor", + "Controls the speed of the orbiting around an anchor." + }; } // namespace namespace openspace::autonavigation { @@ -86,14 +91,13 @@ AutoNavigationHandler::AutoNavigationHandler() ) , _includeRoll(IncludeRollInfo, false) , _stopBehavior( - DefaultStopBehaviorInfo, + StopBehaviorInfo, properties::OptionProperty::DisplayType::Dropdown ) , _applyStopBehaviorWhenIdle(ApplyStopBehaviorWhenIdleInfo, false) , _speedScale(SpeedScaleInfo, 1.f, 0.01f, 2.f) + , _orbitSpeedFactor(OrbitSpeedFactorInfo, 0.5, 0.0, 20.0) { - addPropertySubOwner(_atNodeNavigator); - _defaultCurveOption.addOptions({ { CurveType::AvoidCollision, "AvoidCollision" }, { CurveType::Linear, "Linear" }, @@ -108,16 +112,13 @@ AutoNavigationHandler::AutoNavigationHandler() // Must be listed in the same order as in enum definition _stopBehavior.addOptions({ - { AtNodeNavigator::Behavior::None, "None" }, - { AtNodeNavigator::Behavior::Orbit, "Orbit" } - }); - _stopBehavior = AtNodeNavigator::Behavior::None; - _stopBehavior.onChange([this]() { - _atNodeNavigator.setBehavior( - AtNodeNavigator::Behavior(_stopBehavior.value()) - ); + { StopBehavior::None, "None" }, + { StopBehavior::Orbit, "Orbit" } }); + _stopBehavior = StopBehavior::None; addProperty(_stopBehavior); + + addProperty(_orbitSpeedFactor); } AutoNavigationHandler::~AutoNavigationHandler() {} // NOLINT @@ -150,10 +151,9 @@ void AutoNavigationHandler::updateCamera(double deltaTime) { ghoul_assert(camera() != nullptr, "Camera must not be nullptr"); if (!_isPlaying) { - // For testing, apply at node behavior when idle - // @TODO: Determine how this should work instead + // TODO: Determine how this should work if (_applyStopBehaviorWhenIdle) { - _atNodeNavigator.updateCamera(deltaTime); + applyStopBehavior(deltaTime); } return; } @@ -199,7 +199,7 @@ void AutoNavigationHandler::createPath(PathInstruction& instruction) { // TODO: Improve how curve types are handled const int curveType = _defaultCurveOption; - std::vector waypoints = instruction.waypoints; + std::vector waypoints = instruction.waypoints(); Waypoint waypointToAdd; if (waypoints.empty()) { @@ -212,10 +212,10 @@ void AutoNavigationHandler::createPath(PathInstruction& instruction) { } _currentPath = std::make_unique( - instruction.startPoint, + instruction.startPoint(), waypointToAdd, CurveType(curveType), - instruction.duration + instruction.duration() ); LINFO("Successfully generated camera path"); @@ -367,4 +367,59 @@ void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTim pose.rotation = rollFreeRotation; } +void AutoNavigationHandler::applyStopBehavior(double deltaTime) { + switch (_stopBehavior) { + case StopBehavior::None: + // Do nothing + break; + case StopBehavior::Orbit: + orbitAnchorNode(deltaTime); + break; + default: + throw ghoul::MissingCaseException(); + } +} + +void AutoNavigationHandler::orbitAnchorNode(double deltaTime) { + ghoul_assert(anchor() != nullptr, "Node to orbit must be set!"); + + const glm::dvec3 prevPosition = camera()->positionVec3(); + const glm::dquat prevRotation = camera()->rotationQuaternion(); + + const glm::dvec3 up = camera()->lookUpVectorWorldSpace(); + const double speedFactor = 0.1 * _orbitSpeedFactor; + + glm::dvec3 nodeCenter = anchor()->worldPosition(); + double orbitRadius = glm::distance(prevPosition, nodeCenter); + double distanceToSurface = orbitRadius - anchor()->boundingSphere(); + double orbitSpeed = distanceToSurface * speedFactor; + + // compute a new position along the orbit + const glm::dquat lookAtNodeRotation = helpers::lookAtQuaternion( + prevPosition, + nodeCenter, + up + ); + const glm::dvec3 targetForward = lookAtNodeRotation * glm::dvec3(0.0, 0.0, -1.0); + const glm::dvec3 rightOrbitTangent = glm::normalize(glm::cross(targetForward, up)); + + glm::dvec3 newPosition = prevPosition + orbitSpeed * deltaTime * rightOrbitTangent; + + // adjust for numerical error + const glm::dvec3 nodeToNewPos = newPosition - nodeCenter; + const double nodeToPrevPosDistance = glm::distance(prevPosition, nodeCenter); + const double distanceDiff = glm::length(nodeToNewPos) - nodeToPrevPosDistance; + newPosition -= distanceDiff * glm::normalize(nodeToNewPos); + + // rotate with the orbit, but keep relative orientation with regards to the anchor + const glm::dquat localRotation = glm::inverse(lookAtNodeRotation) * prevRotation; + const glm::dquat newLookAtRotation = + helpers::lookAtQuaternion(newPosition, nodeCenter, up); + + const glm::dquat newRotation = newLookAtRotation * localRotation; + + camera()->setPositionVec3(newPosition); + camera()->setRotation(newRotation); +} + } // namespace openspace::autonavigation diff --git a/modules/autonavigation/autonavigationhandler.h b/modules/autonavigation/autonavigationhandler.h index f9fee22971..8040ebb46e 100644 --- a/modules/autonavigation/autonavigationhandler.h +++ b/modules/autonavigation/autonavigationhandler.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__ #define __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__ -#include #include #include #include @@ -43,6 +42,11 @@ struct PathInstruction; class AutoNavigationHandler : public properties::PropertyOwner { public: + enum StopBehavior { + None = 0, + Orbit + }; + AutoNavigationHandler(); ~AutoNavigationHandler(); @@ -71,15 +75,17 @@ public: private: void removeRollRotation(CameraPose& pose, double deltaTime); + void applyStopBehavior(double deltaTime); + + void orbitAnchorNode(double deltaTime); std::unique_ptr _currentPath = nullptr; - - AtNodeNavigator _atNodeNavigator; bool _isPlaying = false; properties::OptionProperty _defaultCurveOption; properties::BoolProperty _includeRoll; properties::FloatProperty _speedScale; + properties::FloatProperty _orbitSpeedFactor; // for testing pause behaviors. // TODO: remove later, if it causes problems with regular navigation diff --git a/modules/autonavigation/pathinstruction.cpp b/modules/autonavigation/pathinstruction.cpp index b065fde3ce..566beba40f 100644 --- a/modules/autonavigation/pathinstruction.cpp +++ b/modules/autonavigation/pathinstruction.cpp @@ -39,7 +39,6 @@ namespace { constexpr const char* _loggerCat = "PathInstruction"; constexpr const float Epsilon = 1e-5f; - struct [[codegen::Dictionary(Instruction)]] Parameters { enum class Type { Node, @@ -85,31 +84,27 @@ documentation::Documentation PathInstruction::Documentation() { PathInstruction::PathInstruction(const ghoul::Dictionary& dictionary) { const Parameters p = codegen::bake(dictionary); - duration = p.duration; + _duration = p.duration; bool hasStart = p.startState.has_value(); - startPoint = hasStart ? Waypoint(p.startState.value()) : waypointFromCamera(); + _startPoint = hasStart ? Waypoint(p.startState.value()) : waypointFromCamera(); switch (p.type) { case Parameters::Type::NavigationState: { - type = Type::NavigationState; - if (!p.navigationState.has_value()) { throw ghoul::RuntimeError("A navigation state is required"); } - navigationState = NavigationState(p.navigationState.value()); - waypoints = { Waypoint(navigationState) }; + NavigationState navigationState = NavigationState(p.navigationState.value()); + _waypoints = { Waypoint(navigationState) }; break; } case Parameters::Type::Node: { - type = Type::Node; - if (!p.target.has_value()) { throw ghoul::RuntimeError("A target node is required"); } - nodeIdentifier = p.target.value(); + std::string nodeIdentifier = p.target.value(); const SceneGraphNode* targetNode = sceneGraphNode(nodeIdentifier); if (!targetNode) { @@ -118,10 +113,14 @@ PathInstruction::PathInstruction(const ghoul::Dictionary& dictionary) { )); } - position = p.position; - height = p.height; - useTargetUpDirection = p.useTargetUpDirection.value_or(false); - waypoints = { computeDefaultWaypoint() }; + NodeInfo info { + nodeIdentifier, + p.position, + p.height, + p.useTargetUpDirection.value_or(false) + }; + + _waypoints = { computeDefaultWaypoint(info) }; break; } default: { @@ -132,6 +131,18 @@ PathInstruction::PathInstruction(const ghoul::Dictionary& dictionary) { } } +Waypoint PathInstruction::startPoint() const { + return _startPoint; +} + +std::vector PathInstruction::waypoints() const { + return _waypoints; +} + +std::optional PathInstruction::duration() const { + return _duration; +} + Waypoint PathInstruction::waypointFromCamera() const { Camera* camera = global::navigationHandler->camera(); const glm::dvec3 pos = camera->positionVec3(); @@ -142,19 +153,19 @@ Waypoint PathInstruction::waypointFromCamera() const { // OBS! The desired default waypoint may vary between curve types. // TODO: let the curves update the default position if no exact position is required -Waypoint PathInstruction::computeDefaultWaypoint() const { - const SceneGraphNode* targetNode = sceneGraphNode(nodeIdentifier); +Waypoint PathInstruction::computeDefaultWaypoint(const NodeInfo& info) const { + const SceneGraphNode* targetNode = sceneGraphNode(info.identifier); if (!targetNode) { - LERROR(fmt::format("Could not find target node '{}'", nodeIdentifier)); + LERROR(fmt::format("Could not find target node '{}'", info.identifier)); return Waypoint(); } glm::dvec3 targetPos; - if (position.has_value()) { + if (info.position.has_value()) { // Note that the anchor and reference frame is our targetnode. // The position in instruction is given is relative coordinates targetPos = targetNode->worldPosition() + - targetNode->worldRotationMatrix() * position.value(); + targetNode->worldRotationMatrix() * info.position.value(); } else { const glm::dvec3 nodePos = targetNode->worldPosition(); @@ -175,7 +186,7 @@ Waypoint PathInstruction::computeDefaultWaypoint() const { else { // Go to a point that is being lit up by the sun, slightly offsetted from sun // direction - const glm::dvec3 prevPos = startPoint.position(); + const glm::dvec3 prevPos = _startPoint.position(); const glm::dvec3 targetToPrev = prevPos - nodePos; const glm::dvec3 targetToSun = sunPos - nodePos; @@ -189,25 +200,23 @@ Waypoint PathInstruction::computeDefaultWaypoint() const { const double radius = Waypoint::findValidBoundingSphere(targetNode); const double defaultHeight = 2.0 * radius; - const double targetHeight = height.value_or(defaultHeight); + const double height = info.height.value_or(defaultHeight); - targetPos = nodePos + stepDirection * (radius + targetHeight); + targetPos = nodePos + stepDirection * (radius + height); } - // Up direction glm::dvec3 up = global::navigationHandler->camera()->lookUpVectorWorldSpace(); - if (useTargetUpDirection) { + if (info.useTargetUpDirection) { // @TODO (emmbr 2020-11-17) For now, this is hardcoded to look good for Earth, // which is where it matters the most. A better solution would be to make each // sgn aware of its own 'up' and query up = targetNode->worldRotationMatrix() * glm::dvec3(0.0, 0.0, 1.0); } - // Rotation const glm::dvec3 lookAtPos = targetNode->worldPosition(); const glm::dquat targetRot = helpers::lookAtQuaternion(targetPos, lookAtPos, up); - return Waypoint(targetPos, targetRot, nodeIdentifier); + return Waypoint(targetPos, targetRot, info.identifier); } // Test if the node lies within a given proximity radius of any relevant node in the scene diff --git a/modules/autonavigation/pathinstruction.h b/modules/autonavigation/pathinstruction.h index abe98bca42..21397445ab 100644 --- a/modules/autonavigation/pathinstruction.h +++ b/modules/autonavigation/pathinstruction.h @@ -31,36 +31,33 @@ namespace openspace::autonavigation { -struct PathInstruction { +class PathInstruction { +public: using NavigationState = interaction::NavigationHandler::NavigationState; - enum class Type { - Node, - NavigationState - }; - PathInstruction(const ghoul::Dictionary& dictionary); + Waypoint startPoint() const; + std::vector waypoints() const; + std::optional duration() const; + static documentation::Documentation Documentation(); +private: + struct NodeInfo { + std::string identifier; + std::optional position; + std::optional height; + bool useTargetUpDirection; + }; + Waypoint waypointFromCamera() const; - Waypoint computeDefaultWaypoint() const; + Waypoint computeDefaultWaypoint(const NodeInfo& info) const; SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node) const; - Type type; - - // Node details - std::string nodeIdentifier; - std::optional position; - std::optional height; - bool useTargetUpDirection; - - // Navigation state details - NavigationState navigationState; - - std::optional duration; - Waypoint startPoint; - std::vector waypoints; + Waypoint _startPoint; + std::vector _waypoints; + std::optional _duration; }; } // namespace openspace::autonavigation