Unverified Commit f630944f authored by Alexander Bock's avatar Alexander Bock Committed by GitHub
Browse files

Feature/minvr (#744)

 * Move SGCT external library from ext/sgct to apps/OpenSpace/ext/sgct
 * Remove all GLFW dependencies from openspace-core
 * Add MinVR dependency
 * Add new executable OpenSpace-MinVR that uses MinVR instead of SGCT
parent 56814363
Showing with 781 additions and 55 deletions
+781 -55
......@@ -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
......@@ -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)
......
##########################################################################################
# #
# 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()
Subproject commit c97f70f63578a3d87582f165b789ce96d37c0b17
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
File added
//
// SpoutLibrary.dll
//
// Spout SDK dll compatible with any C++ compiler
//
#include <windows.h>
#include <GL/GL.h>
#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);
////////////////////////////////////////////////////////////////////////////////
File added
set(DEFAULT_APPLICATION OFF)
/*****************************************************************************************
* *
* 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 <openspace/documentation/documentation.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/util/keys.h>
#include <openspace/util/mouse.h>
#include <ghoul/fmt.h>
#include <ghoul/ghoul.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/consolelog.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/logging/visualstudiooutputlog.h>
#include <api/MinVR.h>
#include <GLFW/glfw3.h>
#include <numeric>
// @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<float, 30> 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<std::chrono::high_resolution_clock> lastFrameTime;
} // namespace
#pragma optimize ("", off)
void Handler::onVREvent(const VRDataIndex& eventData) {
std::string type;
if (eventData.exists("EventType")) {
type = static_cast<VRString>(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<const VRAnalogEvent&>(eventData);
}
else if (isButtonEvent) {
if (!global::windowDelegate.isMaster()) {
return;
}
const VRButtonEvent& event = static_cast<const VRButtonEvent&>(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<const VRCursorEvent&>(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<const VRTrackerEvent&>(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<int> intData = eventData.getValue("SynchronizationData");
char* data = reinterpret_cast<char*>(intData.data());
std::vector<char> 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<const VRGraphicsState&>(stateData);
if (state.isInitialRenderCall()) {
windowingGlobals.nWindows = std::max(
windowingGlobals.nWindows,
static_cast<int>(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<const VRGraphicsState&>(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<ConsoleLog>());
#ifdef WIN32
if (IsDebuggerPresent()) {
LogMgr.addLog(std::make_unique<VisualStudioOutputLog>());
}
#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<float>(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<char> 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<int*>(syncBuffer.data());
std::vector<int> intData(nInts);
std::copy(data, data + nInts, intData.begin());
e.addData("NBytes", static_cast<int>(nBytes));
e.addData("FrameNumber", static_cast<int>(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);
}
File added
apps/OpenSpace-MinVR/openspace.ico

78.9 KB

apps/OpenSpace-MinVR/openspace.png

1.3 MB

IDI_ICON1 ICON DISCARDABLE "openspace.ico"
\ No newline at end of file
......@@ -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
......
File moved
......@@ -70,6 +70,7 @@ constexpr const char* SpoutTag = "Spout";
constexpr const char* OpenVRTag = "OpenVR";
sgct::Engine* SgctEngine;
sgct::SharedVector<char> _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<char> 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<char> 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<std::string> sgctArguments = parser.setCommandLine({ argv, argv + argc });
// setCommandLine returns a referece to the vector that will be filled later
const std::vector<std::string>& 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<std::string> 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);
......
......@@ -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<char> encode();
void decode(std::vector<char> data);
void scheduleLoadSingleAsset(std::string assetPath);
void toggleShutdownMode();
......
......@@ -53,13 +53,13 @@ public:
* Encodes all added Syncables in the injected <code>SyncBuffer</code>.
* This method is only called on the SGCT master node
*/
void encodeSyncables();
std::vector<char> encodeSyncables();
/**
* Decodes the <code>SyncBuffer</code> into the added Syncables.
* This method is only called on the SGCT slave nodes
*/
void decodeSyncables();
void decodeSyncables(std::vector<char> data);
/**
* Invokes the presync method of all added Syncables
......
......@@ -26,6 +26,7 @@
#define __OPENSPACE_CORE__WINDOWDELEGATE___H__
#include <ghoul/glm.h>
#include <glbinding/glbinding.h>
#include <vector>
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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment