Use largest of boudning and interaction sphere for creating camera path (closes #1897)

This commit is contained in:
Emma Broman
2022-03-02 10:52:03 +01:00
parent 0c86254168
commit a0433c0419
5 changed files with 54 additions and 44 deletions

View File

@@ -74,6 +74,8 @@ public:
Path::Type defaultPathType() const;
double minValidBoundingSphere() const;
double findValidBoundingSphere(const SceneGraphNode* node) const;
const std::vector<SceneGraphNode*>& relevantNodes();
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<SceneGraphNode*>& PathNavigator::relevantNodes() {
if (!_hasInitializedRelevantNodes) {
findRelevantNodes();

View File

@@ -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