Quick and dirty fix to avoid ZoomOutOverview curve colliding into planet when going between two nodes on the surface of a planet

This commit is contained in:
Emma Broman
2021-10-15 15:18:03 +02:00
parent 4a860fb01d
commit 5d0e811cc3
4 changed files with 72 additions and 39 deletions
@@ -74,6 +74,8 @@ public:
double minValidBoundingSphere() const;
const std::vector<SceneGraphNode*>& relevantNodes();
SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node) const;
/**
* \return The Lua library that contains all Lua functions available to affect the
* path navigation
+2 -36
View File
@@ -289,49 +289,15 @@ Waypoint waypointFromCamera() {
return Waypoint{ pos, rot, node };
}
SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node) {
const std::vector<SceneGraphNode*>& 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()) < Epsilon;
if (isSame) {
continue;
}
constexpr const float proximityRadiusFactor = 3.f;
const float bs = static_cast<float>(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 =
global::navigationHandler->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
@@ -26,6 +26,8 @@
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/navigation/waypoint.h>
#include <openspace/query/query.h>
#include <openspace/scene/scenegraphnode.h>
@@ -69,6 +71,9 @@ ZoomOutOverviewCurve::ZoomOutOverviewCurve(const Waypoint& start, const Waypoint
const glm::dvec3 n1 = startTangentDir;
const glm::dvec3 n2 = endTangentDir;
const glm::dvec3 startPosToEndPos = end.position() - start.position();
const glm::dvec3 halfWayPos = start.position() + 0.5 * startPosToEndPos;
// Decide the step direction for the "overview point" based on the directions
// at the start and end of the path, to try to get a nice curve shape
glm::dvec3 goodStepDirection;
@@ -80,9 +85,33 @@ ZoomOutOverviewCurve::ZoomOutOverviewCurve(const Waypoint& start, const Waypoint
goodStepDirection = glm::normalize(n1 + n2);
}
// OBS! This is a hack to avoid colliding with a close node. Should be done nicely in a
// rewrite of the path types. This has explicitly been added just to allow
// collision free paths between two nodes on a planet surface but might work weird in
// other cases
const PathNavigator& pn = global::navigationHandler->pathNavigator();
const SceneGraphNode* closeNode1 = pn.findNodeNearTarget(start.node());
const SceneGraphNode* closeNode2 = pn.findNodeNearTarget(end.node());
bool hasCloseNode = closeNode1 || closeNode2;
if (hasCloseNode) {
// Step outwards from the node
const SceneGraphNode* node;
if (closeNode1 && closeNode2) {
// pick the biggest one
node = (closeNode1->boundingSphere() > closeNode2->boundingSphere()) ?
closeNode1 : closeNode2;
}
else {
// pick the one that isn't a nullptr
node = (closeNode1) ? closeNode1 : closeNode2;
}
// Let the outwards direction impact the step direction
goodStepDirection += glm::normalize(halfWayPos - node->worldPosition());
goodStepDirection = glm::normalize(goodStepDirection);
}
// Find a direction that is orthogonal to the line between the start and end
// position
const glm::dvec3 startPosToEndPos = end.position() - start.position();
const glm::dvec3 outwardStepVector =
0.5 * glm::length(startPosToEndPos) * goodStepDirection;
@@ -91,8 +120,8 @@ ZoomOutOverviewCurve::ZoomOutOverviewCurve(const Waypoint& start, const Waypoint
const glm::dvec3 stepDirection = glm::normalize(orthogonalComponent);
// Step half-way along the line between the position and then orthogonally
const glm::dvec3 extraKnot = start.position() + 0.5 * startPosToEndPos
+ 1.5 * glm::length(startPosToEndPos) * stepDirection;
const double stepDistance = 1.5 * glm::length(startPosToEndPos);
const glm::dvec3 extraKnot = halfWayPos + stepDistance * stepDirection;
_points.push_back(extraKnot);
}
+36
View File
@@ -34,6 +34,7 @@
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/collisionhelper.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/quaternion.hpp>
@@ -329,6 +330,41 @@ const std::vector<SceneGraphNode*>& PathNavigator::relevantNodes() {
return _relevantNodes;
}
SceneGraphNode* PathNavigator::findNodeNearTarget(const SceneGraphNode* node) const {
const std::vector<SceneGraphNode*>& 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()) < Epsilon;
if (isSame) {
continue;
}
constexpr const float proximityRadiusFactor = 3.f;
const float bs = static_cast<float>(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::findRelevantNodes() {
const std::vector<SceneGraphNode*>& allNodes =
global::renderEngine->scene()->allSceneGraphNodes();