mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-23 05:19:18 -06:00
Use double buffering for time and camera syncing
This commit is contained in:
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
bool busyWaitForDecode();
|
||||
bool logSGCTOutOfOrderErrors();
|
||||
bool useDoubleBuffering();
|
||||
|
||||
private:
|
||||
void initEyeSeparation();
|
||||
@@ -52,12 +53,14 @@ private:
|
||||
void initShowFrameNumber();
|
||||
void initBusyWaitForDecode();
|
||||
void initLogSGCTOutOfOrderErrors();
|
||||
void initUseDoubleBuffering();
|
||||
|
||||
properties::FloatProperty _eyeSeparation;
|
||||
properties::OptionProperty _scenes;
|
||||
properties::BoolProperty _showFrameNumber;
|
||||
properties::BoolProperty _busyWaitForDecode;
|
||||
properties::BoolProperty _logSGCTOutOfOrderErrors;
|
||||
properties::BoolProperty _useDoubleBuffering;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -177,6 +177,8 @@ namespace openspace {
|
||||
[[deprecated("Replaced by Camera::SgctInternal::viewProjectionMatrix()")]]
|
||||
const glm::mat4& viewProjectionMatrix() const;
|
||||
|
||||
void updateDoubleBuffer();
|
||||
|
||||
private:
|
||||
struct SyncData {
|
||||
void serialize(SyncBuffer* syncBuffer) {
|
||||
@@ -193,8 +195,10 @@ namespace openspace {
|
||||
Vec3 position;
|
||||
Quat rotation;
|
||||
glm::vec2 scaling;
|
||||
} syncData;
|
||||
};
|
||||
|
||||
SyncData local;
|
||||
SyncData synced;
|
||||
|
||||
// _focusPosition to be removed
|
||||
Vec3 _focusPosition;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define __TIME_H__
|
||||
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
#include <openspace/util/syncbuffer.h>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
@@ -190,6 +190,8 @@ public:
|
||||
|
||||
bool paused() const;
|
||||
|
||||
void updateDoubleBuffer();
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to change the
|
||||
* current time, retrieve the current time etc. The functions contained are
|
||||
@@ -205,11 +207,29 @@ public:
|
||||
|
||||
private:
|
||||
static Time* _instance; ///< The singleton instance
|
||||
|
||||
/// The time stored as the number of seconds past the J2000 epoch
|
||||
double _time = -1.0;
|
||||
double _dt = 1.0;
|
||||
bool _timeJumped = false;
|
||||
|
||||
struct SyncData {
|
||||
void serialize(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->encode(time);
|
||||
syncBuffer->encode(dt);
|
||||
syncBuffer->encode(timeJumped);
|
||||
};
|
||||
|
||||
void deserialize(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->decode(time);
|
||||
syncBuffer->decode(dt);
|
||||
syncBuffer->decode(timeJumped);
|
||||
}
|
||||
|
||||
double time = -1.0;
|
||||
double dt = 1.0;
|
||||
bool timeJumped = false;
|
||||
|
||||
};
|
||||
|
||||
SyncData local;
|
||||
SyncData synced;
|
||||
|
||||
bool _timePaused = false;
|
||||
|
||||
std::mutex _syncMutex;
|
||||
|
||||
@@ -9,11 +9,11 @@ return {
|
||||
-- of all entities that will be visible during an instance of OpenSpace
|
||||
--Scene = "${SCENE}/default.scene",
|
||||
|
||||
Scene = "${SCENE}/globebrowsing.scene",
|
||||
-- Scene = "${SCENE}/globebrowsing.scene",
|
||||
-- Scene = "${SCENE}/rosetta.scene",
|
||||
-- Scene = "${SCENE}/dawn.scene",
|
||||
-- Scene = "${SCENE}/newhorizons.scene",
|
||||
--Scene = "${SCENE}/osirisrex.scene",
|
||||
Scene = "${SCENE}/osirisrex.scene",
|
||||
|
||||
Paths = {
|
||||
SGCT = "${BASE_PATH}/config/sgct",
|
||||
|
||||
@@ -778,6 +778,11 @@ void OpenSpaceEngine::preSynchronization() {
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
if (_settingsEngine->useDoubleBuffering() && !_isMaster) {
|
||||
Time::ref().updateDoubleBuffer();
|
||||
_renderEngine->camera()->updateDoubleBuffer();
|
||||
}
|
||||
|
||||
if (_isInShutdownMode) {
|
||||
if (_shutdownCountdown <= 0.f) {
|
||||
_windowWrapper->terminate();
|
||||
|
||||
@@ -52,6 +52,7 @@ SettingsEngine::SettingsEngine()
|
||||
, _showFrameNumber("showFrameNumber", "Show frame number", false)
|
||||
, _busyWaitForDecode("busyWaitForDecode", "Busy Wait for decode", false)
|
||||
, _logSGCTOutOfOrderErrors("logSGCTOutOfOrderErrors", "Log SGCT out-of-order", false)
|
||||
, _useDoubleBuffering("useDoubleBuffering", "Use double buffering", false)
|
||||
{
|
||||
setName("Global Properties");
|
||||
}
|
||||
@@ -62,6 +63,7 @@ void SettingsEngine::initialize() {
|
||||
initShowFrameNumber();
|
||||
initBusyWaitForDecode();
|
||||
initLogSGCTOutOfOrderErrors();
|
||||
initUseDoubleBuffering();
|
||||
}
|
||||
|
||||
void SettingsEngine::setModules(std::vector<OpenSpaceModule*> modules) {
|
||||
@@ -109,6 +111,20 @@ bool SettingsEngine::logSGCTOutOfOrderErrors() {
|
||||
return _logSGCTOutOfOrderErrors.value();
|
||||
}
|
||||
|
||||
|
||||
void SettingsEngine::initUseDoubleBuffering() {
|
||||
addProperty(_useDoubleBuffering);
|
||||
_useDoubleBuffering.onChange(
|
||||
[this]() {
|
||||
LINFO("Turn " << (_useDoubleBuffering.value() ? "on" : "off") << " double buffering");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool SettingsEngine::useDoubleBuffering() {
|
||||
return _useDoubleBuffering.value();
|
||||
}
|
||||
|
||||
void SettingsEngine::initSceneFiles() {
|
||||
addProperty(_scenes);
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ namespace openspace {
|
||||
, _focusPosition()
|
||||
{
|
||||
|
||||
syncData.scaling= glm::vec2(1.f, 0.f);
|
||||
syncData.position = Vec3(1.0, 1.0, 1.0);
|
||||
local.scaling= glm::vec2(1.f, 0.f);
|
||||
local.position = Vec3(1.0, 1.0, 1.0);
|
||||
Vec3 eulerAngles(1.0, 1.0, 1.0);
|
||||
syncData.rotation = Quat(eulerAngles);
|
||||
local.rotation = Quat(eulerAngles);
|
||||
}
|
||||
|
||||
Camera::Camera(const Camera& o)
|
||||
@@ -62,7 +62,7 @@ namespace openspace {
|
||||
, _focusPosition(o._focusPosition)
|
||||
, _cachedViewDirection(o._cachedViewDirection)
|
||||
, _cachedLookupVector(o._cachedLookupVector)
|
||||
, syncData(o.syncData)
|
||||
, local(o.local)
|
||||
, _maxFov(o._maxFov)
|
||||
{ }
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace openspace {
|
||||
// Mutators
|
||||
void Camera::setPositionVec3(Vec3 pos) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.position = pos;
|
||||
local.position = pos;
|
||||
|
||||
_cachedCombinedViewMatrix.isDirty = true;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace openspace {
|
||||
|
||||
void Camera::setRotation(Quat rotation) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.rotation = rotation;
|
||||
local.rotation = rotation;
|
||||
_cachedViewDirection.isDirty = true;
|
||||
_cachedLookupVector.isDirty = true;
|
||||
_cachedViewRotationMatrix.isDirty = true;
|
||||
@@ -92,7 +92,7 @@ namespace openspace {
|
||||
|
||||
void Camera::setScaling(glm::vec2 scaling) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.scaling = std::move(scaling);
|
||||
local.scaling = std::move(scaling);
|
||||
}
|
||||
|
||||
void Camera::setMaxFov(float fov) {
|
||||
@@ -104,7 +104,7 @@ namespace openspace {
|
||||
// Relative mutators
|
||||
void Camera::rotate(Quat rotation) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.rotation = rotation * syncData.rotation;
|
||||
local.rotation = rotation * local.rotation;
|
||||
|
||||
_cachedViewDirection.isDirty = true;
|
||||
_cachedLookupVector.isDirty = true;
|
||||
@@ -114,11 +114,11 @@ namespace openspace {
|
||||
|
||||
// Accessors
|
||||
const Camera::Vec3& Camera::positionVec3() const {
|
||||
return syncData.position;
|
||||
return local.position;
|
||||
}
|
||||
|
||||
const Camera::Vec3& Camera::unsynchedPositionVec3() const {
|
||||
return syncData.position;
|
||||
return local.position;
|
||||
}
|
||||
|
||||
const Camera::Vec3& Camera::focusPositionVec3() const {
|
||||
@@ -128,7 +128,7 @@ namespace openspace {
|
||||
const Camera::Vec3& Camera::viewDirectionWorldSpace() const {
|
||||
if (_cachedViewDirection.isDirty) {
|
||||
_cachedViewDirection.datum =
|
||||
syncData.rotation * Vec3(_VIEW_DIRECTION_CAMERA_SPACE);
|
||||
local.rotation * Vec3(_VIEW_DIRECTION_CAMERA_SPACE);
|
||||
_cachedViewDirection.datum = glm::normalize(_cachedViewDirection.datum);
|
||||
_cachedViewDirection.isDirty = true;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace openspace {
|
||||
const Camera::Vec3& Camera::lookUpVectorWorldSpace() const {
|
||||
if (_cachedLookupVector.isDirty) {
|
||||
_cachedLookupVector.datum =
|
||||
syncData.rotation * Vec3(_LOOKUP_VECTOR_CAMERA_SPACE);
|
||||
local.rotation * Vec3(_LOOKUP_VECTOR_CAMERA_SPACE);
|
||||
_cachedLookupVector.datum = glm::normalize(_cachedLookupVector.datum);
|
||||
_cachedLookupVector.isDirty = true;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ namespace openspace {
|
||||
}
|
||||
|
||||
const glm::vec2& Camera::scaling() const {
|
||||
return syncData.scaling;
|
||||
return local.scaling;
|
||||
}
|
||||
|
||||
float Camera::maxFov() const {
|
||||
@@ -167,19 +167,19 @@ namespace openspace {
|
||||
|
||||
const Camera::Mat4& Camera::viewRotationMatrix() const {
|
||||
if (_cachedViewRotationMatrix.isDirty) {
|
||||
_cachedViewRotationMatrix.datum = glm::mat4_cast(glm::inverse(syncData.rotation));
|
||||
_cachedViewRotationMatrix.datum = glm::mat4_cast(glm::inverse(local.rotation));
|
||||
}
|
||||
return _cachedViewRotationMatrix.datum;
|
||||
}
|
||||
|
||||
const Camera::Quat& Camera::rotationQuaternion() const {
|
||||
return syncData.rotation;
|
||||
return local.rotation;
|
||||
}
|
||||
|
||||
const Camera::Mat4& Camera::combinedViewMatrix() const {
|
||||
if (_cachedCombinedViewMatrix.isDirty) {
|
||||
Mat4 cameraTranslation =
|
||||
glm::inverse(glm::translate(Mat4(1.0), syncData.position));
|
||||
glm::inverse(glm::translate(Mat4(1.0), local.position));
|
||||
_cachedCombinedViewMatrix.datum =
|
||||
Mat4(sgctInternal.viewMatrix()) *
|
||||
Mat4(viewRotationMatrix()) *
|
||||
@@ -192,12 +192,12 @@ namespace openspace {
|
||||
// Synchronization
|
||||
void Camera::serialize(SyncBuffer* syncBuffer) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.serialize(syncBuffer);
|
||||
local.serialize(syncBuffer);
|
||||
}
|
||||
|
||||
void Camera::deserialize(SyncBuffer* syncBuffer) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.deserialize(syncBuffer);
|
||||
synced.deserialize(syncBuffer);
|
||||
}
|
||||
|
||||
void Camera::invalidateCache() {
|
||||
@@ -266,7 +266,7 @@ namespace openspace {
|
||||
// Deprecated
|
||||
void Camera::setPosition(psc pos) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
syncData.position = pos.dvec3();
|
||||
local.position = pos.dvec3();
|
||||
}
|
||||
|
||||
void Camera::setFocusPosition(psc pos) {
|
||||
@@ -275,11 +275,11 @@ namespace openspace {
|
||||
}
|
||||
|
||||
psc Camera::position() const {
|
||||
return psc(syncData.position);
|
||||
return psc(local.position);
|
||||
}
|
||||
|
||||
psc Camera::unsynchedPosition() const {
|
||||
return psc(syncData.position);
|
||||
return psc(local.position);
|
||||
}
|
||||
|
||||
psc Camera::focusPosition() const {
|
||||
@@ -297,4 +297,8 @@ namespace openspace {
|
||||
const glm::mat4& Camera::viewProjectionMatrix() const {
|
||||
return sgctInternal.viewProjectionMatrix();
|
||||
}
|
||||
|
||||
void Camera::updateDoubleBuffer(){
|
||||
local = synced;
|
||||
}
|
||||
} // namespace openspace
|
||||
|
||||
@@ -42,20 +42,14 @@ namespace openspace {
|
||||
Time* Time::_instance = nullptr;
|
||||
|
||||
Time::Time(double secondsJ2000)
|
||||
: _time(secondsJ2000)
|
||||
, _dt(1.0)
|
||||
, _timeJumped(false)
|
||||
, _timePaused(false)
|
||||
{
|
||||
|
||||
local.time = secondsJ2000;
|
||||
}
|
||||
|
||||
|
||||
Time::Time(const Time& other)
|
||||
: _time(other._time)
|
||||
, _dt(other._dt)
|
||||
, _timeJumped(other._timeJumped)
|
||||
, _timePaused(other._timePaused)
|
||||
: local(other.local)
|
||||
, synced(other.synced)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -92,31 +86,31 @@ bool Time::isInitialized() {
|
||||
}
|
||||
|
||||
void Time::setTime(double value, bool requireJump) {
|
||||
_time = value;
|
||||
_timeJumped = requireJump;
|
||||
local.time = value;
|
||||
local.timeJumped = requireJump;
|
||||
}
|
||||
|
||||
double Time::j2000Seconds() const {
|
||||
return _time;
|
||||
return local.time;
|
||||
}
|
||||
|
||||
double Time::advanceTime(double tickTime) {
|
||||
if (_timePaused)
|
||||
return _time;
|
||||
return local.time;
|
||||
else
|
||||
return _time += _dt * tickTime;
|
||||
return local.time += local.dt * tickTime;
|
||||
}
|
||||
|
||||
void Time::setDeltaTime(double deltaT) {
|
||||
_dt = deltaT;
|
||||
local.dt = deltaT;
|
||||
}
|
||||
|
||||
double Time::deltaTime() const {
|
||||
return _dt;
|
||||
return local.dt;
|
||||
}
|
||||
|
||||
void Time::setPause(bool pause) {
|
||||
_timePaused = pause;
|
||||
_timePaused = pause;
|
||||
}
|
||||
|
||||
bool Time::togglePause() {
|
||||
@@ -125,16 +119,16 @@ bool Time::togglePause() {
|
||||
}
|
||||
|
||||
void Time::setTime(std::string time, bool requireJump) {
|
||||
_time = SpiceManager::ref().ephemerisTimeFromDate(std::move(time));
|
||||
_timeJumped = requireJump;
|
||||
local.time = SpiceManager::ref().ephemerisTimeFromDate(std::move(time));
|
||||
local.timeJumped = requireJump;
|
||||
}
|
||||
|
||||
std::string Time::UTC() const {
|
||||
return SpiceManager::ref().dateFromEphemerisTime(_time);
|
||||
return SpiceManager::ref().dateFromEphemerisTime(local.time);
|
||||
}
|
||||
|
||||
std::string Time::ISO8601() const {
|
||||
std::string datetime = SpiceManager::ref().dateFromEphemerisTime(_time);
|
||||
std::string datetime = SpiceManager::ref().dateFromEphemerisTime(local.time);
|
||||
std::string month = datetime.substr(5, 3);
|
||||
|
||||
std::string MM = "";
|
||||
@@ -158,35 +152,31 @@ std::string Time::ISO8601() const {
|
||||
|
||||
void Time::serialize(SyncBuffer* syncBuffer) {
|
||||
_syncMutex.lock();
|
||||
|
||||
syncBuffer->encode(_time);
|
||||
syncBuffer->encode(_dt);
|
||||
syncBuffer->encode(_timeJumped);
|
||||
|
||||
local.serialize(syncBuffer);
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
void Time::deserialize(SyncBuffer* syncBuffer) {
|
||||
_syncMutex.lock();
|
||||
|
||||
syncBuffer->decode(_time);
|
||||
syncBuffer->decode(_dt);
|
||||
syncBuffer->decode(_timeJumped);
|
||||
|
||||
synced.deserialize(syncBuffer);
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
bool Time::timeJumped() const {
|
||||
return _timeJumped;
|
||||
return local.timeJumped;
|
||||
}
|
||||
|
||||
void Time::setTimeJumped(bool jumped) {
|
||||
_timeJumped = jumped;
|
||||
local.timeJumped = jumped;
|
||||
}
|
||||
|
||||
bool Time::paused() const {
|
||||
return _timePaused;
|
||||
}
|
||||
void Time::updateDoubleBuffer() {
|
||||
local = synced;
|
||||
}
|
||||
|
||||
|
||||
scripting::LuaLibrary Time::luaLibrary() {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user