mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-03 17:30:04 -05:00
Feature/domecasting (#288)
* Improve dome casting feature. Add basic GUI for domecasting. * Reenable remote scripting from Lua console. Add more settings and debug information for domecasting. * Do not try to reconnect to parallel connection forever * Fix interpolation bug for dome casting with globe browsing interaction mode * Show parallel connection properties in correct GUI * Fix bug for dome casting with globe browsing interaction mode. Add property for time tolerance. * Update header file * Clean up dome casting code * Remove obsolete lua functions from ParallelConnection.
This commit is contained in:
@@ -65,6 +65,7 @@ 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);
|
||||
void goToGeo(double latitude, double longitude);
|
||||
@@ -72,7 +73,9 @@ public:
|
||||
void resetKeyBindings();
|
||||
|
||||
void addKeyframe(const datamessagestructures::CameraKeyframe &kf);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& keyframes() const;
|
||||
|
||||
void bindKeyLocal(
|
||||
Key key,
|
||||
@@ -96,6 +99,8 @@ public:
|
||||
// Accessors
|
||||
ghoul::Dictionary getCameraStateDictionary();
|
||||
SceneGraphNode* const focusNode() const;
|
||||
glm::dvec3 focusNodeToCameraVector() const;
|
||||
glm::quat focusNodeToCameraRotation() const;
|
||||
Camera* const camera() const;
|
||||
const InputState& inputState() const;
|
||||
|
||||
|
||||
@@ -82,9 +82,12 @@ namespace interaction {
|
||||
|
||||
// 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;
|
||||
@@ -119,6 +122,7 @@ public:
|
||||
// Accessors
|
||||
SceneGraphNode* focusNode();
|
||||
Interpolator<double>& rotateToFocusNodeInterpolator();
|
||||
virtual bool followingNodeRotation() const = 0;
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime) = 0;
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime) = 0;
|
||||
@@ -195,6 +199,7 @@ public:
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
|
||||
private:
|
||||
std::vector<datamessagestructures::CameraKeyframe> _keyframes;
|
||||
@@ -245,6 +250,7 @@ public:
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
|
||||
protected:
|
||||
//void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
@@ -260,6 +266,7 @@ public:
|
||||
virtual void setFocusNode(SceneGraphNode* focusNode);
|
||||
//virtual void update(Camera& camera, const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
void goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv,
|
||||
bool resetCameraDirection);
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
void addToCommand(std::string c);
|
||||
|
||||
properties::BoolProperty _isVisible;
|
||||
bool _remoteScripting;
|
||||
properties::BoolProperty _remoteScripting;
|
||||
|
||||
size_t _inputPosition;
|
||||
std::vector<std::string> _commandsHistory;
|
||||
|
||||
@@ -51,16 +51,28 @@ struct CameraKeyframe {
|
||||
|
||||
glm::dvec3 _position;
|
||||
glm::dquat _rotation;
|
||||
bool _followNodeRotation;
|
||||
std::string _focusNode;
|
||||
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
//add position
|
||||
// Add position
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_position), reinterpret_cast<char*>(&_position) + sizeof(_position));
|
||||
|
||||
//add orientation
|
||||
// Add orientation
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_rotation), reinterpret_cast<char*>(&_rotation) + sizeof(_rotation));
|
||||
|
||||
//add timestamp
|
||||
|
||||
// Follow focus node rotation?
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_followNodeRotation), reinterpret_cast<char*>(&_followNodeRotation) + sizeof(_followNodeRotation));
|
||||
|
||||
int nodeNameLength = _focusNode.size();
|
||||
|
||||
// Add focus node
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&nodeNameLength), reinterpret_cast<char*>(&nodeNameLength) + sizeof(nodeNameLength));
|
||||
buffer.insert(buffer.end(), _focusNode.data(), _focusNode.data() + nodeNameLength);
|
||||
|
||||
// Add timestamp
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
|
||||
};
|
||||
|
||||
@@ -68,17 +80,31 @@ struct CameraKeyframe {
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
//position
|
||||
// Position
|
||||
size = sizeof(_position);
|
||||
memcpy(&_position, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//orientation
|
||||
|
||||
// Orientation
|
||||
size = sizeof(_rotation);
|
||||
memcpy(&_rotation, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Follow focus node rotation?
|
||||
size = sizeof(_followNodeRotation);
|
||||
memcpy(&_followNodeRotation, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Focus node
|
||||
int nodeNameLength;
|
||||
size = sizeof(int);
|
||||
memcpy(&nodeNameLength, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
size = nodeNameLength;
|
||||
_focusNode = std::string(buffer.data() + offset, buffer.data() + offset + size);
|
||||
offset += size;
|
||||
|
||||
//timestamp
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
};
|
||||
@@ -97,19 +123,19 @@ struct TimeKeyframe {
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
//add current time
|
||||
// Add current time
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_time), reinterpret_cast<char*>(&_time) + sizeof(_time));
|
||||
|
||||
//add delta time
|
||||
// Add delta time
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_dt), reinterpret_cast<char*>(&_dt) + sizeof(_dt));
|
||||
|
||||
//add wether time is paused or not
|
||||
// Add whether time is paused or not
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_paused), reinterpret_cast<char*>(&_paused) + sizeof(_paused));
|
||||
|
||||
//add wether a time jump is necessary (recompute paths etc)
|
||||
// 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
|
||||
// Add timestamp
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
|
||||
};
|
||||
|
||||
@@ -117,27 +143,27 @@ struct TimeKeyframe {
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
//current time
|
||||
// Current time
|
||||
size = sizeof(_time);
|
||||
memcpy(&_time, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//delta time
|
||||
// Delta time
|
||||
size = sizeof(_dt);
|
||||
memcpy(&_dt, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//is time paused?
|
||||
// Is time paused?
|
||||
size = sizeof(_paused);
|
||||
memcpy(&_paused, buffer.data() + offset, size);
|
||||
offset += sizeof(_paused);
|
||||
|
||||
//is a time jump required?
|
||||
// Is a time jump required?
|
||||
size = sizeof(_requiresTimeJump);
|
||||
memcpy(&_requiresTimeJump, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// timestamp
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
//openspace includes
|
||||
#include <openspace/network/messagestructures.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/numericalproperty.h>
|
||||
|
||||
//glm includes
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
@@ -57,7 +60,7 @@ struct addrinfo;
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ParallelConnection {
|
||||
class ParallelConnection : public properties::PropertyOwner {
|
||||
public:
|
||||
enum class Status : uint32_t {
|
||||
Disconnected = 0,
|
||||
@@ -99,17 +102,21 @@ class ParallelConnection {
|
||||
ParallelConnection();
|
||||
~ParallelConnection();
|
||||
void clientConnect();
|
||||
void setPort(const std::string &port);
|
||||
void setAddress(const std::string &address);
|
||||
void setName(const std::string& name);
|
||||
void setPort(std::string port);
|
||||
void setAddress(std::string address);
|
||||
void setName(std::string name);
|
||||
bool isHost();
|
||||
const std::string& hostName();
|
||||
void requestHostship(const std::string &password);
|
||||
void requestHostship();
|
||||
void resignHostship();
|
||||
void setPassword(const std::string &password);
|
||||
void setPassword(std::string password);
|
||||
void setHostPassword(std::string hostPassword);
|
||||
void signalDisconnect();
|
||||
void preSynchronization();
|
||||
void sendScript(const std::string& script);
|
||||
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
|
||||
@@ -145,7 +152,6 @@ private:
|
||||
void connectionStatusMessageReceived(const std::vector<char>& messageContent);
|
||||
void nConnectionsMessageReceived(const std::vector<char>& messageContent);
|
||||
|
||||
void broadcast();
|
||||
void sendCameraKeyframe();
|
||||
void sendTimeKeyframe();
|
||||
|
||||
@@ -158,10 +164,18 @@ private:
|
||||
|
||||
double calculateBufferedKeyframeTime(double originalTime);
|
||||
|
||||
uint32_t _passCode;
|
||||
std::string _port;
|
||||
std::string _address;
|
||||
std::string _name;
|
||||
properties::StringProperty _password;
|
||||
properties::StringProperty _hostPassword;
|
||||
properties::StringProperty _port;
|
||||
properties::StringProperty _address;
|
||||
properties::StringProperty _name;
|
||||
properties::FloatProperty _bufferTime;
|
||||
properties::FloatProperty _timeKeyframeInterval;
|
||||
properties::FloatProperty _cameraKeyframeInterval;
|
||||
properties::FloatProperty _timeTolerance;
|
||||
|
||||
double _lastTimeKeyframeTimestamp;
|
||||
double _lastCameraKeyframeTimestamp;
|
||||
|
||||
_SOCKET _clientSocket;
|
||||
|
||||
@@ -191,7 +205,6 @@ private:
|
||||
double _initialTimeDiff;
|
||||
|
||||
std::unique_ptr<std::thread> _connectionThread;
|
||||
std::unique_ptr<std::thread> _broadcastThread;
|
||||
std::unique_ptr<std::thread> _sendThread;
|
||||
std::unique_ptr<std::thread> _listenThread;
|
||||
std::unique_ptr<std::thread> _handlerThread;
|
||||
|
||||
@@ -99,6 +99,8 @@ public:
|
||||
|
||||
glm::dvec3 worldPosition() const;
|
||||
const glm::dmat3& worldRotationMatrix() const;
|
||||
glm::dmat4 modelTransform() const;
|
||||
glm::dmat4 inverseModelTransform() const;
|
||||
double worldScale() const;
|
||||
|
||||
SceneGraphNode* parent() const;
|
||||
@@ -147,6 +149,9 @@ private:
|
||||
glm::dvec3 _worldPositionCached;
|
||||
glm::dmat3 _worldRotationCached;
|
||||
double _worldScaleCached;
|
||||
|
||||
glm::dmat4 _modelTransformCached;
|
||||
glm::dmat4 _inverseModelTransformCached;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef __OPENSPACE_CORE___TIMEMANAGER___H__
|
||||
#define __OPENSPACE_CORE___TIMEMANAGER___H__
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
|
||||
@@ -35,7 +36,9 @@ public:
|
||||
void preSynchronization(double dt);
|
||||
void addKeyframe(const datamessagestructures::TimeKeyframe& kf);
|
||||
void removeKeyframesBefore(double timestamp);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& keyframes() const;
|
||||
private:
|
||||
void consumeKeyframes(double dt);
|
||||
std::deque<datamessagestructures::TimeKeyframe> _keyframes;
|
||||
|
||||
@@ -30,6 +30,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guihelpcomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiorigincomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiperformancecomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiparallelcomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guipropertycomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guitimecomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiiswacomponent.h
|
||||
@@ -44,6 +45,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guihelpcomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiorigincomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiperformancecomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiparallelcomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guipropertycomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guitimecomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiiswacomponent.cpp
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <modules/onscreengui/include/guiorigincomponent.h>
|
||||
#include <modules/onscreengui/include/guitimecomponent.h>
|
||||
#include <modules/onscreengui/include/guiiswacomponent.h>
|
||||
#include <modules/onscreengui/include/guiparallelcomponent.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/properties/property.h>
|
||||
|
||||
@@ -72,6 +73,7 @@ public:
|
||||
GuiPropertyComponent _virtualProperty;
|
||||
GuiTimeComponent _time;
|
||||
GuiIswaComponent _iswa;
|
||||
GuiParallelComponent _parallel;
|
||||
|
||||
private:
|
||||
void renderAndUpdatePropertyVisibility();
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
#define __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
|
||||
#include <modules/onscreengui/include/guicomponent.h>
|
||||
#include <modules/onscreengui/include/guipropertycomponent.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
namespace gui {
|
||||
|
||||
class GuiParallelComponent : public GuiPropertyComponent {
|
||||
public:
|
||||
GuiParallelComponent();
|
||||
void render() override;
|
||||
private:
|
||||
void renderDisconnected();
|
||||
void renderClientWithHost();
|
||||
void renderClientWithoutHost();
|
||||
void renderClientCommon();
|
||||
void renderHost();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <openspace/engine/virtualpropertymanager.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
@@ -59,7 +60,8 @@ OnScreenGUIModule::OnScreenGUIModule()
|
||||
&(OsEng.windowWrapper()),
|
||||
&(OsEng.settingsEngine()),
|
||||
&(OsEng.interactionHandler()),
|
||||
&(OsEng.renderEngine())
|
||||
&(OsEng.renderEngine()),
|
||||
&(OsEng.parallelConnection())
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -322,6 +322,7 @@ void GUI::initialize() {
|
||||
_virtualProperty.initialize();
|
||||
_performance.initialize();
|
||||
_help.initialize();
|
||||
_parallel.initialize();
|
||||
_iswa.initialize();
|
||||
}
|
||||
|
||||
@@ -329,6 +330,7 @@ void GUI::deinitialize() {
|
||||
ImGui::Shutdown();
|
||||
|
||||
_iswa.deinitialize();
|
||||
_parallel.deinitialize();
|
||||
_help.deinitialize();
|
||||
_performance.deinitialize();
|
||||
_globalProperty.deinitialize();
|
||||
@@ -408,6 +410,7 @@ void GUI::initializeGL() {
|
||||
_globalProperty.initializeGL();
|
||||
_performance.initializeGL();
|
||||
_help.initializeGL();
|
||||
_parallel.initializeGL();
|
||||
_iswa.initializeGL();
|
||||
}
|
||||
|
||||
@@ -426,6 +429,7 @@ void GUI::deinitializeGL() {
|
||||
}
|
||||
|
||||
_iswa.deinitializeGL();
|
||||
_parallel.deinitializeGL();
|
||||
_help.deinitializeGL();
|
||||
_performance.deinitializeGL();
|
||||
_globalProperty.deinitializeGL();
|
||||
@@ -471,14 +475,15 @@ void GUI::endFrame() {
|
||||
if (_screenSpaceProperty.isEnabled()) {
|
||||
_screenSpaceProperty.render();
|
||||
}
|
||||
|
||||
if (_virtualProperty.isEnabled()) {
|
||||
_virtualProperty.render();
|
||||
}
|
||||
|
||||
if (_help.isEnabled()) {
|
||||
_help.render();
|
||||
}
|
||||
if (_parallel.isEnabled()) {
|
||||
_parallel.render();
|
||||
}
|
||||
if (_iswa.isEnabled()) {
|
||||
_iswa.render();
|
||||
}
|
||||
@@ -570,6 +575,10 @@ void GUI::render() {
|
||||
ImGui::Checkbox("Global Properties", &globalProperty);
|
||||
_globalProperty.setEnabled(globalProperty);
|
||||
|
||||
bool parallel = _parallel.isEnabled();
|
||||
ImGui::Checkbox("Parallel Connection", ¶llel);
|
||||
_parallel.setEnabled(parallel);
|
||||
|
||||
bool virtualProperty = _virtualProperty.isEnabled();
|
||||
ImGui::Checkbox("Virtual Properties", &virtualProperty);
|
||||
_virtualProperty.setEnabled(virtualProperty);
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/onscreengui/include/guiparallelcomponent.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "GuiParallelComponent";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
namespace gui {
|
||||
|
||||
GuiParallelComponent::GuiParallelComponent()
|
||||
: GuiPropertyComponent("GuiParallelComponent")
|
||||
{
|
||||
setVisibility(properties::Property::Visibility::All);
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderDisconnected() {
|
||||
ImGui::Text("Not connected");
|
||||
|
||||
const bool connect = ImGui::Button("Connect");
|
||||
|
||||
if (connect) {
|
||||
OsEng.parallelConnection().clientConnect();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientWithHost() {
|
||||
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
std::string connectionInfo = "Session hosted by \"" + parallel.hostName() + "\"\n";
|
||||
size_t nConnections = parallel.nConnections();
|
||||
size_t nClients = nConnections - 1;
|
||||
|
||||
if (nClients > 2) {
|
||||
std::string c = std::to_string(nClients - 1);
|
||||
connectionInfo += "You and " + c + " more clients are connected";
|
||||
}
|
||||
else if (nClients == 2) {
|
||||
std::string c = std::to_string(nClients - 1);
|
||||
connectionInfo += "You and " + c + " more client are connected";
|
||||
}
|
||||
else if (nClients == 1) {
|
||||
connectionInfo += "You are the only client";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
renderClientCommon();
|
||||
|
||||
const std::deque<datamessagestructures::TimeKeyframe> timeKeyframes = OsEng.timeManager().keyframes();
|
||||
const std::vector<datamessagestructures::CameraKeyframe> cameraKeyframes = OsEng.interactionHandler().keyframes();
|
||||
|
||||
std::string timeKeyframeInfo = "TimeKeyframes : " + std::to_string(timeKeyframes.size());
|
||||
std::string cameraKeyframeInfo = "CameraKeyframes : " + std::to_string(cameraKeyframes.size());
|
||||
std::string latencyStandardDeviation = "Latency standard deviation: " + std::to_string(parallel.latencyStandardDeviation()) + " s";
|
||||
|
||||
const bool resetTimeOffset = ImGui::Button("Reset time offset");
|
||||
|
||||
if (resetTimeOffset) {
|
||||
parallel.resetTimeOffset();
|
||||
}
|
||||
|
||||
ImGui::Text(timeKeyframeInfo.c_str());
|
||||
ImGui::Text(cameraKeyframeInfo.c_str());
|
||||
ImGui::Text(latencyStandardDeviation.c_str());
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientWithoutHost() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
std::string connectionInfo = "Connected to parallel session with no host\n";
|
||||
size_t nConnections = parallel.nConnections();
|
||||
|
||||
if (nConnections > 2) {
|
||||
std::string c = std::to_string(nConnections - 1);
|
||||
connectionInfo += "You and " + c + " more users are connected";
|
||||
}
|
||||
else if (nConnections == 2) {
|
||||
std::string c = std::to_string(nConnections - 1);
|
||||
connectionInfo += "You and " + c + " more users are connected";
|
||||
}
|
||||
else if (nConnections == 1) {
|
||||
connectionInfo += "You are the only one here";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
|
||||
renderClientCommon();
|
||||
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientCommon() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
bool requestHostship = ImGui::Button("Request hostship");
|
||||
const bool disconnect = ImGui::Button("Disconnect");
|
||||
|
||||
if (requestHostship) {
|
||||
parallel.requestHostship();
|
||||
}
|
||||
|
||||
if (disconnect) {
|
||||
parallel.signalDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderHost() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
size_t nConnections = parallel.nConnections();
|
||||
|
||||
std::string connectionInfo = "";
|
||||
size_t nClients = nConnections - 1;
|
||||
if (nClients == 1) {
|
||||
connectionInfo = "Hosting session with 1 client";
|
||||
} else {
|
||||
connectionInfo =
|
||||
"Hosting session with " + std::to_string(nClients) + " clients";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
|
||||
const bool resignHostship = ImGui::Button("Resign hostship");
|
||||
if (resignHostship) {
|
||||
parallel.resignHostship();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiParallelComponent::render() {
|
||||
bool v = _isEnabled;
|
||||
ImGui::Begin("Parallel Connection", &v);
|
||||
_isEnabled = v;
|
||||
|
||||
ParallelConnection::Status status = OsEng.parallelConnection().status();
|
||||
|
||||
switch (status) {
|
||||
case ParallelConnection::Status::Disconnected:
|
||||
renderDisconnected();
|
||||
break;
|
||||
case ParallelConnection::Status::ClientWithHost:
|
||||
renderClientWithHost();
|
||||
break;
|
||||
case ParallelConnection::Status::ClientWithoutHost:
|
||||
renderClientWithoutHost();
|
||||
break;
|
||||
case ParallelConnection::Status::Host:
|
||||
renderHost();
|
||||
break;
|
||||
}
|
||||
|
||||
GuiPropertyComponent::renderPropertyOwner(&OsEng.parallelConnection());
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace openspace
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/interaction/luaconsole.h>
|
||||
#include <openspace/network/networkengine.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scripting/scriptscheduler.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
@@ -133,7 +134,7 @@ OpenSpaceEngine::OpenSpaceEngine(
|
||||
, _settingsEngine(new SettingsEngine)
|
||||
, _timeManager(new TimeManager)
|
||||
, _downloadManager(nullptr)
|
||||
, _parallelConnection(new ParallelConnection)
|
||||
, _parallelConnection(std::make_unique<ParallelConnection>())
|
||||
, _windowWrapper(std::move(windowWrapper))
|
||||
, _globalPropertyNamespace(new properties::PropertyOwner(""))
|
||||
, _virtualPropertyManager(new VirtualPropertyManager)
|
||||
@@ -150,7 +151,8 @@ OpenSpaceEngine::OpenSpaceEngine(
|
||||
_globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_renderEngine.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_windowWrapper.get());
|
||||
|
||||
_globalPropertyNamespace->addPropertySubOwner(_parallelConnection.get());
|
||||
|
||||
FactoryManager::initialize();
|
||||
FactoryManager::ref().addFactory(
|
||||
std::make_unique<ghoul::TemplateFactory<Renderable>>(),
|
||||
@@ -369,6 +371,10 @@ void OpenSpaceEngine::create(int argc, char** argv,
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::destroy() {
|
||||
if (_engine->parallelConnection().status() != ParallelConnection::Status::Disconnected) {
|
||||
_engine->parallelConnection().signalDisconnect();
|
||||
}
|
||||
|
||||
LTRACE("OpenSpaceEngine::destroy(begin)");
|
||||
for (const auto& func : _engine->_moduleCallbacks.deinitializeGL) {
|
||||
func();
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/interpolator.h>
|
||||
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
@@ -188,6 +188,10 @@ void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> int
|
||||
_currentInteractionMode->setFocusNode(focusNode);
|
||||
}
|
||||
|
||||
InteractionMode * InteractionHandler::interactionMode() {
|
||||
return _currentInteractionMode.get();
|
||||
}
|
||||
|
||||
void InteractionHandler::setInteractionMode(const std::string& interactionModeKey) {
|
||||
if (_interactionModes.find(interactionModeKey) != _interactionModes.end()) {
|
||||
setInteractionMode(_interactionModes[interactionModeKey]);
|
||||
@@ -265,6 +269,15 @@ SceneGraphNode* const InteractionHandler::focusNode() const {
|
||||
return _currentInteractionMode->focusNode();
|
||||
}
|
||||
|
||||
glm::dvec3 InteractionHandler::focusNodeToCameraVector() const {
|
||||
return _camera->positionVec3() - focusNode()->worldPosition();
|
||||
}
|
||||
|
||||
glm::quat InteractionHandler::focusNodeToCameraRotation() const {
|
||||
glm::dmat4 invWorldRotation = glm::inverse(focusNode()->worldRotationMatrix());
|
||||
return glm::quat(invWorldRotation) * glm::quat(_camera->rotationQuaternion());
|
||||
}
|
||||
|
||||
Camera* const InteractionHandler::camera() const {
|
||||
return _camera;
|
||||
}
|
||||
@@ -621,9 +634,17 @@ void InteractionHandler::addKeyframe(const datamessagestructures::CameraKeyframe
|
||||
_inputState->addKeyframe(kf);
|
||||
}
|
||||
|
||||
void InteractionHandler::removeKeyframesAfter(double timestamp) {
|
||||
_inputState->removeKeyframesAfter(timestamp);
|
||||
}
|
||||
|
||||
void InteractionHandler::clearKeyframes() {
|
||||
_inputState->clearKeyframes();
|
||||
}
|
||||
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& InteractionHandler::keyframes() const {
|
||||
return _inputState->keyframes();
|
||||
}
|
||||
|
||||
} // namespace interaction
|
||||
} // namespace openspace
|
||||
|
||||
@@ -65,16 +65,21 @@ namespace interaction {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
auto compareTimestamps = [](const datamessagestructures::CameraKeyframe a,
|
||||
datamessagestructures::CameraKeyframe b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
};
|
||||
|
||||
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, compareTimestamps), _keyframes.end());
|
||||
_keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), _keyframes.end());
|
||||
}
|
||||
|
||||
_keyframes.push_back(kf);
|
||||
bool InputState::compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
}
|
||||
|
||||
void InputState::clearOldKeyframes() {
|
||||
@@ -169,9 +174,6 @@ namespace interaction {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
InteractionMode::InteractionMode()
|
||||
: _rotateToFocusNodeInterpolator(Interpolator<double>([](double t){
|
||||
return pow(t, 2);
|
||||
@@ -241,8 +243,40 @@ void KeyframeInteractionMode::updateCameraStateFromMouseStates(Camera& camera, d
|
||||
|
||||
double t = (now - prevTime) / (nextTime - prevTime);
|
||||
|
||||
camera.setPositionVec3(prevKeyframe->_position * (1 - t) + nextKeyframe->_position * t);
|
||||
camera.setRotation(glm::slerp(prevKeyframe->_rotation, nextKeyframe->_rotation, t));
|
||||
Scene* scene = camera.parent()->scene();
|
||||
SceneGraphNode* prevFocusNode = scene->sceneGraphNode(prevKeyframe->_focusNode);
|
||||
SceneGraphNode* nextFocusNode = scene->sceneGraphNode(nextKeyframe->_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;
|
||||
|
||||
// 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 (nextKeyframe->_followNodeRotation) {
|
||||
nextKeyframeCameraRotation = nextFocusNode->worldRotationMatrix() * glm::dmat3(nextKeyframe->_rotation);
|
||||
nextKeyframeCameraPosition = nextFocusNode->worldRotationMatrix() * nextKeyframeCameraPosition;
|
||||
}
|
||||
|
||||
// Transform position based on focus node position
|
||||
prevKeyframeCameraPosition += prevFocusNode->worldPosition();
|
||||
nextKeyframeCameraPosition += nextFocusNode->worldPosition();
|
||||
|
||||
// Linear interpolation
|
||||
camera.setPositionVec3(prevKeyframeCameraPosition * (1 - t) + nextKeyframeCameraPosition * t);
|
||||
camera.setRotation(glm::slerp(prevKeyframeCameraRotation, nextKeyframeCameraRotation, t));
|
||||
}
|
||||
|
||||
bool KeyframeInteractionMode::followingNodeRotation() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// OrbitalInteractionMode
|
||||
@@ -486,6 +520,10 @@ void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera, do
|
||||
}
|
||||
}
|
||||
|
||||
bool OrbitalInteractionMode::followingNodeRotation() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double deltaTime) {
|
||||
_mouseStates->updateMouseStatesFromInput(inputState, deltaTime);
|
||||
}
|
||||
@@ -687,6 +725,10 @@ void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& came
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
}
|
||||
|
||||
bool GlobeBrowsingInteractionMode::followingNodeRotation() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
void GlobeBrowsingInteractionMode::goToChunk(Camera& camera,
|
||||
globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <openspace/interaction/luaconsole.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
@@ -57,19 +58,13 @@ namespace openspace {
|
||||
LuaConsole::LuaConsole()
|
||||
: properties::PropertyOwner("LuaConsole")
|
||||
, _isVisible("isVisible", "Is Visible", false)
|
||||
, _remoteScripting(true)
|
||||
, _remoteScripting("remoteScripting", "Remote scripting", false)
|
||||
, _inputPosition(0)
|
||||
, _activeCommand(0)
|
||||
, _autoCompleteInfo({NoAutoComplete, false, ""})
|
||||
{
|
||||
_isVisible.onChange([this](){
|
||||
if (_isVisible) {
|
||||
_remoteScripting = false;
|
||||
} else {
|
||||
_remoteScripting = OsEng.parallelConnection().isHost();
|
||||
}
|
||||
});
|
||||
addProperty(_isVisible);
|
||||
addProperty(_remoteScripting);
|
||||
}
|
||||
|
||||
void LuaConsole::initialize() {
|
||||
@@ -164,7 +159,19 @@ bool LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio
|
||||
if (key == CommandInputButton) {
|
||||
// Button left of 1 and above TAB
|
||||
// How to deal with different keyboard languages? ---abock
|
||||
_isVisible = !_isVisible;
|
||||
if (_isVisible) {
|
||||
if (_remoteScripting) {
|
||||
_remoteScripting = false;
|
||||
} else {
|
||||
_isVisible = false;
|
||||
}
|
||||
} else {
|
||||
_isVisible = true;
|
||||
if (OsEng.parallelConnection().status() == ParallelConnection::Status::Host) {
|
||||
_remoteScripting = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+138
-149
@@ -61,14 +61,17 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
//openspace includes
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/interaction/interactionmode.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/openspace.h>
|
||||
#include <openspace/scripting/script_helper.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
//lua functions
|
||||
@@ -77,22 +80,26 @@
|
||||
namespace {
|
||||
const uint32_t ProtocolVersion = 2;
|
||||
const size_t MaxLatencyDiffs = 64;
|
||||
const double BroadcastIntervalMilliseconds = 100;
|
||||
const std::string _loggerCat = "ParallelConnection";
|
||||
const int nFrametimesBuffer = 4;
|
||||
const int nBroadcastIntervalsBuffer = 2;
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ParallelConnection::ParallelConnection()
|
||||
: _passCode(0)
|
||||
, _port("20501")
|
||||
, _address("127.0.0.1")
|
||||
, _name("Local Connection")
|
||||
: properties::PropertyOwner("ParallelConnection")
|
||||
, _password("password", "Password")
|
||||
, _hostPassword("hostPassword", "Host Password")
|
||||
, _port("port", "Port", "20501")
|
||||
, _address("address", "Address", "localhost")
|
||||
, _name("name", "Connection name", "Anonymous")
|
||||
, _bufferTime("bufferTime", "Buffer Time", 1, 0.5, 10)
|
||||
, _timeKeyframeInterval("timeKeyframeInterval", "Time keyframe interval", 0.1, 0, 1)
|
||||
, _cameraKeyframeInterval("cameraKeyframeInterval", "Camera Keyframe interval", 0.1, 0, 1)
|
||||
, _timeTolerance("timeTolerance", "Time tolerance", 1, 0.5, 5)
|
||||
, _lastTimeKeyframeTimestamp(0)
|
||||
, _lastCameraKeyframeTimestamp(0)
|
||||
, _clientSocket(INVALID_SOCKET)
|
||||
, _connectionThread(nullptr)
|
||||
, _broadcastThread(nullptr)
|
||||
, _sendThread(nullptr)
|
||||
, _listenThread(nullptr)
|
||||
, _handlerThread(nullptr)
|
||||
@@ -105,6 +112,19 @@ ParallelConnection::ParallelConnection()
|
||||
, _disconnect(false)
|
||||
, _initializationTimejumpRequired(false)
|
||||
{
|
||||
addProperty(_name);
|
||||
|
||||
addProperty(_port);
|
||||
addProperty(_address);
|
||||
addProperty(_bufferTime);
|
||||
|
||||
addProperty(_password);
|
||||
addProperty(_hostPassword);
|
||||
|
||||
addProperty(_timeKeyframeInterval);
|
||||
addProperty(_cameraKeyframeInterval);
|
||||
addProperty(_timeTolerance);
|
||||
|
||||
_connectionEvent = std::make_shared<ghoul::Event<>>();
|
||||
_handlerThread = std::make_unique<std::thread>(&ParallelConnection::threadManagement, this);
|
||||
}
|
||||
@@ -186,8 +206,7 @@ void ParallelConnection::disconnect(){
|
||||
|
||||
//tell send thread to stop sending and listen thread to stop listenin
|
||||
_isConnected.store(false);
|
||||
|
||||
//tell broadcast thread to stop broadcasting (we're no longer host)
|
||||
|
||||
setStatus(Status::Disconnected);
|
||||
|
||||
//join connection thread and delete it
|
||||
@@ -207,13 +226,7 @@ void ParallelConnection::disconnect(){
|
||||
_listenThread->join();
|
||||
_listenThread = nullptr;
|
||||
}
|
||||
|
||||
//join broadcast thread and delete it
|
||||
if(_broadcastThread != nullptr){
|
||||
_broadcastThread->join();
|
||||
_broadcastThread = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// disconnect and cleanup completed
|
||||
_disconnect = false;
|
||||
}
|
||||
@@ -241,7 +254,7 @@ void ParallelConnection::clientConnect(){
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
// Resolve the local address and port to be used by the server
|
||||
int result = getaddrinfo(_address.c_str(), _port.c_str(), &hints, &addresult);
|
||||
int result = getaddrinfo(_address.value().c_str(), _port.value().c_str(), &hints, &addresult);
|
||||
if (result != 0)
|
||||
{
|
||||
LERROR("Failed to parse hints for Parallel Connection");
|
||||
@@ -308,57 +321,39 @@ void ParallelConnection::establishConnection(addrinfo *info){
|
||||
LERROR("Failed to set socket option 'keep alive'. Error code: " << _ERRNO);
|
||||
|
||||
|
||||
//while the connection thread is still running
|
||||
while (_tryConnect.load()){
|
||||
|
||||
LINFO("Attempting to connect to server "<< _address << " on port " << _port);
|
||||
LINFO("Attempting to connect to server "<< _address << " on port " << _port);
|
||||
|
||||
//try to connect
|
||||
result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen);
|
||||
//try to connect
|
||||
result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen);
|
||||
|
||||
//if the connection was successfull
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
//if the connection was successfull
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
|
||||
LINFO("Connection established with server at ip: "<< _address);
|
||||
LINFO("Connection established with server at ip: "<< _address);
|
||||
|
||||
//we're connected
|
||||
_isConnected.store(true);
|
||||
//we're connected
|
||||
_isConnected.store(true);
|
||||
|
||||
//start sending messages
|
||||
_sendThread = std::make_unique<std::thread>(&ParallelConnection::sendFunc, this);
|
||||
//start sending messages
|
||||
_sendThread = std::make_unique<std::thread>(&ParallelConnection::sendFunc, this);
|
||||
|
||||
//start listening for communication
|
||||
_listenThread = std::make_unique<std::thread>(&ParallelConnection::listenCommunication, this);
|
||||
//start listening for communication
|
||||
_listenThread = std::make_unique<std::thread>(&ParallelConnection::listenCommunication, this);
|
||||
|
||||
//we no longer need to try to establish connection
|
||||
_tryConnect.store(false);
|
||||
//we no longer need to try to establish connection
|
||||
_tryConnect.store(false);
|
||||
|
||||
_sendBufferMutex.lock();
|
||||
_sendBuffer.clear();
|
||||
_sendBufferMutex.unlock();
|
||||
_sendBufferMutex.lock();
|
||||
_sendBuffer.clear();
|
||||
_sendBufferMutex.unlock();
|
||||
|
||||
//send authentication
|
||||
sendAuthentication();
|
||||
} else {
|
||||
LINFO("Connection attempt failed.");
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
//on windows: try to connect once per second
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
#else
|
||||
if(!_isConnected.load()){
|
||||
//on unix disconnect and display error message if we're not connected
|
||||
LERROR("Failed to establish a connection with server "<< _address << " on port " << _port<<", terminating connection.");
|
||||
|
||||
//signal disconnect
|
||||
signalDisconnect();
|
||||
|
||||
//stop loop
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
//send authentication
|
||||
sendAuthentication();
|
||||
} else {
|
||||
LINFO("Connection attempt failed.");
|
||||
signalDisconnect();
|
||||
}
|
||||
|
||||
//cleanup
|
||||
@@ -366,8 +361,10 @@ void ParallelConnection::establishConnection(addrinfo *info){
|
||||
}
|
||||
|
||||
void ParallelConnection::sendAuthentication() {
|
||||
|
||||
std::string name = _name.value();
|
||||
//length of this nodes name
|
||||
uint32_t nameLength = static_cast<uint32_t>(_name.length());
|
||||
uint32_t nameLength = static_cast<uint32_t>(name.length());
|
||||
|
||||
//total size of the buffer: (passcode + namelength + name)
|
||||
size_t size = 2 * sizeof(uint32_t) + nameLength;
|
||||
@@ -376,14 +373,16 @@ void ParallelConnection::sendAuthentication() {
|
||||
std::vector<char> buffer;
|
||||
buffer.reserve(size);
|
||||
|
||||
uint32_t passCode = hash(_password.value());
|
||||
|
||||
//write passcode to buffer
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_passCode), reinterpret_cast<char*>(&_passCode) + sizeof(uint32_t));
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&passCode), reinterpret_cast<char*>(&passCode) + sizeof(uint32_t));
|
||||
|
||||
//write the length of the nodes name to buffer
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&nameLength), reinterpret_cast<char*>(&nameLength) + sizeof(uint32_t));
|
||||
|
||||
//write this node's name to buffer
|
||||
buffer.insert(buffer.end(), _name.begin(), _name.end());
|
||||
buffer.insert(buffer.end(), name.begin(), name.end());
|
||||
|
||||
//send buffer
|
||||
queueOutMessage(Message(MessageType::Authentication, buffer));
|
||||
@@ -505,6 +504,10 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) {
|
||||
}
|
||||
_latencyDiffs.push_back(latencyDiff);
|
||||
|
||||
return originalTime + timeDiff + latencyDiff + _bufferTime;
|
||||
}
|
||||
|
||||
double ParallelConnection::latencyStandardDeviation() const {
|
||||
double accumulatedLatencyDiffSquared = 0;
|
||||
double accumulatedLatencyDiff = 0;
|
||||
for (double diff : _latencyDiffs) {
|
||||
@@ -516,16 +519,14 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) {
|
||||
|
||||
// V(X) = E(x^2) - E(x)^2
|
||||
double latencyVariance = expectedLatencyDiffSquared - expectedLatencyDiff*expectedLatencyDiff;
|
||||
double latencyStandardDeviation = std::sqrt(latencyVariance);
|
||||
|
||||
double frametime = OsEng.windowWrapper().averageDeltaTime();
|
||||
|
||||
double latencyCompensation = std::max(expectedLatencyDiff + 2 * latencyStandardDeviation, latencyDiff);
|
||||
|
||||
return originalTime + timeDiff + nBroadcastIntervalsBuffer * BroadcastIntervalMilliseconds / 1000 + latencyCompensation + nFrametimesBuffer * frametime;
|
||||
|
||||
return std::sqrt(latencyVariance);
|
||||
}
|
||||
|
||||
double ParallelConnection::timeTolerance() const {
|
||||
return _timeTolerance;
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::dataMessageReceived(const std::vector<char>& messageContent) {
|
||||
|
||||
//the type of data message received
|
||||
@@ -534,26 +535,26 @@ void ParallelConnection::dataMessageReceived(const std::vector<char>& messageCon
|
||||
|
||||
switch(static_cast<datamessagestructures::Type>(type)) {
|
||||
case datamessagestructures::Type::CameraData: {
|
||||
|
||||
datamessagestructures::CameraKeyframe kf(buffer);
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.interactionHandler().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.interactionHandler().addKeyframe(kf);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::TimeData: {
|
||||
|
||||
datamessagestructures::TimeKeyframe kf(buffer);
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.timeManager().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.timeManager().addKeyframe(kf);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::ScriptData: {
|
||||
datamessagestructures::ScriptMessage sm;
|
||||
sm.deserialize(buffer);
|
||||
OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No);
|
||||
|
||||
|
||||
OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No);
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
@@ -691,17 +692,6 @@ void ParallelConnection::connectionStatusMessageReceived(const std::vector<char>
|
||||
|
||||
setStatus(status);
|
||||
|
||||
if (status == Status::Host) { // assigned as host
|
||||
_broadcastThread = std::make_unique<std::thread>(&ParallelConnection::broadcast, this);
|
||||
} else { // assigned as client
|
||||
|
||||
// delete broadcasting thread
|
||||
// (the thread is allowed to terminate once the status is set to non-host.)
|
||||
if (_broadcastThread != nullptr) {
|
||||
_broadcastThread->join();
|
||||
_broadcastThread = nullptr;
|
||||
}
|
||||
}
|
||||
OsEng.interactionHandler().clearKeyframes();
|
||||
OsEng.timeManager().clearKeyframes();
|
||||
|
||||
@@ -879,22 +869,22 @@ int ParallelConnection::receiveData(_SOCKET & socket, std::vector<char> &buffer,
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParallelConnection::setPort(const std::string &port){
|
||||
_port = port;
|
||||
void ParallelConnection::setPort(std::string port){
|
||||
_port = std::move(port);
|
||||
}
|
||||
|
||||
void ParallelConnection::setAddress(const std::string &address){
|
||||
_address = address;
|
||||
void ParallelConnection::setAddress(std::string address){
|
||||
_address = std::move(address);
|
||||
}
|
||||
|
||||
void ParallelConnection::setName(const std::string& name){
|
||||
_name = name;
|
||||
void ParallelConnection::setName(std::string name){
|
||||
_name = std::move(name);
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::requestHostship(const std::string &password){
|
||||
void ParallelConnection::requestHostship(){
|
||||
std::vector<char> buffer;
|
||||
uint32_t passcode = hash(password);
|
||||
uint32_t passcode = hash(_hostPassword);
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&passcode), reinterpret_cast<char*>(&passcode) + sizeof(uint32_t));
|
||||
queueOutMessage(Message(MessageType::HostshipRequest, buffer));
|
||||
}
|
||||
@@ -904,8 +894,12 @@ void ParallelConnection::resignHostship() {
|
||||
queueOutMessage(Message(MessageType::HostshipResignation, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::setPassword(const std::string& pwd){
|
||||
_passCode = hash(pwd);
|
||||
void ParallelConnection::setPassword(std::string pwd){
|
||||
_password = std::move(pwd);
|
||||
}
|
||||
|
||||
void ParallelConnection::setHostPassword(std::string pwd) {
|
||||
_hostPassword = std::move(pwd);
|
||||
}
|
||||
|
||||
bool ParallelConnection::initNetworkAPI(){
|
||||
@@ -934,11 +928,11 @@ bool ParallelConnection::initNetworkAPI(){
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParallelConnection::sendScript(const std::string& script) {
|
||||
void ParallelConnection::sendScript(std::string script) {
|
||||
if (!isHost()) return;
|
||||
|
||||
datamessagestructures::ScriptMessage sm;
|
||||
sm._script = script;
|
||||
sm._script = std::move(script);
|
||||
|
||||
std::vector<char> buffer;
|
||||
sm.serialize(buffer);
|
||||
@@ -946,6 +940,13 @@ void ParallelConnection::sendScript(const std::string& script) {
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::ScriptData, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::resetTimeOffset() {
|
||||
OsEng.interactionHandler().clearKeyframes();
|
||||
OsEng.timeManager().clearKeyframes();
|
||||
std::lock_guard<std::mutex> latencyLock(_latencyMutex);
|
||||
_latencyDiffs.clear();
|
||||
}
|
||||
|
||||
void ParallelConnection::preSynchronization(){
|
||||
|
||||
std::unique_lock<std::mutex> unqlock(_receiveBufferMutex);
|
||||
@@ -959,12 +960,23 @@ void ParallelConnection::preSynchronization(){
|
||||
if (Time::ref().timeJumped()) {
|
||||
_timeJumped = true;
|
||||
}
|
||||
double now = OsEng.runTime();
|
||||
|
||||
if (_lastCameraKeyframeTimestamp + _cameraKeyframeInterval < now) {
|
||||
sendCameraKeyframe();
|
||||
_lastCameraKeyframeTimestamp = now;
|
||||
}
|
||||
if (_lastTimeKeyframeTimestamp + _timeKeyframeInterval < now) {
|
||||
sendTimeKeyframe();
|
||||
_lastTimeKeyframeTimestamp = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParallelConnection::setStatus(Status status) {
|
||||
if (_status != status) {
|
||||
_status = status;
|
||||
_timeJumped = true;
|
||||
_connectionEvent->publish("statusChanged");
|
||||
}
|
||||
}
|
||||
@@ -1000,26 +1012,40 @@ const std::string& ParallelConnection::hostName() {
|
||||
}
|
||||
|
||||
void ParallelConnection::sendCameraKeyframe() {
|
||||
//create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._position = OsEng.interactionHandler().camera()->positionVec3();
|
||||
kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion();
|
||||
SceneGraphNode* focusNode = OsEng.interactionHandler().focusNode();
|
||||
if (!focusNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
//timestamp as current runtime of OpenSpace instance
|
||||
// Create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._position = OsEng.interactionHandler().focusNodeToCameraVector();
|
||||
|
||||
kf._followNodeRotation = OsEng.interactionHandler().interactionMode()->followingNodeRotation();
|
||||
if (kf._followNodeRotation) {
|
||||
kf._position = glm::inverse(focusNode->worldRotationMatrix()) * kf._position;
|
||||
kf._rotation = OsEng.interactionHandler().focusNodeToCameraRotation();
|
||||
} else {
|
||||
kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion();
|
||||
}
|
||||
|
||||
kf._focusNode = focusNode->name();
|
||||
|
||||
// Timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
//create a buffer for the keyframe
|
||||
// Create a buffer for the keyframe
|
||||
std::vector<char> buffer;
|
||||
|
||||
//fill the keyframe buffer
|
||||
// Fill the keyframe buffer
|
||||
kf.serialize(buffer);
|
||||
|
||||
//send message
|
||||
// Send message
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::CameraData, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::sendTimeKeyframe() {
|
||||
//create a keyframe with current position and orientation of camera
|
||||
// Create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
|
||||
kf._dt = Time::ref().deltaTime();
|
||||
@@ -1027,33 +1053,20 @@ void ParallelConnection::sendTimeKeyframe() {
|
||||
kf._requiresTimeJump = _timeJumped;
|
||||
kf._time = Time::ref().j2000Seconds();
|
||||
|
||||
//timestamp as current runtime of OpenSpace instance
|
||||
// Timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
//create a buffer for the keyframe
|
||||
// Create a buffer for the keyframe
|
||||
std::vector<char> buffer;
|
||||
|
||||
//fill the keyframe buffer
|
||||
// Fill the keyframe buffer
|
||||
kf.serialize(buffer);
|
||||
|
||||
//send message
|
||||
// Send message
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::TimeData, buffer));
|
||||
_timeJumped = false;
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::broadcast(){
|
||||
_timeJumped = true;
|
||||
//while we're still connected and we're the host
|
||||
while (_isConnected && isHost()) {
|
||||
sendCameraKeyframe();
|
||||
sendTimeKeyframe();
|
||||
|
||||
//100 ms sleep - send keyframes 10 times per second
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(BroadcastIntervalMilliseconds)));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ParallelConnection::hash(const std::string &val) {
|
||||
uint32_t hashVal = 0, i;
|
||||
size_t len = val.length();
|
||||
@@ -1080,30 +1093,6 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() {
|
||||
return {
|
||||
"parallel",
|
||||
{
|
||||
{
|
||||
"setPort",
|
||||
&luascriptfunctions::setPort,
|
||||
"number",
|
||||
"Set the port for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setAddress",
|
||||
&luascriptfunctions::setAddress,
|
||||
"string",
|
||||
"Set the address for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setPassword",
|
||||
&luascriptfunctions::setPassword,
|
||||
"string",
|
||||
"Set the password for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setDisplayName",
|
||||
&luascriptfunctions::setDisplayName,
|
||||
"string",
|
||||
"Set your display name for the parallel connection"
|
||||
},
|
||||
{
|
||||
"connect",
|
||||
&luascriptfunctions::connect,
|
||||
@@ -1119,7 +1108,7 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() {
|
||||
{
|
||||
"requestHostship",
|
||||
&luascriptfunctions::requestHostship,
|
||||
"string",
|
||||
"",
|
||||
"Request to be the host for this session"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,109 +26,10 @@ namespace openspace {
|
||||
|
||||
namespace luascriptfunctions {
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPort():
|
||||
* Set the port for parallel connection
|
||||
*/
|
||||
int setPort(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
bool isNumber = (lua_isnumber(L, -1) != 0);
|
||||
if (isNumber) {
|
||||
int value = static_cast<int>(lua_tonumber(L, -1));
|
||||
std::string port = std::to_string(value);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setPort(port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setAddress(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string address = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setAddress(address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setPassword(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string pwd = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setPassword(pwd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setDisplayName(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string name = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setName(name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int connect(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("connect", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().clientConnect();
|
||||
}
|
||||
@@ -137,9 +38,8 @@ int connect(lua_State* L) {
|
||||
|
||||
int disconnect(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("disconnect", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().signalDisconnect();
|
||||
}
|
||||
@@ -147,33 +47,19 @@ int disconnect(lua_State* L) {
|
||||
}
|
||||
|
||||
int requestHostship(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string pwd = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().requestHostship(pwd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("requestHostship", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().requestHostship();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resignHostship(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("resignHostship", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().resignHostship();
|
||||
}
|
||||
|
||||
@@ -288,7 +288,17 @@ void SceneGraphNode::update(const UpdateData& data) {
|
||||
|
||||
newUpdateData.modelTransform.translation = worldPosition();
|
||||
newUpdateData.modelTransform.rotation = worldRotationMatrix();
|
||||
newUpdateData.modelTransform .scale = worldScale();
|
||||
newUpdateData.modelTransform.scale = worldScale();
|
||||
|
||||
glm::dmat4 translation =
|
||||
glm::translate(glm::dmat4(1.0), newUpdateData.modelTransform.translation);
|
||||
glm::dmat4 rotation = glm::dmat4(newUpdateData.modelTransform.rotation);
|
||||
glm::dmat4 scaling =
|
||||
glm::scale(glm::dmat4(1.0), glm::dvec3(newUpdateData.modelTransform.scale,
|
||||
newUpdateData.modelTransform.scale, newUpdateData.modelTransform.scale));
|
||||
|
||||
_modelTransformCached = translation * rotation * scaling;
|
||||
_inverseModelTransformCached = glm::inverse(_modelTransformCached);
|
||||
|
||||
if (_renderable && _renderable->isReady()) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
@@ -541,6 +551,14 @@ const glm::dmat3& SceneGraphNode::worldRotationMatrix() const
|
||||
return _worldRotationCached;
|
||||
}
|
||||
|
||||
glm::dmat4 SceneGraphNode::modelTransform() const {
|
||||
return _modelTransformCached;
|
||||
}
|
||||
|
||||
glm::dmat4 SceneGraphNode::inverseModelTransform() const {
|
||||
return _inverseModelTransformCached;
|
||||
}
|
||||
|
||||
double SceneGraphNode::worldScale() const
|
||||
{
|
||||
return _worldScaleCached;
|
||||
|
||||
@@ -25,10 +25,7 @@
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
namespace {
|
||||
double SecondsOffTolerance = 0.1;
|
||||
}
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -96,8 +93,10 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
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);
|
||||
bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * secondsOffTolerance);
|
||||
|
||||
if (next._dt == time.deltaTime() && withinTolerance) {
|
||||
Time::ref().advanceTime(dt);
|
||||
@@ -121,6 +120,7 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
|
||||
time.setDeltaTime(y1Prime);
|
||||
time.setTime(y1, false);
|
||||
// std::cout << "Correcting time to " << y1 << ", dt=" << y1Prime << "." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,13 @@ void TimeManager::addKeyframe(const TimeKeyframe& kf) {
|
||||
_keyframes.insert(iter, kf);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
void TimeManager::removeKeyframesBefore(double timestamp) {
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
@@ -145,8 +152,11 @@ void TimeManager::clearKeyframes() {
|
||||
_keyframes.clear();
|
||||
}
|
||||
|
||||
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b)
|
||||
{
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& TimeManager::keyframes() const {
|
||||
return _keyframes;
|
||||
}
|
||||
|
||||
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user