diff --git a/.gitmodules b/.gitmodules index 8d23c60cda..1c979bcb37 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,12 +7,16 @@ [submodule "ext/spice"] path = ext/spice url = https://github.com/OpenSpace/Spice.git -[submodule "ext/sgct"] - path = ext/sgct - url = https://github.com/opensgct/sgct.git [submodule "modules/touch/ext/libTUIO11"] path = modules/touch/ext/libTUIO11 url = https://github.com/mkalten/TUIO11_CPP [submodule "modules/sync/ext/libtorrent"] path = modules/sync/ext/libtorrent url = https://github.com/OpenSpace/libtorrent.git +[submodule "apps/OpenSpace-MinVR/ext/minvr"] + path = apps/OpenSpace-MinVR/ext/minvr + url = https://github.com/OpenSpace/minvr + branch = OpenSpace +[submodule "apps/OpenSpace/ext/sgct"] + path = apps/OpenSpace/ext/sgct + url = https://github.com/opensgct/sgct diff --git a/CMakeLists.txt b/CMakeLists.txt index 57e8fdae89..5ce6b3d634 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,47 +124,6 @@ set_folder_location(lz4 "External") set_folder_location(GhoulTest "Unit Tests") link_directories("${GHOUL_LIBRARY_DIRS}") -# SGCT -begin_dependency("SGCT") -set(SGCT_TEXT OFF CACHE BOOL "" FORCE) -set(SGCT_BUILD_CSHARP_PROJECTS OFF CACHE BOOL "" FORCE) -set(SGCT_LIGHT_ONLY ON CACHE BOOL "" FORCE) -set(SGCT_CUSTOMOUTPUTDIRS OFF CACHE BOOL "" FORCE) -set(JPEG_TURBO_WITH_SIMD OFF CACHE BOOL "" FORCE) - -add_subdirectory(${OPENSPACE_EXT_DIR}/sgct) -target_include_directories(openspace-core SYSTEM PUBLIC ${OPENSPACE_EXT_DIR}/sgct/include) -target_link_libraries(openspace-core - sgct_light glew glfw png16_static quat tinyxml2static turbojpeg-static vrpn - ${GLFW_LIBRARIES}) -if (UNIX AND (NOT APPLE)) - target_link_libraries(openspace-core Xcursor Xinerama X11) -endif () - -mark_as_advanced(EXECUTABLE_OUTPUT_PATH GLFW_BUILD_DOCS GLFW_BUILD_EXAMPLES - GLFW_BUILD_TESTS GLFW_INSTALL GLFW_USE_HYBRID_HPG GLFW_USE_OSMESA GLFW_VULKAN_STATIC - INSTALL_BIN_DIR INSTALL_INC_DIR INSTALL_LIB_DIR INSTALL_MAN_DIR INSTALL_PKGCONFIG_DIR - IOKIT_LIBRARY JPEG_TURBO_FORCE32bit JPEG_TURBO_WITH_12BIT JPEG_TURBO_WITH_ARITH_DEC - JPEG_TURBO_WITH_ARITH_ENC JPEG_TURBO_WITH_JPEG7 JPEG_TURBO_WITH_JPEG8 - JPEG_TURBO_WITH_MEM_SRCDST JPEG_TURBO_WITH_SIMD JPEG_TURBO_WITH_TURBOJPEG LIB_SUFFIX - LIBRARY_OUTPUT_PATH M_LIBRARY SGCT_BUILD_ALUT SGCT_BUILD_CSHARP_PROJECTS - SGCT_CUSTOMOUTPUTDIRS SGCT_DOXYGEN SGCT_DOXYGEN_QUIET SGCT_EXAMPLES SGCT_INSTALL - SGCT_LIGHT_ONLY SGCT_NO_EXTERNAL_LIBRARIES SGCT_SPOUT_SUPPORT SGCT_TEXT - SGCT_USE_MSVC_RUNTIMES USE_MSVC_RUNTIME_LIBRARY_DLL) - -set_folder_location(sgct_light "External") -set_folder_location(glew "External/SGCT") -set_folder_location(glfw "External/SGCT") -set_folder_location(png16_static "External/SGCT") -set_folder_location(quat "External/SGCT") -set_folder_location(simd "External/SGCT") -set_folder_location(tinyxml2static "External/SGCT") -set_folder_location(turbojpeg-static "External/SGCT") -set_folder_location(vrpn "External/SGCT") -set_folder_location(zlibstatic "External/SGCT") -end_dependency("SGCT") - - # Spice begin_dependency("Spice") add_subdirectory(${OPENSPACE_EXT_DIR}/spice) diff --git a/apps/OpenSpace-MinVR/CMakeLists.txt b/apps/OpenSpace-MinVR/CMakeLists.txt new file mode 100644 index 0000000000..f03a46e18f --- /dev/null +++ b/apps/OpenSpace-MinVR/CMakeLists.txt @@ -0,0 +1,89 @@ +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2018 # +# # +# 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(${GHOUL_BASE_DIR}/support/cmake/copy_shared_libraries.cmake) +include(${OPENSPACE_CMAKE_EXT_DIR}/application_definition.cmake) +include(${OPENSPACE_CMAKE_EXT_DIR}/global_variables.cmake) + +set(MACOSX_BUNDLE_ICON_FILE openspace.icns) + +set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT ON CACHE BOOL "" FORCE) +add_subdirectory(ext/minvr) + +create_new_application(OpenSpace-MinVR + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/openspace.rc + ${CMAKE_CURRENT_SOURCE_DIR}/openspace.icns +) + +set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/openspace.icns + PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" +) + +target_include_directories(OpenSpace-MinVR PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/minvr/src) + +# @FRAGILE: This will break if we ever compile MinVR without GLFW support. +# Maybe there is a better way to access glfwGetProcAddress, which is probably +# The only thing that we need from this include +target_include_directories(OpenSpace-MinVR PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/minvr/external/GLFW/src/include) + + +target_link_libraries(OpenSpace-MinVR libOpenSpace MinVR) + +# Web Browser and Web gui +# Why not put these in the module's path? Because they do not have access to the +# target as of July 2017, which is needed. +if (OPENSPACE_MODULE_WEBBROWSER AND CEF_ROOT) + # wanted by CEF + set(CMAKE_BUILD_TYPE Debug CACHE INTERNAL "CMAKE_BUILD_TYPE") + + if (WIN32) + set(RESOURCE_FILE ${OPENSPACE_APPS_DIR}/OpenSpace-MinVR/openspace.rc) + endif () + + # Add the CEF binary distribution's cmake/ directory to the module path and + # find CEF to initialize it properly. + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBBROWSER_MODULE_PATH}/cmake") + include(webbrowser_helpers) + + set_cef_targets("${CEF_ROOT}" OpenSpace-MinVR) + run_cef_platform_config("${CEF_ROOT}" "${CEF_TARGET}" "${WEBBROWSER_MODULE_PATH}") +elseif (OPENSPACE_MODULE_WEBBROWSER) + message(WARNING "Web configured to be included, but no CEF_ROOT was found, please try configuring CMake again.") +endif () + +if (OPENSPACE_MODULE_WEBGUI AND WEBGUI_MODULE_PATH) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBGUI_MODULE_PATH}/cmake") + include(webgui_helpers) + build_webgui_source(OpenSpace-MinVR) +elseif(OPENSPACE_MODULE_WEBGUI) + message(WARNING "WebGui is configured to be included, but the web source could not be found. Try configuring CMake again.") +endif() +# End Web Browser and Web gui + +if (MSVC) + # This library is used for being able to output the callstack if an exception escapes + target_link_libraries(OpenSpace-MinVR Dbghelp.lib) +endif() diff --git a/apps/OpenSpace-MinVR/ext/minvr b/apps/OpenSpace-MinVR/ext/minvr new file mode 160000 index 0000000000..c97f70f635 --- /dev/null +++ b/apps/OpenSpace-MinVR/ext/minvr @@ -0,0 +1 @@ +Subproject commit c97f70f63578a3d87582f165b789ce96d37c0b17 diff --git a/apps/OpenSpace-MinVR/ext/readme.md b/apps/OpenSpace-MinVR/ext/readme.md new file mode 100644 index 0000000000..2b6c321821 --- /dev/null +++ b/apps/OpenSpace-MinVR/ext/readme.md @@ -0,0 +1,8 @@ +The spout folder is a copy of the folder: +SpoutSDK/Source in the repository: +https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Binaries +and +https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Include + +Last update: +https://github.com/leadedge/Spout2/commit/28dbea6059cd7968c4d2b296d6739a5fdebe9104 diff --git a/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.dll b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.dll new file mode 100644 index 0000000000..36aca87f87 Binary files /dev/null and b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.dll differ diff --git a/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.h b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.h new file mode 100644 index 0000000000..d50c0a1106 --- /dev/null +++ b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.h @@ -0,0 +1,90 @@ +// +// SpoutLibrary.dll +// +// Spout SDK dll compatible with any C++ compiler +// + +#include +#include + +#define SPOUTLIBRARY_EXPORTS // defined for this DLL. The application imports rather than exports + +#ifdef SPOUTLIBRARY_EXPORTS +#define SPOUTAPI __declspec(dllexport) +#else +#define SPOUTAPI __declspec(dllimport) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// COM-Like abstract interface. +// This interface doesn't require __declspec(dllexport/dllimport) specifier. +// Method calls are dispatched via virtual table. +// Any C++ compiler can use it. +// Instances are obtained via factory function. +// +struct SPOUTLIBRARY +{ + // Sender + virtual bool CreateSender(const char *Sendername, unsigned int width, unsigned int height, DWORD dwFormat = 0) = 0; + virtual void ReleaseSender(DWORD dwMsec = 0) = 0; + virtual bool UpdateSender(const char* Sendername, unsigned int width, unsigned int height) = 0; + virtual bool SendTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, bool bInvert = true, GLuint HostFBO = 0) = 0; + virtual bool SendImage(const unsigned char* pixels, unsigned int width, unsigned int height, GLenum glFormat = GL_RGBA, bool bInvert=false) = 0; + + // Receiver + virtual bool CreateReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool bUseActive = false) = 0; + virtual void ReleaseReceiver() = 0; + virtual bool ReceiveTexture(char* Sendername, unsigned int &width, unsigned int &height, GLuint TextureID = 0, GLuint TextureTarget = 0, bool bInvert = false, GLuint HostFBO = 0) = 0; + virtual bool ReceiveImage(char* Sendername, unsigned int &width, unsigned int &height, unsigned char* pixels, GLenum glFormat = GL_RGBA, bool bInvert = false, GLuint HostFBO=0) = 0; + virtual bool CheckReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool &bConnected) = 0; + virtual bool GetImageSize(char* sendername, unsigned int &width, unsigned int &height, bool &bMemoryMode) = 0; + + virtual bool BindSharedTexture() = 0; + virtual bool UnBindSharedTexture() = 0; + + virtual bool DrawSharedTexture(float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = true) = 0; + virtual bool DrawToSharedTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = false, GLuint HostFBO = 0) = 0; + + virtual int GetSenderCount() = 0; + virtual bool GetSenderName(int index, char* sendername, int MaxSize = 256) = 0; + virtual bool GetSenderInfo(const char* sendername, unsigned int &width, unsigned int &height, HANDLE &dxShareHandle, DWORD &dwFormat) = 0; + virtual bool GetActiveSender(char* Sendername) = 0; + virtual bool SetActiveSender(const char* Sendername) = 0; + + // Utilities + virtual bool SetDX9(bool bDX9 = true) = 0; // User request to use DirectX 9 (default is DirectX 11) + virtual bool GetDX9() = 0; // Return the flag that has been set + virtual bool SetMemoryShareMode(bool bMem = true) = 0; + virtual bool GetMemoryShareMode() = 0; + virtual int GetMaxSenders() = 0; // Get maximum senders allowed + virtual void SetMaxSenders(int maxSenders) = 0; // Set maximum senders allowed + virtual bool GetHostPath(const char *sendername, char *hostpath, int maxchars) = 0; // The path of the host that produced the sender + virtual int GetVerticalSync() = 0; + virtual bool SetVerticalSync(bool bSync = true) = 0; + virtual bool SelectSenderPanel(const char* message = NULL) = 0; + + // Access to globals + virtual bool GetSpoutSenderName(char * sendername, int maxchars) = 0; // get the global sender name + virtual bool IsSpoutInitialized() = 0; // has the class been initialized + + // Adapter functions + virtual int GetNumAdapters() = 0; // Get the number of graphics adapters in the system + virtual bool GetAdapterName(int index, char *adaptername, int maxchars) = 0; // Get an adapter name + virtual bool SetAdapter(int index = 0) = 0; // Set required graphics adapter for output + virtual int GetAdapter() = 0; // Get the SpoutDirectX global adapter index + + // Library release function + virtual void Release() = 0; + +}; + + +// Handle type. In C++ language the interface type is used. +typedef SPOUTLIBRARY* SPOUTHANDLE; + +// Factory function that creates instances of the SPOUT object. +extern "C" SPOUTAPI SPOUTHANDLE WINAPI GetSpout(VOID); + + +//////////////////////////////////////////////////////////////////////////////// diff --git a/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.lib b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.lib new file mode 100644 index 0000000000..435552b195 Binary files /dev/null and b/apps/OpenSpace-MinVR/ext/spout/SpoutLibrary.lib differ diff --git a/apps/OpenSpace-MinVR/include.cmake b/apps/OpenSpace-MinVR/include.cmake new file mode 100644 index 0000000000..99cad555da --- /dev/null +++ b/apps/OpenSpace-MinVR/include.cmake @@ -0,0 +1 @@ +set(DEFAULT_APPLICATION OFF) diff --git a/apps/OpenSpace-MinVR/main.cpp b/apps/OpenSpace-MinVR/main.cpp new file mode 100644 index 0000000000..068fd72793 --- /dev/null +++ b/apps/OpenSpace-MinVR/main.cpp @@ -0,0 +1,503 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2018 * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// @TODO: Add Spout support +// @TODO: Reintroduce commandline-parsing +// @TODO: Prevent a third window to open that immediately crashes + +// @TODO: Proper check if the current instance is the master: + + // Print whether a the vrsetup is a host or a client +//std::cout << vrMain->getConfig()->getAttributeValue(vrMain->getName(), "hostType") << std::endl; +//if (vrMain->getConfig()->exists("NumClients", vrMain->getName())) { + // How to read configuration settings for the specific vrsetup + //std::cout << "Number of Clients: " << (std::string)vrMain->getConfig()->getValue("NumClients", vrMain->getName()) << std::endl; +//} + +using namespace MinVR; +using namespace openspace; + +namespace { + +class Handler : public VREventHandler, public VRRenderHandler, public VRInputDevice { +public: + void onVREvent(const VRDataIndex& eventData) override; + void onVRRenderContext(const VRDataIndex& stateData) override; + void onVRRenderScene(const VRDataIndex& stateData) override; + + void appendNewInputEventsSinceLastCall(VRDataQueue* queue) override; +}; + +constexpr const char* _loggerCat = "main_minvr"; + +VRMain engine; +Handler handler; +VRDataQueue eventQueue; + +struct { + int nWindows = 0; + glm::ivec2 windowSize; + glm::ivec2 framebufferSize; + + glm::vec2 mousePosition; + uint32_t mouseButtons = 0; + + float averageDeltatime = -1.f; + float deltaTime = -1.f; +} windowingGlobals; + +struct { + bool modifierShift = false; + bool modifierCtrl = false; + bool modifierAlt = false; +} keyboardState; + +bool HasInitializedGL = false; +std::array LastFrametimes = { 1.f / 60.f }; // we can be optimistic here +constexpr const char* MasterNode = "/MinVR/Desktop1"; +bool IsMasterNode = false; +uint64_t FrameNumber = 0; +std::chrono::time_point lastFrameTime; + +} // namespace + +#pragma optimize ("", off) + +void Handler::onVREvent(const VRDataIndex& eventData) { + std::string type; + if (eventData.exists("EventType")) { + type = static_cast(eventData.getValue("EventType")); + } + else { + LERRORC( + "onVREvent()", + fmt::format("Received an event named {} of unknown type", eventData.getName()) + ); + } + + const bool isButtonEvent = type == "ButtonDown" || type == "ButtonUp" || + type == "ButtonRepeat"; + + if (type == "AnalogUpdate") { + const VRAnalogEvent& event = static_cast(eventData); + } + else if (isButtonEvent) { + if (!global::windowDelegate.isMaster()) { + return; + } + const VRButtonEvent& event = static_cast(eventData); + + const std::string& buttonName = event.getName(); + + if (buttonName.size() >= 3 && buttonName.substr(0, 3) == "Kbd") { + // We have a keyboard event + const size_t beg = 3; // "Kbd" prefix + const size_t sep = buttonName.find('_'); + + std::string keyName = buttonName.substr(beg, sep - beg); + std::string actionName = buttonName.substr(sep + 1); + + Key key = KeyMapping.find(keyName)->second; + + KeyAction action; + if (actionName == "Up") { + action = KeyAction::Release; + } + else if (actionName == "Down") { + action = KeyAction::Press; + } + else if (actionName == "Repeat") { + action = KeyAction::Repeat; + } + else { + LWARNINGC("Key", "Unknown key action " + actionName); + } + + if (key == Key::LeftShift || key == Key::RightShift) { + keyboardState.modifierShift = action != KeyAction::Release; + } + if (key == Key::LeftControl || key == Key::RightControl) { + keyboardState.modifierCtrl = action != KeyAction::Release; + } + if (key == Key::LeftAlt || key == Key::RightAlt) { + keyboardState.modifierAlt = action != KeyAction::Release; + } + + using KM = KeyModifier; + KM mod = KM::NoModifier; + mod |= keyboardState.modifierShift ? KM::Shift : KM::NoModifier; + mod |= keyboardState.modifierCtrl ? KM::Control : KM::NoModifier; + mod |= keyboardState.modifierAlt ? KM::Alt : KM::NoModifier; + + openspace::global::openSpaceEngine.keyboardCallback(key, mod, action); + } + + if (buttonName.size() >= 8 && buttonName.substr(0, 8) == "MouseBtn") { + const size_t beg = 8; // "MouseBtn" prefix + const size_t sep = buttonName.find('_'); + + std::string keyName = buttonName.substr(beg, sep - beg); + std::string actionName = buttonName.substr(sep + 1); + + MouseButton button; + if (keyName == "Left") { + button = MouseButton::Left; + } + else if (keyName == "Middle") { + button = MouseButton::Middle; + } + else if (keyName == "Right") { + button = MouseButton::Right; + } + + MouseAction action; + if (actionName == "Down") { + action = MouseAction::Press; + } + else if (actionName == "Up") { + action = MouseAction::Release; + } + + windowingGlobals.mouseButtons = 0; + if (button == MouseButton::Left && action == MouseAction::Press) { + windowingGlobals.mouseButtons |= 1 << 0; + } + if (button == MouseButton::Middle && action == MouseAction::Press) { + windowingGlobals.mouseButtons |= 1 << 1; + } + if (button == MouseButton::Right && action == MouseAction::Press) { + windowingGlobals.mouseButtons |= 1 << 2; + } + global::openSpaceEngine.mouseButtonCallback(button, action); + } + + } + else if (type == "CursorMove") { + if (!global::windowDelegate.isMaster()) { + return; + } + const VRCursorEvent& event = static_cast(eventData); + + const float* pos = event.getPos(); + windowingGlobals.mousePosition = glm::vec2(pos[0], pos[1]); + openspace::global::openSpaceEngine.mousePositionCallback(pos[0], pos[1]); + + // @TODO(abock): Support mouse wheel + //openspace::global::openSpaceEngine.mouseScrollWheelCallback(posX, posY); + } + else if (type == "TrackerMove") { + const VRTrackerEvent& event = static_cast(eventData); + } + else if (type == "OpenSpaceMessage") { + if (global::windowDelegate.isMaster()) { + // We don't want the message if we are the master as we already have the state + return; + } + const int frameNumber = eventData.getValue("FrameNumber"); + const int nBytes = eventData.getValue("NBytes"); + std::vector intData = eventData.getValue("SynchronizationData"); + char* data = reinterpret_cast(intData.data()); + + std::vector synchronizationBuffer(nBytes); + std::copy(data, data + nBytes, synchronizationBuffer.begin()); + + global::openSpaceEngine.decode(std::move(synchronizationBuffer)); + } + else { + LERRORC("onVREvent()", fmt::format("Received an event of unknown type {}", type)); + } +} + +void Handler::onVRRenderContext(const VRDataIndex& stateData) { + if (stateData.exists("IsGraphics")) { + const VRGraphicsState& state = static_cast(stateData); + + if (state.isInitialRenderCall()) { + windowingGlobals.nWindows = std::max( + windowingGlobals.nWindows, + static_cast(stateData.getValue("WindowID")) + 1 + ); + windowingGlobals.windowSize.x = stateData.getValue("WindowWidth"); + windowingGlobals.windowSize.y = stateData.getValue("WindowHeight"); + + windowingGlobals.framebufferSize.x = stateData.getValue("FramebufferWidth"); + windowingGlobals.framebufferSize.y = stateData.getValue("FramebufferHeight"); + + global::openSpaceEngine.initializeGL(); + + HasInitializedGL = true; + } + } +} + +void Handler::onVRRenderScene(const VRDataIndex& stateData) { + if (stateData.exists("IsGraphics")) { + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + const VRGraphicsState& state = static_cast(stateData); + glm::mat4 projectionMatrix = glm::make_mat4(state.getProjectionMatrix()); + glm::mat4 viewMatrix = glm::make_mat4(state.getViewMatrix()); + try { + openspace::global::openSpaceEngine.render( + glm::mat4(1.f), // @TODO(abock) we should probably use the user position here? + viewMatrix, + projectionMatrix + ); + openspace::global::openSpaceEngine.drawOverlays(); + openspace::global::openSpaceEngine.postDraw(); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } +} + +void Handler::appendNewInputEventsSinceLastCall(VRDataQueue* queue) { + queue->addQueue(eventQueue); + eventQueue.clear(); +} + + +void setupMinVrDelegateFunctions(VRMain& main) { + // Sets up the OpenSpace WindowDelegate callback functions + WindowDelegate& delegate = global::windowDelegate; + + + + delegate.nWindows = []() { return windowingGlobals.nWindows; }; + delegate.currentWindowSize = []() { return windowingGlobals.windowSize; }; + delegate.currentWindowResolution = delegate.currentWindowSize; + delegate.currentDrawBufferResolution = delegate.currentWindowResolution; + delegate.currentViewportSize = delegate.currentWindowResolution; + + delegate.averageDeltaTime = []() -> double { + return windowingGlobals.averageDeltatime; + }; + delegate.deltaTime = []() -> double { return windowingGlobals.deltaTime; }; + + delegate.mousePosition = []() { + return windowingGlobals.mousePosition; + }; + delegate.mouseButtons = [](int) { + return windowingGlobals.mouseButtons; + }; + + delegate.isMaster = []() { return IsMasterNode; }; + + delegate.openGLProcedureAddress = [](const char* func) { + VRWindowToolkit* wtk = engine.getWindowToolkit("VRGLFWWindowToolkit"); + VRglproc procAddress = wtk->getProcAddress(func); + return procAddress; + }; +} + +int main(int argc, char** argv) { + // Initialize the LogManager and add the console log as this will be used every time + // and we need a fall back if something goes wrong between here and when we add the + // logs from the configuration file. If the user requested as specific loglevel in the + // configuration file, we will deinitialize this LogManager and reinitialize it later + // with the correct LogLevel + { + using namespace ghoul::logging; + LogManager::initialize(LogLevel::Debug, LogManager::ImmediateFlush::Yes); + LogMgr.addLog(std::make_unique()); +#ifdef WIN32 + if (IsDebuggerPresent()) { + LogMgr.addLog(std::make_unique()); + } +#endif // WIN32 + } + + ghoul::initialize(); + + // Create the OpenSpace engine and get arguments for the SGCT engine + std::string windowConfiguration; + try { + // Find configuration + //std::string configurationFilePath = commandlineArguments.configurationName; + //if (commandlineArguments.configurationName.empty()) { + LDEBUG("Finding configuration"); + std::string configurationFilePath = configuration::findConfiguration(); + //} + configurationFilePath = absPath(configurationFilePath); + + if (!FileSys.fileExists(configurationFilePath)) { + LFATALC("main", "Could not find configuration: " + configurationFilePath); + exit(EXIT_FAILURE); + } + LINFO(fmt::format("Configuration Path: '{}'", configurationFilePath)); + + // Loading configuration from disk + LDEBUG("Loading configuration from disk"); + global::configuration = configuration::loadConfigurationFromFile( + configurationFilePath + ); + + // If the user requested a commandline-based configuation script that should + // overwrite some of the values, this is the time to do it + //if (!commandlineArguments.configurationOverride.empty()) { + // LDEBUG("Executing Lua script passed through the commandline:"); + // LDEBUG(commandlineArguments.configurationOverride); + // ghoul::lua::runScript( + // global::configuration.state, + // commandlineArguments.configurationOverride + // ); + // parseLuaState(global::configuration); + //} + + // Determining MinVR configuration file + LDEBUG("MinVR Configuration file: " + global::configuration.windowConfiguration); + + windowConfiguration = global::configuration.windowConfiguration; + } + catch (const documentation::SpecificationError& e) { + LFATALC("main", "Loading of configuration file failed"); + for (const documentation::TestResult::Offense& o : e.result.offenses) { + LERRORC(o.offender, ghoul::to_string(o.reason)); + } + for (const documentation::TestResult::Warning& w : e.result.warnings) { + LWARNINGC(w.offender, ghoul::to_string(w.reason)); + } + exit(EXIT_FAILURE); + } + catch (const ghoul::RuntimeError& e) { + // Write out all of the information about the exception and flush the logs + LFATALC(e.component, e.message); + if (ghoul::logging::LogManager::isInitialized()) { + LogMgr.flushLogs(); + } + return EXIT_FAILURE; + } + + global::openSpaceEngine.registerPathTokens(); + global::openSpaceEngine.initialize(); + + engine.addEventHandler(&handler); + engine.addRenderHandler(&handler); + engine.loadConfig(global::configuration.windowConfiguration); + // Yes, this still contains the OpenSpace-specific commandline arguments, but no one + // will ever know if we use the remaining arguments or not; both commandline parsers + // just ignore the arguments they don't understand + engine.initialize(argc, argv); + + setupMinVrDelegateFunctions(engine); + + const std::string& name = engine.getName(); + IsMasterNode = (name == MasterNode); + + if (global::windowDelegate.isMaster()) { + engine.addInputDevice(&handler); + } + + lastFrameTime = std::chrono::high_resolution_clock::now(); + // run loop-di-loop + do { + if (HasInitializedGL) { + auto now = std::chrono::high_resolution_clock::now(); + std::chrono::nanoseconds dt = now - lastFrameTime; + double dtSec = dt.count() / (1000.0 * 1000.0 * 1000.0); + windowingGlobals.deltaTime = static_cast(dtSec); + std::rotate( + LastFrametimes.begin(), + LastFrametimes.begin() + 1, + LastFrametimes.end() + ); + LastFrametimes.back() = windowingGlobals.deltaTime; + lastFrameTime = now; + + windowingGlobals.averageDeltatime = std::accumulate( + LastFrametimes.begin(), + LastFrametimes.end(), + 0.f + ) / LastFrametimes.size(); + + + + global::openSpaceEngine.preSynchronization(); + + if (global::windowDelegate.isMaster()) { + std::vector syncBuffer = global::openSpaceEngine.encode(); + VRDataIndex e("OpenSpace_Sync"); + + e.addData("EventType", "OpenSpaceMessage"); + + // Pad the buffer to a multiple of 4 + const int nBytes = syncBuffer.size(); + const int nInts = nBytes % 4 != 0 ? (nBytes / 4 + 1) : nBytes; + syncBuffer.resize((nInts) * 4); + + // Just look away for a bit! + int* data = reinterpret_cast(syncBuffer.data()); + std::vector intData(nInts); + std::copy(data, data + nInts, intData.begin()); + + e.addData("NBytes", static_cast(nBytes)); + e.addData("FrameNumber", static_cast(FrameNumber)); + e.addData("SynchronizationData", intData); + eventQueue.push(e); + } + + engine.synchronizeAndProcessEvents(); + + engine.updateAllModels(); + + // @TODO(abock): Not sure if this should be before updateAllModels or here + global::openSpaceEngine.postSynchronizationPreDraw(); + + ++FrameNumber; + } + + engine.renderOnAllDisplays(); + } while (!engine.getShutdown()); + + + + global::openSpaceEngine.deinitializeGL(); + + // This assumes that `shutdown` destroys the OpenGL state and thus have to happen + // after the deinitializeGL function + engine.shutdown(); + global::openSpaceEngine.deinitialize(); + + exit(EXIT_SUCCESS); +} diff --git a/apps/OpenSpace-MinVR/openspace.icns b/apps/OpenSpace-MinVR/openspace.icns new file mode 100644 index 0000000000..eb15eda9b8 Binary files /dev/null and b/apps/OpenSpace-MinVR/openspace.icns differ diff --git a/apps/OpenSpace-MinVR/openspace.ico b/apps/OpenSpace-MinVR/openspace.ico new file mode 100644 index 0000000000..d5dc3c82aa Binary files /dev/null and b/apps/OpenSpace-MinVR/openspace.ico differ diff --git a/apps/OpenSpace-MinVR/openspace.png b/apps/OpenSpace-MinVR/openspace.png new file mode 100644 index 0000000000..83d23abe7c Binary files /dev/null and b/apps/OpenSpace-MinVR/openspace.png differ diff --git a/apps/OpenSpace-MinVR/openspace.rc b/apps/OpenSpace-MinVR/openspace.rc new file mode 100644 index 0000000000..86a250bb5d --- /dev/null +++ b/apps/OpenSpace-MinVR/openspace.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "openspace.ico" \ No newline at end of file diff --git a/apps/OpenSpace/CMakeLists.txt b/apps/OpenSpace/CMakeLists.txt index 406963976d..5a5dc99e47 100644 --- a/apps/OpenSpace/CMakeLists.txt +++ b/apps/OpenSpace/CMakeLists.txt @@ -100,6 +100,56 @@ target_compile_definitions(OpenSpace PRIVATE ${SPOUT_DEFINITIONS} ) +set(SGCT_TEXT OFF CACHE BOOL "" FORCE) +set(SGCT_BUILD_CSHARP_PROJECTS OFF CACHE BOOL "" FORCE) +set(SGCT_LIGHT_ONLY ON CACHE BOOL "" FORCE) +set(SGCT_CUSTOMOUTPUTDIRS OFF CACHE BOOL "" FORCE) +set(JPEG_TURBO_WITH_SIMD OFF CACHE BOOL "" FORCE) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/sgct) +target_include_directories(OpenSpace SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/sgct/include) +target_link_libraries( + OpenSpace + sgct_light glew glfw png16_static quat tinyxml2static turbojpeg-static + vrpn + ${GLFW_LIBRARIES} +) + +if (TARGET sgct_light) + set_property(TARGET sgct_light PROPERTY FOLDER "External") +endif () +if (TARGET glew) + set_property(TARGET glew PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET glfw) + set_property(TARGET glfw PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET png16_static) + set_property(TARGET png16_static PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET quat) + set_property(TARGET quat PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET simd) + set_property(TARGET simd PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET tinyxml2static) + set_property(TARGET tinyxml2static PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET turbojpeg-static) + set_property(TARGET turbojpeg-static PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET vrpn) + set_property(TARGET vrpn PROPERTY FOLDER "External/SGCT") +endif () +if (TARGET zlibstatic) + set_property(TARGET zlibstatic PROPERTY FOLDER "External/SGCT") +endif () + +if (UNIX AND (NOT APPLE)) + target_link_libraries(OpenSpace Xcursor Xinerama X11) +endif () + # Web Browser and Web gui # Why not put these in the module's path? Because they do not have access to the diff --git a/ext/sgct b/apps/OpenSpace/ext/sgct similarity index 100% rename from ext/sgct rename to apps/OpenSpace/ext/sgct diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 1f92ec9431..e14730eb51 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -70,6 +70,7 @@ constexpr const char* SpoutTag = "Spout"; constexpr const char* OpenVRTag = "OpenVR"; sgct::Engine* SgctEngine; +sgct::SharedVector _synchronizationBuffer; #ifdef OPENVR_SUPPORT sgct::SGCTWindow* FirstOpenVRWindow = nullptr; @@ -580,7 +581,9 @@ void mainCharCallback(unsigned int codepoint, int mods) { void mainEncodeFun() { LTRACE("main::mainEncodeFun(begin)"); - openspace::global::openSpaceEngine.encode(); + std::vector data = openspace::global::openSpaceEngine.encode(); + _synchronizationBuffer.setVal(std::move(data)); + sgct::SharedData::instance()->writeVector(&_synchronizationBuffer); LTRACE("main::mainEncodeFun(end)"); } @@ -588,7 +591,9 @@ void mainEncodeFun() { void mainDecodeFun() { LTRACE("main::mainDecodeFun(begin)"); - openspace::global::openSpaceEngine.decode(); + sgct::SharedData::instance()->readVector(&_synchronizationBuffer); + std::vector data = _synchronizationBuffer.getVal(); + openspace::global::openSpaceEngine.decode(std::move(data)); LTRACE("main::mainDecodeFun(end)"); } @@ -795,6 +800,9 @@ void setSgctDelegateFunctions() { sgctDelegate.currentWindowId = []() { return sgct::Engine::instance()->getCurrentWindowPtr()->getId(); }; + sgctDelegate.openGLProcedureAddress = [](const char* func) { + return glfwGetProcAddress(func); + }; } int main(int argc, char** argv) { @@ -848,13 +856,18 @@ int main(int argc, char** argv) { "evaluated before it is passed to OpenSpace." )); - std::vector sgctArguments = parser.setCommandLine({ argv, argv + argc }); + // setCommandLine returns a referece to the vector that will be filled later + const std::vector& sgctArguments = parser.setCommandLine( + { argv, argv + argc } + ); bool showHelp = parser.execute(); if (showHelp) { parser.displayHelp(std::cout); exit(EXIT_SUCCESS); } + // Take an actual copy of the arguments + std::vector arguments = sgctArguments; // // Set up SGCT functions for window delegate @@ -926,9 +939,9 @@ int main(int argc, char** argv) { // Prepend the outgoing sgctArguments with the program name // as well as the configuration file that sgct is supposed to use - sgctArguments.insert(sgctArguments.begin(), argv[0]); - sgctArguments.insert(sgctArguments.begin() + 1, "-config"); - sgctArguments.insert(sgctArguments.begin() + 2, absPath(windowConfiguration)); + arguments.insert(arguments.begin(), argv[0]); + arguments.insert(arguments.begin() + 1, "-config"); + arguments.insert(arguments.begin() + 2, absPath(windowConfiguration)); // Need to set this before the creation of the sgct::Engine sgct::MessageHandler::instance()->setLogToConsole(false); @@ -941,7 +954,7 @@ int main(int argc, char** argv) { #endif LDEBUG("Creating SGCT Engine"); - SgctEngine = new sgct::Engine(sgctArguments); + SgctEngine = new sgct::Engine(arguments); // Bind functions SgctEngine->setInitOGLFunction(mainInitFunc); diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 0bf56f5948..5fb860fff1 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -79,8 +79,9 @@ public: void mouseButtonCallback(MouseButton button, MouseAction action); void mousePositionCallback(double x, double y); void mouseScrollWheelCallback(double posX, double posY); - void encode(); - void decode(); + void externalControlCallback(const char* receivedChars, int size, int clientId); + std::vector encode(); + void decode(std::vector data); void scheduleLoadSingleAsset(std::string assetPath); void toggleShutdownMode(); diff --git a/include/openspace/engine/syncengine.h b/include/openspace/engine/syncengine.h index ff63f2bea0..93f6677405 100644 --- a/include/openspace/engine/syncengine.h +++ b/include/openspace/engine/syncengine.h @@ -53,13 +53,13 @@ public: * Encodes all added Syncables in the injected SyncBuffer. * This method is only called on the SGCT master node */ - void encodeSyncables(); + std::vector encodeSyncables(); /** * Decodes the SyncBuffer into the added Syncables. * This method is only called on the SGCT slave nodes */ - void decodeSyncables(); + void decodeSyncables(std::vector data); /** * Invokes the presync method of all added Syncables diff --git a/include/openspace/engine/windowdelegate.h b/include/openspace/engine/windowdelegate.h index 9062dced0a..d1d463c20e 100644 --- a/include/openspace/engine/windowdelegate.h +++ b/include/openspace/engine/windowdelegate.h @@ -26,6 +26,7 @@ #define __OPENSPACE_CORE__WINDOWDELEGATE___H__ #include +#include #include namespace openspace { @@ -105,6 +106,11 @@ struct WindowDelegate { int (*nWindows)() = []() { return 0; }; int (*currentWindowId)() = []() { return 0; }; + + using GLProcAddress = void(*)(void); + + GLProcAddress (*openGLProcedureAddress)(const char*) = + [](const char*) -> GLProcAddress { return []() {}; }; }; } // namespace openspace diff --git a/include/openspace/util/keys.h b/include/openspace/util/keys.h index 38b73a34cb..aee3490345 100644 --- a/include/openspace/util/keys.h +++ b/include/openspace/util/keys.h @@ -228,12 +228,6 @@ static const std::map KeyModifierMapping = { }; static const std::map KeyMapping = { - { "SPACE", Key::Space }, - { "APOSTROPHE", Key::Apostrophe }, - { "COMMA", Key::Comma }, - { "MINUS", Key::Minus }, - { "PERIOD", Key::Period }, - { "SLASH", Key::Slash }, { "0", Key::Num0 }, { "1", Key::Num1 }, { "2", Key::Num2 }, @@ -244,8 +238,7 @@ static const std::map KeyMapping = { { "7", Key::Num7 }, { "8", Key::Num8 }, { "9", Key::Num9 }, - { "SEMI COLON", Key::SemiColon }, - { "EQUAL", Key::Equal }, + { "A", Key::A }, { "B", Key::B }, { "C", Key::C }, @@ -272,34 +265,87 @@ static const std::map KeyMapping = { { "X", Key::X }, { "Y", Key::Y }, { "Z", Key::Z }, + + { "LeftBracket", Key::LeftBracket }, + { "LEFTBRACKET", Key::LeftBracket }, { "LEFT_BRACKET", Key::LeftBracket }, + { "Backslash", Key::BackSlash }, { "BACKSLASH", Key::BackSlash }, + { "RightBracket", Key::RightBracket }, + { "RIGHTBRACKET", Key::RightBracket }, { "RIGHT_BRACKET", Key::RightBracket }, + { "GraveAccent", Key::GraveAccent }, + { "GRAVEACCENT", Key::GraveAccent }, { "GRAVE_ACCENT", Key::GraveAccent }, + { "Space", Key::Space }, + { "SPACE", Key::Space }, + { "Apostrophe", Key::Apostrophe }, + { "APOSTROPHE", Key::Apostrophe }, + { "Comma", Key::Comma }, + { "COMMA", Key::Comma }, + { "Minus", Key::Minus }, + { "MINUS", Key::Minus }, + { "Period", Key::Period }, + { "PERIOD", Key::Period }, + { "Slash", Key::Slash }, + { "SLASH", Key::Slash }, + { "Semicolon", Key::SemiColon }, + { "SEMICOLON", Key::SemiColon }, + { "SEMI COLON", Key::SemiColon }, + { "Equal", Key::Equal }, + { "EQUAL", Key::Equal }, + + { "World1", Key::World1 }, + { "WORLD1", Key::World1 }, { "WORLD_1", Key::World1 }, + { "World2", Key::World2 }, + { "WORLD2", Key::World2 }, { "WORLD_2", Key::World2 }, + { "Esc", Key::Escape }, { "ESC", Key::Escape }, { "ESCAPE", Key::Escape}, + { "Enter", Key::Enter }, { "ENTER", Key::Enter }, + { "Tab", Key::Tab }, { "TAB", Key::Tab }, + { "Backspace", Key::BackSpace }, { "BACKSPACE", Key::BackSpace }, + { "Insert", Key::Insert }, { "INSERT", Key::Insert }, { "DEL", Key::Delete }, + { "Delete", Key::Delete }, { "DELETE", Key::Delete }, + { "Right", Key::Right }, { "RIGHT", Key::Right }, + { "Left", Key::Left }, { "LEFT", Key::Left }, + { "Down", Key::Down }, { "DOWN", Key::Down }, + { "Up", Key::Up }, { "UP", Key::Up }, + { "PageUp", Key::PageUp }, { "PAGEUP", Key::PageUp }, - { "PAGEDOWN", Key::PageDown }, { "PAGE_UP", Key::PageUp }, + { "PageDown", Key::PageDown }, + { "PAGEDOWN", Key::PageDown }, { "PAGE_DOWN", Key::PageDown }, + { "Home", Key::Home }, { "HOME", Key::Home }, + { "End", Key::End }, { "END", Key::End }, + { "CapsLock", Key::CapsLock }, + { "CAPSLOCK", Key::CapsLock }, { "CAPS_LOCK", Key::CapsLock }, + { "ScrollLock", Key::ScrollLock }, + { "SCROLLLOCK", Key::ScrollLock }, { "SCROLL_LOCK", Key::ScrollLock }, + { "NumLock", Key::NumLock }, + { "NUMLOCK", Key::NumLock }, { "NUM_LOCK", Key::NumLock }, + { "PrintScreen", Key::PrintScreen }, + { "PRINTSCREEN", Key::PrintScreen }, { "PRINT_SCREEN", Key::PrintScreen }, + { "Pause", Key::Pause }, { "PAUSE", Key::Pause }, { "F1", Key::F1 }, { "F2", Key::F2 }, @@ -326,37 +372,88 @@ static const std::map KeyMapping = { { "F23", Key::F23 }, { "F24", Key::F24 }, { "F25", Key::F25 }, + { "Keypad0", Key::Keypad0 }, + { "KP0", Key::Keypad0 }, { "KP_0", Key::Keypad0 }, + { "Keypad1", Key::Keypad1 }, + { "KP1", Key::Keypad1 }, { "KP_1", Key::Keypad1 }, + { "Keypad2", Key::Keypad2 }, + { "KP2", Key::Keypad2 }, { "KP_2", Key::Keypad2 }, + { "Keypad3", Key::Keypad3 }, + { "KP3", Key::Keypad3 }, { "KP_3", Key::Keypad3 }, + { "Keypad4", Key::Keypad4 }, + { "KP4", Key::Keypad4 }, { "KP_4", Key::Keypad4 }, + { "Keypad5", Key::Keypad5 }, + { "KP5", Key::Keypad5 }, { "KP_5", Key::Keypad5 }, + { "Keypad6", Key::Keypad6 }, + { "KP6", Key::Keypad6 }, { "KP_6", Key::Keypad6 }, + { "Keypad7", Key::Keypad7 }, + { "KP7", Key::Keypad7 }, { "KP_7", Key::Keypad7 }, + { "Keypad8", Key::Keypad8 }, + { "KP8", Key::Keypad8 }, { "KP_8", Key::Keypad8 }, + { "Keypad9", Key::Keypad9 }, + { "KP9", Key::Keypad9 }, { "KP_9", Key::Keypad9 }, + { "KeypadDecimal", Key::KeypadDecimal }, + { "KPDECIMAL", Key::KeypadDecimal }, { "KP_DECIMAL", Key::KeypadDecimal }, + { "KeypadDivide", Key::KeypadDivide }, + { "KPDIVIDE", Key::KeypadDivide }, { "KP_DIVIDE", Key::KeypadDivide }, + { "KeypadMultiply", Key::KeypadMultiply }, + { "KPMULTIPLY", Key::KeypadMultiply }, { "KP_MULTIPLY", Key::KeypadMultiply }, + { "KeypadSubtract", Key::KeypadSubtract }, + { "KPSUBTRACT", Key::KeypadSubtract }, { "KP_SUBTRACT", Key::KeypadSubtract }, + { "KeypadAdd", Key::KeypadAdd }, + { "KPADD", Key::KeypadAdd }, { "KP_ADD", Key::KeypadAdd }, + { "KeypadEnter", Key::KeypadEnter }, + { "KPENTER", Key::KeypadEnter }, { "KP_ENTER", Key::KeypadEnter }, + { "KeypadEqual", Key::KeypadEnter }, + { "KPEQUAL", Key::KeypadEnter }, { "KP_EQUAL", Key::KeypadEnter }, + { "LeftShift", Key::LeftShift }, { "LSHIFT", Key::LeftShift }, + { "LEFTSHIFT", Key::LeftShift }, { "LEFT_SHIFT", Key::LeftShift }, + { "LeftControl", Key::LeftControl }, { "LCTRL", Key::LeftControl }, + { "LEFTCONTROL", Key::LeftControl }, { "LEFT_CONTROL", Key::LeftControl }, + { "LeftAlt", Key::LeftAlt }, { "LALT", Key::LeftAlt }, + { "LEFTALT", Key::LeftAlt }, { "LEFT_ALT", Key::LeftAlt }, + { "LeftSuper", Key::LeftSuper }, + { "LEFTSUPER", Key::LeftSuper }, { "LEFT_SUPER", Key::LeftSuper }, + { "RightShift", Key::RightShift }, { "RSHIFT", Key::RightShift }, + { "RIGHTSHIFT", Key::RightShift }, { "RIGHT_SHIFT", Key::RightShift }, + { "RightControl", Key::RightControl }, { "RCTRL", Key::RightControl }, + { "RIGHTCONTROL", Key::RightControl }, { "RIGHT_CONTROL", Key::RightControl }, + { "RightAlt", Key::RightAlt }, { "RALT", Key::RightAlt }, + { "RIGHTALT", Key::RightAlt }, { "RIGHT_ALT", Key::RightAlt }, + { "RightSuper", Key::RightSuper }, + { "RIGHTSUPER", Key::RightSuper }, { "RIGHT_SUPER", Key::RightSuper }, + { "Menu", Key::Menu }, { "MENU", Key::Menu } }; diff --git a/include/openspace/util/syncbuffer.h b/include/openspace/util/syncbuffer.h index 4ab0da89c0..1ee6fdf2b3 100644 --- a/include/openspace/util/syncbuffer.h +++ b/include/openspace/util/syncbuffer.h @@ -28,11 +28,6 @@ #include #include -namespace sgct { - template - class SharedVector; -} // namespace sgct - namespace openspace { class SyncBuffer { @@ -56,16 +51,19 @@ public: template void decode(T& value); - void write(); + void reset(); - void read(); + //void write(); + //void read(); + + void setData(std::vector data); + std::vector data(); private: size_t _n; size_t _encodeOffset = 0; size_t _decodeOffset = 0; std::vector _dataStream; - std::unique_ptr> _synchronizationBuffer; }; } // namespace openspace diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp index de112aced3..e545aff7e1 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace openspace::globebrowsing { @@ -55,20 +56,20 @@ std::shared_ptr RawTileDataReader::readTileData(TileIndex tileIndex, if (dataDestination && !pboMappedDataDestination) { // Write only to cpu data destination - memset(dataDestination, 255, _initData.totalNumBytes()); + std::memset(dataDestination, 255, _initData.totalNumBytes()); readImageData(io, worstError, dataDestination); } else if (!dataDestination && pboMappedDataDestination) { // Write only to pbo mapped data destination - memset(pboMappedDataDestination, 255, _initData.totalNumBytes()); + std::memset(pboMappedDataDestination, 255, _initData.totalNumBytes()); readImageData(io, worstError, pboMappedDataDestination); } else if (dataDestination && pboMappedDataDestination) { // Write to both data destinations - memset(dataDestination, 255, _initData.totalNumBytes()); + std::memset(dataDestination, 255, _initData.totalNumBytes()); readImageData(io, worstError, dataDestination); size_t numBytes = _initData.totalNumBytes(); - memcpy(pboMappedDataDestination, dataDestination, numBytes); + std::memcpy(pboMappedDataDestination, dataDestination, numBytes); } else { ghoul_assert(false, "Need to specify a data destination"); diff --git a/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp index 8b446d8a48..d037ff41dd 100644 --- a/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp @@ -28,7 +28,10 @@ #include #include #include +#include #include +#include +#include #include #include #include diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 800b6eb3c6..ab6aba63c7 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -82,10 +82,6 @@ #include #include -// @TODO(abock): Replace this with callback in windowdelegate -#define GLFW_INCLUDE_NONE -#include - #if defined(_MSC_VER) && defined(OPENSPACE_ENABLE_VLD) #include #endif @@ -339,8 +335,8 @@ void OpenSpaceEngine::initialize() { void OpenSpaceEngine::initializeGL() { LTRACE("OpenSpaceEngine::initializeGL(begin)"); + glbinding::Binding::initialize(global::windowDelegate.openGLProcedureAddress); //glbinding::Binding::useCurrentContext(); - glbinding::Binding::initialize(glfwGetProcAddress); rendering::helper::initialize(); @@ -1230,14 +1226,16 @@ void OpenSpaceEngine::mouseScrollWheelCallback(double posX, double posY) { global::navigationHandler.mouseScrollWheelCallback(posY); } -void OpenSpaceEngine::encode() { - global::syncEngine.encodeSyncables(); +std::vector OpenSpaceEngine::encode() { + std::vector buffer = global::syncEngine.encodeSyncables(); global::networkEngine.publishStatusMessage(); global::networkEngine.sendMessages(); + + return buffer; } -void OpenSpaceEngine::decode() { - global::syncEngine.decodeSyncables(); +void OpenSpaceEngine::decode(std::vector data) { + global::syncEngine.decodeSyncables(std::move(data)); } void OpenSpaceEngine::toggleShutdownMode() { diff --git a/src/engine/syncengine.cpp b/src/engine/syncengine.cpp index 7a72615ff9..8dfb74907b 100644 --- a/src/engine/syncengine.cpp +++ b/src/engine/syncengine.cpp @@ -37,19 +37,32 @@ SyncEngine::SyncEngine(unsigned int syncBufferSize) } // should be called on sgct master -void SyncEngine::encodeSyncables() { +std::vector SyncEngine::encodeSyncables() { for (Syncable* syncable : _syncables) { syncable->encode(&_syncBuffer); } - _syncBuffer.write(); + + std::vector data = _syncBuffer.data(); + _syncBuffer.reset(); + return data; + + //_dataStream.resize(_encodeOffset); + //_synchronizationBuffer->setVal(_dataStream); + //sgct::SharedData::instance()->writeVector(_synchronizationBuffer.get()); + //_dataStream.resize(_n); + //_encodeOffset = 0; + //_decodeOffset = 0; + //_syncBuffer.write(); } //should be called on sgct slaves -void SyncEngine::decodeSyncables() { - _syncBuffer.read(); +void SyncEngine::decodeSyncables(std::vector data) { + _syncBuffer.setData(std::move(data)); for (Syncable* syncable : _syncables) { syncable->decode(&_syncBuffer); } + + _syncBuffer.reset(); } void SyncEngine::preSynchronization(IsMaster isMaster) { diff --git a/src/rendering/loadingscreen.cpp b/src/rendering/loadingscreen.cpp index be7361cffe..19600d5c80 100644 --- a/src/rendering/loadingscreen.cpp +++ b/src/rendering/loadingscreen.cpp @@ -240,11 +240,6 @@ void LoadingScreen::render() { color, rendering::helper::Anchor::NW ); - - LINFOC("P", ghoul::to_string(p)); - LINFOC("P2", ghoul::to_string(p - progressbarSize / 2.f)); - LINFOC("S", ghoul::to_string(progressbarSize)); - LINFOC("S2", ghoul::to_string(progressbarSize * glm::vec2(progress, 1.f))); } // diff --git a/src/util/syncbuffer.cpp b/src/util/syncbuffer.cpp index 4b6fd54309..e69dcead5a 100644 --- a/src/util/syncbuffer.cpp +++ b/src/util/syncbuffer.cpp @@ -24,13 +24,10 @@ #include -#include - namespace openspace { SyncBuffer::SyncBuffer(size_t n) : _n(n) - , _synchronizationBuffer(new sgct::SharedVector()) { _dataStream.resize(_n); } @@ -71,20 +68,36 @@ void SyncBuffer::decode(std::string& s) { s = decode(); } -void SyncBuffer::write() { +void SyncBuffer::setData(std::vector data) { + _dataStream = std::move(data); +} + +std::vector SyncBuffer::data() { _dataStream.resize(_encodeOffset); - _synchronizationBuffer->setVal(_dataStream); - sgct::SharedData::instance()->writeVector(_synchronizationBuffer.get()); + + return _dataStream; +} + +void SyncBuffer::reset() { _dataStream.resize(_n); _encodeOffset = 0; _decodeOffset = 0; } -void SyncBuffer::read() { - sgct::SharedData::instance()->readVector(_synchronizationBuffer.get()); - _dataStream = _synchronizationBuffer->getVal(); - _encodeOffset = 0; - _decodeOffset = 0; -} +//void SyncBuffer::write() { +// _dataStream.resize(_encodeOffset); +// _synchronizationBuffer->setVal(_dataStream); +// sgct::SharedData::instance()->writeVector(_synchronizationBuffer.get()); +// _dataStream.resize(_n); +// _encodeOffset = 0; +// _decodeOffset = 0; +//} +// +//void SyncBuffer::read() { +// sgct::SharedData::instance()->readVector(_synchronizationBuffer.get()); +// _dataStream = _synchronizationBuffer->getVal(); +// _encodeOffset = 0; +// _decodeOffset = 0; +//} } // namespace openspace