Merge /u/amalon/flightgear/ branch vr_1 into next
https://sourceforge.net/p/flightgear/flightgear/merge-requests/253/
This commit is contained in:
commit
c50fe8de07
12 changed files with 458 additions and 5 deletions
|
@ -151,6 +151,11 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
|
||||||
if(HTS_ENGINE_FOUND)
|
if(HTS_ENGINE_FOUND)
|
||||||
set(SYSTEM_HTS_ENGINE_DEFAULT 1)
|
set(SYSTEM_HTS_ENGINE_DEFAULT 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(osgXR 0.3)
|
||||||
|
if (osgXR_FOUND)
|
||||||
|
set(ENABLE_OSGXR_DEFAULT 1)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# FlightGear build options
|
# FlightGear build options
|
||||||
|
@ -171,6 +176,7 @@ option(SYSTEM_GSM "Set to ON to build IAXClient with the system's GSM lib
|
||||||
option(SYSTEM_FLITE "Set to ON to build Flightgear with the system's Flite library" ${SYSTEM_FLITE_DEFAULT})
|
option(SYSTEM_FLITE "Set to ON to build Flightgear with the system's Flite library" ${SYSTEM_FLITE_DEFAULT})
|
||||||
option(SYSTEM_HTS_ENGINE "Set to ON to build Flightgear with the system's HTS Engine library" ${SYSTEM_HTS_ENGINE_DEFAULT})
|
option(SYSTEM_HTS_ENGINE "Set to ON to build Flightgear with the system's HTS Engine library" ${SYSTEM_HTS_ENGINE_DEFAULT})
|
||||||
option(SYSTEM_CPPUNIT "Set to ON to build Flightgear with the system's CppUnit library")
|
option(SYSTEM_CPPUNIT "Set to ON to build Flightgear with the system's CppUnit library")
|
||||||
|
option(ENABLE_OSGXR "Set to ON to build Flightgear with OpenXR support via the osgXR library" ${ENABLE_OSGXR_DEFAULT})
|
||||||
|
|
||||||
# additional utilities
|
# additional utilities
|
||||||
option(ENABLE_FGELEV "Set to ON to build the fgelev application (default)" ON)
|
option(ENABLE_FGELEV "Set to ON to build the fgelev application (default)" ON)
|
||||||
|
|
|
@ -4,6 +4,10 @@ function(setup_fgfs_includes target)
|
||||||
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src/FDM/JSBSim)
|
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src/FDM/JSBSim)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_OSGXR)
|
||||||
|
target_include_directories(${target} PRIVATE ${osgXR_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(${target} PRIVATE ${PLIB_INCLUDE_DIR})
|
target_include_directories(${target} PRIVATE ${PLIB_INCLUDE_DIR})
|
||||||
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/cjson)
|
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/cjson)
|
||||||
# only actually needed for httpd.cxx
|
# only actually needed for httpd.cxx
|
||||||
|
|
|
@ -23,6 +23,10 @@ function(setup_fgfs_libraries target)
|
||||||
target_link_libraries(${target} ${X11_LIBRARIES})
|
target_link_libraries(${target} ${X11_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_OSGXR)
|
||||||
|
target_link_libraries(${target} osgXR::osgXR)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${target} fgsqlite3 fgvoicesynth fgembeddedresources)
|
target_link_libraries(${target} fgsqlite3 fgvoicesynth fgembeddedresources)
|
||||||
|
|
||||||
target_link_libraries(${target}
|
target_link_libraries(${target}
|
||||||
|
|
|
@ -60,6 +60,8 @@ _fgfs_options=(
|
||||||
'--enable-skyblend[Enable sky blending]' \
|
'--enable-skyblend[Enable sky blending]' \
|
||||||
'--disable-textures[Disable textures]' \
|
'--disable-textures[Disable textures]' \
|
||||||
'--enable-textures[Enable textures]' \
|
'--enable-textures[Enable textures]' \
|
||||||
|
'--disable-vr[Disable VR]' \
|
||||||
|
'--enable-vr[Enable VR]' \
|
||||||
'--disable-wireframe[Disable wireframe drawing mode]' \
|
'--disable-wireframe[Disable wireframe drawing mode]' \
|
||||||
'--enable-wireframe[Enable wireframe drawing mode]' \
|
'--enable-wireframe[Enable wireframe drawing mode]' \
|
||||||
'--notrim[Do NOT attempt to trim the model (only with fdm=jsbsim)]' \
|
'--notrim[Do NOT attempt to trim the model (only with fdm=jsbsim)]' \
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define FLIGHTGEAR_VERSION "@FLIGHTGEAR_VERSION@"
|
#define FLIGHTGEAR_VERSION "@FLIGHTGEAR_VERSION@"
|
||||||
#define FLIGHTGEAR_MAJOR_VERSION @FG_VERSION_MAJOR@
|
#define FLIGHTGEAR_MAJOR_VERSION @FG_VERSION_MAJOR@
|
||||||
#define FLIGHTGEAR_MINOR_VERSION @FG_VERSION_MINOR@
|
#define FLIGHTGEAR_MINOR_VERSION @FG_VERSION_MINOR@
|
||||||
|
#define FLIGHTGEAR_PATCH_VERSION @FG_VERSION_PATCH@
|
||||||
|
|
||||||
#cmakedefine ENABLE_UIUC_MODEL
|
#cmakedefine ENABLE_UIUC_MODEL
|
||||||
#cmakedefine ENABLE_LARCSIM
|
#cmakedefine ENABLE_LARCSIM
|
||||||
|
@ -75,3 +76,5 @@
|
||||||
|
|
||||||
#cmakedefine HAVE_SENTRY
|
#cmakedefine HAVE_SENTRY
|
||||||
#define SENTRY_API_KEY "@sentry_api_key@"
|
#define SENTRY_API_KEY "@sentry_api_key@"
|
||||||
|
|
||||||
|
#cmakedefine ENABLE_OSGXR
|
||||||
|
|
|
@ -1900,6 +1900,10 @@ struct OptionDesc {
|
||||||
{"disable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", false, "", 0 },
|
{"disable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", false, "", 0 },
|
||||||
{"enable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", true, "", 0 },
|
{"enable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", true, "", 0 },
|
||||||
{"materials-file", true, OPTION_STRING, "/sim/rendering/materials-file", false, "", 0 },
|
{"materials-file", true, OPTION_STRING, "/sim/rendering/materials-file", false, "", 0 },
|
||||||
|
#ifdef ENABLE_OSGXR
|
||||||
|
{"disable-vr", false, OPTION_BOOL, "/sim/vr/enabled", false, "", 0 },
|
||||||
|
{"enable-vr", false, OPTION_BOOL, "/sim/vr/enabled", true, "", 0 },
|
||||||
|
#endif
|
||||||
{"disable-terrasync", false, OPTION_BOOL, "/sim/terrasync/enabled", false, "", 0 },
|
{"disable-terrasync", false, OPTION_BOOL, "/sim/terrasync/enabled", false, "", 0 },
|
||||||
{"enable-terrasync", false, OPTION_BOOL, "/sim/terrasync/enabled", true, "", 0 },
|
{"enable-terrasync", false, OPTION_BOOL, "/sim/terrasync/enabled", true, "", 0 },
|
||||||
{"terrasync-dir", true, OPTION_IGNORE, "", false, "", 0 },
|
{"terrasync-dir", true, OPTION_IGNORE, "", false, "", 0 },
|
||||||
|
|
|
@ -28,8 +28,15 @@ set(HEADERS
|
||||||
viewmgr.hxx
|
viewmgr.hxx
|
||||||
sview.hxx
|
sview.hxx
|
||||||
GraphicsPresets.hxx
|
GraphicsPresets.hxx
|
||||||
|
VRManager.hxx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (ENABLE_OSGXR)
|
||||||
|
list(APPEND SOURCES
|
||||||
|
VRManager.cxx
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (YES)
|
if (YES)
|
||||||
list(APPEND HEADERS PUICamera.hxx)
|
list(APPEND HEADERS PUICamera.hxx)
|
||||||
list(APPEND SOURCES PUICamera.cxx)
|
list(APPEND SOURCES PUICamera.cxx)
|
||||||
|
|
|
@ -477,7 +477,7 @@ void CameraGroup::buildDistortionCamera(const SGPropertyNode* psNode,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
||||||
{
|
{
|
||||||
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
|
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
|
||||||
const SGPropertyNode* windowNode = cameraNode->getNode("window");
|
const SGPropertyNode* windowNode = cameraNode->getNode("window");
|
||||||
|
@ -491,7 +491,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
||||||
window = wBuild->buildWindow(cameraNode);
|
window = wBuild->buildWindow(cameraNode);
|
||||||
}
|
}
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Matrix vOff;
|
osg::Matrix vOff;
|
||||||
|
@ -599,7 +599,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
||||||
if (it == _cameras.end()) {
|
if (it == _cameras.end()) {
|
||||||
SG_LOG(SG_VIEW, SG_ALERT, "CameraGroup::buildCamera: "
|
SG_LOG(SG_VIEW, SG_ALERT, "CameraGroup::buildCamera: "
|
||||||
"failed to find parent camera for relative camera!");
|
"failed to find parent camera for relative camera!");
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
parentInfo = (*it);
|
parentInfo = (*it);
|
||||||
if (projectionNode->getNameString() == "right-of-perspective") {
|
if (projectionNode->getNameString() == "right-of-perspective") {
|
||||||
|
@ -717,6 +717,18 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
||||||
info->flags = info->flags | CameraInfo::VIEW_ABSOLUTE;
|
info->flags = info->flags | CameraInfo::VIEW_ABSOLUTE;
|
||||||
//buildDistortionCamera(psNode, camera);
|
//buildDistortionCamera(psNode, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraGroup::removeCamera(CameraInfo *info)
|
||||||
|
{
|
||||||
|
for (auto it = _cameras.begin(); it != _cameras.end(); ++it) {
|
||||||
|
if (*it == info) {
|
||||||
|
_cameras.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
|
void CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
|
||||||
|
@ -970,6 +982,9 @@ void reloadCompositors(CameraGroup *cgroup)
|
||||||
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
||||||
options->setPropertyNode(globals->get_props());
|
options->setPropertyNode(globals->get_props());
|
||||||
|
|
||||||
|
if (info->reloadCompositorCallback.valid())
|
||||||
|
info->reloadCompositorCallback->preReloadCompositor(cgroup, info);
|
||||||
|
|
||||||
// Force deletion
|
// Force deletion
|
||||||
info->compositor.reset(nullptr);
|
info->compositor.reset(nullptr);
|
||||||
// Then replace it with a new instance
|
// Then replace it with a new instance
|
||||||
|
@ -981,6 +996,9 @@ void reloadCompositors(CameraGroup *cgroup)
|
||||||
viewport,
|
viewport,
|
||||||
compositor_path,
|
compositor_path,
|
||||||
options));
|
options));
|
||||||
|
|
||||||
|
if (info->reloadCompositorCallback.valid())
|
||||||
|
info->reloadCompositorCallback->postReloadCompositor(cgroup, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
cgroup->_viewer->getViewerBase()->startThreading();
|
cgroup->_viewer->getViewerBase()->startThreading();
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace flightgear
|
||||||
|
|
||||||
class CameraGroupListener;
|
class CameraGroupListener;
|
||||||
class GraphicsWindow;
|
class GraphicsWindow;
|
||||||
|
class CameraGroup;
|
||||||
|
|
||||||
/** A wrapper around osg::Camera that contains some extra information.
|
/** A wrapper around osg::Camera that contains some extra information.
|
||||||
*/
|
*/
|
||||||
|
@ -76,7 +77,7 @@ struct CameraInfo : public osg::Referenced
|
||||||
flags(flags_),
|
flags(flags_),
|
||||||
physicalWidth(0), physicalHeight(0), bezelHeightTop(0),
|
physicalWidth(0), physicalHeight(0), bezelHeightTop(0),
|
||||||
bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0),
|
bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0),
|
||||||
relativeCameraParent(0) { }
|
relativeCameraParent(0), reloadCompositorCallback(nullptr) { }
|
||||||
/** The name as given in the config file.
|
/** The name as given in the config file.
|
||||||
*/
|
*/
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -120,6 +121,14 @@ struct CameraInfo : public osg::Referenced
|
||||||
* Compositor path and should use the default one.
|
* Compositor path and should use the default one.
|
||||||
*/
|
*/
|
||||||
std::string compositor_path;
|
std::string compositor_path;
|
||||||
|
|
||||||
|
struct ReloadCompositorCallback : public virtual osg::Referenced
|
||||||
|
{
|
||||||
|
virtual void preReloadCompositor(CameraGroup *, CameraInfo *) = 0;
|
||||||
|
virtual void postReloadCompositor(CameraGroup *, CameraInfo *) = 0;
|
||||||
|
};
|
||||||
|
osg::ref_ptr<ReloadCompositorCallback> reloadCompositorCallback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CameraGroup : public osg::Referenced
|
class CameraGroup : public osg::Referenced
|
||||||
|
@ -150,7 +159,11 @@ public:
|
||||||
* @param cameraNode the property node.
|
* @param cameraNode the property node.
|
||||||
* @return a CameraInfo object for the camera.
|
* @return a CameraInfo object for the camera.
|
||||||
*/
|
*/
|
||||||
void buildCamera(SGPropertyNode* cameraNode);
|
CameraInfo* buildCamera(SGPropertyNode* cameraNode);
|
||||||
|
/** Remove a camera from the camera group.
|
||||||
|
* @param info the camera info to remove.
|
||||||
|
*/
|
||||||
|
void removeCamera(CameraInfo *info);
|
||||||
/** Create a camera from properties that will draw the GUI and add
|
/** Create a camera from properties that will draw the GUI and add
|
||||||
* it to the camera group.
|
* it to the camera group.
|
||||||
* @param cameraNode the property node. This can be 0, in which
|
* @param cameraNode the property node. This can be 0, in which
|
||||||
|
|
221
src/Viewer/VRManager.cxx
Normal file
221
src/Viewer/VRManager.cxx
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
// Copyright (C) 2021 James Hogan
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "VRManager.hxx"
|
||||||
|
#include "WindowBuilder.hxx"
|
||||||
|
#include "renderer.hxx"
|
||||||
|
|
||||||
|
#include <osgXR/Settings>
|
||||||
|
|
||||||
|
#include <simgear/scene/viewer/CompositorPass.hxx>
|
||||||
|
|
||||||
|
#include <Main/fg_props.hxx>
|
||||||
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
|
namespace flightgear
|
||||||
|
{
|
||||||
|
|
||||||
|
VRManager::VRManager() :
|
||||||
|
_reloadCompositorCallback(new ReloadCompositorCallback(this)),
|
||||||
|
_propXrLayersValidation("/sim/vr/openxr/layers/validation"),
|
||||||
|
_propXrExtensionsDepthInfo("/sim/vr/openxr/extensions/depth-info"),
|
||||||
|
_propXrRuntimeName("/sim/vr/openxr/runtime/name"),
|
||||||
|
_propXrSystemName("/sim/vr/openxr/system/name"),
|
||||||
|
_propStateString("/sim/vr/state-string"),
|
||||||
|
_propPresent("/sim/vr/present"),
|
||||||
|
_propRunning("/sim/vr/running"),
|
||||||
|
_propEnabled("/sim/vr/enabled"),
|
||||||
|
_propDepthInfo("/sim/vr/depth-info"),
|
||||||
|
_propValidationLayer("/sim/vr/validation-layer"),
|
||||||
|
_propMode("/sim/vr/mode"),
|
||||||
|
_propSwapchainMode("/sim/vr/swapchain-mode"),
|
||||||
|
_listenerEnabled(this, &osgXR::Manager::setEnabled),
|
||||||
|
_listenerDepthInfo(this, &VRManager::setDepthInfo),
|
||||||
|
_listenerValidationLayer(this, &VRManager::setValidationLayer),
|
||||||
|
_listenerMode(this, &VRManager::setVRMode),
|
||||||
|
_listenerSwapchainMode(this, &VRManager::setSwapchainMode)
|
||||||
|
{
|
||||||
|
uint32_t fgVersion = (FLIGHTGEAR_MAJOR_VERSION << 16 |
|
||||||
|
FLIGHTGEAR_MINOR_VERSION << 8 |
|
||||||
|
FLIGHTGEAR_PATCH_VERSION);
|
||||||
|
_settings->setApp("FlightGear", fgVersion);
|
||||||
|
_settings->preferEnvBlendMode(osgXR::Settings::OPAQUE);
|
||||||
|
|
||||||
|
// Hook into viewer, but don't enable VR just yet
|
||||||
|
osgViewer::View *view = globals->get_renderer()->getView();
|
||||||
|
if (view) {
|
||||||
|
setViewer(globals->get_renderer()->getViewerBase());
|
||||||
|
view->apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
syncReadOnlyProperties();
|
||||||
|
|
||||||
|
_propEnabled.node(true)->addChangeListener(&_listenerEnabled, true);
|
||||||
|
_propDepthInfo.node(true)->addChangeListener(&_listenerDepthInfo, true);
|
||||||
|
_propValidationLayer.node(true)->addChangeListener(&_listenerValidationLayer, true);
|
||||||
|
_propMode.node(true)->addChangeListener(&_listenerMode, true);
|
||||||
|
_propSwapchainMode.node(true)->addChangeListener(&_listenerSwapchainMode, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
VRManager *VRManager::instance()
|
||||||
|
{
|
||||||
|
static osg::ref_ptr<VRManager> single = new VRManager;
|
||||||
|
return single;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::syncProperties()
|
||||||
|
{
|
||||||
|
// If the state has changed, properties may need synchronising
|
||||||
|
if (checkAndResetStateChanged()) {
|
||||||
|
syncReadOnlyProperties();
|
||||||
|
syncSettingProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::syncReadOnlyProperties()
|
||||||
|
{
|
||||||
|
_propXrLayersValidation = hasValidationLayer();
|
||||||
|
_propXrExtensionsDepthInfo = hasDepthInfoExtension();
|
||||||
|
_propXrRuntimeName = getRuntimeName();
|
||||||
|
_propXrSystemName = getSystemName();
|
||||||
|
|
||||||
|
_propStateString = getStateString();
|
||||||
|
_propPresent = getPresent();
|
||||||
|
_propRunning = isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::syncSettingProperties()
|
||||||
|
{
|
||||||
|
bool enabled = getEnabled();
|
||||||
|
if (_propEnabled != enabled)
|
||||||
|
_propEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::setValidationLayer(bool validationLayer)
|
||||||
|
{
|
||||||
|
_settings->setValidationLayer(validationLayer);
|
||||||
|
syncSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::setDepthInfo(bool depthInfo)
|
||||||
|
{
|
||||||
|
_settings->setDepthInfo(depthInfo);
|
||||||
|
syncSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::setVRMode(const char * mode)
|
||||||
|
{
|
||||||
|
osgXR::Settings::VRMode vrMode = osgXR::Settings::VRMODE_AUTOMATIC;
|
||||||
|
|
||||||
|
if (strcmp(mode, "AUTOMATIC") == 0) {
|
||||||
|
vrMode = osgXR::Settings::VRMODE_AUTOMATIC;
|
||||||
|
} else if (strcmp(mode, "SLAVE_CAMERAS") == 0) {
|
||||||
|
vrMode = osgXR::Settings::VRMODE_SLAVE_CAMERAS;
|
||||||
|
} else if (strcmp(mode, "SCENE_VIEW") == 0) {
|
||||||
|
vrMode = osgXR::Settings::VRMODE_SCENE_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
_settings->setVRMode(vrMode);
|
||||||
|
syncSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::setSwapchainMode(const char * mode)
|
||||||
|
{
|
||||||
|
osgXR::Settings::SwapchainMode swapchainMode = osgXR::Settings::SWAPCHAIN_AUTOMATIC;
|
||||||
|
|
||||||
|
if (strcmp(mode, "AUTOMATIC") == 0) {
|
||||||
|
swapchainMode = osgXR::Settings::SWAPCHAIN_AUTOMATIC;
|
||||||
|
} else if (strcmp(mode,"MULTIPLE") == 0) {
|
||||||
|
swapchainMode = osgXR::Settings::SWAPCHAIN_MULTIPLE;
|
||||||
|
} else if (strcmp(mode,"SINGLE") == 0) {
|
||||||
|
swapchainMode = osgXR::Settings::SWAPCHAIN_SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_settings->setSwapchainMode(swapchainMode);
|
||||||
|
syncSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::update()
|
||||||
|
{
|
||||||
|
osgXR::Manager::update();
|
||||||
|
syncProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::doCreateView(osgXR::View *xrView)
|
||||||
|
{
|
||||||
|
// Restarted in osgXR::Manager::update()
|
||||||
|
_viewer->stopThreading();
|
||||||
|
|
||||||
|
// Construct a property tree for the camera
|
||||||
|
SGPropertyNode_ptr camNode = new SGPropertyNode;
|
||||||
|
WindowBuilder *windowBuilder = WindowBuilder::getWindowBuilder();
|
||||||
|
setValue(camNode->getNode("window/name", true),
|
||||||
|
windowBuilder->getDefaultWindowName());
|
||||||
|
|
||||||
|
// Build a camera
|
||||||
|
CameraGroup *cgroup = CameraGroup::getDefault();
|
||||||
|
CameraInfo *info = cgroup->buildCamera(camNode);
|
||||||
|
|
||||||
|
// Notify osgXR about the new compositor's scene slave cameras
|
||||||
|
if (info) {
|
||||||
|
_camInfos[xrView] = info;
|
||||||
|
_xrViews[info] = xrView;
|
||||||
|
info->reloadCompositorCallback = _reloadCompositorCallback;
|
||||||
|
|
||||||
|
postReloadCompositor(cgroup, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::doDestroyView(osgXR::View *xrView)
|
||||||
|
{
|
||||||
|
// Restarted in osgXR::Manager::update()
|
||||||
|
_viewer->stopThreading();
|
||||||
|
|
||||||
|
CameraGroup *cgroup = CameraGroup::getDefault();
|
||||||
|
auto it = _camInfos.find(xrView);
|
||||||
|
if (it != _camInfos.end()) {
|
||||||
|
osg::ref_ptr<CameraInfo> info = (*it).second;
|
||||||
|
_camInfos.erase(it);
|
||||||
|
|
||||||
|
auto it2 = _xrViews.find(info.get());
|
||||||
|
if (it2 != _xrViews.end())
|
||||||
|
_xrViews.erase(it2);
|
||||||
|
|
||||||
|
cgroup->removeCamera(info.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::preReloadCompositor(CameraGroup *cgroup, CameraInfo *info)
|
||||||
|
{
|
||||||
|
osgXR::View *xrView = _xrViews[info];
|
||||||
|
|
||||||
|
auto& passes = info->compositor->getPassList();
|
||||||
|
for (auto& pass: passes)
|
||||||
|
if (pass->type == "scene")
|
||||||
|
xrView->removeSlave(pass->camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRManager::postReloadCompositor(CameraGroup *cgroup, CameraInfo *info)
|
||||||
|
{
|
||||||
|
osgXR::View *xrView = _xrViews[info];
|
||||||
|
|
||||||
|
auto& passes = info->compositor->getPassList();
|
||||||
|
for (auto& pass: passes)
|
||||||
|
if (pass->type == "scene")
|
||||||
|
xrView->addSlave(pass->camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
158
src/Viewer/VRManager.hxx
Normal file
158
src/Viewer/VRManager.hxx
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
// Copyright (C) 2021 James Hogan
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifndef VRMANAGER_HXX
|
||||||
|
#define VRMANAGER_HXX 1
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_OSGXR
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/observer_ptr>
|
||||||
|
|
||||||
|
#include <osgXR/Manager>
|
||||||
|
|
||||||
|
#include <simgear/props/propertyObject.hxx>
|
||||||
|
#include <simgear/scene/viewer/CompositorPass.hxx>
|
||||||
|
|
||||||
|
#include "CameraGroup.hxx"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace flightgear
|
||||||
|
{
|
||||||
|
|
||||||
|
class VRManager : public osgXR::Manager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
class ReloadCompositorCallback : public CameraInfo::ReloadCompositorCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ReloadCompositorCallback(VRManager *manager) :
|
||||||
|
_manager(manager)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void preReloadCompositor(CameraGroup *cgroup, CameraInfo *info)
|
||||||
|
{
|
||||||
|
_manager->preReloadCompositor(cgroup, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void postReloadCompositor(CameraGroup *cgroup, CameraInfo *info)
|
||||||
|
{
|
||||||
|
_manager->postReloadCompositor(cgroup, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
osg::observer_ptr<VRManager> _manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
VRManager();
|
||||||
|
|
||||||
|
static VRManager *instance();
|
||||||
|
|
||||||
|
void syncProperties();
|
||||||
|
void syncReadOnlyProperties();
|
||||||
|
void syncSettingProperties();
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
|
||||||
|
void setValidationLayer(bool validationLayer);
|
||||||
|
void setDepthInfo(bool depthInfo);
|
||||||
|
|
||||||
|
void setVRMode(const char * mode);
|
||||||
|
void setSwapchainMode(const char * mode);
|
||||||
|
|
||||||
|
// osgXR::Manager overrides
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
void doCreateView(osgXR::View *xrView) override;
|
||||||
|
void doDestroyView(osgXR::View *xrView) override;
|
||||||
|
|
||||||
|
void preReloadCompositor(CameraGroup *cgroup, CameraInfo *info);
|
||||||
|
void postReloadCompositor(CameraGroup *cgroup, CameraInfo *info);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
typedef std::map<osgXR::View *, osg::ref_ptr<CameraInfo>> XRViewToCamInfo;
|
||||||
|
XRViewToCamInfo _camInfos;
|
||||||
|
|
||||||
|
typedef std::map<CameraInfo *, osg::ref_ptr<osgXR::View>> CamInfoToXRView;
|
||||||
|
CamInfoToXRView _xrViews;
|
||||||
|
|
||||||
|
osg::ref_ptr<ReloadCompositorCallback> _reloadCompositorCallback;
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
|
||||||
|
SGPropObjBool _propXrLayersValidation;
|
||||||
|
SGPropObjBool _propXrExtensionsDepthInfo;
|
||||||
|
SGPropObjString _propXrRuntimeName;
|
||||||
|
SGPropObjString _propXrSystemName;
|
||||||
|
|
||||||
|
SGPropObjString _propStateString;
|
||||||
|
SGPropObjBool _propPresent;
|
||||||
|
SGPropObjBool _propRunning;
|
||||||
|
|
||||||
|
SGPropObjBool _propEnabled;
|
||||||
|
SGPropObjBool _propDepthInfo;
|
||||||
|
SGPropObjBool _propValidationLayer;
|
||||||
|
SGPropObjString _propMode;
|
||||||
|
SGPropObjString _propSwapchainMode;
|
||||||
|
|
||||||
|
// Property listeners
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Listener : public SGPropertyChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void (VRManager::*SetterFn)(T v);
|
||||||
|
|
||||||
|
Listener(VRManager *manager, SetterFn setter) :
|
||||||
|
_manager(manager),
|
||||||
|
_setter(setter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void valueChanged(SGPropertyNode *node) override
|
||||||
|
{
|
||||||
|
(_manager->*_setter)(node->template getValue<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
VRManager *_manager;
|
||||||
|
SetterFn _setter;
|
||||||
|
};
|
||||||
|
typedef Listener<bool> ListenerBool;
|
||||||
|
typedef Listener<const char *> ListenerString;
|
||||||
|
|
||||||
|
ListenerBool _listenerEnabled;
|
||||||
|
ListenerBool _listenerDepthInfo;
|
||||||
|
ListenerBool _listenerValidationLayer;
|
||||||
|
ListenerString _listenerMode;
|
||||||
|
ListenerString _listenerSwapchainMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ENABLE_OSGXR
|
||||||
|
|
||||||
|
#endif
|
|
@ -52,6 +52,7 @@
|
||||||
#include "renderer.hxx"
|
#include "renderer.hxx"
|
||||||
#include "CameraGroup.hxx"
|
#include "CameraGroup.hxx"
|
||||||
#include "FGEventHandler.hxx"
|
#include "FGEventHandler.hxx"
|
||||||
|
#include "VRManager.hxx"
|
||||||
#include "WindowBuilder.hxx"
|
#include "WindowBuilder.hxx"
|
||||||
#include "WindowSystemAdapter.hxx"
|
#include "WindowSystemAdapter.hxx"
|
||||||
#include <Main/sentryIntegration.hxx>
|
#include <Main/sentryIntegration.hxx>
|
||||||
|
@ -328,6 +329,12 @@ void fgOSResetProperties()
|
||||||
fgTie("/sim/rendering/osg-displaysettings/double-buffer", displaySettings, &DisplaySettings::getDoubleBuffer, &DisplaySettings::setDoubleBuffer );
|
fgTie("/sim/rendering/osg-displaysettings/double-buffer", displaySettings, &DisplaySettings::getDoubleBuffer, &DisplaySettings::setDoubleBuffer );
|
||||||
fgTie("/sim/rendering/osg-displaysettings/depth-buffer", displaySettings, &DisplaySettings::getDepthBuffer, &DisplaySettings::setDepthBuffer );
|
fgTie("/sim/rendering/osg-displaysettings/depth-buffer", displaySettings, &DisplaySettings::getDepthBuffer, &DisplaySettings::setDepthBuffer );
|
||||||
fgTie("/sim/rendering/osg-displaysettings/rgb", displaySettings, &DisplaySettings::getRGB, &DisplaySettings::setRGB );
|
fgTie("/sim/rendering/osg-displaysettings/rgb", displaySettings, &DisplaySettings::getRGB, &DisplaySettings::setRGB );
|
||||||
|
|
||||||
|
#ifdef ENABLE_OSGXR
|
||||||
|
fgSetBool("/sim/vr/built", true);
|
||||||
|
#else
|
||||||
|
fgSetBool("/sim/vr/built", false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -389,6 +396,9 @@ int fgOSMainLoop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globals->get_renderer()->update();
|
globals->get_renderer()->update();
|
||||||
|
#ifdef ENABLE_OSGXR
|
||||||
|
VRManager::instance()->update();
|
||||||
|
#endif
|
||||||
viewer_base->frame( globals->get_sim_time_sec() );
|
viewer_base->frame( globals->get_sim_time_sec() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,6 +447,9 @@ void fgOSCloseWindow()
|
||||||
viewer_base->stopThreading();
|
viewer_base->stopThreading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_OSGXR
|
||||||
|
VRManager::instance()->destroyAndWait();
|
||||||
|
#endif
|
||||||
FGScenery::resetPagerSingleton();
|
FGScenery::resetPagerSingleton();
|
||||||
flightgear::addSentryBreadcrumb("fgOSCloseWindow, clearing camera group", "info");
|
flightgear::addSentryBreadcrumb("fgOSCloseWindow, clearing camera group", "info");
|
||||||
flightgear::CameraGroup::setDefault(NULL);
|
flightgear::CameraGroup::setDefault(NULL);
|
||||||
|
|
Loading…
Reference in a new issue