1
0
Fork 0

Merge /u/amalon/flightgear/ branch vr_1 into next

https://sourceforge.net/p/flightgear/flightgear/merge-requests/253/
This commit is contained in:
b'Fernando Garc\xc3\xada Li\xc3\xb1\xc3\xa1n 2021-09-03 22:19:11 +00:00
commit c50fe8de07
12 changed files with 458 additions and 5 deletions

View file

@ -151,6 +151,11 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
if(HTS_ENGINE_FOUND)
set(SYSTEM_HTS_ENGINE_DEFAULT 1)
endif()
find_package(osgXR 0.3)
if (osgXR_FOUND)
set(ENABLE_OSGXR_DEFAULT 1)
endif()
endif()
# 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_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(ENABLE_OSGXR "Set to ON to build Flightgear with OpenXR support via the osgXR library" ${ENABLE_OSGXR_DEFAULT})
# additional utilities
option(ENABLE_FGELEV "Set to ON to build the fgelev application (default)" ON)

View file

@ -4,6 +4,10 @@ function(setup_fgfs_includes target)
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src/FDM/JSBSim)
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 ${PROJECT_SOURCE_DIR}/3rdparty/cjson)
# only actually needed for httpd.cxx

View file

@ -23,6 +23,10 @@ function(setup_fgfs_libraries target)
target_link_libraries(${target} ${X11_LIBRARIES})
endif()
if(ENABLE_OSGXR)
target_link_libraries(${target} osgXR::osgXR)
endif()
target_link_libraries(${target} fgsqlite3 fgvoicesynth fgembeddedresources)
target_link_libraries(${target}

View file

@ -60,6 +60,8 @@ _fgfs_options=(
'--enable-skyblend[Enable sky blending]' \
'--disable-textures[Disable textures]' \
'--enable-textures[Enable textures]' \
'--disable-vr[Disable VR]' \
'--enable-vr[Enable VR]' \
'--disable-wireframe[Disable wireframe drawing mode]' \
'--enable-wireframe[Enable wireframe drawing mode]' \
'--notrim[Do NOT attempt to trim the model (only with fdm=jsbsim)]' \

View file

@ -27,6 +27,7 @@
#define FLIGHTGEAR_VERSION "@FLIGHTGEAR_VERSION@"
#define FLIGHTGEAR_MAJOR_VERSION @FG_VERSION_MAJOR@
#define FLIGHTGEAR_MINOR_VERSION @FG_VERSION_MINOR@
#define FLIGHTGEAR_PATCH_VERSION @FG_VERSION_PATCH@
#cmakedefine ENABLE_UIUC_MODEL
#cmakedefine ENABLE_LARCSIM
@ -75,3 +76,5 @@
#cmakedefine HAVE_SENTRY
#define SENTRY_API_KEY "@sentry_api_key@"
#cmakedefine ENABLE_OSGXR

View file

@ -1900,6 +1900,10 @@ struct OptionDesc {
{"disable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", false, "", 0 },
{"enable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", true, "", 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 },
{"enable-terrasync", false, OPTION_BOOL, "/sim/terrasync/enabled", true, "", 0 },
{"terrasync-dir", true, OPTION_IGNORE, "", false, "", 0 },

View file

@ -28,8 +28,15 @@ set(HEADERS
viewmgr.hxx
sview.hxx
GraphicsPresets.hxx
VRManager.hxx
)
if (ENABLE_OSGXR)
list(APPEND SOURCES
VRManager.cxx
)
endif()
if (YES)
list(APPEND HEADERS PUICamera.hxx)
list(APPEND SOURCES PUICamera.cxx)

View file

@ -477,7 +477,7 @@ void CameraGroup::buildDistortionCamera(const SGPropertyNode* psNode,
#endif
}
void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
{
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
const SGPropertyNode* windowNode = cameraNode->getNode("window");
@ -491,7 +491,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
window = wBuild->buildWindow(cameraNode);
}
if (!window) {
return;
return nullptr;
}
osg::Matrix vOff;
@ -599,7 +599,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
if (it == _cameras.end()) {
SG_LOG(SG_VIEW, SG_ALERT, "CameraGroup::buildCamera: "
"failed to find parent camera for relative camera!");
return;
return nullptr;
}
parentInfo = (*it);
if (projectionNode->getNameString() == "right-of-perspective") {
@ -717,6 +717,18 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
info->flags = info->flags | CameraInfo::VIEW_ABSOLUTE;
//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,
@ -970,6 +982,9 @@ void reloadCompositors(CameraGroup *cgroup)
SGReaderWriterOptions::fromPath(globals->get_fg_root());
options->setPropertyNode(globals->get_props());
if (info->reloadCompositorCallback.valid())
info->reloadCompositorCallback->preReloadCompositor(cgroup, info);
// Force deletion
info->compositor.reset(nullptr);
// Then replace it with a new instance
@ -981,6 +996,9 @@ void reloadCompositors(CameraGroup *cgroup)
viewport,
compositor_path,
options));
if (info->reloadCompositorCallback.valid())
info->reloadCompositorCallback->postReloadCompositor(cgroup, info);
}
cgroup->_viewer->getViewerBase()->startThreading();

View file

@ -51,6 +51,7 @@ namespace flightgear
class CameraGroupListener;
class GraphicsWindow;
class CameraGroup;
/** A wrapper around osg::Camera that contains some extra information.
*/
@ -76,7 +77,7 @@ struct CameraInfo : public osg::Referenced
flags(flags_),
physicalWidth(0), physicalHeight(0), bezelHeightTop(0),
bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0),
relativeCameraParent(0) { }
relativeCameraParent(0), reloadCompositorCallback(nullptr) { }
/** The name as given in the config file.
*/
std::string name;
@ -120,6 +121,14 @@ struct CameraInfo : public osg::Referenced
* Compositor path and should use the default one.
*/
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
@ -150,7 +159,11 @@ public:
* @param cameraNode the property node.
* @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
* it to the camera group.
* @param cameraNode the property node. This can be 0, in which

221
src/Viewer/VRManager.cxx Normal file
View 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
View 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

View file

@ -52,6 +52,7 @@
#include "renderer.hxx"
#include "CameraGroup.hxx"
#include "FGEventHandler.hxx"
#include "VRManager.hxx"
#include "WindowBuilder.hxx"
#include "WindowSystemAdapter.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/depth-buffer", displaySettings, &DisplaySettings::getDepthBuffer, &DisplaySettings::setDepthBuffer );
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();
#ifdef ENABLE_OSGXR
VRManager::instance()->update();
#endif
viewer_base->frame( globals->get_sim_time_sec() );
}
@ -437,6 +447,9 @@ void fgOSCloseWindow()
viewer_base->stopThreading();
}
}
#ifdef ENABLE_OSGXR
VRManager::instance()->destroyAndWait();
#endif
FGScenery::resetPagerSingleton();
flightgear::addSentryBreadcrumb("fgOSCloseWindow, clearing camera group", "info");
flightgear::CameraGroup::setDefault(NULL);