Feature/time interpolation (#669)

* Initial implementation
* Better approximation of target time
* Correctly use double precision for time passing
* Cleanup
* Adding proportional adjustment of delta time at end of interpolation
* Keyframe based time interpolation
* Add property for time interpolation duration. Move time interpolation methods to TimeManager.
* Fix bugs with time gui
* Make several clicks on delta time buttons work as expected
* Clean up
* Improve time interpolation for parallel connection
* Improve time API. Fix time interpolation bugs.
* Fix mac compile issue
* Add hour button
* Add missing + sign
* Remove newer images from projection buffer when going back in time
* Add comment about clearing projection buffer
* Fix bug with jumping time in parallel connection
* Rename integrateFromTime to previousFrameTime
* Compile fix for iswa module
* Address code review comments
* Code cleanup
* Fix bug causig unsmooth behaviour when pausing while interpolating in time
This commit is contained in:
Emil Axelsson
2018-07-13 11:07:35 +02:00
committed by GitHub
parent 6007f1d70d
commit 902e3e6dac
42 changed files with 1465 additions and 586 deletions
+12 -2
View File
@@ -65,13 +65,23 @@ public:
*/
operator const T&() const;
/**
* Explicitly access data
*/
T& data();
/**
* Explicitly access const data
*/
const T& data() const;
protected:
virtual void encode(SyncBuffer* syncBuffer) override;
virtual void decode(SyncBuffer* syncBuffer) override;
virtual void postSync(bool isMaster) override;
T data;
T doubleBufferedData;
T _data;
T _doubleBufferedData;
std::mutex _mutex;
};
+18 -8
View File
@@ -27,38 +27,48 @@
namespace openspace {
template<class T>
SyncData<T>::SyncData(const T& val) : data(val) {}
SyncData<T>::SyncData(const T& val) : _data(val) {}
template<class T>
SyncData<T>::SyncData(const SyncData<T>& o) : data(o.data) {}
SyncData<T>::SyncData(const SyncData<T>& o) : _data(o._data) {}
template<class T>
SyncData<T>& SyncData<T>::operator=(const T& rhs) {
data = rhs;
_data = rhs;
return *this;
}
template<class T>
SyncData<T>::operator T&() {
return data;
return _data;
}
template<class T>
SyncData<T>::operator const T&() const {
return data;
return _data;
}
template<class T>
T& SyncData<T>::data() {
return _data;
}
template<class T>
const T& SyncData<T>::data() const {
return _data;
}
template<class T>
void SyncData<T>::encode(SyncBuffer* syncBuffer) {
_mutex.lock();
syncBuffer->encode(data);
syncBuffer->encode(_data);
_mutex.unlock();
}
template<class T>
void SyncData<T>::decode(SyncBuffer* syncBuffer) {
_mutex.lock();
syncBuffer->decode(doubleBufferedData);
syncBuffer->decode(_doubleBufferedData);
_mutex.unlock();
}
@@ -67,7 +77,7 @@ void SyncData<T>::postSync(bool isMaster) {
// apply synced update
if (!isMaster) {
_mutex.lock();
data = doubleBufferedData;
_data = _doubleBufferedData;
_mutex.unlock();
}
}
+4 -57
View File
@@ -89,22 +89,16 @@ public:
* Sets the current time to the specified value in seconds past the J2000 epoch. This
* value can be negative to represent dates before the epoch.
* \param value The number of seconds after the J2000 epoch
* \param requireJump Whether or not the time change is big enough to require a
* time-jump; defaults to true as most calls to set time will require recomputation of
* planetary paths etc.
*/
void setTime(double j2000Seconds, bool requireJump = true);
void setTime(double j2000Seconds);
/**
* Sets the current time to the specified value given as a Spice compliant string as
* described in the Spice documentation
* (http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/str2et_c.html)
* \param time The time to be set as a date string
* \param requireJump Whether or not the time change is big enough to require a
* time-jump; defaults to true as most calls to set time will require recomputation of
* planetary paths etc.
*/
void setTime(std::string time, bool requireJump = true);
void setTime(std::string time);
/**
* Returns the current time as the number of seconds past the J2000 epoch. If the
@@ -126,39 +120,6 @@ public:
*/
std::string ISO8601() const;
/**
* Sets the delta time value that is the number of seconds that should pass for each
* real-time second. This value is used in the advanceTime(double) method to easily
* advance the simulation time.
* \param deltaT The number of seconds that should pass for each real-time second
*/
void setDeltaTime(double deltaT);
/**
* Returns the delta time, that is the number of seconds that pass in the simulation
* for each real-time second
* \return The number of seconds that pass for each real-time second
*/
double deltaTime() const;
/**
* Sets the pause function, i.e. setting the deltaTime to 0 (<code>pause</code> =
* <code>true</code>) and restoring it when the function is called with a parameter of
* <code>false</code>.
* \param pause If <code>true</code>, the simulation time stops;
* if <code>false</code>, the simulation time continues at the previous rate
*/
void setPause(bool pause);
/**
* Toggles the pause function, i.e. setting the deltaTime to 0 and restoring it when
* the function is called a second time. It returns the pause state (<code>true</code>
* if the time is now paused, <code>false</code> otherwise)
* \return The new pause state (<code>true</code> if the time is now paused,
* <code>false</code> otherwise)
*/
bool togglePause();
/**
* Advances the simulation time using the deltaTime() and the <code>tickTime</code>.
* The deltaTime() is the number of simulation seconds that pass for each real-time
@@ -171,30 +132,16 @@ public:
*/
double advanceTime(double tickTime);
bool timeJumped() const;
void setTimeJumped(bool jumped);
bool paused() const;
/**
* Returns the Lua library that contains all Lua functions available to change the
* current time, retrieve the current time etc. The functions contained are
* - openspace::luascriptfunctions::time_setDeltaTime
* - openspace::luascriptfunctions::time_deltaTime
* - openspace::luascriptfunctions::time_setTime
* - openspace::luascriptfunctions::time_currentTime
* - openspace::luascriptfunctions::time_currentTimeUTC
* current time, retrieve the current time etc.
* \return The Lua library that contains all Lua functions available to change the
* Time singleton
* time
*/
static scripting::LuaLibrary luaLibrary();
private:
double _time;
double _dt = 1.0;
bool _timeJumped = false;
bool _timePaused = false;
};
} // namespace openspace
+83 -12
View File
@@ -32,41 +32,112 @@
#include <utility>
#include <vector>
#include <deque>
#include <functional>
#include <openspace/util/timeline.h>
#include <openspace/util/time.h>
#include <openspace/util/syncdata.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/floatproperty.h>
namespace openspace {
class TimeManager {
struct TimeKeyframeData {
Time time;
double delta;
bool pause = false;
bool jump = false;
};
class TimeManager : public properties::PropertyOwner {
public:
TimeManager();
using CallbackHandle = int;
using TimeChangeCallback = std::function<void()>;
Time& time();
const Time& time() const;
const Time& integrateFromTime() const;
const Timeline<TimeKeyframeData>& timeline();
std::vector<Syncable*> getSyncables();
void preSynchronization(double dt);
void addKeyframe(double timestamp, Time keyframeTime);
void removeKeyframesBefore(double timestamp);
void removeKeyframesAfter(double timestamp);
void clearKeyframes();
TimeKeyframeData interpolate(double applicationTime);
void setTimeNextFrame(Time t);
void setDeltaTime(double deltaTime);
void setPause(bool pause);
/**
* Returns the delta time, unaffected by pause
*/
double targetDeltaTime() const;
/*
* Returns the current delta time, as affected by pause
*/
double deltaTime() const;
bool isPaused() const;
float defaultTimeInterpolationDuration() const;
float defaultDeltaTimeInterpolationDuration() const;
float defaultPauseInterpolationDuration() const;
float defaultUnpauseInterpolationDuration() const;
void interpolateTime(double targetTime, double durationSeconds);
void interpolateDeltaTime(double targetDeltaTime, double durationSeconds);
void interpolatePause(bool pause, double durationSeconds);
void addKeyframe(double timestamp, TimeKeyframeData kf);
void removeKeyframesBefore(double timestamp, bool inclusive = false);
void removeKeyframesAfter(double timestamp, bool inclusive = false);
size_t nKeyframes() const;
void clearKeyframes();
CallbackHandle addTimeChangeCallback(TimeChangeCallback cb);
CallbackHandle addDeltaTimeChangeCallback(TimeChangeCallback cb);
CallbackHandle addTimeJumpCallback(TimeChangeCallback cb);
CallbackHandle addTimelineChangeCallback(TimeChangeCallback cb);
void removeTimeChangeCallback(CallbackHandle handle);
void removeDeltaTimeChangeCallback(CallbackHandle handle);
void removeTimeJumpCallback(CallbackHandle handle);
void removeTimelineChangeCallback(CallbackHandle handle);
private:
void progressTime(double dt);
void applyKeyframeData(const TimeKeyframeData& keyframe);
TimeKeyframeData interpolate(const Keyframe<TimeKeyframeData>& past,
const Keyframe<TimeKeyframeData>& future, double time);
Timeline<TimeKeyframeData> _timeline;
SyncData<Time> _currentTime;
SyncData<Time> _integrateFromTime;
bool _timePaused = false;
double _targetDeltaTime = 1.0;
double _deltaTime = 0.0;
double _lastTime = 0;
double _lastDeltaTime = 0;
properties::FloatProperty _defaultTimeInterpolationDuration;
properties::FloatProperty _defaultDeltaTimeInterpolationDuration;
properties::FloatProperty _defaultPauseInterpolationDuration;
properties::FloatProperty _defaultUnpauseInterpolationDuration;
bool _shouldSetTime = false;
Time _timeNextFrame;
Timeline<Time> _timeline;
SyncData<Time> _currentTime;
void consumeKeyframes(double dt);
bool _timelineChanged;
double _latestConsumedTimestamp = -std::numeric_limits<double>::max();
int _nextCallbackHandle = 0;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _timeChangeCallbacks;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _deltaTimeChangeCallbacks;
double _lastTime = 0;
double _lastDeltaTime = 0;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _timeJumpCallbacks;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _timelineChangeCallbacks;
};
} // namespace openspace
@@ -45,6 +45,7 @@ struct TransformData {
struct UpdateData {
TransformData modelTransform;
const Time time;
const Time previousFrameTime;
const bool doPerformanceMeasurement;
};