Started implementing pause/stop behaviors

This commit is contained in:
Emma Broman
2020-04-08 16:27:10 +02:00
parent 9d10abcff3
commit a9005cdcbb
11 changed files with 254 additions and 62 deletions
+2
View File
@@ -25,6 +25,7 @@
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/atnodenavigator.h
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.h
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.h
${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.h
@@ -38,6 +39,7 @@ set(HEADER_FILES
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/atnodenavigator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule_lua.inl
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.cpp
+113
View File
@@ -0,0 +1,113 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/autonavigation/atnodenavigator.h>
#include <modules/autonavigation/waypoint.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/query/query.h>
#include <openspace/util/camera.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "AtAnchorNavigator";
constexpr const openspace::properties::Property::PropertyInfo OrbitSpeedFactorInfo = {
"OrbitSpeedFactor",
"Orbit Speed Factor",
"Controls the speed of the orbiting around an anchor."
};
} // namespace
namespace openspace::autonavigation {
AtNodeNavigator::AtNodeNavigator()
: properties::PropertyOwner({ "AtAnchorNavigator" })
, _orbitSpeedFactor(OrbitSpeedFactorInfo, 0.5, 0.0, 20.0)
{
addProperty(_orbitSpeedFactor);
_behavior = Behavior::None;
}
AtNodeNavigator::~AtNodeNavigator() {} // NOLINT
void AtNodeNavigator::setNode(std::string identifier) {
SceneGraphNode* node = sceneGraphNode(identifier);
if (!node) {
LERROR(fmt::format(
"Could not find scene graph node '{}' to navigate in relation to.", identifier
));
return;
}
_node = node;
}
void AtNodeNavigator::setBehavior(Behavior behavior) {
_behavior = behavior;
}
void AtNodeNavigator::updateCamera(double deltaTime) {
switch (_behavior)
{
case Behavior::Orbit:
orbitNode(deltaTime);
break;
case Behavior::None:
// Do nothing
break;
default:
LERROR("Unknown behaviour type!");
break;
}
}
Camera* AtNodeNavigator::camera() const {
return global::navigationHandler.camera();
}
// Move along the right vector for the camera, while looking at the center of the node
void AtNodeNavigator::orbitNode(double deltaTime) {
ghoul_assert(_node != nullptr, "Node to orbit must be set!")
glm::dvec3 prevPosition = camera()->positionVec3();
glm::dquat prevRotation = camera()->rotationQuaternion();
glm::dvec3 nodeCenter = _node->worldPosition();
double distanceToNode = glm::distance(prevPosition, nodeCenter) - _node->boundingSphere();
double orbitSpeed = distanceToNode * 0.1 * _orbitSpeedFactor;
const glm::dvec3 up = camera()->lookUpVectorWorldSpace();
glm::dvec3 forward = prevRotation * glm::dvec3(0.0, 0.0, -1.0);
glm::dvec3 right = glm::normalize(glm::cross(forward, up));
glm::dvec3 newPosition = prevPosition + orbitSpeed * deltaTime * right;
glm::dmat4 lookAtMat = glm::lookAt(newPosition, nodeCenter, up);
glm::dquat newRotation = glm::normalize(glm::inverse(glm::quat_cast(lookAtMat)));
camera()->setPositionVec3(newPosition);
camera()->setRotation(newRotation);
}
} // namespace openspace::autonavigation
+61
View File
@@ -0,0 +1,61 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE___ATNODENAVIGATOR___H__
#define __OPENSPACE_MODULE___ATNODENAVIGATOR___H__
#include <openspace/scene/scenegraphnode.h>
namespace openspace::autonavigation {
class AtNodeNavigator : public properties::PropertyOwner {
public:
enum Behavior {
Orbit,
None
};
AtNodeNavigator();
~AtNodeNavigator();
void setNode(std::string identifier);
void setBehavior(Behavior behavior);
void updateCamera(double deltaTime);
private:
Camera* camera() const;
//Behaviors
void orbitNode(double deltaTime);
SceneGraphNode* _node;
Behavior _behavior;
properties::DoubleProperty _orbitSpeedFactor;
};
} // namespace openspace::autonavigation
#endif // __OPENSPACE_MODULE___ATNODENAVIGATOR___H__
@@ -34,7 +34,6 @@
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/timemanager.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/quaternion.hpp>
@@ -59,7 +58,13 @@ namespace {
"StopAtTargetsPerDefault",
"Stop At Targets Per Default",
"Applied during path creation. If enabled, stops are automatically added between"
" the path segments. The user must then choose to continue the apth after reaching a target"
" the path segments. The user must then choose to continue the path after reaching a target"
};
constexpr const openspace::properties::Property::PropertyInfo DefaultStopBehaviorInfo = {
"DefaultStopBehavior",
"Default Stop Behavior",
"The default camera behavior that is applied when the camera reaches and stops at a target."
};
} // namespace
@@ -71,14 +76,24 @@ AutoNavigationHandler::AutoNavigationHandler()
, _defaultCurveOption(DefaultCurveOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _includeRoll(IncludeRollInfo, false)
, _stopAtTargetsPerDefault(StopAtTargetsPerDefaultInfo, false)
, _defaultStopBehavior(DefaultStopBehaviorInfo, properties::OptionProperty::DisplayType::Dropdown)
{
addPropertySubOwner(_atNodeNavigator);
_defaultCurveOption.addOptions({
{ CurveType::Bezier3, "Bezier3" },
{ CurveType::Linear, "Linear"}
});
addProperty(_defaultCurveOption);
addProperty(_includeRoll);
addProperty(_stopAtTargetsPerDefault);
_defaultStopBehavior.addOptions({
{ AtNodeNavigator::Behavior::None, "None" },
{ AtNodeNavigator::Behavior::Orbit, "Orbit" },
});
addProperty(_defaultStopBehavior);
}
AutoNavigationHandler::~AutoNavigationHandler() {} // NOLINT
@@ -151,7 +166,7 @@ void AutoNavigationHandler::createPath(PathSpecification& spec) {
LINFO("Property for stop at targets per default was overridden by path specification.");
}
const int nrInstructions = spec.instructions()->size();
const int nrInstructions = (int)spec.instructions()->size();
for (int i = 0; i < nrInstructions; i++) {
const Instruction* instruction = spec.instruction(i);
@@ -168,7 +183,7 @@ void AutoNavigationHandler::createPath(PathSpecification& spec) {
// Add info about stops between segments
if (i < nrInstructions - 1) {
addStopDetails(instruction);
addStopDetails(waypoints.back(), instruction);
}
}
}
@@ -188,6 +203,7 @@ void AutoNavigationHandler::createPath(PathSpecification& spec) {
void AutoNavigationHandler::clearPath() {
LINFO("Clearing path...");
_pathSegments.clear();
_stops.clear();
_currentSegmentIndex = 0;
}
@@ -216,30 +232,6 @@ void AutoNavigationHandler::startPath() {
_activeStop = nullptr;
}
void AutoNavigationHandler::pauseAtTarget(int i) {
if (!_isPlaying || _activeStop) {
LERROR("Cannot pause a path that isn't playing");
return;
}
_activeStop = &_stops[i];
if (!_activeStop) return;
bool hasDuration = _activeStop->duration.has_value();
std::string infoString = hasDuration
? fmt::format("{} seconds", _activeStop->duration.value())
: "until continued";
LINFO(fmt::format("Paused path at target {} / {} ({})",
_currentSegmentIndex,
_pathSegments.size(),
infoString
));
_progressedTimeInStop = 0.0;
}
void AutoNavigationHandler::continuePath() {
if (_pathSegments.empty() || hasFinished()) {
LERROR("No path to resume (path is empty or has finished).");
@@ -258,7 +250,7 @@ void AutoNavigationHandler::continuePath() {
_activeStop = nullptr;
}
void AutoNavigationHandler::stopPath() {
void AutoNavigationHandler::abortPath() {
_isPlaying = false;
}
@@ -326,9 +318,41 @@ void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTim
pose.rotation = rollFreeRotation;
}
void AutoNavigationHandler::pauseAtTarget(int i) {
if (!_isPlaying || _activeStop) {
LERROR("Cannot pause a path that isn't playing");
return;
}
if (i < 0 || i > _stops.size() - 1) {
LERROR("Invalid target number: " + std::to_string(i));
return;
}
_activeStop = &_stops[i];
if (!_activeStop) return;
_atNodeNavigator.setBehavior(_activeStop->behavior);
_atNodeNavigator.setNode(_pathSegments[i]->end().nodeDetails.identifier);
bool hasDuration = _activeStop->duration.has_value();
std::string infoString = hasDuration ?
fmt::format("{} seconds", _activeStop->duration.value()) : "until continued";
LINFO(fmt::format("Paused path at target {} / {} ({})",
_currentSegmentIndex,
_pathSegments.size(),
infoString
));
_progressedTimeInStop = 0.0;
}
void AutoNavigationHandler::applyStopBehaviour(double deltaTime) {
_progressedTimeInStop += deltaTime;
// TODO: Apply pause behaviour
_atNodeNavigator.updateCamera(deltaTime);
if (!_activeStop->duration.has_value()) return;
@@ -350,7 +374,7 @@ void AutoNavigationHandler::addSegment(Waypoint& waypoint, const Instruction* in
_pathSegments.push_back(std::unique_ptr<PathSegment>(new PathSegment(segment)));
}
void AutoNavigationHandler::addStopDetails(const Instruction* ins) {
void AutoNavigationHandler::addStopDetails(Waypoint& endWaypoint, const Instruction* ins) {
StopDetails stopEntry;
stopEntry.shouldStop = _stopAtTargetsPerDefault.value();
@@ -360,6 +384,12 @@ void AutoNavigationHandler::addStopDetails(const Instruction* ins) {
if (stopEntry.shouldStop) {
stopEntry.duration = ins->stopDuration;
std::string anchorIdentifier = endWaypoint.nodeDetails.identifier;
stopEntry.behavior = AtNodeNavigator::Behavior(_defaultStopBehavior.value()); // OBS! Will this work if they're not in the same order??
if (ins->stopBehavior.has_value()) {
// TODO:
}
}
_stops.push_back(stopEntry);
@@ -25,6 +25,7 @@
#ifndef __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__
#define __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__
#include <modules/autonavigation/atnodenavigator.h>
#include <modules/autonavigation/pathsegment.h>
#include <openspace/interaction/interpolator.h>
#include <openspace/interaction/navigationhandler.h>
@@ -57,9 +58,8 @@ public:
void createPath(PathSpecification& spec);
void clearPath();
void startPath();
void pauseAtTarget(int i);
void continuePath();
void stopPath();
void abortPath();
// TODO: remove functions for debugging
std::vector<glm::dvec3> getCurvePositions(int nPerSegment); //debug
@@ -69,11 +69,12 @@ private:
Waypoint wayPointFromCamera();
Waypoint lastWayPoint();
void removeRollRotation(CameraPose& pose, double deltaTime);
void pauseAtTarget(int i);
void applyStopBehaviour(double deltaTime);
void addSegment(Waypoint& waypoint, const Instruction* ins);
void addStopDetails(const Instruction* ins);
void addStopDetails(Waypoint& endWaypoint, const Instruction* ins);
// this list essentially represents the camera path
std::vector<std::unique_ptr<PathSegment>> _pathSegments;
@@ -81,11 +82,12 @@ private:
struct StopDetails {
bool shouldStop;
std::optional<double> duration;
// TODO: behaviour
AtNodeNavigator::Behavior behavior;
};
std::vector<StopDetails> _stops; // 1 between every segment
AtNodeNavigator _atNodeNavigator; // responsible for navigation during stops
StopDetails* _activeStop = nullptr;
double _progressedTimeInStop = 0.0;
@@ -95,6 +97,7 @@ private:
properties::OptionProperty _defaultCurveOption;
properties::BoolProperty _includeRoll;
properties::BoolProperty _stopAtTargetsPerDefault;
properties::OptionProperty _defaultStopBehavior;
};
} // namespace openspace::autonavigation
@@ -56,7 +56,7 @@ namespace openspace::autonavigation::luascriptfunctions {
AutoNavigationModule* module = global::moduleEngine.module<AutoNavigationModule>();
AutoNavigationHandler& handler = module->AutoNavigationHandler();
handler.stopPath();
handler.abortPath();
return 0;
}
+5
View File
@@ -38,6 +38,7 @@ namespace {
constexpr const char* KeyDuration = "Duration";
constexpr const char* KeyStopAtTarget = "StopAtTarget";
constexpr const char* KeyStopDetails = "StopDetails";
constexpr const char* KeyBehavior = "Behavior";
constexpr const char* KeyTarget = "Target";
constexpr const char* KeyPosition = "Position";
@@ -65,6 +66,10 @@ Instruction::Instruction(const ghoul::Dictionary& dictionary) {
if (stopDictionary.hasValue<double>(KeyDuration)) {
stopDuration = stopDictionary.value<double>(KeyDuration);
}
if (stopDictionary.hasValue<std::string>(KeyBehavior)) {
stopBehavior = stopDictionary.value<std::string>(KeyBehavior);
}
}
}
+4 -2
View File
@@ -43,9 +43,11 @@ struct Instruction {
std::optional<double> duration;
// TODO: include pause information
std::optional<bool> stopAtTarget;
std::optional<double> stopDuration; // only relevant is stopAtTarget true
// only relevant is stopAtTarget true
std::optional<double> stopDuration;
std::optional<std::string> stopBehavior;
};
struct TargetNodeInstruction : public Instruction {
-12
View File
@@ -227,16 +227,4 @@ glm::dvec3 LinearCurve::positionAt(double u) {
return interpolation::linear(u, _points[0], _points[1]);
}
// TODO: Iprove handling of pauses
PauseCurve::PauseCurve(const Waypoint& waypoint) {
_points.push_back(waypoint.position());
_length = 1.0; // OBS! Length of a pause curve makes no sense, but it also doesn't matter
_rotationInterpolator = RotationInterpolator{ waypoint, waypoint, this, Fixed };
}
glm::dvec3 PauseCurve::positionAt(double u) {
ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");
return _points[0];
}
} // namespace openspace::autonavigation
-9
View File
@@ -35,7 +35,6 @@ namespace openspace::autonavigation {
enum CurveType {
Bezier3,
Linear,
Pause // OBS! Temporary special case for handling pauses
};
class PathCurve {
@@ -76,14 +75,6 @@ public:
glm::dvec3 positionAt(double u);
};
// OBS! This is a temporary class specialised for handling pauses.
// TODO: handle better in the future.
class PauseCurve : public PathCurve {
public:
PauseCurve(const Waypoint& state);
glm::dvec3 positionAt(double u);
};
} // namespace openspace::autonavigation
#endif // __OPENSPACE_MODULE_AUTONAVIGATION___PATHCURVE___H__
-3
View File
@@ -143,9 +143,6 @@ void PathSegment::initCurve() {
case CurveType::Linear:
_curve = std::make_shared<LinearCurve>(_start, _end);
break;
case CurveType::Pause:
_curve = std::make_shared<PauseCurve>(_start);
break;
default:
LERROR("Could not create curve. Type does not exist!");
return;