1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-04 21:45:33 +00:00

Some refactoring

This commit is contained in:
Mads Buvik Sandvei 2020-02-29 23:53:56 +01:00
parent f5e01417ba
commit da03e8bf41
22 changed files with 362 additions and 188 deletions

View file

@ -116,6 +116,8 @@ if(BUILD_VR_OPENXR)
engine_vr.cpp engine_vr.cpp
mwvr/openxranimation.hpp mwvr/openxranimation.hpp
mwvr/openxranimation.cpp mwvr/openxranimation.cpp
mwvr/openxrenvironment.hpp
mwvr/openxrenvironment.cpp
mwvr/openxrinputmanager.hpp mwvr/openxrinputmanager.hpp
mwvr/openxrinputmanager.cpp mwvr/openxrinputmanager.cpp
mwvr/openxrlayer.hpp mwvr/openxrlayer.hpp

View file

@ -61,6 +61,7 @@
#ifdef USE_OPENXR #ifdef USE_OPENXR
#include "mwvr/openxrinputmanager.hpp" #include "mwvr/openxrinputmanager.hpp"
#include "mwvr/openxrviewer.hpp"
#endif #endif
namespace namespace
@ -548,7 +549,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
gameControllerdb = ""; //if it doesn't exist, pass in an empty string gameControllerdb = ""; //if it doesn't exist, pass in an empty string
MWInput::InputManager* input = MWInput::InputManager* input =
#ifdef USE_OPENXR #ifdef USE_OPENXR
new MWVR::OpenXRInputManager(mWindow, mXRViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab); new MWVR::OpenXRInputManager(mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
#else #else
new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab); new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
#endif #endif
@ -736,8 +737,9 @@ void OMW::Engine::go()
#ifdef USE_OPENXR #ifdef USE_OPENXR
auto* root = mViewer->getSceneData(); auto* root = mViewer->getSceneData();
mXRViewer->addChild(root); auto* xrViewer = MWVR::OpenXREnvironment::get().getViewer();
mViewer->setSceneData(mXRViewer); xrViewer->addChild(root);
mViewer->setSceneData(xrViewer);
#ifndef _NDEBUG #ifndef _NDEBUG
//mXR->addPoseUpdateCallback(new MWVR::PoseLogger(MWVR::TrackedLimb::HEAD, MWVR::TrackedSpace::STAGE)); //mXR->addPoseUpdateCallback(new MWVR::PoseLogger(MWVR::TrackedLimb::HEAD, MWVR::TrackedSpace::STAGE));
//mXR->addPoseUpdateCallback(new MWVR::PoseLogger(MWVR::TrackedLimb::HEAD, MWVR::TrackedSpace::VIEW)); //mXR->addPoseUpdateCallback(new MWVR::PoseLogger(MWVR::TrackedLimb::HEAD, MWVR::TrackedSpace::VIEW));
@ -798,7 +800,7 @@ void OMW::Engine::go()
mEnvironment.getWorld()->updateWindowManager(); mEnvironment.getWorld()->updateWindowManager();
#ifdef USE_OPENXR #ifdef USE_OPENXR
mXRViewer->traversals(); xrViewer->traversals();
#else #else
mViewer->updateTraversal(); mViewer->updateTraversal();

View file

@ -14,8 +14,7 @@
#include "mwworld/ptr.hpp" #include "mwworld/ptr.hpp"
#ifdef USE_OPENXR #ifdef USE_OPENXR
#include "mwvr/openxrmanager.hpp" #include "mwvr/openxrenvironment.hpp"
#include "mwvr/openxrviewer.hpp"
#endif #endif
namespace Resource namespace Resource
@ -213,8 +212,7 @@ namespace OMW
Files::ConfigurationManager& mCfgMgr; Files::ConfigurationManager& mCfgMgr;
#ifdef USE_OPENXR #ifdef USE_OPENXR
osg::ref_ptr<MWVR::OpenXRManager> mXR; MWVR::OpenXREnvironment mXrEnvironment;
osg::ref_ptr<MWVR::OpenXRViewer> mXRViewer;
void initVr(); void initVr();
#endif #endif

View file

@ -1,7 +1,7 @@
#include "engine.hpp" #include "engine.hpp"
#include "mwbase/environment.hpp"
#include "mwvr/openxrmanager.hpp" #include "mwvr/openxrmanager.hpp"
#include "mwvr/openxrsession.hpp" #include "mwvr/openxrsession.hpp"
#include "mwvr/openxrviewer.hpp"
#ifndef USE_OPENXR #ifndef USE_OPENXR
#error "USE_OPENXR not defined" #error "USE_OPENXR not defined"
@ -12,14 +12,14 @@ void OMW::Engine::initVr()
if (!mViewer) if (!mViewer)
throw std::logic_error("mViewer must be initialized before calling initVr()"); throw std::logic_error("mViewer must be initialized before calling initVr()");
mXR = new MWVR::OpenXRManager(); mXrEnvironment.setManager(new MWVR::OpenXRManager);
// Ref: https://wiki.openmw.org/index.php?title=Measurement_Units // Ref: https://wiki.openmw.org/index.php?title=Measurement_Units
float unitsPerYard = 64.f; float unitsPerYard = 64.f;
float yardsPerMeter = 0.9144f; float yardsPerMeter = 0.9144f;
float unitsPerMeter = unitsPerYard / yardsPerMeter; float unitsPerMeter = unitsPerYard / yardsPerMeter;
mEnvironment.setXRSession(new MWVR::OpenXRSession(mXR, unitsPerMeter)); mXrEnvironment.setUnitsPerMeter(unitsPerMeter);
mXrEnvironment.setSession(new MWVR::OpenXRSession());
mXRViewer = new MWVR::OpenXRViewer(mXR, mViewer); mXrEnvironment.setViewer(new MWVR::OpenXRViewer(mViewer));
} }

View file

@ -200,26 +200,3 @@ const MWBase::Environment& MWBase::Environment::get()
return *sThis; return *sThis;
} }
#ifdef USE_OPENXR
#include "../mwvr/openxrinputmanager.hpp"
#include "../mwvr/openxrsession.hpp"
MWVR::OpenXRInputManager* MWBase::Environment::getXRInputManager() const
{
assert(mInputManager);
auto xrInputManager = dynamic_cast<MWVR::OpenXRInputManager*>(mInputManager);
assert(xrInputManager);
return xrInputManager;
}
MWVR::OpenXRSession* MWBase::Environment::getXRSession() const
{
return mXrSession;
}
void MWBase::Environment::setXRSession(MWVR::OpenXRSession* xrSession)
{
mXrSession = xrSession;
}
#endif

View file

@ -1,14 +1,6 @@
#ifndef GAME_BASE_ENVIRONMENT_H #ifndef GAME_BASE_ENVIRONMENT_H
#define GAME_BASE_ENVIRONMENT_H #define GAME_BASE_ENVIRONMENT_H
#ifdef USE_OPENXR
namespace MWVR
{
class OpenXRInputManager;
class OpenXRSession;
}
#endif
namespace MWBase namespace MWBase
{ {
class World; class World;
@ -108,15 +100,6 @@ namespace MWBase
static const Environment& get(); static const Environment& get();
///< Return instance of this class. ///< Return instance of this class.
// VR Extensions
#ifdef USE_OPENXR
MWVR::OpenXRInputManager* getXRInputManager() const;
MWVR::OpenXRSession* getXRSession() const;
void setXRSession(MWVR::OpenXRSession* xrSession);
private:
MWVR::OpenXRSession* mXrSession;
#endif
}; };
} }

View file

@ -43,6 +43,7 @@
#ifdef USE_OPENXR #ifdef USE_OPENXR
#include "../mwvr/openxrsession.hpp" #include "../mwvr/openxrsession.hpp"
#include "../mwvr/openxrinputmanager.hpp" #include "../mwvr/openxrinputmanager.hpp"
#include "../mwvr/openxrenvironment.hpp"
#endif #endif
#include "collisiontype.hpp" #include "collisiontype.hpp"
@ -289,7 +290,7 @@ namespace MWPhysics
#ifdef USE_OPENXR #ifdef USE_OPENXR
if (isPlayer) if (isPlayer)
{ {
auto session = MWBase::Environment::get().getXRSession(); auto* session = MWVR::OpenXREnvironment::get().getSession();
if (session) if (session)
{ {
float yaw = session->movementYaw(); float yaw = session->movementYaw();
@ -388,7 +389,7 @@ namespace MWPhysics
#ifdef USE_OPENXR #ifdef USE_OPENXR
if (isPlayer) if (isPlayer)
{ {
auto inputManager = MWBase::Environment::get().getXRInputManager(); auto* inputManager = MWVR::OpenXREnvironment::get().getInputManager();
osg::Vec3 trackingOffset = inputManager->mHeadOffset; osg::Vec3 trackingOffset = inputManager->mHeadOffset;
// Player's tracking height should not affect character position // Player's tracking height should not affect character position

View file

@ -13,6 +13,7 @@
#ifdef USE_OPENXR #ifdef USE_OPENXR
#include "../mwvr/openxrinputmanager.hpp" #include "../mwvr/openxrinputmanager.hpp"
#include "../mwvr/openxrenvironment.hpp"
#endif #endif
#include "npcanimation.hpp" #include "npcanimation.hpp"
@ -126,7 +127,7 @@ namespace MWRender
osg::Vec3d position = getFocalPoint(); osg::Vec3d position = getFocalPoint();
#ifdef USE_OPENXR #ifdef USE_OPENXR
auto inputManager = MWBase::Environment::get().getXRInputManager(); auto* inputManager = MWVR::OpenXREnvironment::get().getInputManager();
if (inputManager) if (inputManager)
{ {
position += inputManager->mHeadOffset; position += inputManager->mHeadOffset;

View file

@ -0,0 +1,106 @@
#include "openxrenvironment.hpp"
#include <cassert>
#include "openxrinputmanager.hpp"
#include "openxrsession.hpp"
#include "openxrmenu.hpp"
#include "../mwbase/environment.hpp"
MWVR::OpenXREnvironment *MWVR::OpenXREnvironment::sThis = 0;
MWVR::OpenXREnvironment::OpenXREnvironment()
: mSession(nullptr)
{
assert (!sThis);
sThis = this;
}
MWVR::OpenXREnvironment::~OpenXREnvironment()
{
cleanup();
sThis = 0;
}
void MWVR::OpenXREnvironment::cleanup()
{
if (mSession)
delete mSession;
mSession = nullptr;
if (mMenuManager)
delete mMenuManager;
mMenuManager = nullptr;
if (mViewer)
delete mViewer;
mViewer = nullptr;
if (mOpenXRManager)
delete mOpenXRManager;
mOpenXRManager = nullptr;
}
const MWVR::OpenXREnvironment& MWVR::OpenXREnvironment::get()
{
assert (sThis);
return *sThis;
}
MWVR::OpenXRInputManager* MWVR::OpenXREnvironment::getInputManager() const
{
auto* inputManager = MWBase::Environment::get().getInputManager();
assert(inputManager);
auto xrInputManager = dynamic_cast<MWVR::OpenXRInputManager*>(inputManager);
assert(xrInputManager);
return xrInputManager;
}
MWVR::OpenXRSession* MWVR::OpenXREnvironment::getSession() const
{
return mSession;
}
void MWVR::OpenXREnvironment::setSession(MWVR::OpenXRSession* xrSession)
{
mSession = xrSession;
}
MWVR::OpenXRMenuManager* MWVR::OpenXREnvironment::getMenuManager() const
{
return mMenuManager;
}
void MWVR::OpenXREnvironment::setMenuManager(MWVR::OpenXRMenuManager* menuManager)
{
mMenuManager = menuManager;
}
MWVR::OpenXRViewer* MWVR::OpenXREnvironment::getViewer() const
{
return mViewer;
}
void MWVR::OpenXREnvironment::setViewer(MWVR::OpenXRViewer* xrViewer)
{
mViewer = xrViewer;
}
MWVR::OpenXRManager* MWVR::OpenXREnvironment::getManager() const
{
return mOpenXRManager;
}
void MWVR::OpenXREnvironment::setManager(MWVR::OpenXRManager* xrManager)
{
mOpenXRManager = xrManager;
}
float MWVR::OpenXREnvironment::unitsPerMeter() const
{
return mUnitsPerMeter;
}
void MWVR::OpenXREnvironment::setUnitsPerMeter(float unitsPerMeter)
{
mUnitsPerMeter = unitsPerMeter;
}

View file

@ -0,0 +1,71 @@
#ifndef OPENXR_ENVIRONMENT_H
#define OPENXR_ENVIRONMENT_H
namespace MWVR
{
class OpenXRInputManager;
class OpenXRSession;
class OpenXRMenuManager;
class OpenXRViewer;
class OpenXRManager;
/// \brief Central hub for mw openxr subsystems
///
/// This class allows each mw openxr subsystem to access any others subsystem's top-level manager class.
///
/// \attention OpenXREnvironment takes ownership of the manager class instances it is handed over in
/// the set* functions.
class OpenXREnvironment
{
static OpenXREnvironment*sThis;
OpenXREnvironment(const OpenXREnvironment&) = delete;
///< not implemented
OpenXREnvironment& operator= (const OpenXREnvironment&) = delete;
///< not implemented
public:
OpenXREnvironment();
~OpenXREnvironment();
void cleanup();
///< Delete all mwvr-subsystems.
static const OpenXREnvironment& get();
///< Return instance of this class.
MWVR::OpenXRInputManager* getInputManager() const;
// The OpenXRInputManager supplants the regular input manager
// which is stored in MWBase::Environment
// void setInputManager(MWVR::OpenXRInputManager*);
MWVR::OpenXRMenuManager* getMenuManager() const;
void setMenuManager(MWVR::OpenXRMenuManager* xrMenuManager);
MWVR::OpenXRSession* getSession() const;
void setSession(MWVR::OpenXRSession* xrSession);
MWVR::OpenXRViewer* getViewer() const;
void setViewer(MWVR::OpenXRViewer* xrViewer);
MWVR::OpenXRManager* getManager() const;
void setManager(MWVR::OpenXRManager* xrManager);
float unitsPerMeter() const;
void setUnitsPerMeter(float unitsPerMeter);
private:
MWVR::OpenXRSession* mSession;
MWVR::OpenXRMenuManager* mMenuManager;
MWVR::OpenXRViewer* mViewer;
MWVR::OpenXRManager* mOpenXRManager;
float mUnitsPerMeter;
};
}
#endif

View file

@ -1,4 +1,5 @@
#include "openxrinputmanager.hpp" #include "openxrinputmanager.hpp"
#include "openxrenvironment.hpp"
#include "openxrmanager.hpp" #include "openxrmanager.hpp"
#include "openxrmanagerimpl.hpp" #include "openxrmanagerimpl.hpp"
@ -63,7 +64,7 @@ namespace MWVR
OpenXRAction(const OpenXRAction&) = default; OpenXRAction(const OpenXRAction&) = default;
OpenXRAction& operator=(const OpenXRAction&) = default; OpenXRAction& operator=(const OpenXRAction&) = default;
public: public:
OpenXRAction(osg::ref_ptr<OpenXRManager> XR, XrAction action, XrActionType actionType, const std::string& actionName, const std::string& localName); OpenXRAction(XrAction action, XrActionType actionType, const std::string& actionName, const std::string& localName);
~OpenXRAction(); ~OpenXRAction();
@ -74,7 +75,6 @@ namespace MWVR
bool getPose(XrPath subactionPath); bool getPose(XrPath subactionPath);
bool applyHaptics(XrPath subactionPath, float amplitude); bool applyHaptics(XrPath subactionPath, float amplitude);
osg::ref_ptr<OpenXRManager> mXR = nullptr;
XrAction mAction = XR_NULL_HANDLE; XrAction mAction = XR_NULL_HANDLE;
XrActionType mType; XrActionType mType;
std::string mName; std::string mName;
@ -182,7 +182,7 @@ namespace MWVR
ControllerActionPaths generateControllerActionPaths(const std::string& controllerAction); ControllerActionPaths generateControllerActionPaths(const std::string& controllerAction);
OpenXRInput(osg::ref_ptr<OpenXRManager> XR); OpenXRInput();
OpenXRAction createAction(XrActionType actionType, const std::string& actionName, const std::string& localName, const std::vector<SubAction>& subActions = {}); OpenXRAction createAction(XrActionType actionType, const std::string& actionName, const std::string& localName, const std::vector<SubAction>& subActions = {});
@ -194,7 +194,6 @@ namespace MWVR
bool nextActionEvent(OpenXRActionEvent& action); bool nextActionEvent(OpenXRActionEvent& action);
PoseSet getHandPoses(int64_t time, TrackedSpace space); PoseSet getHandPoses(int64_t time, TrackedSpace space);
osg::ref_ptr<OpenXRManager> mXR;
SubActionPaths mSubactionPath; SubActionPaths mSubactionPath;
XrActionSet mActionSet = XR_NULL_HANDLE; XrActionSet mActionSet = XR_NULL_HANDLE;
@ -262,12 +261,13 @@ namespace MWVR
XrActionSet XrActionSet
OpenXRInput::createActionSet() OpenXRInput::createActionSet()
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrActionSet actionSet = XR_NULL_HANDLE; XrActionSet actionSet = XR_NULL_HANDLE;
XrActionSetCreateInfo createInfo{ XR_TYPE_ACTION_SET_CREATE_INFO }; XrActionSetCreateInfo createInfo{ XR_TYPE_ACTION_SET_CREATE_INFO };
strcpy_s(createInfo.actionSetName, "gameplay"); strcpy_s(createInfo.actionSetName, "gameplay");
strcpy_s(createInfo.localizedActionSetName, "Gameplay"); strcpy_s(createInfo.localizedActionSetName, "Gameplay");
createInfo.priority = 0; createInfo.priority = 0;
CHECK_XRCMD(xrCreateActionSet(mXR->impl().mInstance, &createInfo, &actionSet)); CHECK_XRCMD(xrCreateActionSet(xr->impl().mInstance, &createInfo, &actionSet));
return actionSet; return actionSet;
} }
@ -283,13 +283,11 @@ namespace MWVR
OpenXRAction::OpenXRAction( OpenXRAction::OpenXRAction(
osg::ref_ptr<OpenXRManager> XR,
XrAction action, XrAction action,
XrActionType actionType, XrActionType actionType,
const std::string& actionName, const std::string& actionName,
const std::string& localName) const std::string& localName)
: mXR(XR) : mAction(action)
, mAction(action)
, mType(actionType) , mType(actionType)
, mName(actionName) , mName(actionName)
, mLocalName(localName) , mLocalName(localName)
@ -306,12 +304,13 @@ namespace MWVR
bool OpenXRAction::getFloat(XrPath subactionPath, float& value) bool OpenXRAction::getFloat(XrPath subactionPath, float& value)
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO }; XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO };
getInfo.action = mAction; getInfo.action = mAction;
getInfo.subactionPath = subactionPath; getInfo.subactionPath = subactionPath;
XrActionStateFloat xrValue{ XR_TYPE_ACTION_STATE_FLOAT }; XrActionStateFloat xrValue{ XR_TYPE_ACTION_STATE_FLOAT };
CHECK_XRCMD(xrGetActionStateFloat(mXR->impl().mSession, &getInfo, &xrValue)); CHECK_XRCMD(xrGetActionStateFloat(xr->impl().mSession, &getInfo, &xrValue));
if (xrValue.isActive) if (xrValue.isActive)
value = xrValue.currentState; value = xrValue.currentState;
@ -320,12 +319,13 @@ namespace MWVR
bool OpenXRAction::getBool(XrPath subactionPath, bool& value) bool OpenXRAction::getBool(XrPath subactionPath, bool& value)
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO }; XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO };
getInfo.action = mAction; getInfo.action = mAction;
getInfo.subactionPath = subactionPath; getInfo.subactionPath = subactionPath;
XrActionStateBoolean xrValue{ XR_TYPE_ACTION_STATE_BOOLEAN }; XrActionStateBoolean xrValue{ XR_TYPE_ACTION_STATE_BOOLEAN };
CHECK_XRCMD(xrGetActionStateBoolean(mXR->impl().mSession, &getInfo, &xrValue)); CHECK_XRCMD(xrGetActionStateBoolean(xr->impl().mSession, &getInfo, &xrValue));
if (xrValue.isActive) if (xrValue.isActive)
value = xrValue.currentState; value = xrValue.currentState;
@ -335,18 +335,20 @@ namespace MWVR
// Pose action only checks if the pose is active or not // Pose action only checks if the pose is active or not
bool OpenXRAction::getPose(XrPath subactionPath) bool OpenXRAction::getPose(XrPath subactionPath)
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO }; XrActionStateGetInfo getInfo{ XR_TYPE_ACTION_STATE_GET_INFO };
getInfo.action = mAction; getInfo.action = mAction;
getInfo.subactionPath = subactionPath; getInfo.subactionPath = subactionPath;
XrActionStatePose xrValue{ XR_TYPE_ACTION_STATE_POSE }; XrActionStatePose xrValue{ XR_TYPE_ACTION_STATE_POSE };
CHECK_XRCMD(xrGetActionStatePose(mXR->impl().mSession, &getInfo, &xrValue)); CHECK_XRCMD(xrGetActionStatePose(xr->impl().mSession, &getInfo, &xrValue));
return xrValue.isActive; return xrValue.isActive;
} }
bool OpenXRAction::applyHaptics(XrPath subactionPath, float amplitude) bool OpenXRAction::applyHaptics(XrPath subactionPath, float amplitude)
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrHapticVibration vibration{ XR_TYPE_HAPTIC_VIBRATION }; XrHapticVibration vibration{ XR_TYPE_HAPTIC_VIBRATION };
vibration.amplitude = amplitude; vibration.amplitude = amplitude;
vibration.duration = XR_MIN_HAPTIC_DURATION; vibration.duration = XR_MIN_HAPTIC_DURATION;
@ -355,7 +357,7 @@ namespace MWVR
XrHapticActionInfo hapticActionInfo{ XR_TYPE_HAPTIC_ACTION_INFO }; XrHapticActionInfo hapticActionInfo{ XR_TYPE_HAPTIC_ACTION_INFO };
hapticActionInfo.action = mAction; hapticActionInfo.action = mAction;
hapticActionInfo.subactionPath = subactionPath; hapticActionInfo.subactionPath = subactionPath;
CHECK_XRCMD(xrApplyHapticFeedback(mXR->impl().mSession, &hapticActionInfo, (XrHapticBaseHeader*)&vibration)); CHECK_XRCMD(xrApplyHapticFeedback(xr->impl().mSession, &hapticActionInfo, (XrHapticBaseHeader*)&vibration));
return true; return true;
} }
@ -408,23 +410,22 @@ namespace MWVR
OpenXRInput::generateControllerActionPaths( OpenXRInput::generateControllerActionPaths(
const std::string& controllerAction) const std::string& controllerAction)
{ {
auto* xr = OpenXREnvironment::get().getManager();
ControllerActionPaths actionPaths; ControllerActionPaths actionPaths;
std::string left = std::string("/user/hand/left") + controllerAction; std::string left = std::string("/user/hand/left") + controllerAction;
std::string right = std::string("/user/hand/right") + controllerAction; std::string right = std::string("/user/hand/right") + controllerAction;
std::string pad = std::string("/user/gamepad") + controllerAction; std::string pad = std::string("/user/gamepad") + controllerAction;
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, left.c_str(), &actionPaths[LEFT_HAND])); CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, left.c_str(), &actionPaths[LEFT_HAND]));
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, right.c_str(), &actionPaths[RIGHT_HAND])); CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, right.c_str(), &actionPaths[RIGHT_HAND]));
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, pad.c_str(), &actionPaths[GAMEPAD])); CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, pad.c_str(), &actionPaths[GAMEPAD]));
return actionPaths; return actionPaths;
} }
OpenXRInput::OpenXRInput( OpenXRInput::OpenXRInput()
osg::ref_ptr<OpenXRManager> XR) : mSubactionPath{ {
: mXR(XR)
, mSubactionPath{ {
generateXrPath("/user/hand/left"), generateXrPath("/user/hand/left"),
generateXrPath("/user/hand/right"), generateXrPath("/user/hand/right"),
generateXrPath("/user/gamepad"), generateXrPath("/user/gamepad"),
@ -468,10 +469,11 @@ namespace MWVR
, mHandPoseAction(std::move(createAction(XR_ACTION_TYPE_POSE_INPUT, "hand_pose", "Hand Pose", { LEFT_HAND, RIGHT_HAND }))) , mHandPoseAction(std::move(createAction(XR_ACTION_TYPE_POSE_INPUT, "hand_pose", "Hand Pose", { LEFT_HAND, RIGHT_HAND })))
, mHapticsAction(std::move(createAction(XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_hand", "Vibrate Hand", { LEFT_HAND, RIGHT_HAND }))) , mHapticsAction(std::move(createAction(XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_hand", "Vibrate Hand", { LEFT_HAND, RIGHT_HAND })))
{ {
auto* xr = OpenXREnvironment::get().getManager();
{ // Set up default bindings for the oculus { // Set up default bindings for the oculus
XrPath oculusTouchInteractionProfilePath; XrPath oculusTouchInteractionProfilePath;
CHECK_XRCMD( CHECK_XRCMD(
xrStringToPath(XR->impl().mInstance, "/interaction_profiles/oculus/touch_controller", &oculusTouchInteractionProfilePath)); xrStringToPath(xr->impl().mInstance, "/interaction_profiles/oculus/touch_controller", &oculusTouchInteractionProfilePath));
std::vector<XrActionSuggestedBinding> bindings{ { std::vector<XrActionSuggestedBinding> bindings{ {
{mHandPoseAction, mPosePath[LEFT_HAND]}, {mHandPoseAction, mPosePath[LEFT_HAND]},
{mHandPoseAction, mPosePath[RIGHT_HAND]}, {mHandPoseAction, mPosePath[RIGHT_HAND]},
@ -500,7 +502,7 @@ namespace MWVR
suggestedBindings.interactionProfile = oculusTouchInteractionProfilePath; suggestedBindings.interactionProfile = oculusTouchInteractionProfilePath;
suggestedBindings.suggestedBindings = bindings.data(); suggestedBindings.suggestedBindings = bindings.data();
suggestedBindings.countSuggestedBindings = (uint32_t)bindings.size(); suggestedBindings.countSuggestedBindings = (uint32_t)bindings.size();
CHECK_XRCMD(xrSuggestInteractionProfileBindings(XR->impl().mInstance, &suggestedBindings)); CHECK_XRCMD(xrSuggestInteractionProfileBindings(xr->impl().mInstance, &suggestedBindings));
/* /*
mSpellModifier; // L-Squeeze mSpellModifier; // L-Squeeze
@ -527,16 +529,16 @@ namespace MWVR
createInfo.action = mHandPoseAction; createInfo.action = mHandPoseAction;
createInfo.poseInActionSpace.orientation.w = 1.f; createInfo.poseInActionSpace.orientation.w = 1.f;
createInfo.subactionPath = mSubactionPath[LEFT_HAND]; createInfo.subactionPath = mSubactionPath[LEFT_HAND];
CHECK_XRCMD(xrCreateActionSpace(XR->impl().mSession, &createInfo, &mHandSpace[LEFT_HAND])); CHECK_XRCMD(xrCreateActionSpace(xr->impl().mSession, &createInfo, &mHandSpace[LEFT_HAND]));
createInfo.subactionPath = mSubactionPath[RIGHT_HAND]; createInfo.subactionPath = mSubactionPath[RIGHT_HAND];
CHECK_XRCMD(xrCreateActionSpace(XR->impl().mSession, &createInfo, &mHandSpace[RIGHT_HAND])); CHECK_XRCMD(xrCreateActionSpace(xr->impl().mSession, &createInfo, &mHandSpace[RIGHT_HAND]));
} }
{ // Set up the action set { // Set up the action set
XrSessionActionSetsAttachInfo attachInfo{ XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO }; XrSessionActionSetsAttachInfo attachInfo{ XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO };
attachInfo.countActionSets = 1; attachInfo.countActionSets = 1;
attachInfo.actionSets = &mActionSet; attachInfo.actionSets = &mActionSet;
CHECK_XRCMD(xrAttachSessionActionSets(XR->impl().mSession, &attachInfo)); CHECK_XRCMD(xrAttachSessionActionSets(xr->impl().mSession, &attachInfo));
} }
}; };
@ -563,7 +565,8 @@ namespace MWVR
XrAction action = XR_NULL_HANDLE; XrAction action = XR_NULL_HANDLE;
CHECK_XRCMD(xrCreateAction(mActionSet, &createInfo, &action)); CHECK_XRCMD(xrCreateAction(mActionSet, &createInfo, &action));
return OpenXRAction(mXR, action, actionType, actionName, localName);
return OpenXRAction(action, actionType, actionName, localName);
} }
XrPath XrPath
@ -578,7 +581,8 @@ namespace MWVR
void void
OpenXRInput::updateControls() OpenXRInput::updateControls()
{ {
if (!mXR->impl().mSessionRunning) auto* xr = OpenXREnvironment::get().getManager();
if (!xr->impl().mSessionRunning)
return; return;
@ -586,7 +590,7 @@ namespace MWVR
XrActionsSyncInfo syncInfo{ XR_TYPE_ACTIONS_SYNC_INFO }; XrActionsSyncInfo syncInfo{ XR_TYPE_ACTIONS_SYNC_INFO };
syncInfo.countActiveActionSets = 1; syncInfo.countActiveActionSets = 1;
syncInfo.activeActionSets = &activeActionSet; syncInfo.activeActionSets = &activeActionSet;
CHECK_XRCMD(xrSyncActions(mXR->impl().mSession, &syncInfo)); CHECK_XRCMD(xrSyncActions(xr->impl().mSession, &syncInfo));
mGameMenu.update(); mGameMenu.update();
mInventory.update(); mInventory.update();
@ -686,8 +690,9 @@ namespace MWVR
XrPath OpenXRInput::generateXrPath(const std::string& path) XrPath OpenXRInput::generateXrPath(const std::string& path)
{ {
auto* xr = OpenXREnvironment::get().getManager();
XrPath xrpath = 0; XrPath xrpath = 0;
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, path.c_str(), &xrpath)); CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, path.c_str(), &xrpath));
return xrpath; return xrpath;
} }
@ -709,12 +714,13 @@ namespace MWVR
int64_t time, int64_t time,
TrackedSpace space) TrackedSpace space)
{ {
auto* xr = OpenXREnvironment::get().getManager();
PoseSet handPoses{}; PoseSet handPoses{};
XrSpace referenceSpace = XR_NULL_HANDLE; XrSpace referenceSpace = XR_NULL_HANDLE;
if(space == TrackedSpace::STAGE) if(space == TrackedSpace::STAGE)
referenceSpace = mXR->impl().mReferenceSpaceStage; referenceSpace = xr->impl().mReferenceSpaceStage;
if(space == TrackedSpace::VIEW) if(space == TrackedSpace::VIEW)
referenceSpace = mXR->impl().mReferenceSpaceView; referenceSpace = xr->impl().mReferenceSpaceView;
XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION }; XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION };
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY }; XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
@ -750,7 +756,7 @@ namespace MWVR
OpenXRInputManager::OpenXRInputManager( OpenXRInputManager::OpenXRInputManager(
SDL_Window* window, SDL_Window* window,
osg::ref_ptr<OpenXRViewer> viewer, osg::ref_ptr<osgViewer::Viewer> viewer,
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler, osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation, osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
const std::string& userFile, const std::string& userFile,
@ -760,7 +766,7 @@ namespace MWVR
bool grab) bool grab)
: MWInput::InputManager( : MWInput::InputManager(
window, window,
viewer->mViewer, viewer,
screenCaptureHandler, screenCaptureHandler,
screenCaptureOperation, screenCaptureOperation,
userFile, userFile,
@ -768,7 +774,7 @@ namespace MWVR
userControllerBindingsFile, userControllerBindingsFile,
controllerBindingsFile, controllerBindingsFile,
grab) grab)
, mXRInput(new OpenXRInput(viewer->mXR)) , mXRInput(new OpenXRInput())
{ {
// VR mode has no concept of these // VR mode has no concept of these
mControlSwitch["vanitymode"] = false; mControlSwitch["vanitymode"] = false;
@ -793,11 +799,10 @@ namespace MWVR
bool disableControls, bool disableControls,
bool disableEvents) bool disableEvents)
{ {
auto* session = OpenXREnvironment::get().getSession();
mXRInput->updateControls(); mXRInput->updateControls();
auto* session = MWBase::Environment::get().getXRSession();
OpenXRActionEvent event{}; OpenXRActionEvent event{};
while (mXRInput->nextActionEvent(event)) while (mXRInput->nextActionEvent(event))
{ {
@ -814,6 +819,7 @@ namespace MWVR
void OpenXRInputManager::processEvent(const OpenXRActionEvent& event) void OpenXRInputManager::processEvent(const OpenXRActionEvent& event)
{ {
auto* session = OpenXREnvironment::get().getSession();
switch (event.action) switch (event.action)
{ {
case A_GameMenu: case A_GameMenu:
@ -821,7 +827,7 @@ namespace MWVR
toggleMainMenu(); toggleMainMenu();
// Explicitly request position update here so that the player can move the menu // Explicitly request position update here so that the player can move the menu
// using the menu key when the menu can't be toggled. // using the menu key when the menu can't be toggled.
MWBase::Environment::get().getXRSession()->updateMenuPosition(); session->updateMenuPosition();
break; break;
case A_Screenshot: case A_Screenshot:
screenshot(); screenshot();
@ -968,10 +974,11 @@ namespace MWVR
MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::World* world = MWBase::Environment::get().getWorld();
auto player = mPlayer->getPlayer(); auto player = mPlayer->getPlayer();
auto* session = MWBase::Environment::get().getXRSession(); auto* xr = OpenXREnvironment::get().getManager();
auto* session = OpenXREnvironment::get().getSession();
auto currentHeadPose = session->predictedPoses().head[(int)TrackedSpace::STAGE]; auto currentHeadPose = session->predictedPoses().head[(int)TrackedSpace::STAGE];
session->mXR->playerScale(currentHeadPose); xr->playerScale(currentHeadPose);
currentHeadPose.position *= session->unitsPerMeter(); currentHeadPose.position *= OpenXREnvironment::get().unitsPerMeter();
osg::Vec3 vrMovement = currentHeadPose.position - mPreviousHeadPose.position; osg::Vec3 vrMovement = currentHeadPose.position - mPreviousHeadPose.position;
mPreviousHeadPose = currentHeadPose; mPreviousHeadPose = currentHeadPose;
@ -994,13 +1001,10 @@ namespace MWVR
osg::Quat gameworldYaw = osg::Quat(mYaw, osg::Vec3(0, 0, -1)); osg::Quat gameworldYaw = osg::Quat(mYaw, osg::Vec3(0, 0, -1));
mHeadOffset += vrMovement; mHeadOffset += vrMovement;
Log(Debug::Verbose) << "Set head offset";
mVrAngles[0] = pitch; mVrAngles[0] = pitch;
mVrAngles[1] = roll; mVrAngles[1] = roll;
mVrAngles[2] = yaw; mVrAngles[2] = yaw;
world->rotateObject(player, mVrAngles[0], mVrAngles[1], mVrAngles[2], MWBase::RotationFlag_none); world->rotateObject(player, mVrAngles[0], mVrAngles[1], mVrAngles[2], MWBase::RotationFlag_none);
Log(Debug::Verbose) << "yaw=" << yaw << ", pitch=" << pitch << ", roll=" << roll;
MWBase::Environment::get().getWorld()->getRenderingManager().getCamera()->updateCamera(); MWBase::Environment::get().getWorld()->getRenderingManager().getCamera()->updateCamera();
} }

View file

@ -20,7 +20,7 @@ namespace MWVR
public: public:
OpenXRInputManager( OpenXRInputManager(
SDL_Window* window, SDL_Window* window,
osg::ref_ptr<OpenXRViewer> viewer, osg::ref_ptr<osgViewer::Viewer> viewer,
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler, osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation, osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
const std::string& userFile, bool userFileExists, const std::string& userFile, bool userFileExists,
@ -43,7 +43,6 @@ namespace MWVR
void showActivationIndication(bool show); void showActivationIndication(bool show);
osg::ref_ptr<OpenXRViewer> mXRViewer;
std::unique_ptr<OpenXRInput> mXRInput; std::unique_ptr<OpenXRInput> mXRInput;
Pose mPreviousHeadPose{}; Pose mPreviousHeadPose{};
osg::Vec3 mHeadOffset{ 0,0,0 }; osg::Vec3 mHeadOffset{ 0,0,0 };

View file

@ -1,3 +1,4 @@
#include "openxrenvironment.hpp"
#include "openxrmanager.hpp" #include "openxrmanager.hpp"
#include "openxrmanagerimpl.hpp" #include "openxrmanagerimpl.hpp"
#include "../mwinput/inputmanagerimp.hpp" #include "../mwinput/inputmanagerimp.hpp"
@ -198,13 +199,15 @@ namespace MWVR
OpenXRManager::RealizeOperation::operator()( OpenXRManager::RealizeOperation::operator()(
osg::GraphicsContext* gc) osg::GraphicsContext* gc)
{ {
mXR->realize(gc); auto* xr = OpenXREnvironment::get().getManager();
xr->realize(gc);
} }
bool bool
OpenXRManager::RealizeOperation::realized() OpenXRManager::RealizeOperation::realized()
{ {
return mXR->realized(); auto* xr = OpenXREnvironment::get().getManager();
return xr->realized();
} }
void void

View file

@ -85,22 +85,20 @@ namespace MWVR
class RealizeOperation : public osg::GraphicsOperation class RealizeOperation : public osg::GraphicsOperation
{ {
public: public:
RealizeOperation(osg::ref_ptr<OpenXRManager> XR) : osg::GraphicsOperation("OpenXRRealizeOperation", false), mXR(XR) {}; RealizeOperation() : osg::GraphicsOperation("OpenXRRealizeOperation", false){};
void operator()(osg::GraphicsContext* gc) override; void operator()(osg::GraphicsContext* gc) override;
virtual bool realized(); virtual bool realized();
private: private:
osg::ref_ptr<OpenXRManager> mXR;
}; };
class CleanupOperation : public osg::GraphicsOperation class CleanupOperation : public osg::GraphicsOperation
{ {
public: public:
CleanupOperation(osg::ref_ptr<OpenXRManager> XR) : osg::GraphicsOperation("OpenXRCleanupOperation", false), mXR(XR) {}; CleanupOperation() : osg::GraphicsOperation("OpenXRCleanupOperation", false) {};
void operator()(osg::GraphicsContext* gc) override; void operator()(osg::GraphicsContext* gc) override;
private: private:
osg::ref_ptr<OpenXRManager> mXR;
}; };
public: public:

View file

@ -97,4 +97,23 @@ namespace MWVR
{ {
// Doesn't need to do anything // Doesn't need to do anything
} }
OpenXRMenuManager::OpenXRMenuManager(
osg::ref_ptr<osgViewer::Viewer> viewer)
: mOsgViewer(viewer)
{
mMenusRoot->setName("XR Menus Root");
}
OpenXRMenuManager::~OpenXRMenuManager(void)
{
}
void OpenXRMenuManager::showMenus(bool show)
{
}
void OpenXRMenuManager::updatePose(Pose pose)
{
}
} }

View file

@ -42,6 +42,25 @@ namespace MWVR
osg::ref_ptr<osg::Geode> mGeode{ new osg::Geode }; osg::ref_ptr<osg::Geode> mGeode{ new osg::Geode };
osg::ref_ptr<osg::PositionAttitudeTransform> mTransform{ new osg::PositionAttitudeTransform() }; osg::ref_ptr<osg::PositionAttitudeTransform> mTransform{ new osg::PositionAttitudeTransform() };
}; };
class OpenXRMenuManager
{
public:
OpenXRMenuManager(
osg::ref_ptr<osgViewer::Viewer> viewer);
~OpenXRMenuManager(void);
void showMenus(bool show);
void updatePose(Pose pose);
private:
Pose pose{};
osg::ref_ptr<osgViewer::Viewer> mOsgViewer{ nullptr };
osg::ref_ptr<osg::Group> mMenusRoot{ new osg::Group };
std::unique_ptr<OpenXRMenu> mMenu{ nullptr };
};
} }
#endif #endif

View file

@ -1,3 +1,4 @@
#include "openxrenvironment.hpp"
#include "openxrmanager.hpp" #include "openxrmanager.hpp"
#include "openxrmanagerimpl.hpp" #include "openxrmanagerimpl.hpp"
#include "openxrinputmanager.hpp" #include "openxrinputmanager.hpp"
@ -26,11 +27,7 @@
namespace MWVR namespace MWVR
{ {
OpenXRSession::OpenXRSession( OpenXRSession::OpenXRSession()
osg::ref_ptr<OpenXRManager> XR,
float unitsPerMeter)
: mXR(XR)
, mUnitsPerMeter(unitsPerMeter)
{ {
} }
@ -48,8 +45,10 @@ namespace MWVR
void OpenXRSession::swapBuffers(osg::GraphicsContext* gc) void OpenXRSession::swapBuffers(osg::GraphicsContext* gc)
{ {
Timer timer("OpenXRSession::SwapBuffers"); Timer timer("OpenXRSession::SwapBuffers");
static int wat = 0;
if (!mXR->sessionRunning()) auto* xr = OpenXREnvironment::get().getManager();
if (!xr->sessionRunning())
return; return;
if (!mPredictionsReady) if (!mPredictionsReady)
return; return;
@ -60,17 +59,18 @@ namespace MWVR
timer.checkpoint("Rendered"); timer.checkpoint("Rendered");
mXR->endFrame(mXR->impl().frameState().predictedDisplayTime, &mLayerStack); xr->endFrame(xr->impl().frameState().predictedDisplayTime, &mLayerStack);
} }
void OpenXRSession::waitFrame() void OpenXRSession::waitFrame()
{ {
mXR->handleEvents(); auto* xr = OpenXREnvironment::get().getManager();
if (!mXR->sessionRunning()) xr->handleEvents();
if (!xr->sessionRunning())
return; return;
Timer timer("OpenXRSession::waitFrame"); Timer timer("OpenXRSession::waitFrame");
mXR->waitFrame(); xr->waitFrame();
timer.checkpoint("waitFrame"); timer.checkpoint("waitFrame");
predictNext(0); predictNext(0);
@ -152,26 +152,26 @@ namespace MWVR
void OpenXRSession::predictNext(int extraPeriods) void OpenXRSession::predictNext(int extraPeriods)
{ {
auto mPredictedDisplayTime = mXR->impl().frameState().predictedDisplayTime; auto* xr = OpenXREnvironment::get().getManager();
auto* input = OpenXREnvironment::get().getInputManager();
auto input = MWBase::Environment::get().getXRInputManager(); auto mPredictedDisplayTime = xr->impl().frameState().predictedDisplayTime;
auto previousHeadPose = mPredictedPoses.head[(int)TrackedSpace::STAGE]; auto previousHeadPose = mPredictedPoses.head[(int)TrackedSpace::STAGE];
// Update pose predictions // Update pose predictions
mPredictedPoses.head[(int)TrackedSpace::STAGE] = mXR->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::STAGE); mPredictedPoses.head[(int)TrackedSpace::STAGE] = xr->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::STAGE);
mPredictedPoses.head[(int)TrackedSpace::VIEW] = mXR->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::VIEW); mPredictedPoses.head[(int)TrackedSpace::VIEW] = xr->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::VIEW);
mPredictedPoses.hands[(int)TrackedSpace::STAGE] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE); mPredictedPoses.hands[(int)TrackedSpace::STAGE] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE);
mPredictedPoses.hands[(int)TrackedSpace::VIEW] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW); mPredictedPoses.hands[(int)TrackedSpace::VIEW] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW);
auto stageViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::STAGE); auto stageViews = xr->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::STAGE);
auto hmdViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::VIEW); auto hmdViews = xr->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::VIEW);
mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Side::LEFT_HAND] = fromXR(stageViews[(int)Side::LEFT_HAND].pose); mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Side::LEFT_HAND] = fromXR(stageViews[(int)Side::LEFT_HAND].pose);
mPredictedPoses.eye[(int)TrackedSpace::VIEW][(int)Side::LEFT_HAND] = fromXR(hmdViews[(int)Side::LEFT_HAND].pose); mPredictedPoses.eye[(int)TrackedSpace::VIEW][(int)Side::LEFT_HAND] = fromXR(hmdViews[(int)Side::LEFT_HAND].pose);
mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Side::RIGHT_HAND] = fromXR(stageViews[(int)Side::RIGHT_HAND].pose); mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Side::RIGHT_HAND] = fromXR(stageViews[(int)Side::RIGHT_HAND].pose);
mPredictedPoses.eye[(int)TrackedSpace::VIEW][(int)Side::RIGHT_HAND] = fromXR(hmdViews[(int)Side::RIGHT_HAND].pose); mPredictedPoses.eye[(int)TrackedSpace::VIEW][(int)Side::RIGHT_HAND] = fromXR(hmdViews[(int)Side::RIGHT_HAND].pose);
auto newpos = mPredictedPoses.head[(int)TrackedSpace::STAGE].position * mUnitsPerMeter; auto newpos = mPredictedPoses.head[(int)TrackedSpace::STAGE].position * OpenXREnvironment::get().unitsPerMeter();
auto oldpos = previousHeadPose.position * mUnitsPerMeter; auto oldpos = previousHeadPose.position * OpenXREnvironment::get().unitsPerMeter();
Log(Debug::Verbose) << "Head stage: " << newpos << ", diff=" << (newpos - oldpos); Log(Debug::Verbose) << "Head stage: " << newpos << ", diff=" << (newpos - oldpos);
} }

View file

@ -25,7 +25,7 @@ class OpenXRSession
using time_point = clock::time_point; using time_point = clock::time_point;
public: public:
OpenXRSession(osg::ref_ptr<OpenXRManager> XR, float unitsPerMeter); OpenXRSession();
~OpenXRSession(); ~OpenXRSession();
void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer); void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer);
@ -46,11 +46,7 @@ public:
//! Yaw angle to be used for offsetting movement direction //! Yaw angle to be used for offsetting movement direction
float movementYaw(void); float movementYaw(void);
float unitsPerMeter() const { return mUnitsPerMeter; };
osg::ref_ptr<OpenXRManager> mXR;
OpenXRLayerStack mLayerStack{}; OpenXRLayerStack mLayerStack{};
float mUnitsPerMeter = 1.f;
PoseSets mPredictedPoses{}; PoseSets mPredictedPoses{};
bool mPredictionsReady{ false }; bool mPredictionsReady{ false };

View file

@ -2,6 +2,7 @@
#include "openxrsession.hpp" #include "openxrsession.hpp"
#include "openxrmanagerimpl.hpp" #include "openxrmanagerimpl.hpp"
#include "openxrinputmanager.hpp" #include "openxrinputmanager.hpp"
#include "openxrenvironment.hpp"
#include "Windows.h" #include "Windows.h"
#include "../mwrender/vismask.hpp" #include "../mwrender/vismask.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -17,12 +18,10 @@ namespace MWVR
{ {
OpenXRViewer::OpenXRViewer( OpenXRViewer::OpenXRViewer(
osg::ref_ptr<OpenXRManager> XR,
osg::ref_ptr<osgViewer::Viewer> viewer) osg::ref_ptr<osgViewer::Viewer> viewer)
: osg::Group() : osg::Group()
, mXR(XR)
, mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW}) , mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW})
, mRealizeOperation(new RealizeOperation(XR, this)) , mRealizeOperation(new RealizeOperation())
, mViewer(viewer) , mViewer(viewer)
, mPreDraw(new PredrawCallback(this)) , mPreDraw(new PredrawCallback(this))
, mPostDraw(new PostdrawCallback(this)) , mPostDraw(new PostdrawCallback(this))
@ -42,10 +41,6 @@ namespace MWVR
mRightHandTransform->setName("tracker r hand"); mRightHandTransform->setName("tracker r hand");
mRightHandTransform->setUpdateCallback(new TrackedNodeUpdateCallback(this)); mRightHandTransform->setUpdateCallback(new TrackedNodeUpdateCallback(this));
this->addChild(mRightHandTransform); this->addChild(mRightHandTransform);
// TODO: Left off here
mMenusRoot = new osg::Group();
mMenusRoot->setName("XR Menus Root");
} }
OpenXRViewer::~OpenXRViewer(void) OpenXRViewer::~OpenXRViewer(void)
@ -69,7 +64,8 @@ namespace MWVR
void OpenXRViewer::traversals() void OpenXRViewer::traversals()
{ {
mXR->handleEvents(); auto* xr = OpenXREnvironment::get().getManager();
xr->handleEvents();
mViewer->updateTraversal(); mViewer->updateTraversal();
mViewer->renderingTraversals(); mViewer->renderingTraversals();
} }
@ -100,21 +96,23 @@ namespace MWVR
osg::Vec4 clearColor = mainCamera->getClearColor(); osg::Vec4 clearColor = mainCamera->getClearColor();
if (!mXR->realized()) auto* xr = OpenXREnvironment::get().getManager();
mXR->realize(context); if (!xr->realized())
auto* session = MWBase::Environment::get().getXRSession(); xr->realize(context);
auto* session = OpenXREnvironment::get().getSession();
OpenXRSwapchain::Config leftConfig; OpenXRSwapchain::Config leftConfig;
leftConfig.width = mXR->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedImageRectWidth; leftConfig.width = xr->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedImageRectWidth;
leftConfig.height = mXR->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedImageRectHeight; leftConfig.height = xr->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedImageRectHeight;
leftConfig.samples = mXR->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedSwapchainSampleCount; leftConfig.samples = xr->impl().mConfigViews[(int)Side::LEFT_HAND].recommendedSwapchainSampleCount;
OpenXRSwapchain::Config rightConfig; OpenXRSwapchain::Config rightConfig;
rightConfig.width = mXR->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedImageRectWidth; rightConfig.width = xr->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedImageRectWidth;
rightConfig.height = mXR->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedImageRectHeight; rightConfig.height = xr->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedImageRectHeight;
rightConfig.samples = mXR->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedSwapchainSampleCount; rightConfig.samples = xr->impl().mConfigViews[(int)Side::RIGHT_HAND].recommendedSwapchainSampleCount;
auto leftView = new OpenXRWorldView(mXR, "LeftEye", context->getState(), leftConfig, session->unitsPerMeter()); auto leftView = new OpenXRWorldView(xr, "LeftEye", context->getState(), leftConfig);
auto rightView = new OpenXRWorldView(mXR, "RightEye", context->getState(), rightConfig, session->unitsPerMeter()); auto rightView = new OpenXRWorldView(xr, "RightEye", context->getState(), rightConfig);
mViews["LeftEye"] = leftView; mViews["LeftEye"] = leftView;
mViews["RightEye"] = rightView; mViews["RightEye"] = rightView;
@ -153,9 +151,9 @@ namespace MWVR
// Mirror texture doesn't have to be an OpenXR swapchain. // Mirror texture doesn't have to be an OpenXR swapchain.
// It's just convenient. // It's just convenient.
mMirrorTextureSwapchain.reset(new OpenXRSwapchain(mXR, context->getState(), config)); mMirrorTextureSwapchain.reset(new OpenXRSwapchain(xr, context->getState(), config));
//auto menuView = new OpenXRMenu(mXR, config, context->getState(), "MainMenu", osg::Vec2(1.f, 1.f)); //auto menuView = new OpenXRMenu(xr, config, context->getState(), "MainMenu", osg::Vec2(1.f, 1.f));
//mViews["MenuView"] = menuView; //mViews["MenuView"] = menuView;
//auto menuCamera = mCameras["MenuView"] = menuView->createCamera(2, clearColor, context); //auto menuCamera = mCameras["MenuView"] = menuView->createCamera(2, clearColor, context);
@ -167,9 +165,10 @@ namespace MWVR
//menuCamera->setPostDrawCallback(mPostDraw); //menuCamera->setPostDrawCallback(mPostDraw);
//mViewer->addSlave(menuCamera, true); //mViewer->addSlave(menuCamera, true);
mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, leftView, context); mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(xr, session, leftView, context);
mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, rightView, context); mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(xr, session, rightView, context);
mainCamera->getGraphicsContext()->setSwapCallback(new OpenXRViewer::SwapBuffersCallback(this)); mainCamera->getGraphicsContext()->setSwapCallback(new OpenXRViewer::SwapBuffersCallback(this));
mainCamera->setGraphicsContext(nullptr); mainCamera->setGraphicsContext(nullptr);
@ -211,7 +210,8 @@ namespace MWVR
OpenXRViewer::SwapBuffersCallback::swapBuffersImplementation( OpenXRViewer::SwapBuffersCallback::swapBuffersImplementation(
osg::GraphicsContext* gc) osg::GraphicsContext* gc)
{ {
MWBase::Environment::get().getXRSession()->swapBuffers(gc); auto* session = OpenXREnvironment::get().getSession();
session->swapBuffers(gc);
} }
void OpenXRViewer::swapBuffers(osg::GraphicsContext* gc) void OpenXRViewer::swapBuffers(osg::GraphicsContext* gc)
@ -220,6 +220,9 @@ namespace MWVR
if (!mConfigured) if (!mConfigured)
return; return;
auto* session = OpenXREnvironment::get().getSession();
auto* xr = OpenXREnvironment::get().getManager();
Timer timer("OpenXRViewer::SwapBuffers"); Timer timer("OpenXRViewer::SwapBuffers");
auto leftView = mViews["LeftEye"]; auto leftView = mViews["LeftEye"];
@ -229,13 +232,13 @@ namespace MWVR
rightView->swapBuffers(gc); rightView->swapBuffers(gc);
timer.checkpoint("Views"); timer.checkpoint("Views");
mCompositionLayerProjectionViews[0].pose = toXR(MWBase::Environment::get().getXRSession()->predictedPoses().eye[(int)TrackedSpace::STAGE][(int)Side::LEFT_HAND]); mCompositionLayerProjectionViews[0].pose = toXR(session->predictedPoses().eye[(int)TrackedSpace::STAGE][(int)Side::LEFT_HAND]);
mCompositionLayerProjectionViews[1].pose = toXR(MWBase::Environment::get().getXRSession()->predictedPoses().eye[(int)TrackedSpace::STAGE][(int)Side::RIGHT_HAND]); mCompositionLayerProjectionViews[1].pose = toXR(session->predictedPoses().eye[(int)TrackedSpace::STAGE][(int)Side::RIGHT_HAND]);
timer.checkpoint("Poses"); timer.checkpoint("Poses");
// TODO: Keep track of these in the session too. // TODO: Keep track of these in the session too.
auto stageViews = mXR->impl().getPredictedViews(mXR->impl().frameState().predictedDisplayTime, TrackedSpace::STAGE); auto stageViews = xr->impl().getPredictedViews(xr->impl().frameState().predictedDisplayTime, TrackedSpace::STAGE);
mCompositionLayerProjectionViews[0].fov = stageViews[0].fov; mCompositionLayerProjectionViews[0].fov = stageViews[0].fov;
mCompositionLayerProjectionViews[1].fov = stageViews[1].fov; mCompositionLayerProjectionViews[1].fov = stageViews[1].fov;
timer.checkpoint("Fovs"); timer.checkpoint("Fovs");
@ -245,7 +248,7 @@ namespace MWVR
{ {
mLayer.reset(new XrCompositionLayerProjection); mLayer.reset(new XrCompositionLayerProjection);
mLayer->type = XR_TYPE_COMPOSITION_LAYER_PROJECTION; mLayer->type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
mLayer->space = mXR->impl().mReferenceSpaceStage; mLayer->space = xr->impl().mReferenceSpaceStage;
mLayer->viewCount = 2; mLayer->viewCount = 2;
mLayer->views = mCompositionLayerProjectionViews.data(); mLayer->views = mCompositionLayerProjectionViews.data();
} }
@ -260,13 +263,14 @@ namespace MWVR
osg::GraphicsContext* gc) osg::GraphicsContext* gc)
{ {
OpenXRManager::RealizeOperation::operator()(gc); OpenXRManager::RealizeOperation::operator()(gc);
mViewer->realize(gc);
OpenXREnvironment::get().getViewer()->realize(gc);
} }
bool bool
OpenXRViewer::RealizeOperation::realized() OpenXRViewer::RealizeOperation::realized()
{ {
return mViewer->realized(); return OpenXREnvironment::get().getViewer()->realized();
} }
void OpenXRViewer::preDrawCallback(osg::RenderInfo& info) void OpenXRViewer::preDrawCallback(osg::RenderInfo& info)
@ -277,10 +281,12 @@ namespace MWVR
if (name == "LeftEye") if (name == "LeftEye")
{ {
if (mXR->sessionRunning()) auto* xr = OpenXREnvironment::get().getManager();
auto* session = OpenXREnvironment::get().getSession();
if (xr->sessionRunning())
{ {
mXR->beginFrame(); xr->beginFrame();
auto& poses = MWBase::Environment::get().getXRSession()->predictedPoses(); auto& poses = session->predictedPoses();
//auto menuPose = poses.head[(int)TrackedSpace::STAGE]; //auto menuPose = poses.head[(int)TrackedSpace::STAGE];
//mViews["MenuView"]->setPredictedPose(menuPose); //mViews["MenuView"]->setPredictedPose(menuPose);
} }
@ -314,7 +320,8 @@ namespace MWVR
return; return;
} }
auto session = MWBase::Environment::get().getXRSession(); auto* xr = OpenXREnvironment::get().getManager();
auto* session = OpenXREnvironment::get().getSession();
auto& poses = session->predictedPoses(); auto& poses = session->predictedPoses();
auto handPosesStage = poses.hands[(int)TrackedSpace::STAGE]; auto handPosesStage = poses.hands[(int)TrackedSpace::STAGE];
int side = (int)Side::LEFT_HAND; int side = (int)Side::LEFT_HAND;
@ -325,18 +332,18 @@ namespace MWVR
MWVR::Pose handStage = handPosesStage[side]; MWVR::Pose handStage = handPosesStage[side];
MWVR::Pose headStage = poses.head[(int)TrackedSpace::STAGE]; MWVR::Pose headStage = poses.head[(int)TrackedSpace::STAGE];
mXR->playerScale(handStage); xr->playerScale(handStage);
mXR->playerScale(headStage); xr->playerScale(headStage);
auto orientation = handStage.orientation; auto orientation = handStage.orientation;
auto position = handStage.position - headStage.position; auto position = handStage.position - headStage.position;
position = position * session->unitsPerMeter(); position = position * OpenXREnvironment::get().unitsPerMeter();
auto camera = mViewer->getCamera(); auto camera = mViewer->getCamera();
auto viewMatrix = camera->getViewMatrix(); auto viewMatrix = camera->getViewMatrix();
// Align orientation with the game world // Align orientation with the game world
auto inputManager = MWBase::Environment::get().getXRInputManager(); auto* inputManager = OpenXREnvironment::get().getInputManager();
if (inputManager) if (inputManager)
{ {
auto playerYaw = osg::Quat(-inputManager->mYaw, osg::Vec3d(0, 0, 1)); auto playerYaw = osg::Quat(-inputManager->mYaw, osg::Vec3d(0, 0, 1));
@ -371,7 +378,7 @@ namespace MWVR
if (hand_transform->getName() == "tracker r hand") if (hand_transform->getName() == "tracker r hand")
offcenter.z() *= -1.; offcenter.z() *= -1.;
osg::Vec3 recenter = orientation * offcenter; osg::Vec3 recenter = orientation * offcenter;
position = position + recenter * session->unitsPerMeter(); position = position + recenter * OpenXREnvironment::get().unitsPerMeter();
hand_transform->setAttitude(orientation); hand_transform->setAttitude(orientation);
hand_transform->setPosition(position); hand_transform->setPosition(position);

View file

@ -25,12 +25,11 @@ namespace MWVR
class RealizeOperation : public OpenXRManager::RealizeOperation class RealizeOperation : public OpenXRManager::RealizeOperation
{ {
public: public:
RealizeOperation(osg::ref_ptr<OpenXRManager> XR, osg::ref_ptr<OpenXRViewer> viewer) : OpenXRManager::RealizeOperation(XR), mViewer(viewer) {}; RealizeOperation() {};
void operator()(osg::GraphicsContext* gc) override; void operator()(osg::GraphicsContext* gc) override;
bool realized() override; bool realized() override;
private: private:
osg::ref_ptr<OpenXRViewer> mViewer;
}; };
class SwapBuffersCallback : public osg::GraphicsContext::SwapCallback class SwapBuffersCallback : public osg::GraphicsContext::SwapCallback
@ -84,7 +83,6 @@ namespace MWVR
public: public:
OpenXRViewer( OpenXRViewer(
osg::ref_ptr<OpenXRManager> XR,
osg::ref_ptr<osgViewer::Viewer> viewer); osg::ref_ptr<osgViewer::Viewer> viewer);
~OpenXRViewer(void); ~OpenXRViewer(void);
@ -107,7 +105,6 @@ namespace MWVR
public: public:
osg::observer_ptr<OpenXRManager> mXR = nullptr;
std::unique_ptr<XrCompositionLayerProjection> mLayer = nullptr; std::unique_ptr<XrCompositionLayerProjection> mLayer = nullptr;
std::vector<XrCompositionLayerProjectionView> mCompositionLayerProjectionViews; std::vector<XrCompositionLayerProjectionView> mCompositionLayerProjectionViews;
osg::ref_ptr<OpenXRManager::RealizeOperation> mRealizeOperation = nullptr; osg::ref_ptr<OpenXRManager::RealizeOperation> mRealizeOperation = nullptr;
@ -126,9 +123,6 @@ namespace MWVR
std::mutex mMutex; std::mutex mMutex;
bool mConfigured{ false }; bool mConfigured{ false };
osg::ref_ptr<osg::Group> mMenusRoot{ new osg::Group };
std::unique_ptr<OpenXRMenu> mMenus{ nullptr };
}; };
} }

View file

@ -1,4 +1,5 @@
#include "openxrworldview.hpp" #include "openxrworldview.hpp"
#include "openxrenvironment.hpp"
#include "openxrmanager.hpp" #include "openxrmanager.hpp"
#include "openxrmanagerimpl.hpp" #include "openxrmanagerimpl.hpp"
#include "../mwinput/inputmanagerimp.hpp" #include "../mwinput/inputmanagerimp.hpp"
@ -99,7 +100,7 @@ namespace MWVR
{ {
MWVR::Pose pose = predictedPose(); MWVR::Pose pose = predictedPose();
mXR->playerScale(pose); mXR->playerScale(pose);
osg::Vec3 position = pose.position * mUnitsPerMeter; osg::Vec3 position = pose.position * OpenXREnvironment::get().unitsPerMeter();
osg::Quat orientation = pose.orientation; osg::Quat orientation = pose.orientation;
float y = position.y(); float y = position.y();
@ -123,10 +124,8 @@ namespace MWVR
osg::ref_ptr<OpenXRManager> XR, osg::ref_ptr<OpenXRManager> XR,
std::string name, std::string name,
osg::ref_ptr<osg::State> state, osg::ref_ptr<osg::State> state,
OpenXRSwapchain::Config config, OpenXRSwapchain::Config config)
float unitsPerMeter)
: OpenXRView(XR, name, config, state) : OpenXRView(XR, name, config, state)
, mUnitsPerMeter(unitsPerMeter)
{ {
} }
@ -167,7 +166,7 @@ namespace MWVR
// Updating the head pose needs to happen after waitFrame(), // Updating the head pose needs to happen after waitFrame(),
// But i can't call waitFrame from the input manager since it might // But i can't call waitFrame from the input manager since it might
// not always be active. // not always be active.
auto inputManager = MWBase::Environment::get().getXRInputManager(); auto* inputManager = OpenXREnvironment::get().getInputManager();
if (inputManager) if (inputManager)
inputManager->updateHead(); inputManager->updateHead();
@ -191,8 +190,5 @@ namespace MWVR
camera->setViewMatrix(modifiedViewMatrix); camera->setViewMatrix(modifiedViewMatrix);
camera->setProjectionMatrix(projectionMatrix); camera->setProjectionMatrix(projectionMatrix);
slave.updateSlaveImplementation(view); slave.updateSlaveImplementation(view);
} }
} }

View file

@ -26,15 +26,13 @@ namespace MWVR
}; };
public: public:
OpenXRWorldView(osg::ref_ptr<OpenXRManager> XR, std::string name, osg::ref_ptr<osg::State> state, OpenXRSwapchain::Config config, float unitsPerMeter); OpenXRWorldView(osg::ref_ptr<OpenXRManager> XR, std::string name, osg::ref_ptr<osg::State> state, OpenXRSwapchain::Config config);
~OpenXRWorldView(); ~OpenXRWorldView();
//! Projection offset for this view //! Projection offset for this view
osg::Matrix projectionMatrix(); osg::Matrix projectionMatrix();
//! View offset for this view //! View offset for this view
osg::Matrix viewMatrix(); osg::Matrix viewMatrix();
float mUnitsPerMeter = 1.f;
}; };
} }