mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-24 04:58:59 -05:00
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:
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user