diff --git a/modules/autonavigation/CMakeLists.txt b/modules/autonavigation/CMakeLists.txt index eff2a917d5..f7cd4e532c 100644 --- a/modules/autonavigation/CMakeLists.txt +++ b/modules/autonavigation/CMakeLists.txt @@ -26,12 +26,11 @@ 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}/autonavigationmodule.h ${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.h ${CMAKE_CURRENT_SOURCE_DIR}/instruction.h - ${CMAKE_CURRENT_SOURCE_DIR}/pathspecification.h - ${CMAKE_CURRENT_SOURCE_DIR}/pathsegment.h + ${CMAKE_CURRENT_SOURCE_DIR}/path.h ${CMAKE_CURRENT_SOURCE_DIR}/pathcurve.h ${CMAKE_CURRENT_SOURCE_DIR}/rotationinterpolator.h ${CMAKE_CURRENT_SOURCE_DIR}/speedfunction.h @@ -43,13 +42,12 @@ source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/atnodenavigator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule_lua.inl - ${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/instruction.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pathspecification.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pathsegment.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/path.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pathcurve.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rotationinterpolator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/speedfunction.cpp diff --git a/modules/autonavigation/autonavigationhandler.cpp b/modules/autonavigation/autonavigationhandler.cpp index 42e02dd404..4eaddfaece 100644 --- a/modules/autonavigation/autonavigationhandler.cpp +++ b/modules/autonavigation/autonavigationhandler.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -125,8 +124,7 @@ AutoNavigationHandler::AutoNavigationHandler() properties::OptionProperty::DisplayType::Dropdown ) , _includeRoll(IncludeRollInfo, false) - , _stopAtTargetsPerDefault(StopAtTargetsPerDefaultInfo, false) - , _defaultStopBehavior( + , _stopBehavior( DefaultStopBehaviorInfo, properties::OptionProperty::DisplayType::Dropdown ) @@ -147,20 +145,19 @@ AutoNavigationHandler::AutoNavigationHandler() addProperty(_defaultCurveOption); addProperty(_includeRoll); - addProperty(_stopAtTargetsPerDefault); // Must be listed in the same order as in enum definition - _defaultStopBehavior.addOptions({ + _stopBehavior.addOptions({ { AtNodeNavigator::Behavior::None, "None" }, { AtNodeNavigator::Behavior::Orbit, "Orbit" } }); - _defaultStopBehavior = AtNodeNavigator::Behavior::None; - _defaultStopBehavior.onChange([this]() { + _stopBehavior = AtNodeNavigator::Behavior::None; + _stopBehavior.onChange([this]() { _atNodeNavigator.setBehavior( - AtNodeNavigator::Behavior(_defaultStopBehavior.value()) + AtNodeNavigator::Behavior(_stopBehavior.value()) ); }); - addProperty(_defaultStopBehavior); + addProperty(_stopBehavior); addProperty(_applyStopBehaviorWhenIdle); @@ -200,12 +197,8 @@ double AutoNavigationHandler::speedScale() const { return _speedScale; } -const PathSegment& AutoNavigationHandler::currentSegment() const { - return _currentPath.segments[_currentSegmentIndex]; -} - bool AutoNavigationHandler::noCurrentPath() const { - return _currentPath.segments.empty(); + return _currentPath == nullptr; } bool AutoNavigationHandler::hasFinished() const { @@ -213,14 +206,17 @@ bool AutoNavigationHandler::hasFinished() const { return true; } - const int lastIndex = static_cast(_currentPath.segments.size()) - 1; - return _currentSegmentIndex > lastIndex; + return _currentPath->hasReachedEnd(); } void AutoNavigationHandler::updateCamera(double deltaTime) { ghoul_assert(camera() != nullptr, "Camera must not be nullptr"); - if (!_isPlaying || _currentPath.segments.empty()) { + if (noCurrentPath()) { + return; + } + + if (!_isPlaying) { // For testing, apply at node behavior when idle // @TODO: Determine how this should work instead if (_applyStopBehaviorWhenIdle) { @@ -235,10 +231,8 @@ void AutoNavigationHandler::updateCamera(double deltaTime) { LINFO("Cannot start simulation time during camera motion"); } - PathSegment& currentSegment = _currentPath.segments[_currentSegmentIndex]; - - CameraPose newPose = currentSegment.traversePath(deltaTime); - const std::string newAnchor = currentSegment.currentAnchor(); + CameraPose newPose = _currentPath->traversePath(deltaTime); + const std::string newAnchor = _currentPath->currentAnchor(); // Set anchor node in orbitalNavigator, to render visible nodes and add activate // navigation when we reach the end. @@ -254,65 +248,70 @@ void AutoNavigationHandler::updateCamera(double deltaTime) { camera()->setPositionVec3(newPose.position); camera()->setRotation(newPose.rotation); - const int index = _currentSegmentIndex; - - if (currentSegment.hasReachedEnd()) { - _currentSegmentIndex++; - - if (hasFinished()) { - LINFO("Reached end of path."); - _isPlaying = false; - return; - } + // TODO: make this work again + if (_currentPath->hasReachedEnd()) { + LINFO("Reached end of path"); + _isPlaying = false; + return; } } -void AutoNavigationHandler::createPath(PathSpecification& spec) { +void AutoNavigationHandler::createPath(Instruction& instruction) { clearPath(); // TODO: do this in some initialize function instead _relevantNodes = findRelevantNodes(); - const std::vector& instructions = spec.instructions; - const int nInstructions = static_cast(instructions.size()); + // TODO: Improve how curve types are handled + const int curveType = _defaultCurveOption; - for (int i = 0; i < nInstructions; i++) { - const Instruction& instruction = instructions[i]; - addSegment(instruction, i); + std::vector waypoints = instruction.waypoints(); + Waypoint waypointToAdd; + + if (waypoints.empty()) { + if (instruction.type == Instruction::Type::Node) { + // TODO: allow curves to compute default waypoint instead + waypointToAdd = computeDefaultWaypoint(instruction); + } + else { + LWARNING("No path was created from instruction. Failed creating waypoints"); + return; + } + } + else { + // TODO: allow for an instruction to represent a list of waypoints + waypointToAdd = waypoints[0]; } - ghoul_assert( - _currentPath.stops.size() == (_currentPath.segments.size() - 1), - "Must have exactly one stop entry between every segment." + bool hasStartState = instruction.startState.has_value(); + Waypoint startState = hasStartState ? Waypoint(instruction.startState.value()) + : waypointFromCamera(); + + _currentPath = std::make_unique( + startState, + waypointToAdd, + CurveType(curveType), + instruction.duration ); - // Check if we have a specified start navigation state. If so, update first segment - if (spec.startState.has_value() && _currentPath.segments.size() > 0) { - Waypoint startState{ spec.startState.value() }; - _currentPath.segments[0].setStartPoint(startState); - } - - LINFO(fmt::format( - "Succefully generated camera path with {} segments.", _currentPath.segments.size() - )); + LINFO("Successfully generated camera path"); startPath(); } void AutoNavigationHandler::clearPath() { LINFO("Clearing path..."); - _currentPath.segments.clear(); - _currentSegmentIndex = 0; + _currentPath = nullptr; } void AutoNavigationHandler::startPath() { if (noCurrentPath()) { - LERROR("Cannot start an empty path."); + LERROR("There is no path to start"); return; } //OBS! Until we can handle simulation time: early out if not paused if (!global::timeManager->isPaused()) { - LERROR("Simulation time must be paused to run a camera path."); + LERROR("Simulation time must be paused to run a camera path"); return; } @@ -320,52 +319,48 @@ void AutoNavigationHandler::startPath() { _isPlaying = true; } -void AutoNavigationHandler::continuePath() { - if (hasFinished()) { - LERROR("No path to resume (path is empty or has finished)."); - return; - } - - if (_isPlaying) { - LERROR("Cannot resume a path that is already playing"); - return; - } - - LINFO("Continuing path..."); - - // recompute start camera state for the upcoming path segment, - _currentPath.segments[_currentSegmentIndex].setStartPoint(wayPointFromCamera()); -} +//void AutoNavigationHandler::continuePath() { +// if (hasFinished()) { +// LERROR("No path to resume (path is empty or has finished)."); +// return; +// } +// +// if (_isPlaying) { +// LERROR("Cannot resume a path that is already playing"); +// return; +// } +// +// LINFO("Continuing path..."); +// +// // recompute start camera state for the upcoming path segment, +// _currentPath.segments[_currentSegmentIndex].setStartPoint(wayPointFromCamera()); +//} void AutoNavigationHandler::abortPath() { if (!_isPlaying) { - LWARNING("No camera path is playing."); + LWARNING("No camera path is playing"); return; } _isPlaying = false; - LINFO("Aborted camera path."); + LINFO("Aborted camera path"); } // TODO: remove when not needed // Created for debugging std::vector AutoNavigationHandler::curvePositions(int nPerSegment) { - std::vector positions; - if (noCurrentPath()) { LERROR("There is no current path to sample points from."); - return positions; + return {}; } + std::vector positions; const double du = 1.0 / nPerSegment; - - for (const PathSegment& p : _currentPath.segments) { - const double length = p.pathLength(); - for (double u = 0.0; u < 1.0; u += du) { - glm::dvec3 position = p.interpolatedPose(u * length).position; - positions.push_back(position); - } - positions.push_back(p.endPoint().position()); + const double length = _currentPath->pathLength(); + for (double u = 0.0; u < 1.0; u += du) { + glm::dvec3 position = _currentPath->interpolatedPose(u * length).position; + positions.push_back(position); } + positions.push_back(_currentPath->endPoint().position()); return positions; } @@ -373,23 +368,20 @@ std::vector AutoNavigationHandler::curvePositions(int nPerSegment) { // TODO: remove when not needed // Created for debugging std::vector AutoNavigationHandler::curveOrientations(int nPerSegment) { - std::vector orientations; - if (noCurrentPath()) { LERROR("There is no current path to sample points from."); - return orientations; + return {}; } + std::vector orientations; const double du = 1.0 / nPerSegment; - - for (const PathSegment& p : _currentPath.segments) { - const double length = p.pathLength(); - for (double u = 0.0; u <= 1.0; u += du) { - const glm::dquat orientation = p.interpolatedPose(u * length).rotation; - orientations.push_back(orientation); - } - orientations.push_back(p.endPoint().rotation()); + const double length = _currentPath->pathLength(); + for (double u = 0.0; u <= 1.0; u += du) { + const glm::dquat orientation = + _currentPath->interpolatedPose(u * length).rotation; + orientations.push_back(orientation); } + orientations.push_back(_currentPath->endPoint().rotation()); return orientations; } @@ -398,63 +390,52 @@ std::vector AutoNavigationHandler::curveOrientations(int nPerSegment // TODO: remove when not needed or combined into pose version // Created for debugging std::vector AutoNavigationHandler::curveViewDirections(int nPerSegment) { - std::vector viewDirections; - if (noCurrentPath()) { LERROR("There is no current path to sample points from."); - return viewDirections; + return {}; } + std::vector viewDirections; const double du = 1.0 / nPerSegment; - - for (const PathSegment& p : _currentPath.segments) { - for (double u = 0.0; u < 1.0; u += du) { - const glm::dquat orientation = p.interpolatedPose(u).rotation; - const glm::dvec3 direction = glm::normalize( - orientation * glm::dvec3(0.0, 0.0, -1.0) - ); - viewDirections.push_back(direction); - } - - const glm::dquat orientation = p.interpolatedPose(1.0).rotation; + for (double u = 0.0; u < 1.0; u += du) { + const glm::dquat orientation = _currentPath->interpolatedPose(u).rotation; const glm::dvec3 direction = glm::normalize( orientation * glm::dvec3(0.0, 0.0, -1.0) ); viewDirections.push_back(direction); } + const glm::dquat orientation = _currentPath->interpolatedPose(1.0).rotation; + const glm::dvec3 direction = glm::normalize( + orientation * glm::dvec3(0.0, 0.0, -1.0) + ); + viewDirections.push_back(direction); + return viewDirections; } // TODO: remove when not needed // Created for debugging std::vector AutoNavigationHandler::controlPoints() { - std::vector points; - if (noCurrentPath()) { LERROR("There is no current path to sample points from."); - return points; + return {}; } - for (const PathSegment&p : _currentPath.segments) { - const std::vector curvePoints = p.controlPoints(); - points.insert(points.end(), curvePoints.begin(), curvePoints.end()); - } + std::vector points; + const std::vector curvePoints = _currentPath->controlPoints(); + points.insert(points.end(), curvePoints.begin(), curvePoints.end()); return points; } -Waypoint AutoNavigationHandler::wayPointFromCamera() { +Waypoint AutoNavigationHandler::waypointFromCamera() { const glm::dvec3 pos = camera()->positionVec3(); const glm::dquat rot = camera()->rotationQuaternion(); const std::string node = global::navigationHandler->anchorNode()->identifier(); return Waypoint{ pos, rot, node }; } -Waypoint AutoNavigationHandler::lastWayPoint() { - return noCurrentPath() ? wayPointFromCamera() : _currentPath.segments.back().endPoint(); -} - void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTime) { const glm::dvec3 anchorPos = anchor()->worldPosition(); const glm::dvec3 cameraDir = glm::normalize( @@ -471,39 +452,6 @@ void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTim pose.rotation = rollFreeRotation; } -void AutoNavigationHandler::addSegment(const Instruction& ins, int index) { - // TODO: Improve how curve types are handled - const int curveType = _defaultCurveOption; - - std::vector waypoints = ins.waypoints(); - Waypoint waypointToAdd; - - if (waypoints.empty()) { - if (ins.type == Instruction::Type::Node) { - // TODO: allow curves to compute default waypoint instead - waypointToAdd = computeDefaultWaypoint(ins); - } - else { - LWARNING(fmt::format( - "No path segment was created from instruction {}. " - "No waypoints could be created.", index - )); - return; - } - } - else { - // TODO: allow for an instruction to represent a list of waypoints - waypointToAdd = waypoints[0]; - } - - _currentPath.segments.push_back(PathSegment( - lastWayPoint(), - waypointToAdd, - CurveType(curveType), - ins.duration - )); -} - // Test if the node lies within a given proximity radius of any relevant node in the scene SceneGraphNode* AutoNavigationHandler::findNodeNearTarget(const SceneGraphNode* node) { glm::dvec3 nodePos = node->worldPosition(); @@ -547,7 +495,7 @@ Waypoint AutoNavigationHandler::computeDefaultWaypoint(const Instruction& ins) { const glm::dvec3 nodePos = targetNode->worldPosition(); const glm::dvec3 sunPos = glm::dvec3(0.0, 0.0, 0.0); const SceneGraphNode* closeNode = findNodeNearTarget(targetNode); - const glm::dvec3 prevPos = lastWayPoint().position(); + const glm::dvec3 prevPos = waypointFromCamera().position(); // Position glm::dvec3 stepDirection; diff --git a/modules/autonavigation/autonavigationhandler.h b/modules/autonavigation/autonavigationhandler.h index e29641243f..5d225ab2d8 100644 --- a/modules/autonavigation/autonavigationhandler.h +++ b/modules/autonavigation/autonavigationhandler.h @@ -26,7 +26,7 @@ #define __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__ #include -#include +#include #include #include #include @@ -41,7 +41,6 @@ namespace openspace::autonavigation { struct Waypoint; struct Instruction; struct TargetNodeInstruction; -class PathSpecification; class AutoNavigationHandler : public properties::PropertyOwner { public: @@ -55,17 +54,18 @@ public: int integrationResolutionPerFrame() const; double speedScale() const; - const PathSegment& currentSegment() const; bool noCurrentPath() const; bool hasFinished() const; void updateCamera(double deltaTime); - void createPath(PathSpecification& spec); + void createPath(Instruction& spec); void clearPath(); void startPath(); - void continuePath(); void abortPath(); + // TODO: allow option to pause during a path and then change this to continue playing + //void continuePath(); + // TODO: remove functions for debugging std::vector curvePositions(int nPerSegment); std::vector curveOrientations(int nPerSegment); @@ -74,38 +74,29 @@ public: private: Waypoint wayPointFromCamera(); - Waypoint lastWayPoint(); void removeRollRotation(CameraPose& pose, double deltaTime); - void addSegment(const Instruction& ins, int index); + void addSegment(const Instruction& ins); SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node); Waypoint computeDefaultWaypoint(const Instruction& ins); std::vector findRelevantNodes(); - struct Path { - std::vector segments; - }; - - Path _currentPath; + std::unique_ptr _currentPath = nullptr; AtNodeNavigator _atNodeNavigator; // responsible for navigation during stops - double _progressedTimeInStop = 0.0; - bool _isPlaying = false; - unsigned int _currentSegmentIndex = 0; std::vector _relevantNodes; properties::OptionProperty _defaultCurveOption; properties::BoolProperty _includeRoll; - properties::BoolProperty _stopAtTargetsPerDefault; - properties::OptionProperty _defaultStopBehavior; // for testing pause behaviors. // TODO: remove later, if it causes problems with regular navigation properties::BoolProperty _applyStopBehaviorWhenIdle; + properties::OptionProperty _stopBehavior; properties::StringListProperty _relevantNodeTags; properties::FloatProperty _defaultPositionOffsetAngle; diff --git a/modules/autonavigation/autonavigationmodule.cpp b/modules/autonavigation/autonavigationmodule.cpp index ad42b7499d..b0b5b6ff33 100644 --- a/modules/autonavigation/autonavigationmodule.cpp +++ b/modules/autonavigation/autonavigationmodule.cpp @@ -59,8 +59,7 @@ double AutoNavigationModule::minValidBoundingSphere() const { std::vector AutoNavigationModule::documentations() const { return { - autonavigation::Instruction::Documentation(), - autonavigation::PathSpecification::Documentation() + autonavigation::Instruction::Documentation() }; } @@ -78,13 +77,13 @@ scripting::LuaLibrary AutoNavigationModule::luaLibrary() const { "", "Returns true if a camera path is currently running, and false otherwise." }, - { - "continuePath", - &autonavigation::luascriptfunctions::continuePath, - {}, - "", - "Continue playing a paused camera path." - }, + //{ + // "continuePath", + // &autonavigation::luascriptfunctions::continuePath, + // {}, + // "", + // "Continue playing a paused camera path." + //}, { "stopPath", &autonavigation::luascriptfunctions::stopPath, @@ -131,14 +130,6 @@ scripting::LuaLibrary AutoNavigationModule::luaLibrary() const { "table", "Generate the path as described by the lua table input argument. " }, - { - "generatePathFromFile", - &autonavigation::luascriptfunctions::generatePathFromFile, - {}, - "string", - "Read an input file with lua instructions and use those to generate a camera " - "path. " - }, { "getPathPositions", &autonavigation::luascriptfunctions::getPathPositions, diff --git a/modules/autonavigation/autonavigationmodule_lua.inl b/modules/autonavigation/autonavigationmodule_lua.inl index 676bdff431..da69e81a9a 100644 --- a/modules/autonavigation/autonavigationmodule_lua.inl +++ b/modules/autonavigation/autonavigationmodule_lua.inl @@ -23,7 +23,6 @@ ****************************************************************************************/ #include -#include #include #include #include @@ -58,15 +57,15 @@ int isFlying(lua_State* L) { return 1; } -int continuePath(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath"); - - AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().continuePath(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; -} +//int continuePath(lua_State* L) { +// ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath"); +// +// AutoNavigationModule* module = global::moduleEngine->module(); +// module->AutoNavigationHandler().continuePath(); +// +// ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); +// return 0; +//} int stopPath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath"); @@ -146,10 +145,10 @@ int goTo(lua_State* L) { } } - PathSpecification spec = PathSpecification(Instruction{ insDict }); + Instruction instruction(insDict); AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().createPath(spec); + module->AutoNavigationHandler().createPath(instruction); lua_settop(L, 0); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); @@ -181,10 +180,10 @@ int goToHeight(lua_State* L) { } } - PathSpecification spec = PathSpecification(Instruction{ insDict }); + Instruction instruction(insDict); AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().createPath(spec); + module->AutoNavigationHandler().createPath(instruction); lua_settop(L, 0); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); @@ -236,10 +235,10 @@ int goToGeo(lua_State* L) { } } - PathSpecification spec = PathSpecification(Instruction{ insDict }); + Instruction instruction(insDict); AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().createPath(spec); + module->AutoNavigationHandler().createPath(instruction); lua_settop(L, 0); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); @@ -251,74 +250,16 @@ int generatePath(lua_State* L) { ghoul::Dictionary dictionary; ghoul::lua::luaDictionaryFromState(L, dictionary); - PathSpecification spec(dictionary); - - if (spec.instructions.empty()) { - lua_settop(L, 0); - return ghoul::lua::luaError( - L, fmt::format("No instructions for camera path generation were provided.") - ); - } + Instruction instruction(dictionary); AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().createPath(spec); + module->AutoNavigationHandler().createPath(instruction); lua_settop(L, 0); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } -int generatePathFromFile(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePathFromFile"); - - const std::string& filepath = - ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); - - if (filepath.empty()) { - return ghoul::lua::luaError(L, "Filepath string is empty"); - } - - const std::filesystem::path file = absPath(filepath); - - LINFO(fmt::format("Reading path instructions from file: {}", file)); - - if (!std::filesystem::is_regular_file(file)) { - throw ghoul::FileNotFoundError(file.string(), "PathSpecification"); - } - - // Try to read the dictionary - ghoul::Dictionary dictionary; - try { - ghoul::lua::loadDictionaryFromFile(file.string(), dictionary); - openspace::documentation::testSpecificationAndThrow( - PathSpecification::Documentation(), - dictionary, - "PathSpecification" - ); - } - catch (ghoul::RuntimeError& e) { - return ghoul::lua::luaError( - L, fmt::format("Unable to read dictionary from file: {}", e.message) - ); - } - - PathSpecification spec(dictionary); - - if (spec.instructions.empty()) { - return ghoul::lua::luaError( - L, fmt::format("No instructions for camera path generation were provided") - ); - } - - LINFOC("AutoNavigationModule", "Reading succeeded. Creating path"); - - AutoNavigationModule* module = global::moduleEngine->module(); - module->AutoNavigationHandler().createPath(spec); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; -} - // TODO: remove when not needed // Created for debugging. Access info for rendereable path int getPathPositions(lua_State* L) { diff --git a/modules/autonavigation/instruction.cpp b/modules/autonavigation/instruction.cpp index 285dc16a9b..305e779245 100644 --- a/modules/autonavigation/instruction.cpp +++ b/modules/autonavigation/instruction.cpp @@ -61,9 +61,13 @@ namespace { std::optional useTargetUpDirection; // (NavigationState): A navigation state that will be the target - // of this path segment. + // of this path segment std::optional navigationState [[codegen::reference("core_navigation_state")]]; + + // A navigation state that determines the start state for the camera path + std::optional startState + [[codegen::reference("core_navigation_state")]]; }; #include "instruction_codegen.cpp" } // namespace diff --git a/modules/autonavigation/instruction.h b/modules/autonavigation/instruction.h index 8353d39ba8..6c51287c0f 100644 --- a/modules/autonavigation/instruction.h +++ b/modules/autonavigation/instruction.h @@ -32,6 +32,8 @@ namespace openspace::autonavigation { struct Instruction { + using NavigationState = interaction::NavigationHandler::NavigationState; + enum class Type { Node, NavigationState @@ -46,6 +48,7 @@ struct Instruction { Type type; std::optional duration; + std::optional startState; // Node details std::string nodeIdentifier; @@ -54,7 +57,7 @@ struct Instruction { bool useTargetUpDirection; // Navigation state details - interaction::NavigationHandler::NavigationState navigationState; + NavigationState navigationState; std::vector _waypoints; }; diff --git a/modules/autonavigation/pathsegment.cpp b/modules/autonavigation/path.cpp similarity index 85% rename from modules/autonavigation/pathsegment.cpp rename to modules/autonavigation/path.cpp index de34e0f775..5830e87675 100644 --- a/modules/autonavigation/pathsegment.cpp +++ b/modules/autonavigation/path.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include @@ -37,18 +37,17 @@ #include namespace { - constexpr const char* _loggerCat = "PathSegment"; - + constexpr const char* _loggerCat = "Path"; const double Epsilon = 1E-7; } // namespace namespace openspace::autonavigation { -PathSegment::PathSegment(Waypoint start, Waypoint end, CurveType type, - std::optional duration) +Path::Path(Waypoint start, Waypoint end, CurveType type, + std::optional duration) : _start(start), _end(end), _curveType(type) { - initCurve(); + initializePath(); if (duration.has_value()) { _duration = duration.value(); @@ -61,26 +60,25 @@ PathSegment::PathSegment(Waypoint start, Waypoint end, CurveType type, } } -void PathSegment::setStartPoint(Waypoint cs) { +void Path::setStartPoint(Waypoint cs) { _start = std::move(cs); - initCurve(); + initializePath(); // TODO later: maybe recompute duration as well... } -const Waypoint PathSegment::startPoint() const { return _start; } +const Waypoint Path::startPoint() const { return _start; } -const Waypoint PathSegment::endPoint() const { return _end; } +const Waypoint Path::endPoint() const { return _end; } -const double PathSegment::duration() const { return _duration; } +const double Path::duration() const { return _duration; } -const double PathSegment::pathLength() const { return _curve->length(); } +const double Path::pathLength() const { return _curve->length(); } -// TODO: remove function for debugging -const std::vector PathSegment::controlPoints() const { +const std::vector Path::controlPoints() const { return _curve->points(); } -CameraPose PathSegment::traversePath(double dt) { +CameraPose Path::traversePath(double dt) { if (!_curve || !_rotationInterpolator || !_speedFunction) { // TODO: handle better (abort path somehow) return _start.pose; @@ -103,20 +101,20 @@ CameraPose PathSegment::traversePath(double dt) { return interpolatedPose(_traveledDistance); } -std::string PathSegment::currentAnchor() const { +std::string Path::currentAnchor() const { bool pastHalfway = (_traveledDistance / pathLength()) > 0.5; return (pastHalfway) ? _end.nodeDetails.identifier : _start.nodeDetails.identifier; } -bool PathSegment::hasReachedEnd() const { +bool Path::hasReachedEnd() const { return (_traveledDistance / pathLength()) >= 1.0; } -double PathSegment::speedAtTime(double time) const { +double Path::speedAtTime(double time) const { return _speedFunction->scaledValue(time, _duration, pathLength()); } -CameraPose PathSegment::interpolatedPose(double distance) const { +CameraPose Path::interpolatedPose(double distance) const { double u = distance / pathLength(); CameraPose cs; cs.position = _curve->positionAt(u); @@ -124,7 +122,7 @@ CameraPose PathSegment::interpolatedPose(double distance) const { return cs; } -void PathSegment::initCurve() { +void Path::initializePath() { _curve.reset(); switch (_curveType) diff --git a/modules/autonavigation/pathsegment.h b/modules/autonavigation/path.h similarity index 93% rename from modules/autonavigation/pathsegment.h rename to modules/autonavigation/path.h index 44ee5e3c99..593f729824 100644 --- a/modules/autonavigation/pathsegment.h +++ b/modules/autonavigation/path.h @@ -34,11 +34,13 @@ namespace openspace::autonavigation { -class PathSegment { +class Path { public: - PathSegment(Waypoint start, Waypoint end, CurveType type, + Path(Waypoint start, Waypoint end, CurveType type, std::optional duration = std::nullopt); + // TODO: add a constructor that takes an instruction and curve type? + void setStartPoint(Waypoint wp); const Waypoint startPoint() const; @@ -46,7 +48,7 @@ public: const double duration() const; const double pathLength() const; - const std::vector controlPoints() const; // debugging + const std::vector controlPoints() const; CameraPose traversePath(double dt); std::string currentAnchor() const; @@ -56,7 +58,7 @@ public: CameraPose interpolatedPose(double distance) const; private: - void initCurve(); + void initializePath(); Waypoint _start; Waypoint _end; diff --git a/modules/autonavigation/pathspecification.cpp b/modules/autonavigation/pathspecification.cpp deleted file mode 100644 index 33275358ac..0000000000 --- a/modules/autonavigation/pathspecification.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/***************************************************************************************** - * * - * 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 - -#include -#include -#include - -namespace { - constexpr const char* _loggerCat = "PathSpecification"; - - struct [[codegen::Dictionary(PathSpecification)]] Parameters { - // A list of path instructions - std::vector instructions - [[codegen::reference("autonavigation_pathinstruction")]]; - - // A navigation state that determines the start state for the camera path - std::optional startState - [[codegen::reference("core_navigation_state")]]; - }; -#include "pathspecification_codegen.cpp" -} // namespace - -namespace openspace::autonavigation { - -documentation::Documentation PathSpecification::Documentation() { - return codegen::doc("autonavigation_pathspecification"); -} - -PathSpecification::PathSpecification(const ghoul::Dictionary& dictionary) { - const Parameters p = codegen::bake(dictionary); - - const std::vector instructionDicts = p.instructions; - int counter = 1; - for (const ghoul::Dictionary& dict : instructionDicts) { - try { - instructions.push_back(Instruction(dict)); - } - catch (ghoul::RuntimeError& e) { - LERROR(fmt::format("Failed reading instruction {}: {}", counter, e.message)); - } - counter++; - } - - if (p.startState.has_value()) { - startState = NavigationState(p.startState.value()); - } -} - -PathSpecification::PathSpecification(const Instruction instruction) { - instructions.push_back(instruction); -} - -} // namespace openspace::autonavigation diff --git a/modules/autonavigation/pathspecification.h b/modules/autonavigation/pathspecification.h deleted file mode 100644 index 5148b9e400..0000000000 --- a/modules/autonavigation/pathspecification.h +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************************** - * * - * 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___PATHSPECIFICATION___H__ -#define __OPENSPACE_MODULE___PATHSPECIFICATION___H__ - -#include -#include -#include -#include -#include - -namespace openspace::autonavigation { - -struct PathSpecification { - using NavigationState = interaction::NavigationHandler::NavigationState; - - PathSpecification() = default; - PathSpecification(const ghoul::Dictionary& dictionary); - PathSpecification(const Instruction instruction); - - static documentation::Documentation Documentation(); - - std::vector instructions; - std::optional startState; -}; - -} // namespace openspace::autonavigation - -#endif // __OPENSPACE_MODULE___PATHSPECIFICATION___H__