From 5a970ee6e07ddb72d54c7e373256e9c3a595511d Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Thu, 6 Oct 2022 22:13:06 +0200 Subject: [PATCH 1/4] Add a function to skip immediately to the end of a playing camera path --- include/openspace/navigation/pathnavigator.h | 3 ++ src/navigation/pathnavigator.cpp | 48 ++++++++++++++------ src/navigation/pathnavigator_lua.inl | 5 ++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/include/openspace/navigation/pathnavigator.h b/include/openspace/navigation/pathnavigator.h index 681e7acc03..c684abbadf 100644 --- a/include/openspace/navigation/pathnavigator.h +++ b/include/openspace/navigation/pathnavigator.h @@ -72,6 +72,7 @@ public: void abortPath(); void pausePath(); void continuePath(); + void skipToEnd(); Path::Type defaultPathType() const; double minValidBoundingSphere() const; @@ -99,6 +100,8 @@ private: bool _isPlaying = false; bool _startSimulationTimeOnFinish = false; + bool _setCameraToEndNextFrame = false; + properties::OptionProperty _defaultPathType; properties::BoolProperty _includeRoll; properties::FloatProperty _speedScale; diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index 42e6ca9f33..7ab680b944 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -214,6 +214,18 @@ void PathNavigator::updateCamera(double deltaTime) { return; } + if (_setCameraToEndNextFrame) { + LDEBUG("Skipped to end of camera path"); + camera()->setPose(_currentPath->endPoint().pose()); + global::navigationHandler->orbitalNavigator().setFocusNode( + _currentPath->endPoint().nodeIdentifier(), + false + ); + handlePathEnd(); + _setCameraToEndNextFrame = false; + return; + } + // Prevent long delta times due to e.g. computations from other actions to cause // really big jumps in the motion along the path // OBS! Causes problems if the general FPS is lower than 10, but then the user should @@ -241,19 +253,6 @@ void PathNavigator::updateCamera(double deltaTime) { if (_currentPath->hasReachedEnd()) { LINFO("Reached target"); handlePathEnd(); - - if (_applyIdleBehaviorOnFinish) { - constexpr const char ApplyIdleBehaviorScript[] = - "openspace.setPropertyValueSingle(" - "'NavigationHandler.OrbitalNavigator.IdleBehavior.ApplyIdleBehavior'," - "true" - ");"; - - global::scriptEngine->queueScript( - ApplyIdleBehaviorScript, - openspace::scripting::ScriptEngine::RemoteScripting::Yes - ); - } return; } } @@ -368,6 +367,14 @@ void PathNavigator::continuePath() { _isPlaying = true; } +void PathNavigator::skipToEnd() { + if (!openspace::global::navigationHandler->pathNavigator().isPlayingPath()) { + LWARNING("No camera path is currently active"); + } + + _setCameraToEndNextFrame = true; +} + Path::Type PathNavigator::defaultPathType() const { return static_cast(_defaultPathType.value()); } @@ -430,15 +437,25 @@ const std::vector& PathNavigator::relevantNodes() { void PathNavigator::handlePathEnd() { _isPlaying = false; + global::openSpaceEngine->resetMode(); if (_startSimulationTimeOnFinish) { openspace::global::scriptEngine->queueScript( "openspace.time.setPause(false)", scripting::ScriptEngine::RemoteScripting::Yes ); + _startSimulationTimeOnFinish = false; + } + + if (_applyIdleBehaviorOnFinish) { + global::scriptEngine->queueScript( + "openspace.setPropertyValueSingle(" + "'NavigationHandler.OrbitalNavigator.IdleBehavior.ApplyIdleBehavior'," + "true" + ");", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); } - _startSimulationTimeOnFinish = false; - global::openSpaceEngine->resetMode(); } void PathNavigator::findRelevantNodes() { @@ -504,6 +521,7 @@ scripting::LuaLibrary PathNavigator::luaLibrary() { codegen::lua::ContinuePath, codegen::lua::PausePath, codegen::lua::StopPath, + codegen::lua::SkipToEnd, codegen::lua::FlyTo, codegen::lua::FlyToHeight, codegen::lua::FlyToNavigationState, diff --git a/src/navigation/pathnavigator_lua.inl b/src/navigation/pathnavigator_lua.inl index 0a60a57bbb..a2ade6c473 100644 --- a/src/navigation/pathnavigator_lua.inl +++ b/src/navigation/pathnavigator_lua.inl @@ -46,6 +46,11 @@ namespace { openspace::global::navigationHandler->pathNavigator().abortPath(); } +// Immediately skips to the end of the current camera path, if one is being played. +[[codegen::luawrap]] void skipToEnd() { + openspace::global::navigationHandler->pathNavigator().skipToEnd(); +} + /** * Move the camera to the node with the specified identifier. The optional double * specifies the duration of the motion, in seconds. If the optional bool is set to true From 819229222991caafb9759077efc1ffac88569306 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Thu, 6 Oct 2022 22:25:27 +0200 Subject: [PATCH 2/4] Move `findNodeNearTarget` function from path to pathnavigator To reduce conflicts between wisdome installation branch and master --- include/openspace/navigation/pathnavigator.h | 7 ++++ src/navigation/path.cpp | 39 +------------------- src/navigation/pathnavigator.cpp | 39 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/include/openspace/navigation/pathnavigator.h b/include/openspace/navigation/pathnavigator.h index c684abbadf..8f3d8d1895 100644 --- a/include/openspace/navigation/pathnavigator.h +++ b/include/openspace/navigation/pathnavigator.h @@ -80,6 +80,13 @@ public: const std::vector& relevantNodes(); + /** + * Find a node close to the given node. Closeness is determined by a factor times + * the bounding sphere of the object + * \return pointer to the SGN if one was found, nullptr otherwise + */ + static SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node); + /** * \return The Lua library that contains all Lua functions available to affect the * path navigation diff --git a/src/navigation/path.cpp b/src/navigation/path.cpp index 10b9004471..0b3fd62ed2 100644 --- a/src/navigation/path.cpp +++ b/src/navigation/path.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -440,50 +439,14 @@ Waypoint waypointFromCamera() { return Waypoint{ pos, rot, node }; } -SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node) { - const std::vector& relevantNodes = - global::navigationHandler->pathNavigator().relevantNodes(); - - for (SceneGraphNode* n : relevantNodes) { - bool isSame = (n->identifier() == node->identifier()); - // If the nodes are in the very same position, they are probably representing - // the same object - isSame |= - glm::distance(n->worldPosition(), node->worldPosition()) < LengthEpsilon; - - if (isSame) { - continue; - } - - constexpr float proximityRadiusFactor = 3.f; - - const float bs = static_cast(n->boundingSphere()); - const float proximityRadius = proximityRadiusFactor * bs; - const glm::dvec3 posInModelCoords = - glm::inverse(n->modelTransform()) * glm::dvec4(node->worldPosition(), 1.0); - - bool isClose = collision::isPointInsideSphere( - posInModelCoords, - glm::dvec3(0.0, 0.0, 0.0), - proximityRadius - ); - - if (isClose) { - return n; - } - } - - return nullptr; -} - // Compute a target position close to the specified target node, using knowledge of // the start point and a desired distance from the node's center glm::dvec3 computeGoodStepDirection(const SceneGraphNode* targetNode, const Waypoint& startPoint) { const glm::dvec3 nodePos = targetNode->worldPosition(); - const SceneGraphNode* closeNode = findNodeNearTarget(targetNode); const SceneGraphNode* sun = sceneGraphNode(SunIdentifier); + const SceneGraphNode* closeNode = PathNavigator::findNodeNearTarget(targetNode); // @TODO (2021-07-09, emmbr): Not nice to depend on a specific scene graph node, // as it might not exist. Ideally, each SGN could know about their preferred diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index 7ab680b944..a4b74cc394 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -497,6 +498,44 @@ void PathNavigator::findRelevantNodes() { _relevantNodes = resultingNodes; } + +SceneGraphNode* PathNavigator::findNodeNearTarget(const SceneGraphNode* node) { + constexpr float LengthEpsilon = 1e-5f; + const std::vector& relNodes = + global::navigationHandler->pathNavigator().relevantNodes(); + + for (SceneGraphNode* n : relNodes) { + bool isSame = (n->identifier() == node->identifier()); + // If the nodes are in the very same position, they are probably representing + // the same object + isSame |= + glm::distance(n->worldPosition(), node->worldPosition()) < LengthEpsilon; + + if (isSame) { + continue; + } + + constexpr float proximityRadiusFactor = 3.f; + + const float bs = static_cast(n->boundingSphere()); + const float proximityRadius = proximityRadiusFactor * bs; + const glm::dvec3 posInModelCoords = + glm::inverse(n->modelTransform()) * glm::dvec4(node->worldPosition(), 1.0); + + bool isClose = collision::isPointInsideSphere( + posInModelCoords, + glm::dvec3(0.0, 0.0, 0.0), + proximityRadius + ); + + if (isClose) { + return n; + } + } + + return nullptr; +} + void PathNavigator::removeRollRotation(CameraPose& pose, double deltaTime) { const glm::dvec3 anchorPos = anchor()->worldPosition(); const glm::dvec3 cameraDir = glm::normalize( From bcdeeef351e9f3957b849899419fc4fce978f5df Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Thu, 6 Oct 2022 22:28:08 +0200 Subject: [PATCH 3/4] Remove an extra line --- src/navigation/pathnavigator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index a4b74cc394..d1638cc7c4 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -498,7 +498,6 @@ void PathNavigator::findRelevantNodes() { _relevantNodes = resultingNodes; } - SceneGraphNode* PathNavigator::findNodeNearTarget(const SceneGraphNode* node) { constexpr float LengthEpsilon = 1e-5f; const std::vector& relNodes = From 06a22c25928ba3783694f0902fa505e96e44a367 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 7 Oct 2022 09:17:58 +0200 Subject: [PATCH 4/4] Fix problem with camera path not finishing properly on skipToEnd --- include/openspace/navigation/path.h | 6 ++++++ src/navigation/path.cpp | 5 +++++ src/navigation/pathnavigator.cpp | 1 + 3 files changed, 12 insertions(+) diff --git a/include/openspace/navigation/path.h b/include/openspace/navigation/path.h index a376684cd4..fc9fd79a0e 100644 --- a/include/openspace/navigation/path.h +++ b/include/openspace/navigation/path.h @@ -75,6 +75,12 @@ public: */ CameraPose traversePath(double dt, float speedScale = 1.f); + /** + * Function that can be used to permaturely quit a path ,for example when skipping + * to the end + */ + void quitPath(); + /** * Return the identifer of the node that is the current appropriate anchor node, of * the start and end waypoint's reference node. Dtermined based on how far along the diff --git a/src/navigation/path.cpp b/src/navigation/path.cpp index 0b3fd62ed2..48032b2d44 100644 --- a/src/navigation/path.cpp +++ b/src/navigation/path.cpp @@ -177,6 +177,11 @@ CameraPose Path::traversePath(double dt, float speedScale) { return newPose; } +void Path::quitPath() { + _traveledDistance = pathLength(); + _shouldQuit = true; +} + std::string Path::currentAnchor() const { bool pastHalfway = (_traveledDistance / pathLength()) > 0.5; return (pastHalfway) ? _end.nodeIdentifier() : _start.nodeIdentifier(); diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index d1638cc7c4..0caefdbfd4 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -217,6 +217,7 @@ void PathNavigator::updateCamera(double deltaTime) { if (_setCameraToEndNextFrame) { LDEBUG("Skipped to end of camera path"); + _currentPath->quitPath(); camera()->setPose(_currentPath->endPoint().pose()); global::navigationHandler->orbitalNavigator().setFocusNode( _currentPath->endPoint().nodeIdentifier(),