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:
Emil Axelsson
2017-04-13 23:16:00 +02:00
committed by GitHub
parent a2af627835
commit 5589de995b
21 changed files with 637 additions and 342 deletions
@@ -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);
+1 -1
View File
@@ -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;
+44 -18
View File
@@ -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;
+26 -13
View File
@@ -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;
+5
View File
@@ -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
+3
View File
@@ -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;
+2
View File
@@ -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
+2
View File
@@ -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__
+3 -1
View File
@@ -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;
}
+11 -2
View File
@@ -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", &parallel);
_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
+8 -2
View File
@@ -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();
+22 -1
View File
@@ -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
+54 -12
View File
@@ -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) {
+16 -9
View File
@@ -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
View File
@@ -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"
},
{
+12 -126
View File
@@ -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();
}
+19 -1
View File
@@ -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;
+17 -7
View File
@@ -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;
}