diff --git a/include/openspace/navigation/pathnavigator.h b/include/openspace/navigation/pathnavigator.h index 082775b7b4..8e4801ae3f 100644 --- a/include/openspace/navigation/pathnavigator.h +++ b/include/openspace/navigation/pathnavigator.h @@ -74,6 +74,8 @@ public: Path::Type defaultPathType() const; double minValidBoundingSphere() const; + double findValidBoundingSphere(const SceneGraphNode* node) const; + const std::vector& relevantNodes(); /** diff --git a/include/openspace/navigation/waypoint.h b/include/openspace/navigation/waypoint.h index 2257242a31..39624bfd74 100644 --- a/include/openspace/navigation/waypoint.h +++ b/include/openspace/navigation/waypoint.h @@ -41,8 +41,6 @@ public: Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::string& ref); explicit Waypoint(const NavigationState& ns); - static double findValidBoundingSphere(const SceneGraphNode* node); - CameraPose pose() const; glm::dvec3 position() const; glm::dquat rotation() const; diff --git a/src/navigation/path.cpp b/src/navigation/path.cpp index 6bf807c5d9..1bd4eb3b30 100644 --- a/src/navigation/path.cpp +++ b/src/navigation/path.cpp @@ -498,9 +498,10 @@ Waypoint computeWaypointFromNodeInfo(const NodeInfo& info, const Waypoint& start ); } else { - const double radius = Waypoint::findValidBoundingSphere(targetNode); - const double defaultHeight = radius * - global::navigationHandler->pathNavigator().arrivalDistanceFactor(); + const PathNavigator& navigator = global::navigationHandler->pathNavigator(); + + const double radius = navigator.findValidBoundingSphere(targetNode); + const double defaultHeight = radius * navigator.arrivalDistanceFactor(); const double height = info.height.value_or(defaultHeight); const double distanceFromNodeCenter = radius + height; diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index 4ad7c1eda5..fb161cdedf 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -343,6 +343,49 @@ double PathNavigator::minValidBoundingSphere() const { return _minValidBoundingSphere; } +double PathNavigator::findValidBoundingSphere(const SceneGraphNode* node) const { + ghoul_assert(node != nullptr, "Node must not be nulltpr"); + auto sphere = [](const SceneGraphNode* n) { + // Use the biggest of the bounding sphere and interaction sphere, + // so we don't accidentally choose a bounding sphere that is much smaller + // than the interaction sphere of the node + double bs = n->boundingSphere(); + double is = n->interactionSphere(); + return is > bs ? is : bs; + }; + + double result = sphere(node); + + if (result < _minValidBoundingSphere) { + // If the bs of the target is too small, try to find a good value in a child node. + // Only check the closest children, to avoid deep traversal in the scene graph. + // Alsp. the chance to find a bounding sphere that represents the visual size of + // the target well is higher for these nodes + for (SceneGraphNode* child : node->children()) { + result = sphere(child); + if (result > _minValidBoundingSphere) { + LDEBUG(fmt::format( + "The scene graph node '{}' has no, or a very small, bounding sphere. " + "Using bounding sphere of child node '{}' in computations.", + node->identifier(), + child->identifier() + )); + return result; + } + } + + LDEBUG(fmt::format( + "The scene graph node '{}' has no, or a very small, bounding sphere. Using " + "minimal value. This might lead to unexpected results.", + node->identifier()) + ); + + result = _minValidBoundingSphere; + } + + return result; +} + const std::vector& PathNavigator::relevantNodes() { if (!_hasInitializedRelevantNodes) { findRelevantNodes(); diff --git a/src/navigation/waypoint.cpp b/src/navigation/waypoint.cpp index db4b2be596..7db02e9014 100644 --- a/src/navigation/waypoint.cpp +++ b/src/navigation/waypoint.cpp @@ -49,7 +49,9 @@ Waypoint::Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::stri LERROR(fmt::format("Could not find node '{}'", _nodeIdentifier)); return; } - _validBoundingSphere = findValidBoundingSphere(node); + + const PathNavigator& navigator = global::navigationHandler->pathNavigator(); + _validBoundingSphere = navigator.findValidBoundingSphere(node); } Waypoint::Waypoint(const NavigationState& ns) { @@ -61,7 +63,8 @@ Waypoint::Waypoint(const NavigationState& ns) { } _nodeIdentifier = ns.anchor; - _validBoundingSphere = findValidBoundingSphere(anchorNode); + const PathNavigator& navigator = global::navigationHandler->pathNavigator(); + _validBoundingSphere = navigator.findValidBoundingSphere(anchorNode); _pose = ns.cameraPose(); } @@ -89,41 +92,4 @@ double Waypoint::validBoundingSphere() const { return _validBoundingSphere; } -double Waypoint::findValidBoundingSphere(const SceneGraphNode* node) { - double bs = node->boundingSphere(); - - const double minValidBoundingSphere = - global::navigationHandler->pathNavigator().minValidBoundingSphere(); - - if (bs < minValidBoundingSphere) { - // If the bs of the target is too small, try to find a good value in a child node. - // Only check the closest children, to avoid deep traversal in the scene graph. - // Alsp. the chance to find a bounding sphere that represents the visual size of - // the target well is higher for these nodes - for (SceneGraphNode* child : node->children()) { - bs = child->boundingSphere(); - if (bs > minValidBoundingSphere) { - LDEBUG(fmt::format( - "The scene graph node '{}' has no, or a very small, bounding sphere. " - "Using bounding sphere of child node '{}' in computations.", - node->identifier(), - child->identifier() - )); - - return bs; - } - } - - LDEBUG(fmt::format( - "The scene graph node '{}' has no, or a very small, bounding sphere. Using " - "minimal value. This might lead to unexpected results.", - node->identifier()) - ); - - bs = minValidBoundingSphere; - } - - return bs; -} - } // namespace openspace::interaction