238 lines
7.6 KiB
C++
238 lines
7.6 KiB
C++
// -*-c++-*-
|
|
// SPDX-License-Identifier: LGPL-2.1-only
|
|
// Copyright (C) 2021 James Hogan <james@albanarts.com>
|
|
|
|
#ifndef OSGXR_Manager
|
|
#define OSGXR_Manager 1
|
|
|
|
#include <osg/Camera>
|
|
#include <osg/Node>
|
|
#include <osg/ref_ptr>
|
|
|
|
#include <osgViewer/View>
|
|
#include <osgViewer/ViewerBase>
|
|
|
|
#include <osgXR/Export>
|
|
#include <osgXR/Mirror>
|
|
#include <osgXR/Settings>
|
|
#include <osgXR/View>
|
|
|
|
#include <list>
|
|
|
|
namespace osgXR {
|
|
|
|
// Internal state class
|
|
class XRState;
|
|
|
|
/**
|
|
* Public VR state manager class.
|
|
* Applications can extend this class to allow tighter integration with osgXR.
|
|
*/
|
|
class OSGXR_EXPORT Manager : public osgViewer::ViewConfig
|
|
{
|
|
public:
|
|
|
|
Manager();
|
|
virtual ~Manager();
|
|
|
|
/// Use if viewer is a CompositeViewer.
|
|
void setViewer(osgViewer::ViewerBase *viewer)
|
|
{
|
|
_viewer = viewer;
|
|
}
|
|
|
|
/// Set the NodeMasks to use for visibility masks.
|
|
void setVisibilityMaskNodeMasks(osg::Node::NodeMask left,
|
|
osg::Node::NodeMask right) const;
|
|
|
|
void configure(osgViewer::View& view) const override;
|
|
|
|
/**
|
|
* Perform a regular update.
|
|
* This will poll for OpenXR events, and handle any pending VR start /
|
|
* stop operations (possibly invoking the Manager's view callbacks).
|
|
* Some of these operations require threading on the viewer to be
|
|
* temporarily stopped, but in all cases it is started again.
|
|
*/
|
|
virtual void update();
|
|
|
|
/// Find whether state has changed since last call, and reset.
|
|
bool checkAndResetStateChanged();
|
|
|
|
/// Find whether VR seems to be present.
|
|
bool getPresent() const;
|
|
|
|
/**
|
|
* Get whether VR is currently set to be enabled.
|
|
* When enabled, osgXR will try to keep VR running.
|
|
* @return Whether VR is enabled
|
|
*/
|
|
bool getEnabled() const;
|
|
/**
|
|
* Set whether VR is currently set to be enabled.
|
|
* When enabled, osgXR will try to keep VR running.
|
|
* @param enabled Whether VR is enabled.
|
|
*/
|
|
void setEnabled(bool enabled);
|
|
|
|
/**
|
|
* Start destroying the VR state and wait for safe shutdown.
|
|
*/
|
|
void destroyAndWait();
|
|
|
|
/**
|
|
* Find whether this manager is in the process of being destroyed.
|
|
*/
|
|
bool isDestroying() const;
|
|
|
|
/**
|
|
* Get whether a VR session is currently running.
|
|
* @return Whether a VR session is currently running.
|
|
*/
|
|
bool isRunning() const;
|
|
|
|
/// Arrange reinit as needed for new settings.
|
|
void syncSettings();
|
|
|
|
/// Arrange reinit as needed of action setup.
|
|
void syncActionSetup();
|
|
|
|
/*
|
|
* OpenXR information.
|
|
*/
|
|
|
|
/**
|
|
* Find whether OpenXR's validation layer is supported.
|
|
* This looks to see whether the OpenXR validation API layer (i.e.
|
|
* XR_APILAYER_LUNARG_core_validation) is available.
|
|
*/
|
|
bool hasValidationLayer() const;
|
|
|
|
/**
|
|
* Find whether OpenXR supports the submission of depth information.
|
|
* This looks to see whether the OpenXR instance extension for
|
|
* submitting depth information to help the runtime perform better
|
|
* reprojection (i.e. XR_KHR_composition_layer_depth) is available.
|
|
*/
|
|
bool hasDepthInfoExtension() const;
|
|
|
|
/**
|
|
* Find whether OpenXR supports the visibility mask extension.
|
|
* This looks to see whether the OpenXR instance extension for getting
|
|
* visibility masks is available, which can be used to reduce fragment
|
|
* load.
|
|
*/
|
|
bool hasVisibilityMaskExtension() const;
|
|
|
|
/// Find the name of the OpenXR runtime.
|
|
const char *getRuntimeName() const;
|
|
|
|
/// Find the name of the OpenXR system in use.
|
|
const char *getSystemName() const;
|
|
|
|
/// Get a string describing the state (for user consumption).
|
|
const char *getStateString() const;
|
|
|
|
/*
|
|
* For implementation by derived classes.
|
|
*/
|
|
|
|
/**
|
|
* Callback telling the app to configure a new view.
|
|
* This callback allows osgXR to tell the app to configure a new view of
|
|
* the world. The application should notify osgXR of the addition and
|
|
* removal of slave cameras which osgXR should hook into using the
|
|
* osgXR::View parameter.
|
|
* The implementation may stop threading, and it will be started again
|
|
* before update() returns.
|
|
* @param xrView The new osgXR::View with a public API to allow the
|
|
* application to retrieve what it needs in relation to
|
|
* the view and to inform osgXR of changes.
|
|
*/
|
|
virtual void doCreateView(View *xrView) = 0;
|
|
|
|
/**
|
|
* Callback telling the app to destroy an existing view.
|
|
* This callback allows osgXR to tell the app to remove an existing view
|
|
* of the world that it had requested via doCreateView(). The
|
|
* application should notify osgXR of the removal of any slave cameras
|
|
* which it has already informed osgXR about.
|
|
* The implementation may stop threading, and it will be started again
|
|
* before update() returns.
|
|
*/
|
|
virtual void doDestroyView(View *xrView) = 0;
|
|
|
|
/**
|
|
* Callback telling the app that the VR session is now running.
|
|
* This happens after the OpenXR session has started running, and views
|
|
* have been configured (see doCreateView()). The app should start
|
|
* rendering the VR views, and may choose to reconfigure the desktop
|
|
* window to make a VR mirror visible.
|
|
*/
|
|
virtual void onRunning();
|
|
|
|
/**
|
|
* Callback telling the app that the VR session has now stopped.
|
|
* This happens after the OpenXR session has stopped, and views have
|
|
* been removed (see doDestroyView()). The app should stop rendering the
|
|
* VR views, and may choose to reconfigure the desktop window so as to
|
|
* no longer show a VR mirror.
|
|
*/
|
|
virtual void onStopped();
|
|
|
|
/**
|
|
* Callback telling the app that the VR session is in focus.
|
|
* This happens when the VR session enters focus and can get VR input
|
|
* from the user. The app may choose to resume the experience if it was
|
|
* previously paused due to onUnfocus().
|
|
*/
|
|
virtual void onFocus();
|
|
|
|
/**
|
|
* Callback telling the app that the VR session is no longer in focus.
|
|
* This happens when the VR session leaves focus and can no longer get
|
|
* VR input from the user. The VR runtime may be presenting a modal
|
|
* pop-up on top of the application's rendered frames. The app may
|
|
* choose to pause the experience.
|
|
*/
|
|
virtual void onUnfocus();
|
|
|
|
|
|
/// Add a custom mirror to the queue of mirrors to configure.
|
|
void addMirror(Mirror *mirror);
|
|
|
|
/// Set up a camera to render a VR mirror.
|
|
void setupMirrorCamera(osg::Camera *camera);
|
|
|
|
/*
|
|
* Internal
|
|
*/
|
|
|
|
inline Settings *_getSettings()
|
|
{
|
|
return _settings.get();
|
|
}
|
|
|
|
inline XRState *_getXrState()
|
|
{
|
|
return _state;
|
|
}
|
|
|
|
void _setupMirrors();
|
|
|
|
protected:
|
|
|
|
osg::ref_ptr<osgViewer::ViewerBase> _viewer;
|
|
osg::ref_ptr<Settings> _settings;
|
|
bool _destroying;
|
|
|
|
private:
|
|
|
|
std::list<osg::ref_ptr<Mirror> > _mirrorQueue;
|
|
osg::ref_ptr<XRState> _state;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|