Add code for different path segments from Ingelas old branch

This commit is contained in:
Emma Broman
2020-01-10 15:48:37 -05:00
parent 3e283d1630
commit 0a984df58c
7 changed files with 595 additions and 102 deletions

View File

@@ -27,8 +27,9 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.h
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.h
${CMAKE_CURRENT_SOURCE_DIR}/transferfunctions.h
${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.h
${CMAKE_CURRENT_SOURCE_DIR}/pathspecification.h
${CMAKE_CURRENT_SOURCE_DIR}/pathsegment.h
)
source_group("Header Files" FILES ${HEADER_FILES})
@@ -36,8 +37,9 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationmodule_lua.inl
${CMAKE_CURRENT_SOURCE_DIR}/autonavigationhandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/transferfunctions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/helperfunctions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pathspecification.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pathsegment.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -24,7 +24,7 @@
#include <modules/autonavigation/autonavigationhandler.h>
#include <modules/autonavigation/transferfunctions.h>
#include <modules/autonavigation/helperfunctions.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
@@ -60,49 +60,13 @@ const double AutoNavigationHandler::pathDuration() const {
PathSegment& AutoNavigationHandler::currentPathSegment() {
for (PathSegment& ps : _pathSegments) {
double endTime = ps.startTime + ps.duration;
double endTime = ps.startTime() + ps.duration();
if (endTime > _currentTime) {
return ps;
}
}
}
void AutoNavigationHandler::updateCamera(double deltaTime) {
ghoul_assert(camera() != nullptr, "Camera must not be nullptr");
if (!_isPlaying || _pathSegments.empty()) return;
PathSegment cps = currentPathSegment();
// INTERPOLATE (TODO: make a function, and allow different methods)
double t = (_currentTime - cps.startTime) / cps.duration;
t = transferfunctions::cubicEaseInOut(t); // TEST
t = std::max(0.0, std::min(t, 1.0));
// TODO: don't set every frame and
// Set anchor node in orbitalNavigator, to render visible nodes and
// add possibility to navigate when we reach the end.
CameraState cs = (t < 0.5) ? cps.start : cps.end;
global::navigationHandler.orbitalNavigator().setAnchorNode(cs.referenceNode);
// TODO: add different ways to interpolate later
glm::dvec3 cameraPosition = cps.start.position * (1.0 - t) + cps.end.position * t;
glm::dquat cameraRotation =
glm::slerp(cps.start.rotation, cps.end.rotation, t);
camera()->setPositionVec3(cameraPosition);
camera()->setRotation(cameraRotation);
_currentTime += deltaTime;
// reached the end of the path => stop playing
if (_currentTime > _pathDuration) {
_isPlaying = false;
// TODO: implement suitable stop behaviour
}
}
void AutoNavigationHandler::createPath(PathSpecification& spec) {
clearPath();
bool success = true;
@@ -110,18 +74,69 @@ void AutoNavigationHandler::createPath(PathSpecification& spec) {
const Instruction& ins = spec.instructions()->at(i);
success = handleInstruction(ins, i);
if (!success)
if (!success)
break;
}
if (success) {
LINFO("Succefully generated camera path. Starting.");
if (success)
startPath();
}
else
else
LINFO("Could not create path.");
}
void AutoNavigationHandler::updateCamera(double deltaTime) {
ghoul_assert(camera() != nullptr, "Camera must not be nullptr");
if (!_isPlaying || _pathSegments.empty()) return;
PathSegment cps = currentPathSegment();
// Interpolation variable
double t = (_currentTime - cps.startTime()) / cps.duration();
t = std::max(0.0, std::min(t, 1.0));
// TODO: don't set every frame
// Set anchor node in orbitalNavigator, to render visible nodes and
// add possibility to navigate when we reach the end.
CameraState cs = (t < 0.5) ? cps.start() : cps.end();
global::navigationHandler.orbitalNavigator().setAnchorNode(cs.referenceNode);
glm::dvec3 cameraPosition = cps.getPositionAt(t);
glm::dquat cameraRotation = cps.getRotationAt(t);
camera()->setPositionVec3(cameraPosition);
camera()->setRotation(cameraRotation);
_currentTime += deltaTime;
// reached the end of the path => stop playing
if (_currentTime > _pathDuration) {
_isPlaying = false;
// TODO: implement suitable stop behaviour
}
}
//TODO: remove! No londer used
void AutoNavigationHandler::addToPath(const SceneGraphNode* node, const double duration) {
ghoul_assert(node != nullptr, "Target node must not be nullptr");
ghoul_assert(duration > 0, "Duration must be larger than zero.");
CameraState start = getStartState();
glm::dvec3 targetPos = computeTargetPositionAtNode(node, start.position);
CameraState end = cameraStateFromTargetPosition(
targetPos, node->worldPosition(), node->identifier());
// compute startTime
double startTime = 0.0;
if (!_pathSegments.empty()) {
PathSegment last = _pathSegments.back();
startTime = last.startTime() + last.duration();
}
PathSegment newSegment{ start, end, duration, startTime };
_pathSegments.push_back(newSegment);
}
void AutoNavigationHandler::clearPath() {
_pathSegments.clear();
_pathDuration = 0.0;
@@ -133,12 +148,52 @@ void AutoNavigationHandler::startPath() {
_pathDuration = 0.0;
for (auto ps : _pathSegments) {
_pathDuration += ps.duration;
_pathDuration += ps.duration();
}
_currentTime = 0.0;
_isPlaying = true;
}
glm::dvec3 AutoNavigationHandler::computeTargetPositionAtNode(
const SceneGraphNode* node, glm::dvec3 prevPos, std::optional<double> height)
{
glm::dvec3 targetPos = node->worldPosition();
glm::dvec3 targetToPrevVector = prevPos - targetPos;
double radius = static_cast<double>(node->boundingSphere());
double desiredDistance;
if (height.has_value()) {
desiredDistance = height.value();
}
else {
desiredDistance = 2 * radius;
}
// TODO: compute actual distance above surface and validate negative values
// move target position out from surface, along vector to camera
targetPos += glm::normalize(targetToPrevVector) * (radius + desiredDistance);
return targetPos;
}
CameraState AutoNavigationHandler::cameraStateFromTargetPosition(
glm::dvec3 targetPos, glm::dvec3 lookAtPos, std::string node)
{
ghoul_assert(camera() != nullptr, "Camera must not be nullptr");
glm::dmat4 lookAtMat = glm::lookAt(
targetPos,
lookAtPos,
camera()->lookUpVectorWorldSpace()
);
glm::dquat targetRot = glm::normalize(glm::inverse(glm::quat_cast(lookAtMat)));
return CameraState{ targetPos, targetRot, node};
}
CameraState AutoNavigationHandler::getStartState() {
CameraState cs;
if (_pathSegments.empty()) {
@@ -147,7 +202,7 @@ CameraState AutoNavigationHandler::getStartState() {
cs.referenceNode = global::navigationHandler.anchorNode()->identifier();
}
else {
cs = _pathSegments.back().end;
cs = _pathSegments.back().end();
}
return cs;
@@ -155,28 +210,30 @@ CameraState AutoNavigationHandler::getStartState() {
bool AutoNavigationHandler::handleInstruction(const Instruction& instruction, int index)
{
CameraState startState = getStartState();
CameraState endState;
CameraState startState, endState;
double duration, startTime;
bool success = true;
startState = getStartState();
switch (instruction.type)
{
case InstructionType::TargetNode:
LINFO("Handle target node instruction");
success = endFromTargetNodeInstruction(
endState, startState, instruction, index
);
break;
case InstructionType::NavigationState:
LINFO("Handle navigation state instruction");
success = endFromNavigationStateInstruction(
endState, instruction, index
);
break;
default:
LERROR(fmt::format("Non-implemented instruction type: {}.", instruction.type));
success = false;
// TODO: error message
break;
}
@@ -199,7 +256,7 @@ bool AutoNavigationHandler::handleInstruction(const Instruction& instruction, in
startTime = 0.0;
if (!_pathSegments.empty()) {
PathSegment& last = _pathSegments.back();
startTime = last.startTime + last.duration;
startTime = last.startTime() + last.duration();
}
// create new path
@@ -236,28 +293,15 @@ bool AutoNavigationHandler::endFromTargetNodeInstruction(
targetPos = targetNode->worldPosition() + targetNode->worldRotationMatrix() * props->position.value();
}
else {
bool hasHeight = props->height.has_value();
// TODO: compute defualt height in a better way
double defaultHeight = 2 * targetNode->boundingSphere();
double height = hasHeight? props->height.value() : defaultHeight;
targetPos = computeTargetPositionAtNode(
targetNode,
prevState.position,
height
props->height
);
}
glm::dmat4 lookAtMat = glm::lookAt(
targetPos,
targetNode->worldPosition(),
camera()->lookUpVectorWorldSpace()
);
glm::dquat targetRot = glm::normalize(glm::inverse(glm::quat_cast(lookAtMat)));
endState = CameraState{ targetPos, targetRot, identifier };
endState = cameraStateFromTargetPosition(
targetPos, targetNode->worldPosition(), identifier);
return true;
}
@@ -313,20 +357,4 @@ bool AutoNavigationHandler::endFromNavigationStateInstruction(
return true;
}
glm::dvec3 AutoNavigationHandler::computeTargetPositionAtNode(
const SceneGraphNode* node, glm::dvec3 prevPos, double height)
{
// TODO: compute actual distance above surface and validate negative values
glm::dvec3 targetPos = node->worldPosition();
glm::dvec3 targetToPrevVector = prevPos - targetPos;
double radius = static_cast<double>(node->boundingSphere());
// move target position out from surface, along vector to camera
targetPos += glm::normalize(targetToPrevVector) * (radius + height);
return targetPos;
}
} // namespace openspace::autonavigation

View File

@@ -25,6 +25,7 @@
#ifndef __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__
#define __OPENSPACE_MODULE___AUTONAVIGATIONHANDLER___H__
#include <modules/autonavigation/pathsegment.h>
#include <modules/autonavigation/pathspecification.h>
#include <openspace/interaction/interpolator.h>
#include <openspace/properties/propertyowner.h>
@@ -37,18 +38,7 @@ namespace openspace {
namespace openspace::autonavigation {
struct CameraState {
glm::dvec3 position;
glm::dquat rotation;
std::string referenceNode;
};
struct PathSegment {
CameraState start;
CameraState end;
double duration;
double startTime;
};
struct CameraState;
class AutoNavigationHandler : public properties::PropertyOwner {
public:
@@ -62,23 +52,27 @@ public:
const double pathDuration() const;
PathSegment& currentPathSegment();
void updateCamera(double deltaTime);
void createPath(PathSpecification& spec);
void updateCamera(double deltaTime);
void addToPath(const SceneGraphNode* node, double duration = 5.0); // TODO: remove
void clearPath();
void startPath();
// TODO: move to privates
glm::dvec3 computeTargetPositionAtNode(const SceneGraphNode* node,
const glm::dvec3 prevPos, std::optional<double> height = std::nullopt);
// TODO: move to privates
CameraState cameraStateFromTargetPosition(glm::dvec3 targetPos,
glm::dvec3 lookAtPos, std::string node);
private:
CameraState getStartState();
bool handleInstruction(const Instruction& instruction, int index);
bool endFromTargetNodeInstruction(CameraState& endState, CameraState& prevState, const Instruction& instruction, int index);
bool endFromNavigationStateInstruction(CameraState& endState, const Instruction& instruction, int index);
glm::dvec3 computeTargetPositionAtNode(const SceneGraphNode* node,
glm::dvec3 prevPos, double height);
std::vector<PathSegment> _pathSegments;
double _pathDuration;

View File

@@ -0,0 +1,134 @@
/*****************************************************************************************
* *
* 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/helperfunctions.h>
namespace openspace::autonavigation::helpers {
// Shift and scale to a subinterval [start,end]
double shiftAndScale(double t, double start, double end) {
ghoul_assert(0.0 < start && start < end && end < 1.0,
"Values must be 0.0 < start < end < 1.0!");
double tScaled = t / (end - start) - start;
return std::max(0.0, std::min(tScaled, 1.0));
}
} // helpers
namespace openspace::autonavigation::easingfunctions {
double linear(double t) { return t; };
double step(double t) { return (t > 0.5); };
double circularEaseOut(double p){
return sqrt((2 - p) * p);
}
double cubicEaseIn(double t) { return (t*t*t); };
double cubicEaseOut(double t) {
double p = 1 - t;
return (p*p*p);
}
double cubicEaseInOut(double t) {
if (t < 0.5) {
return 4 * t * t * t;
}
else {
double f = ((2 * t) - 2);
return 0.5 * f * f * f + 1;
}
}
double quadraticEaseInOut(double t) {
if (t < 0.5) {
return 2 * t * t;
}
else {
return (-2 * t * t) + (4 * t) - 1;
}
}
double exponentialEaseInOut(double t) {
if (t == 0.0 || t == 1.0) return t;
if (t < 0.5) {
return 0.5 * glm::pow(2, (20 * t) - 10);
}
else {
return -0.5 * glm::pow(2, (-20 * t) + 10) + 1;
}
}
} // easingfunctions
namespace openspace::autonavigation::interpolator {
// TODO: make into template function
glm::dvec3 cubicBezier(double t, const glm::dvec3 &cp1, const glm::dvec3 &cp2,
const glm::dvec3 &cp3, const glm::dvec3 &cp4 )
{
double a = 1.0 - t;
return cp1 * a * a * a
+ cp2 * t * a * a * 3.0
+ cp3 * t * t * a * 3.0
+ cp4 * t * t * t;
}
glm::dvec3 piecewiseCubicBezier(double t, const std::vector<glm::dvec3> &controlPoints) {
size_t n = controlPoints.size();
ghoul_assert(n > 4, "Minimum of four control points needed for interpolation!");
double n_seg = (n - 1.0) / 3.0;
ghoul_assert(std::fmod(n_seg, 1.0) == 0, "A vector containing 3n + 1 control points must be provided!");
// for control points equally spaced in time
double t_seg = std::fmod(t * n_seg, 1.0);
t_seg = std::max(0.0, std::min(t_seg, 1.0));
size_t idx = std::floor(t * n_seg) * 3;
return cubicBezier(t_seg, controlPoints[idx], controlPoints[idx + 1],
controlPoints[idx + 2], controlPoints[idx + 3]);
}
glm::dvec3 piecewiseLinear(double t, const std::vector<glm::dvec3> &controlPoints) {
size_t n = controlPoints.size();
ghoul_assert(n > 2, "Minimum of two control points needed for interpolation!");
size_t n_seg = n - 1;
// for control points equally spaced in time
double t_seg = std::fmod( t*n_seg, 1.0 );
t_seg = std::max(0.0, std::min(t_seg, 1.0));
size_t idx = std::floor(t*n_seg);
return (1.0 - t_seg) * controlPoints[idx] + t_seg * controlPoints[idx + 1];
}
} // interpolator

View File

@@ -0,0 +1,75 @@
/*****************************************************************************************
* *
* 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___EASINGFUNCTIONS___H__
#define __OPENSPACE_MODULE___EASINGFUNCTIONS___H__
#include <ghoul/glm.h>
#include <ghoul/misc/assert.h>
#include <ghoul/logging/logmanager.h>
#include <vector>
#include <cmath>
namespace openspace::autonavigation::helpers {
// Make interpolator parameter t [0,1] progress only inside a subinterval
double shiftAndScale(double t, double newStart, double newEnd);
} // helpers
namespace openspace::autonavigation::easingfunctions {
// Based on functions from https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
double linear(double t);
double step(double t);
double circularEaseOut(double p);
double cubicEaseIn(double t);
double cubicEaseOut(double t);
double cubicEaseInOut(double t);
double quadraticEaseInOut(double t);
double exponentialEaseInOut(double t);
}
// TODO: include interpolator.h to helperfunctions
// error when interpolator.h is included and used both here and in pathsegment
namespace openspace::autonavigation::interpolator {
glm::dvec3 cubicBezier(double t, const glm::dvec3 &cp1, const glm::dvec3 &cp2,
const glm::dvec3 &cp3, const glm::dvec3 &cp4);
glm::dvec3 piecewiseCubicBezier(double t, const std::vector<glm::dvec3> &controlPoints);
glm::dvec3 piecewiseLinear(double t, const std::vector<glm::dvec3> &controlPoints);
} // namespace
#endif

View File

@@ -0,0 +1,186 @@
/*****************************************************************************************
* *
* 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/pathsegment.h>
#include <modules/autonavigation/helperfunctions.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/query/query.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <ghoul/Misc/interpolator.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "PathSegment";
} // namespace
namespace openspace::autonavigation {
PathSegment::PathSegment(
CameraState start, CameraState end, double duration, double startTime, CurveType type)
: _start(start), _end(end), _duration(duration), _startTime(startTime), _curveType(type)
{
switch(_curveType) {
case Bezier:
generateBezier();
break;
case Bezier2:
generateBezier2();
break;
case Linear:
break;
case Linear2:
generateLinear2();
break;
default:
LERROR(fmt::format("Cannot create curve of type {}. Type does not exist!", _curveType));
}
}
CameraState PathSegment::start() const { return _start; }
CameraState PathSegment::end() const { return _end; }
double PathSegment::duration() const { return _duration; }
double PathSegment::startTime() const { return _startTime; }
glm::vec3 PathSegment::getPositionAt(double t) {
t = easingfunctions::cubicEaseInOut(t);
switch(_curveType) {
case Bezier:
return interpolator::cubicBezier(t,
_controlPoints[0], _controlPoints[1], _controlPoints[2], _controlPoints[3]);
break;
case Bezier2:
return interpolator::piecewiseCubicBezier(t, _controlPoints);
break;
case Linear:
return ghoul::interpolateLinear(t, _start.position, _end.position);
break;
case Linear2:
return interpolator::piecewiseLinear(t, _controlPoints);
break;
default:
LERROR(fmt::format("Cannot get position for curve type {}. Type does not exist!", _curveType));
}
}
glm::dquat PathSegment::getRotationAt(double t) {
double tRot = helpers::shiftAndScale(t, 0.1, 0.9);
tRot = easingfunctions::cubicEaseInOut(tRot);
switch (_curveType) {
case Linear2:
return getLookAtRotation(
tRot,
getPositionAt(t),
global::navigationHandler.camera()->lookUpVectorWorldSpace()
);
break;
default:
return glm::slerp(_start.rotation, _end.rotation, tRot);
}
}
glm::dquat PathSegment::getLookAtRotation(double t, glm::dvec3 currentPos, glm::dvec3 up) {
glm::dvec3 startLookAtPos = sceneGraphNode(_start.referenceNode)->worldPosition();
glm::dvec3 endLookAtPos = sceneGraphNode(_end.referenceNode)->worldPosition();
glm::dvec3 lookAtPos = ghoul::interpolateLinear(t, startLookAtPos, endLookAtPos);
glm::dmat4 lookAtMat = glm::lookAt(
currentPos,
lookAtPos,
up
);
return glm::normalize(glm::inverse(glm::quat_cast(lookAtMat)));
}
// A single bezier segment with four control points
void PathSegment::generateBezier() {
glm::dvec3 startNodePos = sceneGraphNode(_start.referenceNode)->worldPosition();
glm::dvec3 endNodePos = sceneGraphNode(_end.referenceNode)->worldPosition();
// vectors pointing away from target nodes
glm::dvec3 startDirection =_start.position - startNodePos;
glm::dvec3 endDirection = _end.position - endNodePos;
_controlPoints.push_back(_start.position);
_controlPoints.push_back(_start.position + 10.0 * startDirection);
_controlPoints.push_back(_end.position + 10.0 * endDirection);
_controlPoints.push_back(_end.position);
}
void PathSegment::generateBezier2() {
// START:
glm::dvec3 startNodePos = sceneGraphNode(_start.referenceNode)->worldPosition();
glm::dvec3 startDirection = _start.position - startNodePos;
// END:
glm::dvec3 endNodePos = sceneGraphNode(_end.referenceNode)->worldPosition();
glm::dvec3 endDirection = _end.position - endNodePos;
// MIDDLE: one knot and two control points parallell to target nodes
glm::dvec3 AB = endNodePos - startNodePos;
glm::dvec3 C = normalize(startDirection + endDirection);
glm::dvec3 CparAB = glm::dot(C, normalize(AB))* normalize(AB);
glm::dvec3 CortAB = normalize(C - CparAB);
double d = length(AB);
// TODO: set points that actually look good
_controlPoints.push_back(_start.position);
_controlPoints.push_back(_start.position + 2.0 * startDirection);
_controlPoints.push_back(_start.position + 1.5 * d * CortAB);
_controlPoints.push_back(_start.position + 1.5 * d * CortAB + 0.5 * AB);
_controlPoints.push_back(_end.position + 1.5 * d * CortAB);
_controlPoints.push_back(_end.position + 2.0 * endDirection);
_controlPoints.push_back(_end.position);
}
void PathSegment::generateLinear2() {
// START:
glm::dvec3 startNodePos = sceneGraphNode(_start.referenceNode)->worldPosition();
glm::dvec3 startDirection = _start.position - startNodePos;
// END:
glm::dvec3 endNodePos = sceneGraphNode(_end.referenceNode)->worldPosition();
glm::dvec3 endDirection = _end.position - endNodePos;
// MIDDLE:
glm::dvec3 AB = endNodePos - startNodePos;
glm::dvec3 C = normalize(startDirection + endDirection);
glm::dvec3 CparAB = glm::dot(C, normalize(AB))* normalize(AB);
glm::dvec3 CortAB = normalize(C - CparAB);
double d = length(AB);
_controlPoints.push_back(_start.position);
_controlPoints.push_back(_start.position + 2.0 * d * CortAB + 0.5 * AB); //TODO: use scale instead of 2.0
_controlPoints.push_back(_end.position);
}
} // namespace openspace::autonavigation

View File

@@ -0,0 +1,74 @@
/*****************************************************************************************
* *
* 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___PATHSEGMENT___H__
#define __OPENSPACE_MODULE___PATHSEGMENT___H__
#include <ghoul/glm.h>
#include <vector>
namespace openspace::autonavigation {
struct CameraState {
glm::dvec3 position;
glm::dquat rotation;
std::string referenceNode;
};
enum CurveType {
Bezier,
Bezier2,
Linear,
Linear2
};
class PathSegment {
public:
PathSegment(CameraState start, CameraState end, double duration, double startTime, CurveType type = Bezier);
CameraState start() const;
CameraState end() const;
double duration() const;
double startTime() const;
glm::vec3 getPositionAt(double t);
glm::dquat getRotationAt(double t);
glm::dquat getLookAtRotation(double t, glm::dvec3 currentPos, glm::dvec3 up);
private:
void generateBezier();
void generateBezier2();
void generateLinear2();
CameraState _start;
CameraState _end;
double _duration;
double _startTime;
CurveType _curveType;
std::vector<glm::dvec3> _controlPoints;
};
} // namespace openspace::autonavigation
#endif // __OPENSPACE_MODULE___PATHSEGMENT___H__