mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-24 04:58:59 -05:00
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:
@@ -34,7 +34,7 @@ namespace openspace::datamessagestructures {
|
||||
|
||||
enum class Type : uint32_t {
|
||||
CameraData = 0,
|
||||
TimeData,
|
||||
TimelineData,
|
||||
ScriptData
|
||||
};
|
||||
|
||||
@@ -52,26 +52,27 @@ struct CameraKeyframe {
|
||||
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer) {
|
||||
void serialize(std::vector<char> &buffer) const {
|
||||
// Add position
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_position),
|
||||
reinterpret_cast<char*>(&_position) + sizeof(_position)
|
||||
reinterpret_cast<const char*>(&_position),
|
||||
reinterpret_cast<const char*>(&_position) + sizeof(_position)
|
||||
);
|
||||
|
||||
// Add orientation
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_rotation),
|
||||
reinterpret_cast<char*>(&_rotation) + sizeof(_rotation)
|
||||
reinterpret_cast<const char*>(&_rotation),
|
||||
reinterpret_cast<const char*>(&_rotation) + sizeof(_rotation)
|
||||
);
|
||||
|
||||
// Follow focus node rotation?
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_followNodeRotation),
|
||||
reinterpret_cast<char*>(&_followNodeRotation) + sizeof(_followNodeRotation)
|
||||
reinterpret_cast<const char*>(&_followNodeRotation),
|
||||
reinterpret_cast<const char*>(&_followNodeRotation) +
|
||||
sizeof(_followNodeRotation)
|
||||
);
|
||||
|
||||
int nodeNameLength = static_cast<int>(_focusNode.size());
|
||||
@@ -79,8 +80,8 @@ struct CameraKeyframe {
|
||||
// Add focus node
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&nodeNameLength),
|
||||
reinterpret_cast<char*>(&nodeNameLength) + sizeof(nodeNameLength)
|
||||
reinterpret_cast<const char*>(&nodeNameLength),
|
||||
reinterpret_cast<const char*>(&nodeNameLength) + sizeof(nodeNameLength)
|
||||
);
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
@@ -90,20 +91,19 @@ struct CameraKeyframe {
|
||||
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_scale),
|
||||
reinterpret_cast<char*>(&_scale) + sizeof(_scale)
|
||||
reinterpret_cast<const char*>(&_scale),
|
||||
reinterpret_cast<const char*>(&_scale) + sizeof(_scale)
|
||||
);
|
||||
|
||||
// Add timestamp
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_timestamp),
|
||||
reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp)
|
||||
reinterpret_cast<const char*>(&_timestamp),
|
||||
reinterpret_cast<const char*>(&_timestamp) + sizeof(_timestamp)
|
||||
);
|
||||
};
|
||||
|
||||
void deserialize(const std::vector<char> &buffer) {
|
||||
int offset = 0;
|
||||
size_t deserialize(const std::vector<char> &buffer, size_t offset = 0) {
|
||||
int size = 0;
|
||||
|
||||
// Position
|
||||
@@ -138,6 +138,9 @@ struct CameraKeyframe {
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
return offset;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -153,71 +156,65 @@ struct TimeKeyframe {
|
||||
bool _requiresTimeJump;
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
// Add current time
|
||||
void serialize(std::vector<char> &buffer) const {
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_time),
|
||||
reinterpret_cast<char*>(&_time) + sizeof(_time)
|
||||
);
|
||||
|
||||
// Add delta time
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_dt),
|
||||
reinterpret_cast<char*>(&_dt) + sizeof(_dt)
|
||||
);
|
||||
|
||||
// Add whether time is paused or not
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_paused),
|
||||
reinterpret_cast<char*>(&_paused) + sizeof(_paused)
|
||||
);
|
||||
|
||||
// Add whether a time jump is necessary (recompute paths etc)
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_requiresTimeJump),
|
||||
reinterpret_cast<char*>(&_requiresTimeJump) + sizeof(_requiresTimeJump)
|
||||
);
|
||||
|
||||
// Add timestamp
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<char*>(&_timestamp),
|
||||
reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp)
|
||||
reinterpret_cast<const char*>(this),
|
||||
reinterpret_cast<const char*>(this) + sizeof(TimeKeyframe)
|
||||
);
|
||||
};
|
||||
|
||||
void deserialize(const std::vector<char> &buffer){
|
||||
int offset = 0;
|
||||
size_t deserialize(const std::vector<char> &buffer, size_t offset = 0){
|
||||
*this = *reinterpret_cast<const TimeKeyframe*>(buffer.data() + offset);
|
||||
offset += sizeof(TimeKeyframe);
|
||||
return offset;
|
||||
};
|
||||
};
|
||||
|
||||
struct TimeTimeline {
|
||||
TimeTimeline() {}
|
||||
TimeTimeline(const std::vector<char> &buffer) {
|
||||
deserialize(buffer);
|
||||
}
|
||||
|
||||
bool _clear = true;
|
||||
std::vector<TimeKeyframe> _keyframes;
|
||||
|
||||
void serialize(std::vector<char> &buffer) const {
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<const char*>(&_clear),
|
||||
reinterpret_cast<const char*>(&_clear) + sizeof(bool)
|
||||
);
|
||||
|
||||
int64_t nKeyframes = _keyframes.size();
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
reinterpret_cast<const char*>(&nKeyframes),
|
||||
reinterpret_cast<const char*>(&nKeyframes) + sizeof(int64_t)
|
||||
);
|
||||
for (const auto k : _keyframes) {
|
||||
k.serialize(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
size_t deserialize(const std::vector<char> &buffer, size_t offset = 0) {
|
||||
int size = 0;
|
||||
|
||||
// Current time
|
||||
size = sizeof(_time);
|
||||
memcpy(&_time, buffer.data() + offset, size);
|
||||
size = sizeof(_clear);
|
||||
memcpy(&_clear, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Delta time
|
||||
size = sizeof(_dt);
|
||||
memcpy(&_dt, buffer.data() + offset, size);
|
||||
int64_t nKeyframes = _keyframes.size();
|
||||
size = sizeof(nKeyframes);
|
||||
memcpy(&nKeyframes, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Is time paused?
|
||||
size = sizeof(_paused);
|
||||
memcpy(&_paused, buffer.data() + offset, size);
|
||||
offset += sizeof(_paused);
|
||||
|
||||
// Is a time jump required?
|
||||
size = sizeof(_requiresTimeJump);
|
||||
memcpy(&_requiresTimeJump, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
// offset += size;
|
||||
_keyframes.resize(nKeyframes);
|
||||
for (auto& k : _keyframes) {
|
||||
offset = k.deserialize(buffer, offset);
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -229,11 +226,11 @@ struct ScriptMessage {
|
||||
|
||||
std::string _script;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
void serialize(std::vector<char> &buffer) const {
|
||||
buffer.insert(buffer.end(), _script.begin(), _script.end());
|
||||
};
|
||||
|
||||
void deserialize(const std::vector<char> &buffer){
|
||||
void deserialize(const std::vector<char> &buffer) {
|
||||
_script.assign(buffer.begin(), buffer.end());
|
||||
};
|
||||
};
|
||||
|
||||
@@ -62,9 +62,10 @@ public:
|
||||
|
||||
struct DataMessage {
|
||||
DataMessage() = default;
|
||||
DataMessage(datamessagestructures::Type t, std::vector<char> c);
|
||||
DataMessage(datamessagestructures::Type t, double timestamp, std::vector<char> c);
|
||||
|
||||
datamessagestructures::Type type;
|
||||
double timestamp;
|
||||
std::vector<char> content;
|
||||
};
|
||||
|
||||
@@ -83,6 +84,7 @@ public:
|
||||
|
||||
ParallelConnection::Message receiveMessage();
|
||||
|
||||
static const unsigned int ProtocolVersion;
|
||||
private:
|
||||
std::unique_ptr<ghoul::io::TcpSocket> _socket;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#ifndef __OPENSPACE_CORE___PARALLELPEER___H__
|
||||
#define __OPENSPACE_CORE___PARALLELPEER___H__
|
||||
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
@@ -62,7 +66,6 @@ public:
|
||||
void sendScript(std::string script);
|
||||
void resetTimeOffset();
|
||||
double latencyStandardDeviation() const;
|
||||
double timeTolerance() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
@@ -85,24 +88,26 @@ private:
|
||||
void nConnectionsMessageReceived(const std::vector<char>& message);
|
||||
|
||||
void sendCameraKeyframe();
|
||||
void sendTimeKeyframe();
|
||||
void sendTimeTimeline();
|
||||
|
||||
void setStatus(ParallelConnection::Status status);
|
||||
void setHostName(const std::string& hostName);
|
||||
void setNConnections(size_t nConnections);
|
||||
|
||||
double calculateBufferedKeyframeTime(double originalTime);
|
||||
double convertTimestamp(double originalTime);
|
||||
void analyzeTimeDifference(double messageTimestamp);
|
||||
|
||||
properties::StringProperty _password;
|
||||
properties::StringProperty _hostPassword;
|
||||
// Change to properties::IntProperty ? ---abock
|
||||
|
||||
// While the port should in theory be an int,
|
||||
// we use a StringProperty to avoid a slider in the GUI.
|
||||
properties::StringProperty _port;
|
||||
properties::StringProperty _address;
|
||||
properties::StringProperty _name;
|
||||
properties::FloatProperty _bufferTime;
|
||||
properties::FloatProperty _timeKeyframeInterval;
|
||||
properties::FloatProperty _cameraKeyframeInterval;
|
||||
properties::FloatProperty _timeTolerance;
|
||||
|
||||
double _lastTimeKeyframeTimestamp = 0.0;
|
||||
double _lastCameraKeyframeTimestamp = 0.0;
|
||||
@@ -119,6 +124,7 @@ private:
|
||||
std::mutex _receiveBufferMutex;
|
||||
|
||||
std::atomic<bool> _timeJumped;
|
||||
std::atomic<bool> _timeTimelineChanged;
|
||||
std::mutex _latencyMutex;
|
||||
std::deque<double> _latencyDiffs;
|
||||
double _initialTimeDiff;
|
||||
@@ -127,6 +133,9 @@ private:
|
||||
std::shared_ptr<ghoul::Event<>> _connectionEvent;
|
||||
|
||||
ParallelConnection _connection;
|
||||
|
||||
TimeManager::CallbackHandle _timeJumpCallback = -1;
|
||||
TimeManager::CallbackHandle _timeTimelineChangeCallback = -1;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user