mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
feature/time-refactor (#294)
- Change Time class to become a non-singleton - Move ownership of the current time to TimeManager(instead of singleton access). - Store the Time as a Syncable in TimeManager instead of representing all member variables of Time as Syncables. - Pass a Time object around in the update/render methods, so that renderables don't have to query the OpenSpaceEngine to know if time is paused or if it jumped. - Introduce Timeline and Keyframe classes - Make use of Timelineand Keyframeclasses in KeyframeInteractionMode and TimeManager - Added basic unit tests for Timelineand Keyframe Future work: Add interpolation schemes for keyframes. Possibly use keyframes+interpolation feature to tween/morph properties, or figure out if this should be a separate mechanism.
This commit is contained in:
@@ -65,7 +65,6 @@ public:
|
||||
|
||||
// Interaction mode setters
|
||||
void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict);
|
||||
void setInteractionMode(const std::string& interactionModeKey);
|
||||
InteractionMode* interactionMode();
|
||||
|
||||
void goToChunk(int x, int y, int level);
|
||||
@@ -73,9 +72,10 @@ public:
|
||||
|
||||
void resetKeyBindings();
|
||||
|
||||
void addKeyframe(const datamessagestructures::CameraKeyframe &kf);
|
||||
void addKeyframe(double timestamp, KeyframeInteractionMode::CameraPose pose);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
size_t nKeyframes() const;
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& keyframes() const;
|
||||
|
||||
void bindKeyLocal(
|
||||
@@ -134,7 +134,7 @@ private:
|
||||
|
||||
std::string generateJson() const override;
|
||||
|
||||
void setInteractionMode(std::shared_ptr<InteractionMode> interactionMode);
|
||||
void setInteractionMode(InteractionMode* interactionMode);
|
||||
|
||||
bool _cameraUpdatedFromScript = false;
|
||||
|
||||
@@ -143,14 +143,18 @@ private:
|
||||
std::unique_ptr<InputState> _inputState;
|
||||
Camera* _camera;
|
||||
|
||||
std::shared_ptr<InteractionMode> _currentInteractionMode;
|
||||
InteractionMode* _currentInteractionMode;
|
||||
|
||||
std::map<std::string, std::shared_ptr<InteractionMode>> _interactionModes;
|
||||
std::shared_ptr<OrbitalInteractionMode::MouseStates> _mouseStates;
|
||||
|
||||
std::unique_ptr<OrbitalInteractionMode> _orbitalInteractionMode;
|
||||
std::unique_ptr<GlobeBrowsingInteractionMode> _globeBrowsingInteractionMode;
|
||||
std::unique_ptr<KeyframeInteractionMode> _keyframeInteractionMode;
|
||||
|
||||
// Properties
|
||||
properties::StringProperty _origin;
|
||||
|
||||
properties::OptionProperty _interactionModeOption;
|
||||
|
||||
properties::BoolProperty _rotationalFriction;
|
||||
properties::BoolProperty _horizontalFriction;
|
||||
properties::BoolProperty _verticalFriction;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <openspace/util/timeline.h>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
#include <modules/globebrowsing/tile/tileindex.h>
|
||||
@@ -80,14 +81,6 @@ namespace interaction {
|
||||
void mousePositionCallback(double mouseX, double mouseY);
|
||||
void mouseScrollWheelCallback(double mouseScrollDelta);
|
||||
|
||||
// Mutators
|
||||
void addKeyframe(const datamessagestructures::CameraKeyframe &kf);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
void clearOldKeyframes();
|
||||
|
||||
static bool compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b);
|
||||
|
||||
// Accessors
|
||||
const std::list<std::pair<Key, KeyModifier> >& getPressedKeys() const;
|
||||
const std::list<MouseButton>& getPressedMouseButtons() const;
|
||||
@@ -104,9 +97,6 @@ namespace interaction {
|
||||
std::list<MouseButton> _mouseButtonsDown;
|
||||
glm::dvec2 _mousePosition;
|
||||
double _mouseScrollDelta;
|
||||
|
||||
// Remote input via keyframes
|
||||
std::vector<datamessagestructures::CameraKeyframe> _keyframes;
|
||||
};
|
||||
|
||||
|
||||
@@ -194,16 +184,23 @@ protected:
|
||||
class KeyframeInteractionMode : public InteractionMode
|
||||
{
|
||||
public:
|
||||
struct CameraPose {
|
||||
glm::dvec3 position;
|
||||
glm::quat rotation;
|
||||
std::string focusNode;
|
||||
bool followFocusNodeRotation;
|
||||
};
|
||||
|
||||
KeyframeInteractionMode();
|
||||
~KeyframeInteractionMode();
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
Timeline<CameraPose>& timeline();
|
||||
|
||||
private:
|
||||
std::vector<datamessagestructures::CameraKeyframe> _keyframes;
|
||||
double _currentKeyframeTime;
|
||||
Timeline<CameraPose> _cameraPoseTimeline;
|
||||
};
|
||||
|
||||
class GlobeBrowsingInteractionMode;
|
||||
|
||||
@@ -55,8 +55,6 @@ namespace openspace {
|
||||
* The synchronization of the simulation time requires
|
||||
*/
|
||||
|
||||
class SyncBuffer;
|
||||
|
||||
class Time {
|
||||
public:
|
||||
/**
|
||||
@@ -90,20 +88,6 @@ public:
|
||||
|
||||
static Time now();
|
||||
|
||||
/**
|
||||
* Returns the reference to the Time singleton object.
|
||||
* \return The reference to the Time singleton object
|
||||
* \pre The Time singleton must have been initialized
|
||||
*/
|
||||
static Time& ref();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the singleton has been successfully initialized,
|
||||
* <code>false</code> otherwise
|
||||
* \return <code>true</code> if the singleton has been successfully initialized,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
static bool isInitialized();
|
||||
|
||||
/**
|
||||
* Sets the current time to the specified value in seconds past the J2000 epoch. This
|
||||
@@ -210,15 +194,10 @@ public:
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
std::vector<Syncable*> getSyncables();
|
||||
|
||||
private:
|
||||
static Time* _instance; ///< The singleton instance
|
||||
|
||||
SyncData<double> _time;
|
||||
SyncData<double> _dt;
|
||||
SyncData<bool> _timeJumped;
|
||||
|
||||
double _time;
|
||||
double _dt;
|
||||
bool _timeJumped;
|
||||
bool _timePaused = false;
|
||||
};
|
||||
|
||||
|
||||
96
include/openspace/util/timeline.h
Normal file
96
include/openspace/util/timeline.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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_CORE___TIMELINE___H__
|
||||
#define __OPENSPACE_CORE___TIMELINE___H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <cstddef>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
/**
|
||||
* Base class for keyframes
|
||||
*/
|
||||
struct KeyframeBase {
|
||||
size_t id;
|
||||
double timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Templated class for keyframes containing data
|
||||
*/
|
||||
template <typename T>
|
||||
struct Keyframe : public KeyframeBase {
|
||||
Keyframe(size_t i, double t, T p)
|
||||
: KeyframeBase{i, t}
|
||||
, data(p)
|
||||
{}
|
||||
T data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Templated class for timelines
|
||||
*/
|
||||
template <typename T>
|
||||
class Timeline {
|
||||
public:
|
||||
Timeline();
|
||||
virtual ~Timeline();
|
||||
void addKeyframe(double time, T data);
|
||||
void clearKeyframes();
|
||||
void removeKeyframe(size_t id);
|
||||
void removeKeyframesBefore(double timestamp, bool inclusive = false);
|
||||
void removeKeyframesAfter(double timestamp, bool inclusive = false);
|
||||
void removeKeyframesBetween(double begin, double end, bool inclusiveBegin = false, bool inclusiveEnd = false);
|
||||
size_t nKeyframes() const;
|
||||
const Keyframe<T>* firstKeyframeAfter(double timestamp, bool inclusive = false) const;
|
||||
const Keyframe<T>* lastKeyframeBefore(double timestamp, bool inclusive = false) const;
|
||||
const std::deque<Keyframe<T>>& keyframes() const;
|
||||
private:
|
||||
size_t _nextKeyframeId;
|
||||
std::deque<Keyframe<T>> _keyframes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if the timestamp of a is smaller the timestamp of b.
|
||||
*/
|
||||
bool compareKeyframeTimes(const KeyframeBase& a, const KeyframeBase& b);
|
||||
|
||||
/**
|
||||
* Return true if a is smaller than the timestamp of b.
|
||||
*/
|
||||
bool compareTimeWithKeyframeTime(double a, const KeyframeBase& b);
|
||||
|
||||
/**
|
||||
* Return true if the timestamp of a is smaller than b.
|
||||
*/
|
||||
bool compareKeyframeTimeWithTime(const KeyframeBase& a, double b);
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#include <openspace/util/timeline.inl>;
|
||||
|
||||
#endif // __OPENSPACE_CORE___TIMELINE___H__
|
||||
121
include/openspace/util/timeline.inl
Normal file
121
include/openspace/util/timeline.inl
Normal file
@@ -0,0 +1,121 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
namespace openspace {
|
||||
|
||||
template <typename T>
|
||||
Timeline<T>::Timeline()
|
||||
: _nextKeyframeId(1)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
Timeline<T>::~Timeline() {}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::addKeyframe(double timestamp, T data) {
|
||||
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, data);
|
||||
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), keyframe, &compareKeyframeTimes);
|
||||
_keyframes.insert(iter, keyframe);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::removeKeyframesAfter(double timestamp, bool inclusive) {
|
||||
auto iter = inclusive
|
||||
? std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime)
|
||||
: std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime);
|
||||
|
||||
_keyframes.erase(iter, _keyframes.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::removeKeyframesBefore(double timestamp, bool inclusive) {
|
||||
auto iter = inclusive
|
||||
? std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime)
|
||||
: std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime);
|
||||
|
||||
_keyframes.erase(_keyframes.begin(), iter);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::removeKeyframesBetween(double begin, double end, bool inclusiveBegin, bool inclusiveEnd) {
|
||||
auto beginIter = inclusiveBegin
|
||||
? std::lower_bound(_keyframes.begin(), _keyframes.end(), begin, &compareKeyframeTimeWithTime)
|
||||
: std::upper_bound(_keyframes.begin(), _keyframes.end(), begin, &compareTimeWithKeyframeTime);
|
||||
|
||||
auto endIter = inclusiveEnd
|
||||
? std::upper_bound(beginIter, _keyframes.end(), end, &compareTimeWithKeyframeTime)
|
||||
: std::lower_bound(beginIter, _keyframes.end(), end, &compareKeyframeTimeWithTime);
|
||||
|
||||
_keyframes.erase(beginIter, endIter);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::clearKeyframes() {
|
||||
_keyframes.clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::removeKeyframe(size_t id) {
|
||||
_keyframes.erase(std::remove_if(_keyframes.begin(), _keyframes.end(), [id] (Keyframe<T> keyframe) {
|
||||
return keyframe.id == id;
|
||||
}), _keyframes.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t Timeline<T>::nKeyframes() const {
|
||||
return _keyframes.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const Keyframe<T>* Timeline<T>::firstKeyframeAfter(double timestamp, bool inclusive) const {
|
||||
auto it = inclusive
|
||||
? std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime)
|
||||
: std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime);
|
||||
if (it == _keyframes.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &(*it);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const Keyframe<T>* Timeline<T>::lastKeyframeBefore(double timestamp, bool inclusive) const {
|
||||
auto it = inclusive
|
||||
? std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime)
|
||||
: std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime);
|
||||
if (it == _keyframes.begin()) {
|
||||
return nullptr;
|
||||
}
|
||||
it--;
|
||||
return &(*it);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
const std::deque<Keyframe<T>>& Timeline<T>::keyframes() const {
|
||||
return _keyframes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -27,24 +27,26 @@
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
#include <openspace/util/timeline.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/syncdata.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class TimeManager {
|
||||
public:
|
||||
Time& time();
|
||||
std::vector<Syncable*> getSyncables();
|
||||
void preSynchronization(double dt);
|
||||
void addKeyframe(const datamessagestructures::TimeKeyframe& kf);
|
||||
void addKeyframe(double timestamp, Time kf);
|
||||
void removeKeyframesBefore(double timestamp);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& keyframes() const;
|
||||
size_t nKeyframes() const;
|
||||
private:
|
||||
Timeline<Time> _timeline;
|
||||
SyncData<Time> _currentTime;
|
||||
void consumeKeyframes(double dt);
|
||||
std::deque<datamessagestructures::TimeKeyframe> _keyframes;
|
||||
static bool compareKeyframeTimes(
|
||||
const datamessagestructures::TimeKeyframe& a,
|
||||
const datamessagestructures::TimeKeyframe& b);
|
||||
double _latestConsumedTimestamp;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/powerscaledcoordinate.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -44,11 +45,8 @@ struct TransformData {
|
||||
|
||||
struct UpdateData {
|
||||
TransformData modelTransform;
|
||||
double time;
|
||||
double delta;
|
||||
bool timePaused;
|
||||
bool isTimeJump;
|
||||
bool doPerformanceMeasurement;
|
||||
const Time time;
|
||||
const bool doPerformanceMeasurement;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,6 +55,7 @@ struct RenderData {
|
||||
// psc position to be removed in favor of the double precision position defined in
|
||||
// the translation in transform.
|
||||
psc position;
|
||||
const Time time;
|
||||
bool doPerformanceMeasurement;
|
||||
int renderBinMask;
|
||||
TransformData modelTransform;
|
||||
|
||||
@@ -230,7 +230,7 @@ void RenderableSphericalGrid::render(const RenderData& data){
|
||||
}
|
||||
|
||||
void RenderableSphericalGrid::update(const UpdateData& data) {
|
||||
_parentMatrix = SpiceManager::ref().positionTransformMatrix("IAU_JUPITER", "GALACTIC", data.time);
|
||||
_parentMatrix = SpiceManager::ref().positionTransformMatrix("IAU_JUPITER", "GALACTIC", data.time.j2000Seconds());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ void RenderableTrailOrbit::update(const UpdateData& data) {
|
||||
|
||||
// 2
|
||||
// Write the current location into the floating position
|
||||
glm::vec3 p = _translation->position(data.time);
|
||||
glm::vec3 p = _translation->position(data.time.j2000Seconds());
|
||||
_vertexArray[_primaryRenderInformation.first] = { p.x, p.y, p.z };
|
||||
|
||||
glBindVertexArray(_primaryRenderInformation._vaoID);
|
||||
@@ -316,22 +316,22 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails(
|
||||
{
|
||||
// If we are doing a time jump, it is in general faster to recalculate everything
|
||||
// than to only update parts of the array
|
||||
if (data.isTimeJump) {
|
||||
if (data.time.timeJumped()) {
|
||||
_needsFullSweep = true;
|
||||
}
|
||||
if (_needsFullSweep) {
|
||||
fullSweep(data.time);
|
||||
fullSweep(data.time.j2000Seconds());
|
||||
return { true, UpdateReport::All } ;
|
||||
}
|
||||
|
||||
// When time stands still (at the iron hill), we don't need to perform any work
|
||||
if (data.delta == 0.0) {
|
||||
if (data.time.deltaTime() == 0.0) {
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
double secondsPerPoint = _period / (_resolution - 1);
|
||||
// How much time has passed since the last permanent point
|
||||
double delta = data.time - _lastPointTime;
|
||||
double delta = data.time.j2000Seconds() - _lastPointTime;
|
||||
|
||||
// We'd like to test for equality with 0 here, but due to rounding issues, we won't
|
||||
// get there. If this check is not here, we will trigger the positive or negative
|
||||
@@ -357,7 +357,7 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails(
|
||||
// If we would need to generate more new points than there are total points in the
|
||||
// array, it is faster to regenerate the entire array
|
||||
if (nNewPoints >= _resolution) {
|
||||
fullSweep(data.time);
|
||||
fullSweep(data.time.j2000Seconds());
|
||||
return { true, UpdateReport::All };
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails(
|
||||
// If we would need to generate more new points than there are total points in the
|
||||
// array, it is faster to regenerate the entire array
|
||||
if (nNewPoints >= _resolution) {
|
||||
fullSweep(data.time);
|
||||
fullSweep(data.time.j2000Seconds());
|
||||
return { true, UpdateReport::All };
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ void RenderableTrailTrajectory::update(const UpdateData& data) {
|
||||
// If only trail so far should be rendered, we need to find the corresponding time
|
||||
// in the array and only render it until then
|
||||
_primaryRenderInformation.first = 0;
|
||||
double t = (data.time - _start) / (_end - _start);
|
||||
double t = (data.time.j2000Seconds() - _start) / (_end - _start);
|
||||
_primaryRenderInformation.count = std::min(
|
||||
static_cast<GLsizei>(ceil(_vertexArray.size() * t)),
|
||||
static_cast<GLsizei>(_vertexArray.size() - 1)
|
||||
@@ -264,7 +264,7 @@ void RenderableTrailTrajectory::update(const UpdateData& data) {
|
||||
|
||||
// If we are inside the valid time, we additionally want to draw a line from the last
|
||||
// correct point to the current location of the object
|
||||
if (data.time >= _start && data.time <= _end && !_renderFullTrail) {
|
||||
if (data.time.j2000Seconds() >= _start && data.time.j2000Seconds() <= _end && !_renderFullTrail) {
|
||||
// Copy the last valid location
|
||||
glm::dvec3 v0(
|
||||
_vertexArray[_primaryRenderInformation.count - 1].x,
|
||||
@@ -273,7 +273,7 @@ void RenderableTrailTrajectory::update(const UpdateData& data) {
|
||||
);
|
||||
|
||||
// And get the current location of the object
|
||||
glm::dvec3 p = _translation->position(data.time);
|
||||
glm::dvec3 p = _translation->position(data.time.j2000Seconds());
|
||||
glm::dvec3 v1 = { p.x, p.y, p.z };
|
||||
|
||||
// Comptue the difference between the points in double precision
|
||||
|
||||
@@ -180,7 +180,7 @@ void RenderableGlobe::render(const RenderData& data) {
|
||||
}
|
||||
|
||||
void RenderableGlobe::update(const UpdateData& data) {
|
||||
_time = data.time;
|
||||
_time = data.time.j2000Seconds();
|
||||
_distanceSwitch.update(data);
|
||||
|
||||
glm::dmat4 translation =
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
#ifdef GLOBEBROWSING_USE_GDAL
|
||||
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/timerange.h>
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
@@ -197,7 +199,7 @@ public:
|
||||
|
||||
typedef std::string TimeKey;
|
||||
|
||||
std::shared_ptr<TileProvider> getTileProvider(Time t = Time::ref());
|
||||
std::shared_ptr<TileProvider> getTileProvider(Time t = OsEng.timeManager().time());
|
||||
std::shared_ptr<TileProvider> getTileProvider(TimeKey timekey);
|
||||
|
||||
private:
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/transferfunction.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include <modules/iswa/rendering/iswabasegroup.h>
|
||||
@@ -115,7 +118,7 @@ protected:
|
||||
* this should be the data file.
|
||||
* @return true if update was successfull
|
||||
*/
|
||||
virtual bool downloadTextureResource(double timestamp = Time::ref().j2000Seconds()) = 0;
|
||||
virtual bool downloadTextureResource(double timestamp = OsEng.timeManager().time().j2000Seconds()) = 0;
|
||||
virtual bool readyToRender() const = 0;
|
||||
/**
|
||||
* should set all uniforms needed to render
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
#include <ccmc/Kameleon.h>
|
||||
#endif
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
#include <modules/kameleon/include/kameleonwrapper.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
@@ -43,6 +45,7 @@
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/properties/selectionproperty.h>
|
||||
#include <modules/iswa/ext/json/json.hpp>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
|
||||
@@ -92,7 +95,7 @@ public:
|
||||
|
||||
std::future<DownloadManager::MemoryFile> fetchImageCygnet(int id, double timestamp);
|
||||
std::future<DownloadManager::MemoryFile> fetchDataCygnet(int id, double timestamp);
|
||||
std::string iswaUrl(int id, double timestamp = Time::ref().j2000Seconds(), std::string type = "image");
|
||||
std::string iswaUrl(int id, double timestamp = OsEng.timeManager().time().j2000Seconds(), std::string type = "image");
|
||||
|
||||
std::shared_ptr<IswaBaseGroup> iswaGroup(std::string name);
|
||||
|
||||
|
||||
@@ -528,8 +528,8 @@ std::vector<unsigned int> RenderableMultiresVolume::getBuffers() {
|
||||
}*/
|
||||
|
||||
void RenderableMultiresVolume::update(const UpdateData& data) {
|
||||
_timestep++;
|
||||
_time = data.time;
|
||||
_timestep++;
|
||||
_time = data.time.j2000Seconds();
|
||||
|
||||
if (_gatheringStats) {
|
||||
std::chrono::system_clock::time_point frameEnd = std::chrono::system_clock::now();
|
||||
|
||||
@@ -240,10 +240,10 @@ void RenderableCrawlingLine::update(const UpdateData& data) {
|
||||
_source,
|
||||
//"ECLIPJ2000",
|
||||
"GALACTIC",
|
||||
data.time
|
||||
data.time.j2000Seconds()
|
||||
);
|
||||
|
||||
glm::dmat3 tm = SpiceManager::ref().frameTransformationMatrix(_instrumentName, "ECLIPJ2000", data.time);
|
||||
glm::dmat3 tm = SpiceManager::ref().frameTransformationMatrix(_instrumentName, "ECLIPJ2000", data.time.j2000Seconds());
|
||||
|
||||
//_positions[SourcePosition] = { 0.f, 0.f, 0.f, 0.f };
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
if (!isInFov) {
|
||||
// If the target is not in the field of view, we don't need to perform any
|
||||
// surface intercepts
|
||||
glm::vec3 o = orthogonalProjection(bound, data.time, target);
|
||||
glm::vec3 o = orthogonalProjection(bound, data.time.j2000Seconds(), target);
|
||||
|
||||
second = {
|
||||
{ o.x, o.y, o.z },
|
||||
@@ -426,7 +426,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
_instrument.name,
|
||||
ref.first,
|
||||
_instrument.aberrationCorrection,
|
||||
data.time,
|
||||
data.time.j2000Seconds(),
|
||||
bound
|
||||
);
|
||||
|
||||
@@ -443,7 +443,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
r.surfaceVector = SpiceManager::ref().frameTransformationMatrix(
|
||||
ref.first,
|
||||
_instrument.referenceFrame,
|
||||
data.time
|
||||
data.time.j2000Seconds()
|
||||
) * r.surfaceVector;
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
}
|
||||
else {
|
||||
// This point did not intersect the target though others did
|
||||
glm::vec3 o = orthogonalProjection(bound, data.time, target);
|
||||
glm::vec3 o = orthogonalProjection(bound, data.time.j2000Seconds(), target);
|
||||
second = {
|
||||
{ o.x, o.y, o.z },
|
||||
RenderInformation::VertexColorTypeInFieldOfView
|
||||
@@ -516,7 +516,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
_instrument.name,
|
||||
makeBodyFixedReferenceFrame(_instrument.referenceFrame).first,
|
||||
_instrument.aberrationCorrection,
|
||||
data.time,
|
||||
data.time.j2000Seconds(),
|
||||
probe
|
||||
).interceptFound;
|
||||
};
|
||||
@@ -531,7 +531,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
_instrument.name,
|
||||
ref.first,
|
||||
_instrument.aberrationCorrection,
|
||||
data.time,
|
||||
data.time.j2000Seconds(),
|
||||
probe
|
||||
);
|
||||
|
||||
@@ -539,7 +539,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
r.surfaceVector = SpiceManager::ref().frameTransformationMatrix(
|
||||
ref.first,
|
||||
_instrument.referenceFrame,
|
||||
data.time
|
||||
data.time.j2000Seconds()
|
||||
) * r.surfaceVector;
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string&
|
||||
};
|
||||
}
|
||||
else {
|
||||
const glm::vec3 o = orthogonalProjection(tBound, data.time, target);
|
||||
const glm::vec3 o = orthogonalProjection(tBound, data.time.j2000Seconds(), target);
|
||||
|
||||
_orthogonalPlane.data[indexForBounds(i) + m] = {
|
||||
{ o.x, o.y, o.z },
|
||||
@@ -1003,8 +1003,8 @@ void RenderableFov::update(const UpdateData& data) {
|
||||
_drawFOV = ImageSequencer::ref().instrumentActive(_instrument.name);
|
||||
}
|
||||
|
||||
if (_drawFOV && !data.timePaused) {
|
||||
auto t = determineTarget(data.time);
|
||||
if (_drawFOV && !data.time.paused()) {
|
||||
auto t = determineTarget(data.time.j2000Seconds());
|
||||
std::string target = t.first;
|
||||
bool inFOV = t.second;
|
||||
|
||||
@@ -1012,7 +1012,7 @@ void RenderableFov::update(const UpdateData& data) {
|
||||
updateGPU();
|
||||
|
||||
double t2 = (ImageSequencer::ref().getNextCaptureTime());
|
||||
double diff = (t2 - data.time);
|
||||
double diff = (t2 - data.time.j2000Seconds());
|
||||
_interpolationTime = 0.0;
|
||||
float interpolationStart = 7.0; //seconds before
|
||||
if (diff <= interpolationStart) {
|
||||
|
||||
@@ -277,7 +277,7 @@ void RenderableModelProjection::update(const UpdateData& data) {
|
||||
if (_depthFboProgramObject->isDirty())
|
||||
_depthFboProgramObject->rebuildFromFile();
|
||||
|
||||
_time = data.time;
|
||||
_time = data.time.j2000Seconds();
|
||||
|
||||
if (openspace::ImageSequencer::ref().isReady()) {
|
||||
openspace::ImageSequencer::ref().updateSequencer(_time);
|
||||
|
||||
@@ -159,7 +159,7 @@ void RenderablePlaneProjection::render(const RenderData& data) {
|
||||
}
|
||||
|
||||
void RenderablePlaneProjection::update(const UpdateData& data) {
|
||||
double time = data.time;
|
||||
double time = data.time.j2000Seconds();
|
||||
const Image img = openspace::ImageSequencer::ref().getLatestImageForInstrument(_instrument);
|
||||
|
||||
if (img.path == "")
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
@@ -465,7 +464,7 @@ void RenderablePlanetProjection::update(const UpdateData& data) {
|
||||
|
||||
_projectionComponent.update();
|
||||
|
||||
_time = Time::ref().j2000Seconds();
|
||||
_time = data.time.j2000Seconds();
|
||||
_capture = false;
|
||||
|
||||
if (openspace::ImageSequencer::ref().isReady()){
|
||||
|
||||
@@ -137,11 +137,11 @@ void RenderableShadowCylinder::render(const RenderData& data){
|
||||
}
|
||||
|
||||
void RenderableShadowCylinder::update(const UpdateData& data) {
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_bodyFrame, _mainFrame, data.time);
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_bodyFrame, _mainFrame, data.time.j2000Seconds());
|
||||
if (_shader->isDirty()) {
|
||||
_shader->rebuildFromFile();
|
||||
}
|
||||
createCylinder(data.time);
|
||||
createCylinder(data.time.j2000Seconds());
|
||||
}
|
||||
|
||||
glm::vec4 psc_addition(glm::vec4 v1, glm::vec4 v2) {
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/directory.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <modules/newhorizons/util/decoder.h>
|
||||
|
||||
@@ -83,14 +85,10 @@ bool ImageSequencer::isReady() {
|
||||
return _hasData;
|
||||
}
|
||||
|
||||
void ImageSequencer::updateSequencer(double time) {
|
||||
if (Time::ref().timeJumped() && Time::ref().deltaTime() == 0) {
|
||||
Time::ref().setDeltaTime(0.1);
|
||||
} // Time is not properly updated when time jump with dt = 0
|
||||
|
||||
if (_currentTime != time) {
|
||||
void ImageSequencer::updateSequencer(const Time& time) {
|
||||
if (_currentTime != time.j2000Seconds()) {
|
||||
_previousTime = _currentTime;
|
||||
_currentTime = time;
|
||||
_currentTime = time.j2000Seconds();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +277,7 @@ bool ImageSequencer::getImagePaths(std::vector<Image>& captures,
|
||||
|
||||
// check if this instance is either in range or
|
||||
// a valid candidate to recieve data
|
||||
if (!instrumentActive(instrumentRequest) && !Time::ref().timeJumped()) return false;
|
||||
if (!instrumentActive(instrumentRequest) && !OsEng.timeManager().time().timeJumped()) return false;
|
||||
|
||||
|
||||
//if (!Time::ref().timeJumped() && projectee == getCurrentTarget().second)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class Time;
|
||||
class SequenceParser;
|
||||
|
||||
/**
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
* Updates sequencer with current <code>time</code>. This is used internally for keeping
|
||||
* track of both current simulation time and the time of the previously rendered frame.
|
||||
*/
|
||||
void updateSequencer(double time);
|
||||
void updateSequencer(const Time& time);
|
||||
/**
|
||||
* Runs parser and recieves the datastructures filled by it.
|
||||
* \see SequenceParser
|
||||
|
||||
@@ -82,11 +82,11 @@ void GuiParallelComponent::renderClientWithHost() {
|
||||
ImGui::Text("%s", connectionInfo.c_str());
|
||||
renderClientCommon();
|
||||
|
||||
const std::deque<datamessagestructures::TimeKeyframe> timeKeyframes = OsEng.timeManager().keyframes();
|
||||
const std::vector<datamessagestructures::CameraKeyframe> cameraKeyframes = OsEng.interactionHandler().keyframes();
|
||||
const size_t nTimeKeyframes = OsEng.timeManager().nKeyframes();
|
||||
const size_t nCameraKeyframes = OsEng.interactionHandler().nKeyframes();
|
||||
|
||||
std::string timeKeyframeInfo = "TimeKeyframes : " + std::to_string(timeKeyframes.size());
|
||||
std::string cameraKeyframeInfo = "CameraKeyframes : " + std::to_string(cameraKeyframes.size());
|
||||
std::string timeKeyframeInfo = "TimeKeyframes : " + std::to_string(nTimeKeyframes);
|
||||
std::string cameraKeyframeInfo = "CameraKeyframes : " + std::to_string(nCameraKeyframes);
|
||||
std::string latencyStandardDeviation = "Latency standard deviation: " + std::to_string(parallel.latencyStandardDeviation()) + " s";
|
||||
|
||||
const bool resetTimeOffset = ImGui::Button("Reset time offset");
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <modules/onscreengui/include/guitimecomponent.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include "imgui.h"
|
||||
@@ -37,7 +38,7 @@ GuiTimeComponent::GuiTimeComponent()
|
||||
{}
|
||||
|
||||
void GuiTimeComponent::render() {
|
||||
float deltaTime = static_cast<float>(Time::ref().deltaTime());
|
||||
float deltaTime = static_cast<float>(OsEng.timeManager().time().deltaTime());
|
||||
|
||||
bool changed = ImGui::SliderFloat("Delta Time", &deltaTime, -50000.f, 50000.f);
|
||||
if (changed) {
|
||||
|
||||
@@ -211,7 +211,7 @@ void RenderableConstellationBounds::update(const UpdateData& data) {
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(
|
||||
_originReferenceFrame,
|
||||
"GALACTIC",
|
||||
data.time
|
||||
data.time.j2000Seconds()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -531,7 +531,7 @@ void RenderablePlanet::update(const UpdateData& data) {
|
||||
// set spice-orientation in accordance to timestamp
|
||||
_stateMatrix = data.modelTransform.rotation;
|
||||
//_stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time);
|
||||
_time = data.time;
|
||||
_time = data.time.j2000Seconds();
|
||||
}
|
||||
|
||||
void RenderablePlanet::loadTexture() {
|
||||
|
||||
@@ -119,7 +119,7 @@ void SpiceRotation::update(const UpdateData& data) {
|
||||
_matrix = SpiceManager::ref().positionTransformMatrix(
|
||||
_sourceFrame,
|
||||
_destinationFrame,
|
||||
data.time
|
||||
data.time.j2000Seconds()
|
||||
);
|
||||
}
|
||||
catch (const SpiceManager::SpiceException&) {
|
||||
|
||||
@@ -267,7 +267,7 @@ void KeplerTranslation::update(const UpdateData& data) {
|
||||
_orbitPlaneDirty = false;
|
||||
}
|
||||
|
||||
double t = data.time - _epoch;
|
||||
double t = data.time.j2000Seconds() - _epoch;
|
||||
double meanMotion = 2.0 * glm::pi<double>() / _period;
|
||||
double meanAnomaly = glm::radians(_meanAnomalyAtEpoch.value()) + t * meanMotion;
|
||||
double e = eccentricAnomaly(meanAnomaly);
|
||||
|
||||
@@ -166,7 +166,7 @@ glm::dvec3 SpiceTranslation::position() const {
|
||||
void SpiceTranslation::update(const UpdateData& data) {
|
||||
double lightTime = 0.0;
|
||||
_position = SpiceManager::ref().targetPosition(
|
||||
_target, _origin, _frame, {}, data.time, lightTime
|
||||
_target, _origin, _frame, {}, data.time.j2000Seconds(), lightTime
|
||||
) * glm::pow(10.0, 3.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void RenderableToyVolume::update(const UpdateData& data) {
|
||||
_raycaster->setColor(_color);
|
||||
_raycaster->setStepSize(_stepSize);
|
||||
_raycaster->setModelTransform(transform);
|
||||
_raycaster->setTime(data.time);
|
||||
_raycaster->setTime(data.time.j2000Seconds());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/util/task.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/taskloader.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/time.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/timeline.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/timemanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/time_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/util/timerange.cpp
|
||||
@@ -299,6 +300,8 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/task.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/taskloader.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/time.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timeline.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timeline.inl
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timerange.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h
|
||||
|
||||
@@ -177,7 +177,6 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
);
|
||||
|
||||
SpiceManager::initialize();
|
||||
Time::initialize();
|
||||
TransformationManager::initialize();
|
||||
}
|
||||
|
||||
@@ -384,7 +383,7 @@ void OpenSpaceEngine::destroy() {
|
||||
func();
|
||||
}
|
||||
|
||||
_engine->_syncEngine->removeSyncables(Time::ref().getSyncables());
|
||||
_engine->_syncEngine->removeSyncables(_engine->timeManager().getSyncables());
|
||||
_engine->_syncEngine->removeSyncables(_engine->_renderEngine->getSyncables());
|
||||
_engine->_syncEngine->removeSyncable(_engine->_scriptEngine.get());
|
||||
|
||||
@@ -396,7 +395,6 @@ void OpenSpaceEngine::destroy() {
|
||||
|
||||
delete _engine;
|
||||
FactoryManager::deinitialize();
|
||||
Time::deinitialize();
|
||||
SpiceManager::deinitialize();
|
||||
|
||||
|
||||
@@ -563,7 +561,7 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
|
||||
Scene* previousScene = _renderEngine->scene();
|
||||
if (previousScene) {
|
||||
_syncEngine->removeSyncables(Time::ref().getSyncables());
|
||||
_syncEngine->removeSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->removeSyncable(_scriptEngine.get());
|
||||
|
||||
@@ -606,7 +604,7 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
);
|
||||
}
|
||||
|
||||
_syncEngine->addSyncables(Time::ref().getSyncables());
|
||||
_syncEngine->addSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->addSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->addSyncable(_scriptEngine.get());
|
||||
|
||||
@@ -996,7 +994,7 @@ void OpenSpaceEngine::preSynchronization() {
|
||||
double dt = _windowWrapper->averageDeltaTime();
|
||||
_timeManager->preSynchronization(dt);
|
||||
|
||||
auto scheduledScripts = _scriptScheduler->progressTo(Time::ref().j2000Seconds());
|
||||
auto scheduledScripts = _scriptScheduler->progressTo(timeManager().time().j2000Seconds());
|
||||
for (auto it = scheduledScripts.first; it != scheduledScripts.second; ++it) {
|
||||
_scriptEngine->queueScript(
|
||||
*it, ScriptEngine::RemoteScripting::Yes
|
||||
|
||||
@@ -60,6 +60,15 @@ namespace {
|
||||
const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/main.hbs";
|
||||
const char* KeybindingTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/keybinding.hbs";
|
||||
const char* JsFilename = "${OPENSPACE_DATA}/web/keybindings/script.js";
|
||||
|
||||
const int IdOrbitalInteractionMode = 0;
|
||||
const char* KeyOrbitalInteractionMode = "Orbital";
|
||||
|
||||
const int IdGlobeBrowsingInteractionMode = 1;
|
||||
const char* KeyGlobeBrowsingInteractionMode = "GlobeBrowsing";
|
||||
|
||||
const int IdKeyframeInteractionMode = 2;
|
||||
const char* KeyKeyframeInteractionMode = "Keyframe";
|
||||
} // namespace
|
||||
|
||||
#include "interactionhandler_lua.inl"
|
||||
@@ -85,6 +94,11 @@ InteractionHandler::InteractionHandler()
|
||||
, _verticalFriction("verticalFriction", "Vertical Friction", true)
|
||||
, _sensitivity("sensitivity", "Sensitivity", 0.5f, 0.001f, 1.f)
|
||||
, _rapidness("rapidness", "Rapidness", 1.f, 0.1f, 60.f)
|
||||
, _interactionModeOption(
|
||||
"interactionMode",
|
||||
"Interaction Mode",
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
{
|
||||
_origin.onChange([this]() {
|
||||
SceneGraphNode* node = sceneGraphNode(_origin.value());
|
||||
@@ -100,24 +114,17 @@ InteractionHandler::InteractionHandler()
|
||||
_inputState = std::make_unique<InputState>();
|
||||
// Inject the same mouse states to both orbital and global interaction mode
|
||||
_mouseStates = std::make_unique<OrbitalInteractionMode::MouseStates>(_sensitivity * pow(10.0,-4), 1);
|
||||
_interactionModes.insert(
|
||||
std::pair<std::string, std::shared_ptr<InteractionMode>>(
|
||||
"Orbital",
|
||||
std::make_shared<OrbitalInteractionMode>(_mouseStates)
|
||||
));
|
||||
_interactionModes.insert(
|
||||
std::pair<std::string, std::shared_ptr<InteractionMode>>(
|
||||
"GlobeBrowsing",
|
||||
std::make_shared<GlobeBrowsingInteractionMode>(_mouseStates)
|
||||
));
|
||||
_interactionModes.insert(
|
||||
std::pair<std::string, std::shared_ptr<InteractionMode>>(
|
||||
"Keyframe",
|
||||
std::make_shared<KeyframeInteractionMode>()
|
||||
));
|
||||
|
||||
_orbitalInteractionMode = std::make_unique<OrbitalInteractionMode>(_mouseStates);
|
||||
_globeBrowsingInteractionMode = std::make_unique<GlobeBrowsingInteractionMode>(_mouseStates);
|
||||
_keyframeInteractionMode = std::make_unique<KeyframeInteractionMode>();
|
||||
|
||||
_interactionModeOption.addOption(IdOrbitalInteractionMode, KeyOrbitalInteractionMode);
|
||||
_interactionModeOption.addOption(IdGlobeBrowsingInteractionMode, KeyGlobeBrowsingInteractionMode);
|
||||
_interactionModeOption.addOption(IdKeyframeInteractionMode, KeyKeyframeInteractionMode);
|
||||
|
||||
// Set the interactionMode
|
||||
_currentInteractionMode = _interactionModes["Orbital"];
|
||||
_currentInteractionMode = _orbitalInteractionMode.get();
|
||||
|
||||
// Define lambda functions for changed properties
|
||||
_rotationalFriction.onChange([&]() {
|
||||
@@ -136,8 +143,25 @@ InteractionHandler::InteractionHandler()
|
||||
_mouseStates->setVelocityScaleFactor(_rapidness);
|
||||
});
|
||||
|
||||
_interactionModeOption.onChange([this]() {
|
||||
switch(_interactionModeOption.value()) {
|
||||
case IdGlobeBrowsingInteractionMode:
|
||||
setInteractionMode(_globeBrowsingInteractionMode.get());
|
||||
break;
|
||||
case IdKeyframeInteractionMode:
|
||||
setInteractionMode(_keyframeInteractionMode.get());
|
||||
break;
|
||||
case IdOrbitalInteractionMode:
|
||||
default:
|
||||
setInteractionMode(_orbitalInteractionMode.get());
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Add the properties
|
||||
addProperty(_origin);
|
||||
addProperty(_interactionModeOption);
|
||||
|
||||
addProperty(_rotationalFriction);
|
||||
addProperty(_horizontalFriction);
|
||||
@@ -153,14 +177,9 @@ InteractionHandler::~InteractionHandler() {
|
||||
void InteractionHandler::initialize() {
|
||||
OsEng.parallelConnection().connectionEvent()->subscribe("interactionHandler", "statusChanged", [this]() {
|
||||
if (OsEng.parallelConnection().status() == ParallelConnection::Status::ClientWithHost) {
|
||||
setInteractionMode("Keyframe");
|
||||
} else {
|
||||
auto keyframeModeIter = _interactionModes.find("Keyframe");
|
||||
if (keyframeModeIter != _interactionModes.end()) {
|
||||
if (_currentInteractionMode == keyframeModeIter->second) {
|
||||
setInteractionMode("Orbital");
|
||||
}
|
||||
}
|
||||
setInteractionMode(_keyframeInteractionMode.get());
|
||||
} else if (_currentInteractionMode == _keyframeInteractionMode.get()) {
|
||||
setInteractionMode(_orbitalInteractionMode.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -183,7 +202,7 @@ void InteractionHandler::resetCameraDirection() {
|
||||
_currentInteractionMode->rotateToFocusNodeInterpolator().start();
|
||||
}
|
||||
|
||||
void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> interactionMode) {
|
||||
void InteractionHandler::setInteractionMode(InteractionMode* interactionMode) {
|
||||
// Focus node is passed over from the previous interaction mode
|
||||
SceneGraphNode* focusNode = _currentInteractionMode->focusNode();
|
||||
|
||||
@@ -195,31 +214,13 @@ void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> int
|
||||
}
|
||||
|
||||
InteractionMode * InteractionHandler::interactionMode() {
|
||||
return _currentInteractionMode.get();
|
||||
return _currentInteractionMode;
|
||||
}
|
||||
|
||||
void InteractionHandler::setInteractionMode(const std::string& interactionModeKey) {
|
||||
if (_interactionModes.find(interactionModeKey) != _interactionModes.end()) {
|
||||
setInteractionMode(_interactionModes[interactionModeKey]);
|
||||
LINFO("Interaction mode set to '" << interactionModeKey << "'");
|
||||
}
|
||||
else {
|
||||
std::string listInteractionModes("");
|
||||
for (auto pair : _interactionModes) {
|
||||
listInteractionModes += "'" + pair.first + "', ";
|
||||
}
|
||||
LWARNING("'" << interactionModeKey <<
|
||||
"' is not a valid interaction mode. Candidates are " << listInteractionModes);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractionHandler::goToChunk(int x, int y, int level) {
|
||||
std::shared_ptr<GlobeBrowsingInteractionMode> gbim =
|
||||
std::dynamic_pointer_cast<GlobeBrowsingInteractionMode> (_currentInteractionMode);
|
||||
|
||||
if (gbim) {
|
||||
if (_currentInteractionMode == _globeBrowsingInteractionMode.get()) {
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
gbim->goToChunk(*_camera, globebrowsing::TileIndex(x,y,level), glm::vec2(0.5,0.5), true);
|
||||
_globeBrowsingInteractionMode->goToChunk(*_camera, globebrowsing::TileIndex(x,y,level), glm::vec2(0.5,0.5), true);
|
||||
#endif
|
||||
} else {
|
||||
LWARNING("Interaction mode must be set to 'GlobeBrowsing'");
|
||||
@@ -227,12 +228,9 @@ void InteractionHandler::goToChunk(int x, int y, int level) {
|
||||
}
|
||||
|
||||
void InteractionHandler::goToGeo(double latitude, double longitude) {
|
||||
std::shared_ptr<GlobeBrowsingInteractionMode> gbim =
|
||||
std::dynamic_pointer_cast<GlobeBrowsingInteractionMode> (_currentInteractionMode);
|
||||
|
||||
if (gbim) {
|
||||
if (_currentInteractionMode == _globeBrowsingInteractionMode.get()) {
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
gbim->goToGeodetic2(
|
||||
_globeBrowsingInteractionMode->goToGeodetic2(
|
||||
*_camera,
|
||||
globebrowsing::Geodetic2(latitude, longitude) / 180 * glm::pi<double>(), true
|
||||
);
|
||||
@@ -499,12 +497,6 @@ scripting::LuaLibrary InteractionHandler::luaLibrary() {
|
||||
"that is to be executed, and the optional third argument is a human "
|
||||
"readable description of the command for documentation purposes."
|
||||
},
|
||||
{
|
||||
"setInteractionMode",
|
||||
&luascriptfunctions::setInteractionMode,
|
||||
"string",
|
||||
"Set the interaction mode for the camera"
|
||||
},
|
||||
{
|
||||
"saveCameraStateToFile",
|
||||
&luascriptfunctions::saveCameraStateToFile,
|
||||
@@ -539,20 +531,32 @@ scripting::LuaLibrary InteractionHandler::luaLibrary() {
|
||||
};
|
||||
}
|
||||
|
||||
void InteractionHandler::addKeyframe(const datamessagestructures::CameraKeyframe &kf) {
|
||||
_inputState->addKeyframe(kf);
|
||||
void InteractionHandler::addKeyframe(double timestamp, KeyframeInteractionMode::CameraPose pose) {
|
||||
if (!_keyframeInteractionMode) {
|
||||
return;
|
||||
}
|
||||
_keyframeInteractionMode->timeline().addKeyframe(timestamp, pose);
|
||||
}
|
||||
|
||||
void InteractionHandler::removeKeyframesAfter(double timestamp) {
|
||||
_inputState->removeKeyframesAfter(timestamp);
|
||||
if (!_keyframeInteractionMode) {
|
||||
return;
|
||||
}
|
||||
_keyframeInteractionMode->timeline().removeKeyframesAfter(timestamp);
|
||||
}
|
||||
|
||||
void InteractionHandler::clearKeyframes() {
|
||||
_inputState->clearKeyframes();
|
||||
if (!_keyframeInteractionMode) {
|
||||
return;
|
||||
}
|
||||
_keyframeInteractionMode->timeline().clearKeyframes();
|
||||
}
|
||||
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& InteractionHandler::keyframes() const {
|
||||
return _inputState->keyframes();
|
||||
size_t InteractionHandler::nKeyframes() const {
|
||||
if (!_keyframeInteractionMode) {
|
||||
return 0;
|
||||
}
|
||||
return _keyframeInteractionMode->timeline().keyframes().size();
|
||||
}
|
||||
|
||||
} // namespace interaction
|
||||
|
||||
@@ -169,28 +169,6 @@ int clearKeys(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setInteractionMode():
|
||||
* Set the interaction mode
|
||||
*/
|
||||
int setInteractionMode(lua_State* L) {
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
|
||||
std::string interactionModeKey = luaL_checkstring(L, -1);
|
||||
|
||||
if (interactionModeKey.empty())
|
||||
return luaL_error(L, "interactionmode name string is empty");
|
||||
|
||||
OsEng.interactionHandler().setInteractionMode(interactionModeKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goToChunk(lua_State* L) {
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
|
||||
@@ -60,46 +60,6 @@ namespace interaction {
|
||||
|
||||
}
|
||||
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& InputState::keyframes() const {
|
||||
return _keyframes;
|
||||
}
|
||||
|
||||
void InputState::addKeyframe(const datamessagestructures::CameraKeyframe &kf) {
|
||||
clearOldKeyframes();
|
||||
if (kf._timestamp < OsEng.runTime()) {
|
||||
return;
|
||||
}
|
||||
_keyframes.insert(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), kf);
|
||||
}
|
||||
|
||||
void InputState::removeKeyframesAfter(double timestamp) {
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._timestamp = timestamp;
|
||||
// Remove keyframes after the inserted keyframe.
|
||||
_keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), _keyframes.end());
|
||||
}
|
||||
|
||||
bool InputState::compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
}
|
||||
|
||||
void InputState::clearOldKeyframes() {
|
||||
double now = OsEng.runTime();
|
||||
auto isLater = [now](const datamessagestructures::CameraKeyframe kf) {
|
||||
return kf._timestamp > now;
|
||||
};
|
||||
|
||||
// Remote keyframes with earlier timestamps than the current time.
|
||||
auto nextKeyframe = std::find_if(_keyframes.begin(), _keyframes.end(), isLater);
|
||||
if (nextKeyframe != _keyframes.begin()) {
|
||||
_keyframes.erase(_keyframes.begin(), nextKeyframe - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void InputState::clearKeyframes() {
|
||||
_keyframes.clear();
|
||||
}
|
||||
|
||||
void InputState::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
|
||||
if (action == KeyAction::Press) {
|
||||
_keysDown.push_back(std::pair<Key, KeyModifier>(key, modifier));
|
||||
@@ -205,66 +165,73 @@ Interpolator<double>& InteractionMode::rotateToFocusNodeInterpolator() {
|
||||
|
||||
|
||||
// KeyframeInteractionMode
|
||||
KeyframeInteractionMode::KeyframeInteractionMode(){
|
||||
|
||||
KeyframeInteractionMode::KeyframeInteractionMode()
|
||||
{
|
||||
}
|
||||
|
||||
KeyframeInteractionMode::~KeyframeInteractionMode() {
|
||||
|
||||
}
|
||||
|
||||
void KeyframeInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double) {
|
||||
_keyframes = inputState.keyframes();
|
||||
|
||||
void KeyframeInteractionMode::updateMouseStatesFromInput(const InputState&, double) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
void KeyframeInteractionMode::updateCameraStateFromMouseStates(Camera& camera, double) {
|
||||
if (_keyframes.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
double now = OsEng.runTime();
|
||||
auto isLater = [now](const datamessagestructures::CameraKeyframe kf) {
|
||||
return kf._timestamp > now;
|
||||
};
|
||||
|
||||
auto nextKeyframe = std::find_if(_keyframes.begin(), _keyframes.end(), isLater);
|
||||
if (nextKeyframe == _keyframes.end()) {
|
||||
if (_cameraPoseTimeline.nKeyframes() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextKeyframe == _keyframes.begin()) {
|
||||
camera.setPositionVec3(_keyframes[0]._position);
|
||||
camera.setRotation(_keyframes[0]._rotation);
|
||||
const Keyframe<CameraPose>* nextKeyframe = _cameraPoseTimeline.firstKeyframeAfter(now);
|
||||
const Keyframe<CameraPose>* prevKeyframe = _cameraPoseTimeline.lastKeyframeBefore(now);
|
||||
double nextTime = 0;
|
||||
double prevTime = 0;
|
||||
double t = 0;
|
||||
|
||||
if (nextKeyframe) {
|
||||
nextTime = nextKeyframe->timestamp;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
auto prevKeyframe = nextKeyframe - 1;
|
||||
|
||||
double prevTime = prevKeyframe->_timestamp;
|
||||
double nextTime = nextKeyframe->_timestamp;
|
||||
if (prevKeyframe) {
|
||||
prevTime = prevKeyframe->timestamp;
|
||||
t = (now - prevTime) / (nextTime - prevTime);
|
||||
} else {
|
||||
// If there is no keyframe before: Only use the next keyframe.
|
||||
prevTime = nextTime;
|
||||
prevKeyframe = nextKeyframe;
|
||||
t = 1;
|
||||
}
|
||||
|
||||
double t = (now - prevTime) / (nextTime - prevTime);
|
||||
_cameraPoseTimeline.removeKeyframesBefore(prevTime);
|
||||
|
||||
const CameraPose& prevPose = prevKeyframe->data;
|
||||
const CameraPose& nextPose = nextKeyframe->data;
|
||||
|
||||
Scene* scene = camera.parent()->scene();
|
||||
SceneGraphNode* prevFocusNode = scene->sceneGraphNode(prevKeyframe->_focusNode);
|
||||
SceneGraphNode* nextFocusNode = scene->sceneGraphNode(nextKeyframe->_focusNode);
|
||||
SceneGraphNode* prevFocusNode = scene->sceneGraphNode(prevPose.focusNode);
|
||||
SceneGraphNode* nextFocusNode = scene->sceneGraphNode(nextPose.focusNode);
|
||||
|
||||
if (!prevFocusNode || !nextFocusNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::dvec3 prevKeyframeCameraPosition = prevKeyframe->_position;
|
||||
glm::dvec3 nextKeyframeCameraPosition = nextKeyframe->_position;
|
||||
glm::dquat prevKeyframeCameraRotation = prevKeyframe->_rotation;
|
||||
glm::dquat nextKeyframeCameraRotation = nextKeyframe->_rotation;
|
||||
glm::dvec3 prevKeyframeCameraPosition = prevPose.position;
|
||||
glm::dvec3 nextKeyframeCameraPosition = nextPose.position;
|
||||
glm::dquat prevKeyframeCameraRotation = prevPose.rotation;
|
||||
glm::dquat nextKeyframeCameraRotation = nextPose.rotation;
|
||||
|
||||
// Transform position and rotation based on focus node rotation (if following rotation)
|
||||
if (prevKeyframe->_followNodeRotation) {
|
||||
prevKeyframeCameraRotation = prevFocusNode->worldRotationMatrix() * glm::dmat3(prevKeyframe->_rotation);
|
||||
prevKeyframeCameraPosition = prevFocusNode->worldRotationMatrix() * prevKeyframeCameraPosition;
|
||||
if (prevPose.followFocusNodeRotation) {
|
||||
prevKeyframeCameraRotation = prevFocusNode->worldRotationMatrix() * glm::dmat3(glm::dquat(prevPose.rotation));
|
||||
prevKeyframeCameraPosition = prevFocusNode->worldRotationMatrix() * prevPose.position;
|
||||
}
|
||||
if (nextKeyframe->_followNodeRotation) {
|
||||
nextKeyframeCameraRotation = nextFocusNode->worldRotationMatrix() * glm::dmat3(nextKeyframe->_rotation);
|
||||
nextKeyframeCameraPosition = nextFocusNode->worldRotationMatrix() * nextKeyframeCameraPosition;
|
||||
if (nextPose.followFocusNodeRotation) {
|
||||
nextKeyframeCameraRotation = nextFocusNode->worldRotationMatrix() * glm::dmat3(glm::dquat(nextPose.rotation));
|
||||
nextKeyframeCameraPosition = nextFocusNode->worldRotationMatrix() * nextPose.position;
|
||||
}
|
||||
|
||||
// Transform position based on focus node position
|
||||
@@ -280,6 +247,10 @@ bool KeyframeInteractionMode::followingNodeRotation() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Timeline<KeyframeInteractionMode::CameraPose>& KeyframeInteractionMode::timeline() {
|
||||
return _cameraPoseTimeline;
|
||||
}
|
||||
|
||||
// OrbitalInteractionMode
|
||||
OrbitalInteractionMode::MouseStates::MouseStates(double sensitivity, double velocityScaleFactor)
|
||||
: _sensitivity(sensitivity)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <openspace/network/networkengine.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
|
||||
@@ -95,11 +96,13 @@ void NetworkEngine::publishStatusMessage() {
|
||||
// 8 bytes: delta time as double
|
||||
// Total: 40
|
||||
|
||||
Time& currentTime = OsEng.timeManager().time();
|
||||
|
||||
uint16_t messageSize = 0;
|
||||
|
||||
double time = Time::ref().j2000Seconds();
|
||||
std::string timeString = Time::ref().UTC();
|
||||
double delta = Time::ref().deltaTime();
|
||||
double time = currentTime.j2000Seconds();
|
||||
std::string timeString = currentTime.UTC();
|
||||
double delta = currentTime.deltaTime();
|
||||
|
||||
messageSize += sizeof(time);
|
||||
messageSize += static_cast<uint16_t>(timeString.length());
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#include <openspace/interaction/interactionmode.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/interaction/interactionmode.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/openspace.h>
|
||||
#include <openspace/scripting/script_helper.h>
|
||||
@@ -549,7 +550,13 @@ void ParallelConnection::dataMessageReceived(const std::vector<char>& messageCon
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.interactionHandler().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.interactionHandler().addKeyframe(kf);
|
||||
interaction::KeyframeInteractionMode::CameraPose pose;
|
||||
pose.focusNode = kf._focusNode;
|
||||
pose.position = kf._position;
|
||||
pose.rotation = kf._rotation;
|
||||
pose.followFocusNodeRotation = kf._followNodeRotation;
|
||||
|
||||
OsEng.interactionHandler().addKeyframe(kf._timestamp, pose);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::TimeData: {
|
||||
@@ -557,7 +564,12 @@ void ParallelConnection::dataMessageReceived(const std::vector<char>& messageCon
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.timeManager().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.timeManager().addKeyframe(kf);
|
||||
Time time(kf._time);
|
||||
time.setDeltaTime(kf._dt);
|
||||
time.setPause(kf._paused);
|
||||
time.setTimeJumped(kf._requiresTimeJump);
|
||||
|
||||
OsEng.timeManager().addKeyframe(kf._timestamp, time);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::ScriptData: {
|
||||
@@ -970,7 +982,7 @@ void ParallelConnection::preSynchronization() {
|
||||
}
|
||||
|
||||
if (status() == Status::Host) {
|
||||
if (Time::ref().timeJumped()) {
|
||||
if (OsEng.timeManager().time().timeJumped()) {
|
||||
_timeJumped = true;
|
||||
}
|
||||
double now = OsEng.runTime();
|
||||
@@ -1061,10 +1073,12 @@ void ParallelConnection::sendTimeKeyframe() {
|
||||
// Create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
|
||||
kf._dt = Time::ref().deltaTime();
|
||||
kf._paused = Time::ref().paused();
|
||||
Time& time = OsEng.timeManager().time();
|
||||
|
||||
kf._dt = time.deltaTime();
|
||||
kf._paused = time.paused();
|
||||
kf._requiresTimeJump = _timeJumped;
|
||||
kf._time = Time::ref().j2000Seconds();
|
||||
kf._time = time.j2000Seconds();
|
||||
|
||||
// Timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/performance/performancemeasurement.h>
|
||||
|
||||
|
||||
@@ -264,7 +265,8 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement
|
||||
static_cast<int>(Renderable::RenderBin::Transparent) |
|
||||
static_cast<int>(Renderable::RenderBin::Overlay);
|
||||
|
||||
RenderData data{ *_camera, psc(), doPerformanceMeasurements, renderBinMask };
|
||||
Time time = OsEng.timeManager().time();
|
||||
RenderData data{ *_camera, psc(), time, doPerformanceMeasurements, renderBinMask };
|
||||
RendererTasks tasks;
|
||||
_scene->render(data, tasks);
|
||||
_blackoutFactor = blackoutFactor;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <string>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/volumeraycaster.h>
|
||||
@@ -336,7 +337,9 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
RenderData data = { *_camera, psc(), doPerformanceMeasurements, 0 };
|
||||
Time time = OsEng.timeManager().time();
|
||||
|
||||
RenderData data = { *_camera, psc(), time, doPerformanceMeasurements, 0 };
|
||||
RendererTasks tasks;
|
||||
|
||||
// Capture standard fbo
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <openspace/interaction/luaconsole.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/screenlog.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/rendering/raycastermanager.h>
|
||||
@@ -308,12 +309,10 @@ void RenderEngine::deinitialize() {
|
||||
}
|
||||
|
||||
void RenderEngine::updateScene() {
|
||||
const Time& currentTime = OsEng.timeManager().time();
|
||||
_scene->update({
|
||||
{ glm::dvec3(0), glm::dmat3(1), 1.0 },
|
||||
Time::ref().j2000Seconds(),
|
||||
Time::ref().deltaTime(),
|
||||
Time::ref().paused(),
|
||||
Time::ref().timeJumped(),
|
||||
currentTime,
|
||||
_performanceManager != nullptr
|
||||
});
|
||||
|
||||
@@ -484,8 +483,9 @@ void RenderEngine::renderShutdownInformation(float timer, float fullTime) {
|
||||
}
|
||||
|
||||
void RenderEngine::postDraw() {
|
||||
if (Time::ref().timeJumped()) {
|
||||
Time::ref().setTimeJumped(false);
|
||||
Time& currentTime = OsEng.timeManager().time();
|
||||
if (currentTime.timeJumped()) {
|
||||
currentTime.setTimeJumped(false);
|
||||
}
|
||||
|
||||
if (_shouldTakeScreenshot) {
|
||||
@@ -840,7 +840,7 @@ void RenderEngine::renderInformation() {
|
||||
*_fontDate,
|
||||
penPosition,
|
||||
"Date: %s",
|
||||
Time::ref().UTC().c_str()
|
||||
OsEng.timeManager().time().UTC().c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -851,7 +851,7 @@ void RenderEngine::renderInformation() {
|
||||
*_fontInfo,
|
||||
penPosition,
|
||||
"Simulation increment (s): %.3f",
|
||||
Time::ref().deltaTime()
|
||||
OsEng.timeManager().time().deltaTime()
|
||||
);
|
||||
|
||||
FrametimeType frametimeType = FrametimeType(_frametimeType.value());
|
||||
@@ -936,7 +936,7 @@ void RenderEngine::renderInformation() {
|
||||
|
||||
#ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED
|
||||
bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
|
||||
double currentTime = Time::ref().j2000Seconds();
|
||||
double currentTime = OsEng.timeManager().time().j2000Seconds();
|
||||
|
||||
if (MissionManager::ref().hasCurrentMission()) {
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
RenderData newData = {
|
||||
data.camera,
|
||||
thisPositionPSC,
|
||||
data.time,
|
||||
data.doPerformanceMeasurement,
|
||||
data.renderBinMask,
|
||||
{ _worldPositionCached, _worldRotationCached, _worldScaleCached }
|
||||
|
||||
@@ -86,9 +86,6 @@ glm::dvec3 Translation::position(double time) {
|
||||
update({
|
||||
{},
|
||||
time,
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
});
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ ScriptScheduler::ScheduledScript::ScheduledScript(const ghoul::Dictionary& dicti
|
||||
: time(-std::numeric_limits<double>::max())
|
||||
{
|
||||
std::string timeStr = dictionary.value<std::string>(KeyTime);
|
||||
time = Time::ref().convertTime(timeStr);
|
||||
time = Time::convertTime(timeStr);
|
||||
|
||||
// If a universal script is specified, retrieve it and add a ; as a separator so that
|
||||
// it can be added to the other scripts
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include "time_lua.inl"
|
||||
|
||||
#include <openspace/util/spicemanager.h>
|
||||
@@ -36,9 +38,6 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Time* Time::_instance = nullptr;
|
||||
|
||||
|
||||
double Time::convertTime(const std::string& time) {
|
||||
ghoul_assert(!time.empty(), "timeString must not be empty");
|
||||
return SpiceManager::ref().ephemerisTimeFromDate(time);
|
||||
@@ -54,26 +53,11 @@ Time::Time(const Time& other)
|
||||
: _time(other._time)
|
||||
, _dt(other._dt)
|
||||
, _timeJumped(other._timeJumped)
|
||||
, _timePaused(other._timePaused)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Time::initialize() {
|
||||
ghoul_assert(_instance == nullptr, "Static time must not have been ininitialized");
|
||||
_instance = new Time();
|
||||
}
|
||||
|
||||
void Time::deinitialize() {
|
||||
ghoul_assert(_instance, "Static time must have been ininitialized");
|
||||
delete _instance;
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
Time& Time::ref() {
|
||||
ghoul_assert(_instance, "Static time must have been ininitialized");
|
||||
return *_instance;
|
||||
}
|
||||
|
||||
Time Time::now() {
|
||||
Time now;
|
||||
time_t secondsSince1970;
|
||||
@@ -85,10 +69,6 @@ Time Time::now() {
|
||||
return now;
|
||||
}
|
||||
|
||||
bool Time::isInitialized() {
|
||||
return (_instance != nullptr);
|
||||
}
|
||||
|
||||
void Time::setTime(double value, bool requireJump) {
|
||||
_time = value;
|
||||
_timeJumped = requireJump;
|
||||
@@ -169,10 +149,6 @@ bool Time::paused() const {
|
||||
return _timePaused;
|
||||
}
|
||||
|
||||
std::vector<Syncable*> Time::getSyncables() {
|
||||
return{ &_time, &_dt, &_timeJumped};
|
||||
}
|
||||
|
||||
scripting::LuaLibrary Time::luaLibrary() {
|
||||
return {
|
||||
"time",
|
||||
|
||||
@@ -46,7 +46,7 @@ int time_setDeltaTime(lua_State* L) {
|
||||
const bool isNumber = (lua_isnumber(L, -1) != 0);
|
||||
if (isNumber) {
|
||||
double value = lua_tonumber(L, -1);
|
||||
openspace::Time::ref().setDeltaTime(value);
|
||||
OsEng.timeManager().time().setDeltaTime(value);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
@@ -67,7 +67,7 @@ int time_setDeltaTime(lua_State* L) {
|
||||
* Returns the delta time by calling the Time::deltaTime method
|
||||
*/
|
||||
int time_deltaTime(lua_State* L) {
|
||||
lua_pushnumber(L, openspace::Time::ref().deltaTime());
|
||||
lua_pushnumber(L, OsEng.timeManager().time().deltaTime());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ int time_togglePause(lua_State* L) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
|
||||
openspace::Time::ref().togglePause();
|
||||
OsEng.timeManager().time().togglePause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ int time_setPause(lua_State* L) {
|
||||
}
|
||||
|
||||
bool pause = lua_toboolean(L, -1) == 1;
|
||||
openspace::Time::ref().setPause(pause);
|
||||
OsEng.timeManager().time().setPause(pause);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -130,12 +130,12 @@ int time_setTime(lua_State* L) {
|
||||
}
|
||||
if (isNumber) {
|
||||
double value = lua_tonumber(L, -1);
|
||||
openspace::Time::ref().setTime(value);
|
||||
OsEng.timeManager().time().setTime(value);
|
||||
return 0;
|
||||
}
|
||||
if (isString) {
|
||||
const char* time = lua_tostring(L, -1);
|
||||
openspace::Time::ref().setTime(time);
|
||||
OsEng.timeManager().time().setTime(time);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@@ -148,7 +148,7 @@ int time_setTime(lua_State* L) {
|
||||
* It is returned by calling the Time::currentTime method.
|
||||
*/
|
||||
int time_currentTime(lua_State* L) {
|
||||
lua_pushnumber(L, openspace::Time::ref().j2000Seconds());
|
||||
lua_pushnumber(L, OsEng.timeManager().time().j2000Seconds());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ int time_currentTime(lua_State* L) {
|
||||
* timezone by calling the Time::UTC method
|
||||
*/
|
||||
int time_currentTimeUTC(lua_State* L) {
|
||||
lua_pushstring(L, openspace::Time::ref().UTC().c_str());
|
||||
lua_pushstring(L, OsEng.timeManager().time().UTC().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
41
src/util/timeline.cpp
Normal file
41
src/util/timeline.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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 <openspace/util/timeline.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
bool compareKeyframeTimes(const KeyframeBase& a, const KeyframeBase& b) {
|
||||
return a.timestamp < b.timestamp;
|
||||
}
|
||||
|
||||
bool compareTimeWithKeyframeTime(double a, const KeyframeBase& b) {
|
||||
return a < b.timestamp;
|
||||
}
|
||||
|
||||
bool compareKeyframeTimeWithTime(const KeyframeBase& a, double b) {
|
||||
return a.timestamp < b;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/util/timeline.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -34,8 +34,8 @@ using datamessagestructures::TimeKeyframe;
|
||||
void TimeManager::preSynchronization(double dt) {
|
||||
// double now = OsEng.runTime();
|
||||
removeKeyframesBefore(_latestConsumedTimestamp);
|
||||
if (_keyframes.size() == 0) {
|
||||
Time::ref().advanceTime(dt);
|
||||
if (_timeline.nKeyframes() == 0) {
|
||||
time().advanceTime(dt);
|
||||
} else {
|
||||
consumeKeyframes(dt);
|
||||
}
|
||||
@@ -43,121 +43,116 @@ void TimeManager::preSynchronization(double dt) {
|
||||
|
||||
void TimeManager::consumeKeyframes(double dt) {
|
||||
double now = OsEng.runTime();
|
||||
TimeKeyframe kf;
|
||||
kf._timestamp = now;
|
||||
auto firstFutureKeyframe = std::lower_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
|
||||
|
||||
const std::deque<Keyframe<Time>>& keyframes = _timeline.keyframes();
|
||||
auto firstFutureKeyframe = std::lower_bound(keyframes.begin(), keyframes.end(), now, &compareKeyframeTimeWithTime);
|
||||
|
||||
bool consumingTimeJump = std::find_if(_keyframes.begin(), firstFutureKeyframe, [] (const TimeKeyframe& f) {
|
||||
return f._requiresTimeJump;
|
||||
bool consumingTimeJump = std::find_if(keyframes.begin(), firstFutureKeyframe, [] (const Keyframe<Time>& f) {
|
||||
return f.data.timeJumped();
|
||||
}) != firstFutureKeyframe;
|
||||
|
||||
Time& time = Time::ref();
|
||||
|
||||
if (firstFutureKeyframe == _keyframes.end()) {
|
||||
if (firstFutureKeyframe == keyframes.end()) {
|
||||
// All keyframes are in the past.
|
||||
// Consume the latest one.
|
||||
TimeKeyframe& current = _keyframes.back();
|
||||
time.setTime(current._time, consumingTimeJump);
|
||||
time.setDeltaTime(current._dt);
|
||||
time.setPause(current._paused);
|
||||
_latestConsumedTimestamp = current._timestamp;
|
||||
const Keyframe<Time>& current = keyframes.back();
|
||||
const Time& currentTime = current.data;
|
||||
time().setTime(currentTime.j2000Seconds(), consumingTimeJump);
|
||||
time().setDeltaTime(currentTime.deltaTime());
|
||||
time().setPause(currentTime.paused());
|
||||
_latestConsumedTimestamp = current.timestamp;
|
||||
}
|
||||
else {
|
||||
TimeKeyframe& next = *firstFutureKeyframe;
|
||||
const Keyframe<Time>& next = *firstFutureKeyframe;
|
||||
const Time& nextTime = next.data;
|
||||
|
||||
if (firstFutureKeyframe != _keyframes.begin()) {
|
||||
TimeKeyframe& latest = *(firstFutureKeyframe - 1);
|
||||
if (firstFutureKeyframe != keyframes.begin()) {
|
||||
const Keyframe<Time>& latest = *(firstFutureKeyframe - 1);
|
||||
const Time& latestTime = latest.data;
|
||||
// In case of unconsumed passed keyframes, let the last one
|
||||
// determine whether the time should be paused or not.
|
||||
// If there was a time jump or time is paused, apply it directly.
|
||||
// Then consume the last keyframe.
|
||||
|
||||
time.setPause(latest._paused);
|
||||
time.setTimeJumped(consumingTimeJump);
|
||||
time.setDeltaTime(latest._dt);
|
||||
time().setPause(latestTime.paused());
|
||||
time().setTimeJumped(consumingTimeJump);
|
||||
time().setDeltaTime(latestTime.deltaTime());
|
||||
|
||||
if (consumingTimeJump || latest._paused) {
|
||||
time.setTime(latest._time, consumingTimeJump);
|
||||
if (consumingTimeJump || latestTime.paused()) {
|
||||
time().setTime(latestTime.j2000Seconds(), consumingTimeJump);
|
||||
}
|
||||
_latestConsumedTimestamp = latest._timestamp;
|
||||
_latestConsumedTimestamp = latest.timestamp;
|
||||
}
|
||||
|
||||
// Do not interpolate with time jumping keyframes.
|
||||
// Instead, wait until their timestamp and apply them directly.
|
||||
if (next._requiresTimeJump) {
|
||||
Time::ref().advanceTime(dt);
|
||||
if (nextTime.timeJumped()) {
|
||||
time().advanceTime(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (time.paused()) {
|
||||
if (time().paused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const double secondsOffTolerance = OsEng.parallelConnection().timeTolerance();
|
||||
|
||||
double predictedTime = time.j2000Seconds() + time.deltaTime() * (next._timestamp - now);
|
||||
bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * secondsOffTolerance);
|
||||
double predictedTime = time().j2000Seconds() + time().deltaTime() * (next.timestamp - now);
|
||||
bool withinTolerance = std::abs(predictedTime - nextTime.j2000Seconds()) < std::abs(nextTime.deltaTime() * secondsOffTolerance);
|
||||
|
||||
if (next._dt == time.deltaTime() && withinTolerance) {
|
||||
Time::ref().advanceTime(dt);
|
||||
if (nextTime.deltaTime() == time().deltaTime() && withinTolerance) {
|
||||
time().advanceTime(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
double t0 = now - dt;
|
||||
double t1 = now;
|
||||
double t2 = next._timestamp;
|
||||
double t2 = next.timestamp;
|
||||
|
||||
double parameter = (t1 - t0) / (t2 - t0);
|
||||
|
||||
double y0 = time.j2000Seconds();
|
||||
double yPrime0 = time.deltaTime();
|
||||
double y0 = time().j2000Seconds();
|
||||
double yPrime0 = time().deltaTime();
|
||||
|
||||
double y2 = next._time;
|
||||
double yPrime2 = next._dt;
|
||||
double y2 = nextTime.j2000Seconds();
|
||||
double yPrime2 = nextTime.deltaTime();
|
||||
|
||||
double y1 = (1 - parameter) * y0 + parameter * y2;
|
||||
double y1Prime = (y1 - y0) / dt;
|
||||
|
||||
time.setDeltaTime(y1Prime);
|
||||
time.setTime(y1, false);
|
||||
// std::cout << "Correcting time to " << y1 << ", dt=" << y1Prime << "." << std::endl;
|
||||
time().setDeltaTime(y1Prime);
|
||||
time().setTime(y1, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TimeManager::addKeyframe(const TimeKeyframe& kf) {
|
||||
if (kf._timestamp < OsEng.runTime()) {
|
||||
return;
|
||||
}
|
||||
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
|
||||
_keyframes.insert(iter, kf);
|
||||
|
||||
void TimeManager::addKeyframe(double timestamp, Time time) {
|
||||
_timeline.addKeyframe(timestamp, time);
|
||||
}
|
||||
|
||||
void TimeManager::removeKeyframesAfter(double timestamp) {
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
kf._timestamp = timestamp;
|
||||
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
|
||||
_keyframes.erase(iter, _keyframes.end());
|
||||
_timeline.removeKeyframesAfter(timestamp);
|
||||
}
|
||||
|
||||
|
||||
void TimeManager::removeKeyframesBefore(double timestamp) {
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
kf._timestamp = timestamp;
|
||||
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
|
||||
_keyframes.erase(_keyframes.begin(), iter);
|
||||
_timeline.removeKeyframesBefore(timestamp);
|
||||
}
|
||||
|
||||
void TimeManager::clearKeyframes() {
|
||||
_keyframes.clear();
|
||||
_timeline.clearKeyframes();
|
||||
}
|
||||
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& TimeManager::keyframes() const {
|
||||
return _keyframes;
|
||||
size_t TimeManager::nKeyframes() const {
|
||||
return _timeline.nKeyframes();
|
||||
}
|
||||
|
||||
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
Time& TimeManager::time() {
|
||||
return _currentTime;
|
||||
}
|
||||
|
||||
std::vector<Syncable*> TimeManager::getSyncables() {
|
||||
return{ &_currentTime };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <test_common.inl>
|
||||
#include <test_spicemanager.inl>
|
||||
#include <test_sceneloader.inl>
|
||||
#include <test_timeline.inl>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
//#include <test_chunknode.inl>
|
||||
|
||||
@@ -60,16 +60,16 @@ TEST_F(ScriptSchedulerTest, SimpleForward) {
|
||||
{ "BackwardScript", "BackwardScript1"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03")
|
||||
openspace::Time::convertTime("2000 JAN 03")
|
||||
);
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
@@ -94,20 +94,20 @@ TEST_F(ScriptSchedulerTest, MultipleForwardSingleJump) {
|
||||
|
||||
ScriptScheduler scheduler;
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript2", *(res.first));
|
||||
}
|
||||
@@ -130,16 +130,16 @@ TEST_F(ScriptSchedulerTest, MultipleForwardOrdering) {
|
||||
|
||||
ScriptScheduler scheduler;
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
EXPECT_EQ("ForwardScript2", *(std::next(res.first)));
|
||||
@@ -157,15 +157,15 @@ TEST_F(ScriptSchedulerTest, SimpleBackward) {
|
||||
{ "BackwardScript", "BackwardScript1"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 05"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 05"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
}
|
||||
@@ -188,20 +188,20 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardSingleJump) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
}
|
||||
@@ -224,16 +224,16 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardOrdering) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
EXPECT_EQ("BackwardScript1", *(std::next(res.first)));
|
||||
@@ -280,24 +280,24 @@ TEST_F(ScriptSchedulerTest, ForwardBackwards) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
}
|
||||
@@ -320,18 +320,18 @@ TEST_F(ScriptSchedulerTest, Rewind) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 },
|
||||
{ "2", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
|
||||
scheduler.rewind();
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
}
|
||||
@@ -406,23 +406,23 @@ TEST_F(ScriptSchedulerTest, JumpEqual) {
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 11:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 11:00:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:00:00")
|
||||
);
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:01:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:01:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:00:00")
|
||||
);
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
@@ -445,13 +445,13 @@ TEST_F(ScriptSchedulerTest, SameTime) {
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:00:00")
|
||||
);
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:00:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
}
|
||||
@@ -473,23 +473,23 @@ TEST_F(ScriptSchedulerTest, MultiInnerJump) {
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 10:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 10:00:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 11:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 11:00:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 13:00:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 13:00:00")
|
||||
);
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(
|
||||
openspace::Time::ref().convertTime("2000 JAN 03 12:30:00")
|
||||
openspace::Time::convertTime("2000 JAN 03 12:30:00")
|
||||
);
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
}
|
||||
@@ -513,7 +513,7 @@ TEST_F(ScriptSchedulerTest, MultipleForwardSingleJumpMultipleLoad) {
|
||||
|
||||
ScriptScheduler scheduler;
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -522,14 +522,14 @@ TEST_F(ScriptSchedulerTest, MultipleForwardSingleJumpMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript2", *(res.first));
|
||||
}
|
||||
@@ -552,7 +552,7 @@ TEST_F(ScriptSchedulerTest, MultipleForwardOrderingMultipleLoad) {
|
||||
|
||||
ScriptScheduler scheduler;
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -560,10 +560,10 @@ TEST_F(ScriptSchedulerTest, MultipleForwardOrderingMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 02"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 02"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
EXPECT_EQ("ForwardScript2", *(std::next(res.first)));
|
||||
@@ -587,7 +587,7 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardSingleJumpMultipleLoad) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -595,14 +595,14 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardSingleJumpMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
}
|
||||
@@ -625,7 +625,7 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardOrderingMultipleLoad) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -633,10 +633,10 @@ TEST_F(ScriptSchedulerTest, MultipleBackwardOrderingMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 06"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 06"));
|
||||
ASSERT_EQ(res.first, res.second);
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
EXPECT_EQ("BackwardScript1", *(std::next(res.first)));
|
||||
@@ -660,7 +660,7 @@ TEST_F(ScriptSchedulerTest, ForwardBackwardsMultipleLoad) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -668,18 +668,18 @@ TEST_F(ScriptSchedulerTest, ForwardBackwardsMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript1", *(res.first));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("BackwardScript2", *(res.first));
|
||||
}
|
||||
@@ -702,7 +702,7 @@ TEST_F(ScriptSchedulerTest, RewindMultipleLoad) {
|
||||
{ "BackwardScript", "BackwardScript2"s }
|
||||
};
|
||||
|
||||
scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 01"));
|
||||
scheduler.progressTo(openspace::Time::convertTime("2000 JAN 01"));
|
||||
scheduler.loadScripts({
|
||||
{ "1", testDictionary1 }
|
||||
});
|
||||
@@ -710,12 +710,12 @@ TEST_F(ScriptSchedulerTest, RewindMultipleLoad) {
|
||||
{ "1", testDictionary2 }
|
||||
});
|
||||
|
||||
auto res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 07"));
|
||||
auto res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 07"));
|
||||
ASSERT_EQ(2, std::distance(res.first, res.second));
|
||||
|
||||
scheduler.rewind();
|
||||
|
||||
res = scheduler.progressTo(openspace::Time::ref().convertTime("2000 JAN 04"));
|
||||
res = scheduler.progressTo(openspace::Time::convertTime("2000 JAN 04"));
|
||||
ASSERT_EQ(1, std::distance(res.first, res.second));
|
||||
EXPECT_EQ("ForwardScript1", *(res.first));
|
||||
}
|
||||
|
||||
100
tests/test_timeline.inl
Normal file
100
tests/test_timeline.inl
Normal file
@@ -0,0 +1,100 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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 "gtest/gtest.h"
|
||||
|
||||
#include <openspace/util/timeline.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
using namespace openspace;
|
||||
|
||||
class TimelineTest : public testing::Test {};
|
||||
|
||||
TEST_F(TimelineTest, AddAndCountKeyframes) {
|
||||
Timeline<Time> timeline;
|
||||
timeline.addKeyframe(0.0, Time::now());
|
||||
timeline.addKeyframe(1.0, Time::now());
|
||||
|
||||
ASSERT_EQ(timeline.nKeyframes(), 2);
|
||||
}
|
||||
|
||||
TEST_F(TimelineTest, QueryKeyframes) {
|
||||
Timeline<float> timeline;
|
||||
timeline.addKeyframe(0.0, 0.f);
|
||||
timeline.addKeyframe(1.0, 1.f);
|
||||
|
||||
ASSERT_EQ(timeline.nKeyframes(), 2);
|
||||
|
||||
ASSERT_EQ(timeline.firstKeyframeAfter(0.0)->data, 1.f) << "Incorrect keyframe returned";
|
||||
ASSERT_EQ(timeline.firstKeyframeAfter(0.0, false)->data, 1.f) << "Incorrect keyframe returned";
|
||||
ASSERT_EQ(timeline.firstKeyframeAfter(0.0, true)->data, 0.f) << "Incorrect keyframe returned";
|
||||
|
||||
ASSERT_EQ(timeline.lastKeyframeBefore(1.0)->data, 0.f) << "Incorrect keyframe returned";
|
||||
ASSERT_EQ(timeline.lastKeyframeBefore(1.0, false)->data, 0.f) << "Incorrect keyframe returned";
|
||||
ASSERT_EQ(timeline.lastKeyframeBefore(1.0, true)->data, 1.f) << "Incorrect keyframe returned";
|
||||
}
|
||||
|
||||
TEST_F(TimelineTest, RemoveKeyframes) {
|
||||
Timeline<float> timeline;
|
||||
timeline.addKeyframe(0.0, 0.f);
|
||||
timeline.addKeyframe(1.0, 1.f);
|
||||
|
||||
timeline.removeKeyframesBefore(0.0);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 2);
|
||||
|
||||
timeline.removeKeyframesBefore(0.0, false);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 2);
|
||||
|
||||
timeline.removeKeyframesBefore(0.0, true);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 1);
|
||||
|
||||
timeline.removeKeyframesAfter(1.0);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 1);
|
||||
|
||||
timeline.removeKeyframesAfter(1.0, false);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 1);
|
||||
|
||||
timeline.removeKeyframesAfter(1.0, true);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 0);
|
||||
}
|
||||
|
||||
TEST_F(TimelineTest, RemoveKeyframesInRange) {
|
||||
Timeline<float> timeline;
|
||||
timeline.addKeyframe(0.0, 0.f);
|
||||
timeline.addKeyframe(1.0, 1.f);
|
||||
timeline.addKeyframe(2.0, 2.f);
|
||||
timeline.addKeyframe(3.0, 3.f);
|
||||
|
||||
timeline.removeKeyframesBetween(1.0, 2.0);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 4);
|
||||
|
||||
timeline.removeKeyframesBetween(1.0, 2.0, false, true);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 3);
|
||||
|
||||
timeline.removeKeyframesBetween(1.0, 2.0, true, true);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 2);
|
||||
|
||||
timeline.removeKeyframesBetween(-1.0, 4.0);
|
||||
ASSERT_EQ(timeline.nKeyframes(), 0);
|
||||
}
|
||||
Reference in New Issue
Block a user