mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 12:36:42 +00:00
Basic input management
This commit is contained in:
parent
49e0c6f17b
commit
da73df1707
15 changed files with 585 additions and 241 deletions
|
@ -59,6 +59,10 @@
|
||||||
|
|
||||||
#include "mwstate/statemanagerimp.hpp"
|
#include "mwstate/statemanagerimp.hpp"
|
||||||
|
|
||||||
|
#ifdef USE_OPENXR
|
||||||
|
#include "mwvr/openxrinputmanager.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void checkSDLError(int ret)
|
void checkSDLError(int ret)
|
||||||
|
@ -542,8 +546,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
gameControllerdb = globaldefault;
|
gameControllerdb = globaldefault;
|
||||||
else
|
else
|
||||||
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 = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
#ifdef USE_OPENXR
|
||||||
|
new MWVR::OpenXRInputManager(mWindow, mXRViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||||
|
#else
|
||||||
|
new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||||
|
#endif
|
||||||
mEnvironment.setInputManager (input);
|
mEnvironment.setInputManager (input);
|
||||||
|
|
||||||
std::string myguiResources = (mResDir / "mygui").string();
|
std::string myguiResources = (mResDir / "mygui").string();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
#include "mwbase/environment.hpp"
|
||||||
#include "mwvr/openxrmanager.hpp"
|
#include "mwvr/openxrmanager.hpp"
|
||||||
|
#include "mwvr/openxrsession.hpp"
|
||||||
|
|
||||||
#ifndef USE_OPENXR
|
#ifndef USE_OPENXR
|
||||||
#error "USE_OPENXR not defined"
|
#error "USE_OPENXR not defined"
|
||||||
|
@ -11,6 +13,7 @@ void OMW::Engine::initVr()
|
||||||
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();
|
mXR = new MWVR::OpenXRManager();
|
||||||
|
mEnvironment.setXRSession(new MWVR::OpenXRSession(mXR));
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
#include "statemanager.hpp"
|
#include "statemanager.hpp"
|
||||||
|
|
||||||
|
|
||||||
MWBase::Environment *MWBase::Environment::sThis = 0;
|
MWBase::Environment *MWBase::Environment::sThis = 0;
|
||||||
|
|
||||||
MWBase::Environment::Environment()
|
MWBase::Environment::Environment()
|
||||||
|
@ -198,3 +199,27 @@ const MWBase::Environment& MWBase::Environment::get()
|
||||||
assert (sThis);
|
assert (sThis);
|
||||||
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
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
#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;
|
||||||
|
@ -21,82 +29,94 @@ namespace MWBase
|
||||||
/// the set* functions.
|
/// the set* functions.
|
||||||
class Environment
|
class Environment
|
||||||
{
|
{
|
||||||
static Environment *sThis;
|
|
||||||
|
|
||||||
World *mWorld;
|
static Environment *sThis;
|
||||||
SoundManager *mSoundManager;
|
|
||||||
ScriptManager *mScriptManager;
|
|
||||||
WindowManager *mWindowManager;
|
|
||||||
MechanicsManager *mMechanicsManager;
|
|
||||||
DialogueManager *mDialogueManager;
|
|
||||||
Journal *mJournal;
|
|
||||||
InputManager *mInputManager;
|
|
||||||
StateManager *mStateManager;
|
|
||||||
float mFrameDuration;
|
|
||||||
float mFrameRateLimit;
|
|
||||||
|
|
||||||
Environment (const Environment&);
|
World *mWorld;
|
||||||
///< not implemented
|
SoundManager *mSoundManager;
|
||||||
|
ScriptManager *mScriptManager;
|
||||||
|
WindowManager *mWindowManager;
|
||||||
|
MechanicsManager *mMechanicsManager;
|
||||||
|
DialogueManager *mDialogueManager;
|
||||||
|
Journal *mJournal;
|
||||||
|
InputManager *mInputManager;
|
||||||
|
StateManager *mStateManager;
|
||||||
|
float mFrameDuration;
|
||||||
|
float mFrameRateLimit;
|
||||||
|
|
||||||
Environment& operator= (const Environment&);
|
Environment (const Environment&);
|
||||||
///< not implemented
|
///< not implemented
|
||||||
|
|
||||||
public:
|
Environment& operator= (const Environment&);
|
||||||
|
///< not implemented
|
||||||
|
|
||||||
Environment();
|
public:
|
||||||
|
|
||||||
~Environment();
|
Environment();
|
||||||
|
|
||||||
void setWorld (World *world);
|
~Environment();
|
||||||
|
|
||||||
void setSoundManager (SoundManager *soundManager);
|
void setWorld (World *world);
|
||||||
|
|
||||||
void setScriptManager (MWBase::ScriptManager *scriptManager);
|
void setSoundManager (SoundManager *soundManager);
|
||||||
|
|
||||||
void setWindowManager (WindowManager *windowManager);
|
void setScriptManager (MWBase::ScriptManager *scriptManager);
|
||||||
|
|
||||||
void setMechanicsManager (MechanicsManager *mechanicsManager);
|
void setWindowManager (WindowManager *windowManager);
|
||||||
|
|
||||||
void setDialogueManager (DialogueManager *dialogueManager);
|
void setMechanicsManager (MechanicsManager *mechanicsManager);
|
||||||
|
|
||||||
void setJournal (Journal *journal);
|
void setDialogueManager (DialogueManager *dialogueManager);
|
||||||
|
|
||||||
void setInputManager (InputManager *inputManager);
|
void setJournal (Journal *journal);
|
||||||
|
|
||||||
void setStateManager (StateManager *stateManager);
|
void setInputManager (InputManager *inputManager);
|
||||||
|
|
||||||
void setFrameDuration (float duration);
|
void setStateManager (StateManager *stateManager);
|
||||||
///< Set length of current frame in seconds.
|
|
||||||
|
|
||||||
void setFrameRateLimit(float frameRateLimit);
|
void setFrameDuration (float duration);
|
||||||
float getFrameRateLimit() const;
|
///< Set length of current frame in seconds.
|
||||||
void limitFrameRate(double dt) const;
|
|
||||||
|
|
||||||
World *getWorld() const;
|
void setFrameRateLimit(float frameRateLimit);
|
||||||
|
float getFrameRateLimit() const;
|
||||||
|
void limitFrameRate(double dt) const;
|
||||||
|
|
||||||
SoundManager *getSoundManager() const;
|
World *getWorld() const;
|
||||||
|
|
||||||
ScriptManager *getScriptManager() const;
|
SoundManager *getSoundManager() const;
|
||||||
|
|
||||||
WindowManager *getWindowManager() const;
|
ScriptManager *getScriptManager() const;
|
||||||
|
|
||||||
MechanicsManager *getMechanicsManager() const;
|
WindowManager *getWindowManager() const;
|
||||||
|
|
||||||
DialogueManager *getDialogueManager() const;
|
MechanicsManager *getMechanicsManager() const;
|
||||||
|
|
||||||
Journal *getJournal() const;
|
DialogueManager *getDialogueManager() const;
|
||||||
|
|
||||||
InputManager *getInputManager() const;
|
Journal *getJournal() const;
|
||||||
|
|
||||||
StateManager *getStateManager() const;
|
InputManager* getInputManager() const;
|
||||||
|
|
||||||
float getFrameDuration() const;
|
|
||||||
|
|
||||||
void cleanup();
|
StateManager *getStateManager() const;
|
||||||
///< Delete all mw*-subsystems.
|
|
||||||
|
|
||||||
static const Environment& get();
|
float getFrameDuration() const;
|
||||||
///< Return instance of this class.
|
|
||||||
|
void cleanup();
|
||||||
|
///< Delete all mw*-subsystems.
|
||||||
|
|
||||||
|
static const Environment& get();
|
||||||
|
///< 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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ namespace MWInput
|
||||||
|
|
||||||
// Open all presently connected sticks
|
// Open all presently connected sticks
|
||||||
int numSticks = SDL_NumJoysticks();
|
int numSticks = SDL_NumJoysticks();
|
||||||
|
Log(Debug::Info) << "Detected " << numSticks << " joysticks";
|
||||||
for(int i = 0; i < numSticks; i++)
|
for(int i = 0; i < numSticks; i++)
|
||||||
{
|
{
|
||||||
if(SDL_IsGameController(i))
|
if(SDL_IsGameController(i))
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace MWInput
|
||||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
SDL_Window* mWindow;
|
SDL_Window* mWindow;
|
||||||
bool mWindowVisible;
|
bool mWindowVisible;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
|
@ -218,7 +218,7 @@ namespace MWInput
|
||||||
float mInvUiScalingFactor;
|
float mInvUiScalingFactor;
|
||||||
float mGamepadCursorSpeed;
|
float mGamepadCursorSpeed;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void convertMousePosForMyGUI(int& x, int& y);
|
void convertMousePosForMyGUI(int& x, int& y);
|
||||||
|
|
||||||
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
||||||
|
@ -239,7 +239,7 @@ namespace MWInput
|
||||||
|
|
||||||
bool checkAllowedToUseItems() const;
|
bool checkAllowedToUseItems() const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void toggleMainMenu();
|
void toggleMainMenu();
|
||||||
void toggleSpell();
|
void toggleSpell();
|
||||||
void toggleWeapon();
|
void toggleWeapon();
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#ifdef USE_OPENXR
|
||||||
|
#include "../mwvr/openxrsession.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "collisiontype.hpp"
|
#include "collisiontype.hpp"
|
||||||
#include "actor.hpp"
|
#include "actor.hpp"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
@ -271,14 +275,29 @@ namespace MWPhysics
|
||||||
|
|
||||||
static osg::Vec3f move(osg::Vec3f position, const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time,
|
static osg::Vec3f move(osg::Vec3f position, const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time,
|
||||||
bool isFlying, float waterlevel, float slowFall, const btCollisionWorld* collisionWorld,
|
bool isFlying, float waterlevel, float slowFall, const btCollisionWorld* collisionWorld,
|
||||||
std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker)
|
std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker, bool isPlayer)
|
||||||
{
|
{
|
||||||
const ESM::Position& refpos = ptr.getRefData().getPosition();
|
ESM::Position refpos = ptr.getRefData().getPosition();
|
||||||
// Early-out for totally static creatures
|
// Early-out for totally static creatures
|
||||||
// (Not sure if gravity should still apply?)
|
// (Not sure if gravity should still apply?)
|
||||||
if (!ptr.getClass().isMobile(ptr))
|
if (!ptr.getClass().isMobile(ptr))
|
||||||
return position;
|
return position;
|
||||||
|
|
||||||
|
// In VR, player should move according to current direction of
|
||||||
|
// a selected limb, rather than current orientation of camera.
|
||||||
|
#ifdef USE_OPENXR
|
||||||
|
if (isPlayer)
|
||||||
|
{
|
||||||
|
auto session = MWBase::Environment::get().getXRSession();
|
||||||
|
if (session)
|
||||||
|
{
|
||||||
|
float yaw = session->movementYaw();
|
||||||
|
refpos.rot[2] += yaw;
|
||||||
|
Log(Debug::Verbose) << "yaw = " << yaw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reset per-frame data
|
// Reset per-frame data
|
||||||
physicActor->setWalkingOnWater(false);
|
physicActor->setWalkingOnWater(false);
|
||||||
// Anything to collide with?
|
// Anything to collide with?
|
||||||
|
@ -1275,6 +1294,7 @@ namespace MWPhysics
|
||||||
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
||||||
for(;iter != mMovementQueue.end();++iter)
|
for(;iter != mMovementQueue.end();++iter)
|
||||||
{
|
{
|
||||||
|
bool isPlayer = iter->first == MWMechanics::getPlayer();
|
||||||
ActorMap::iterator foundActor = mActors.find(iter->first);
|
ActorMap::iterator foundActor = mActors.find(iter->first);
|
||||||
if (foundActor == mActors.end()) // actor was already removed from the scene
|
if (foundActor == mActors.end()) // actor was already removed from the scene
|
||||||
continue;
|
continue;
|
||||||
|
@ -1314,7 +1334,7 @@ namespace MWPhysics
|
||||||
for (int i=0; i<numSteps; ++i)
|
for (int i=0; i<numSteps; ++i)
|
||||||
{
|
{
|
||||||
position = MovementSolver::move(position, physicActor->getPtr(), physicActor, iter->second, mPhysicsDt,
|
position = MovementSolver::move(position, physicActor->getPtr(), physicActor, iter->second, mPhysicsDt,
|
||||||
flying, waterlevel, slowFall, mCollisionWorld, mStandingCollisions);
|
flying, waterlevel, slowFall, mCollisionWorld, mStandingCollisions, isPlayer);
|
||||||
if (position != physicActor->getPosition())
|
if (position != physicActor->getPosition())
|
||||||
positionChanged = true;
|
positionChanged = true;
|
||||||
physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct
|
physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct
|
||||||
|
|
|
@ -1,11 +1,34 @@
|
||||||
#include "openxrinputmanager.hpp"
|
#include "openxrinputmanager.hpp"
|
||||||
#include "openxrmanager.hpp"
|
#include "openxrmanager.hpp"
|
||||||
#include "openxrmanagerimpl.hpp"
|
#include "openxrmanagerimpl.hpp"
|
||||||
#include "../mwinput/inputmanagerimp.hpp"
|
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||||
|
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
#include <MyGUI_Widget.h>
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/sdlutil/sdlinputwrapper.hpp>
|
||||||
|
#include <components/sdlutil/sdlvideowrapper.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/controlsstate.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
|
@ -17,6 +40,13 @@
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
struct OpenXRActionEvent
|
||||||
|
{
|
||||||
|
MWInput::InputManager::Actions action;
|
||||||
|
bool onPress;
|
||||||
|
float value = 0.f;
|
||||||
|
};
|
||||||
|
|
||||||
struct OpenXRAction
|
struct OpenXRAction
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -86,7 +116,7 @@ namespace MWVR
|
||||||
float mValue = 0.f;
|
float mValue = 0.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OpenXRInputManagerImpl
|
struct OpenXRInput
|
||||||
{
|
{
|
||||||
using Actions = MWInput::InputManager::Actions;
|
using Actions = MWInput::InputManager::Actions;
|
||||||
|
|
||||||
|
@ -112,18 +142,16 @@ namespace MWVR
|
||||||
|
|
||||||
ControllerActionPaths generateControllerActionPaths(const std::string& controllerAction);
|
ControllerActionPaths generateControllerActionPaths(const std::string& controllerAction);
|
||||||
|
|
||||||
OpenXRInputManagerImpl(osg::ref_ptr<OpenXRManager> XR);
|
OpenXRInput(osg::ref_ptr<OpenXRManager> XR);
|
||||||
|
|
||||||
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 = {});
|
||||||
|
|
||||||
XrActionSet createActionSet(void);
|
XrActionSet createActionSet(void);
|
||||||
|
|
||||||
void updateHandTracking();
|
|
||||||
|
|
||||||
XrPath subactionPath(SubAction subAction);
|
XrPath subactionPath(SubAction subAction);
|
||||||
|
|
||||||
void updateControls();
|
void updateControls();
|
||||||
void updateHead();
|
bool nextActionEvent(OpenXRActionEvent& action);
|
||||||
PoseSet getHandPoses(int64_t time, TrackedSpace space);
|
PoseSet getHandPoses(int64_t time, TrackedSpace space);
|
||||||
|
|
||||||
osg::ref_ptr<OpenXRManager> mXR;
|
osg::ref_ptr<OpenXRManager> mXR;
|
||||||
|
@ -226,7 +254,7 @@ namespace MWVR
|
||||||
};
|
};
|
||||||
|
|
||||||
XrActionSet
|
XrActionSet
|
||||||
OpenXRInputManagerImpl::createActionSet()
|
OpenXRInput::createActionSet()
|
||||||
{
|
{
|
||||||
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 };
|
||||||
|
@ -353,8 +381,8 @@ namespace MWVR
|
||||||
mAction.getFloat(0, mValue);
|
mAction.getFloat(0, mValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRInputManagerImpl::ControllerActionPaths
|
OpenXRInput::ControllerActionPaths
|
||||||
OpenXRInputManagerImpl::generateControllerActionPaths(
|
OpenXRInput::generateControllerActionPaths(
|
||||||
const std::string& controllerAction)
|
const std::string& controllerAction)
|
||||||
{
|
{
|
||||||
ControllerActionPaths actionPaths;
|
ControllerActionPaths actionPaths;
|
||||||
|
@ -370,7 +398,7 @@ namespace MWVR
|
||||||
return actionPaths;
|
return actionPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRInputManagerImpl::OpenXRInputManagerImpl(
|
OpenXRInput::OpenXRInput(
|
||||||
osg::ref_ptr<OpenXRManager> XR)
|
osg::ref_ptr<OpenXRManager> XR)
|
||||||
: mXR(XR)
|
: mXR(XR)
|
||||||
, mSubactionPath{ {
|
, mSubactionPath{ {
|
||||||
|
@ -430,8 +458,8 @@ namespace MWVR
|
||||||
{mLookLeftRight, mThumbstickXPath[RIGHT_HAND]},
|
{mLookLeftRight, mThumbstickXPath[RIGHT_HAND]},
|
||||||
{mMoveLeftRight, mThumbstickXPath[LEFT_HAND]},
|
{mMoveLeftRight, mThumbstickXPath[LEFT_HAND]},
|
||||||
{mMoveForwardBackward, mThumbstickYPath[LEFT_HAND]},
|
{mMoveForwardBackward, mThumbstickYPath[LEFT_HAND]},
|
||||||
{mActivate, mSqueezeClickPath[RIGHT_HAND]},
|
{mActivate, mSqueezeValuePath[RIGHT_HAND]},
|
||||||
{mUse, mTriggerClickPath[RIGHT_HAND]},
|
{mUse, mTriggerValuePath[RIGHT_HAND]},
|
||||||
{mJump, mTriggerValuePath[LEFT_HAND]},
|
{mJump, mTriggerValuePath[LEFT_HAND]},
|
||||||
{mWeapon, mAPath[RIGHT_HAND]},
|
{mWeapon, mAPath[RIGHT_HAND]},
|
||||||
{mSpell, mAPath[RIGHT_HAND]},
|
{mSpell, mAPath[RIGHT_HAND]},
|
||||||
|
@ -442,7 +470,7 @@ namespace MWVR
|
||||||
{mSneak, mXPath[LEFT_HAND]},
|
{mSneak, mXPath[LEFT_HAND]},
|
||||||
{mInventory, mBPath[RIGHT_HAND]},
|
{mInventory, mBPath[RIGHT_HAND]},
|
||||||
{mQuickMenu, mYPath[LEFT_HAND]},
|
{mQuickMenu, mYPath[LEFT_HAND]},
|
||||||
{mSpellModifier, mSqueezeClickPath[LEFT_HAND]},
|
{mSpellModifier, mSqueezeValuePath[LEFT_HAND]},
|
||||||
{mGameMenu, mMenuClickPath[LEFT_HAND]},
|
{mGameMenu, mMenuClickPath[LEFT_HAND]},
|
||||||
} };
|
} };
|
||||||
XrInteractionProfileSuggestedBinding suggestedBindings{ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING };
|
XrInteractionProfileSuggestedBinding suggestedBindings{ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING };
|
||||||
|
@ -490,7 +518,7 @@ namespace MWVR
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenXRAction
|
OpenXRAction
|
||||||
OpenXRInputManagerImpl::createAction(
|
OpenXRInput::createAction(
|
||||||
XrActionType actionType,
|
XrActionType actionType,
|
||||||
const std::string& actionName,
|
const std::string& actionName,
|
||||||
const std::string& localName,
|
const std::string& localName,
|
||||||
|
@ -515,17 +543,8 @@ namespace MWVR
|
||||||
return OpenXRAction(mXR, action, actionType, actionName, localName);
|
return OpenXRAction(mXR, action, actionType, actionName, localName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
OpenXRInputManagerImpl::updateHandTracking()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
//for (auto hand : { LEFT_HAND, RIGHT_HAND }) {
|
|
||||||
// CHECK_XRCMD(xrLocateSpace(mHandSpace[hand], mXR->impl().mReferenceSpaceStage, mXR->impl().predictedDisplayTime(OpenXRFrameIndexer::instance().updateIndex()), &mHandSpaceLocation[hand]));
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
XrPath
|
XrPath
|
||||||
OpenXRInputManagerImpl::subactionPath(
|
OpenXRInput::subactionPath(
|
||||||
SubAction subAction)
|
SubAction subAction)
|
||||||
{
|
{
|
||||||
if (subAction == NONE)
|
if (subAction == NONE)
|
||||||
|
@ -534,7 +553,7 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OpenXRInputManagerImpl::updateControls()
|
OpenXRInput::updateControls()
|
||||||
{
|
{
|
||||||
if (!mXR->impl().mSessionRunning)
|
if (!mXR->impl().mSessionRunning)
|
||||||
return;
|
return;
|
||||||
|
@ -546,9 +565,24 @@ namespace MWVR
|
||||||
syncInfo.activeActionSets = &activeActionSet;
|
syncInfo.activeActionSets = &activeActionSet;
|
||||||
CHECK_XRCMD(xrSyncActions(mXR->impl().mSession, &syncInfo));
|
CHECK_XRCMD(xrSyncActions(mXR->impl().mSession, &syncInfo));
|
||||||
|
|
||||||
updateHead();
|
|
||||||
|
|
||||||
mGameMenu.update();
|
mGameMenu.update();
|
||||||
|
mInventory.update();
|
||||||
|
mActivate.update();
|
||||||
|
mUse.update();
|
||||||
|
mJump.update();
|
||||||
|
mWeapon.update();
|
||||||
|
mSpell.update();
|
||||||
|
mCycleSpellLeft.update();
|
||||||
|
mCycleSpellRight.update();
|
||||||
|
mCycleWeaponLeft.update();
|
||||||
|
mCycleWeaponRight.update();
|
||||||
|
mSneak.update();
|
||||||
|
mQuickMenu.update();
|
||||||
|
mLookLeftRight.update();
|
||||||
|
mMoveForwardBackward.update();
|
||||||
|
mMoveLeftRight.update();
|
||||||
|
mActionsMenu.update();
|
||||||
|
mSpellModifier.update();
|
||||||
|
|
||||||
// This set of actions only care about on-press
|
// This set of actions only care about on-press
|
||||||
if (mActionsMenu.actionOnPress())
|
if (mActionsMenu.actionOnPress())
|
||||||
|
@ -567,9 +601,9 @@ namespace MWVR
|
||||||
{
|
{
|
||||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Activate, true });
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Activate, true });
|
||||||
}
|
}
|
||||||
if (mUse.actionOnPress())
|
if (mUse.actionChanged())
|
||||||
{
|
{
|
||||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Use, true });
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Use, mUse.actionOnPress() });
|
||||||
}
|
}
|
||||||
if (mJump.actionOnPress())
|
if (mJump.actionOnPress())
|
||||||
{
|
{
|
||||||
|
@ -591,7 +625,7 @@ namespace MWVR
|
||||||
// Weapon/Spell actions
|
// Weapon/Spell actions
|
||||||
if (mWeapon.actionOnPress() && !mSpellModifier.actionIsPressed())
|
if (mWeapon.actionOnPress() && !mSpellModifier.actionIsPressed())
|
||||||
{
|
{
|
||||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Weapon, true });
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_ToggleWeapon, true });
|
||||||
}
|
}
|
||||||
if (mCycleWeaponLeft.actionOnPress() && !mSpellModifier.actionIsPressed())
|
if (mCycleWeaponLeft.actionOnPress() && !mSpellModifier.actionIsPressed())
|
||||||
{
|
{
|
||||||
|
@ -603,7 +637,7 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
if (mSpell.actionOnPress() && mSpellModifier.actionIsPressed())
|
if (mSpell.actionOnPress() && mSpellModifier.actionIsPressed())
|
||||||
{
|
{
|
||||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_Spell, true });
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_ToggleSpell, true });
|
||||||
}
|
}
|
||||||
if (mCycleSpellLeft.actionOnPress() && mSpellModifier.actionIsPressed())
|
if (mCycleSpellLeft.actionOnPress() && mSpellModifier.actionIsPressed())
|
||||||
{
|
{
|
||||||
|
@ -619,97 +653,33 @@ namespace MWVR
|
||||||
float moveLeftRight = mMoveLeftRight.value();
|
float moveLeftRight = mMoveLeftRight.value();
|
||||||
float moveForwardBackward = mMoveForwardBackward.value();
|
float moveForwardBackward = mMoveForwardBackward.value();
|
||||||
|
|
||||||
// Until i implement the rest
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_LookLeftRight, false, lookLeftRight });
|
||||||
(void)lookLeftRight;
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_MoveLeftRight, false, moveLeftRight });
|
||||||
(void)moveLeftRight;
|
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_MoveForwardBackward, false, moveForwardBackward });
|
||||||
(void)moveForwardBackward;
|
|
||||||
|
|
||||||
// TODO: Propagate movement to openmw
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRInputManagerImpl::updateHead()
|
XrPath OpenXRInput::generateXrPath(const std::string& path)
|
||||||
{
|
|
||||||
//auto location = mXR->getHeadLocation();
|
|
||||||
|
|
||||||
////std::stringstream ss;
|
|
||||||
////ss << "Head.pose=< position=<"
|
|
||||||
//// << location.pose.position.x << ", " << location.pose.position.y << ", " << location.pose.position.z << "> orientation=<"
|
|
||||||
//// << location.pose.orientation.x << ", " << location.pose.orientation.y << ", " << location.pose.orientation.z << ", " << location.pose.orientation.w << "> >";
|
|
||||||
////mOpenXRLogger.log(ss.str(), 5, "Tracking", "OpenXR");
|
|
||||||
|
|
||||||
//// To keep world movement from physical walking properly oriented, world position must be tracked in differentials from stage position, as orientation between
|
|
||||||
//// stage and world may differ.
|
|
||||||
//osg::Vec3f newHeadStagePosition{ location.pose.position.x, location.pose.position.y, location.pose.position.z };
|
|
||||||
//osg::Vec3f headStageMovement = newHeadStagePosition - mHeadStagePosition;
|
|
||||||
//osg::Vec3f headWorldMovement = yaw() * headStageMovement;
|
|
||||||
|
|
||||||
//// Update positions
|
|
||||||
//mHeadStagePosition = newHeadStagePosition;
|
|
||||||
//mHeadWorldPosition = mHeadWorldPosition + headWorldMovement;
|
|
||||||
|
|
||||||
//// Update orientations
|
|
||||||
//mHeadStageOrientation = osg::fromXR(location.pose.orientation);
|
|
||||||
//mHeadWorldOrientation = yaw() * mHeadStageOrientation;
|
|
||||||
|
|
||||||
//osg::Vec3f up(0.f, 1.f, 0.f);
|
|
||||||
//up = mHeadStageOrientation * up;
|
|
||||||
|
|
||||||
//mHeadUpward = (mHeadWorldOrientation * osg::Vec3f(0.f, 1.f, 0.f));
|
|
||||||
//mHeadUpward.normalize();
|
|
||||||
//mHeadForward = (mHeadWorldOrientation * osg::Vec3f(0.f, 0.f, -1.f));
|
|
||||||
//mHeadForwardmHeadForward.normalize();
|
|
||||||
//mHeadRightward = mHeadForward ^ mHeadUpward;
|
|
||||||
//mHeadRightward.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
XrPath OpenXRInputManagerImpl::generateXrPath(const std::string& path)
|
|
||||||
{
|
{
|
||||||
XrPath xrpath = 0;
|
XrPath xrpath = 0;
|
||||||
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, path.c_str(), &xrpath));
|
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, path.c_str(), &xrpath));
|
||||||
return xrpath;
|
return xrpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRInputManager::OpenXRInputManager(
|
bool OpenXRInput::nextActionEvent(OpenXRActionEvent& action)
|
||||||
osg::ref_ptr<OpenXRManager> XR)
|
|
||||||
: mPrivate(new OpenXRInputManagerImpl(XR))
|
|
||||||
{
|
{
|
||||||
|
action = {};
|
||||||
|
|
||||||
}
|
if (mActionEvents.empty())
|
||||||
|
|
||||||
OpenXRInputManager::~OpenXRInputManager()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenXRInputManager::updateControls()
|
|
||||||
{
|
|
||||||
impl().updateControls();
|
|
||||||
}
|
|
||||||
|
|
||||||
PoseSet
|
|
||||||
OpenXRInputManager::getHandPoses(
|
|
||||||
int64_t time,
|
|
||||||
TrackedSpace space)
|
|
||||||
{
|
|
||||||
|
|
||||||
return mPrivate->getHandPoses(time, space);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenXRInputManager::nextActionEvent(OpenXRActionEvent& action)
|
|
||||||
{
|
|
||||||
if (mPrivate->mActionEvents.empty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
action = mPrivate->mActionEvents.front();
|
action = mActionEvents.front();
|
||||||
mPrivate->mActionEvents.pop_front();
|
mActionEvents.pop_front();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PoseSet
|
PoseSet
|
||||||
OpenXRInputManagerImpl::getHandPoses(
|
OpenXRInput::getHandPoses(
|
||||||
int64_t time,
|
int64_t time,
|
||||||
TrackedSpace space)
|
TrackedSpace space)
|
||||||
{
|
{
|
||||||
|
@ -724,8 +694,7 @@ namespace MWVR
|
||||||
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
||||||
location.next = &velocity;
|
location.next = &velocity;
|
||||||
CHECK_XRCMD(xrLocateSpace(mHandSpace[(int)Chirality::LEFT_HAND], referenceSpace, time, &location));
|
CHECK_XRCMD(xrLocateSpace(mHandSpace[(int)Chirality::LEFT_HAND], referenceSpace, time, &location));
|
||||||
//if (!(velocity.velocityFlags & XR_SPACE_VELOCITY_LINEAR_VALID_BIT))
|
|
||||||
// Log(Debug::Warning) << "Unable to acquire linear velocity";
|
|
||||||
handPoses[(int)Chirality::LEFT_HAND] = MWVR::Pose{
|
handPoses[(int)Chirality::LEFT_HAND] = MWVR::Pose{
|
||||||
osg::fromXR(location.pose.position),
|
osg::fromXR(location.pose.position),
|
||||||
osg::fromXR(location.pose.orientation),
|
osg::fromXR(location.pose.orientation),
|
||||||
|
@ -741,4 +710,220 @@ namespace MWVR
|
||||||
|
|
||||||
return handPoses;
|
return handPoses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PoseSet OpenXRInputManager::getHandPoses(int64_t time, TrackedSpace space)
|
||||||
|
{
|
||||||
|
return mXRInput->getHandPoses(time, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenXRInputManager::OpenXRInputManager(
|
||||||
|
SDL_Window* window,
|
||||||
|
osg::ref_ptr<OpenXRViewer> viewer,
|
||||||
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
|
const std::string& userFile,
|
||||||
|
bool userFileExists,
|
||||||
|
const std::string& userControllerBindingsFile,
|
||||||
|
const std::string& controllerBindingsFile,
|
||||||
|
bool grab)
|
||||||
|
: MWInput::InputManager(
|
||||||
|
window,
|
||||||
|
viewer->mViewer,
|
||||||
|
screenCaptureHandler,
|
||||||
|
screenCaptureOperation,
|
||||||
|
userFile,
|
||||||
|
userFileExists,
|
||||||
|
userControllerBindingsFile,
|
||||||
|
controllerBindingsFile,
|
||||||
|
grab)
|
||||||
|
, mXRInput(new OpenXRInput(viewer->mXR))
|
||||||
|
{
|
||||||
|
// VR mode has no concept of these
|
||||||
|
mControlSwitch["vanitymode"] = false;
|
||||||
|
mGuiCursorEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenXRInputManager::~OpenXRInputManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRInputManager::changeInputMode(bool mode)
|
||||||
|
{
|
||||||
|
// VR mode has no concept of these
|
||||||
|
mGuiCursorEnabled = false;
|
||||||
|
MWInput::InputManager::changeInputMode(mode);
|
||||||
|
MWBase::Environment::get().getWindowManager()->showCrosshair(false);
|
||||||
|
MWBase::Environment::get().getWindowManager()->setCursorVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRInputManager::update(
|
||||||
|
float dt,
|
||||||
|
bool disableControls,
|
||||||
|
bool disableEvents)
|
||||||
|
{
|
||||||
|
|
||||||
|
mXRInput->updateControls();
|
||||||
|
|
||||||
|
auto* session = MWBase::Environment::get().getXRSession();
|
||||||
|
|
||||||
|
OpenXRActionEvent event{};
|
||||||
|
while (mXRInput->nextActionEvent(event))
|
||||||
|
{
|
||||||
|
//Log(Debug::Verbose) << "ActionEvent action=" << event.action << " onPress=" << event.onPress;
|
||||||
|
processEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWInput::InputManager::update(dt, disableControls, disableEvents);
|
||||||
|
|
||||||
|
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
session->showMenu(guiMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRInputManager::processEvent(const OpenXRActionEvent& event)
|
||||||
|
{
|
||||||
|
switch (event.action)
|
||||||
|
{
|
||||||
|
case A_GameMenu:
|
||||||
|
Log(Debug::Verbose) << "A_GameMenu";
|
||||||
|
toggleMainMenu();
|
||||||
|
// Explicitly request position update here so that the player can move the menu
|
||||||
|
// using the menu key when the menu can't be toggled.
|
||||||
|
MWBase::Environment::get().getXRSession()->updateMenuPosition();
|
||||||
|
break;
|
||||||
|
case A_Screenshot:
|
||||||
|
screenshot();
|
||||||
|
break;
|
||||||
|
case A_Inventory:
|
||||||
|
toggleInventory();
|
||||||
|
break;
|
||||||
|
case A_Console:
|
||||||
|
toggleConsole();
|
||||||
|
break;
|
||||||
|
case A_Activate:
|
||||||
|
resetIdleTime();
|
||||||
|
activate();
|
||||||
|
break;
|
||||||
|
// TODO: Movement
|
||||||
|
//case A_MoveLeft:
|
||||||
|
//case A_MoveRight:
|
||||||
|
//case A_MoveForward:
|
||||||
|
//case A_MoveBackward:
|
||||||
|
// handleGuiArrowKey(action);
|
||||||
|
// break;
|
||||||
|
case A_Journal:
|
||||||
|
toggleJournal();
|
||||||
|
break;
|
||||||
|
case A_AutoMove:
|
||||||
|
toggleAutoMove();
|
||||||
|
break;
|
||||||
|
case A_AlwaysRun:
|
||||||
|
toggleWalking();
|
||||||
|
break;
|
||||||
|
case A_ToggleWeapon:
|
||||||
|
toggleWeapon();
|
||||||
|
break;
|
||||||
|
case A_Rest:
|
||||||
|
rest();
|
||||||
|
break;
|
||||||
|
case A_ToggleSpell:
|
||||||
|
toggleSpell();
|
||||||
|
break;
|
||||||
|
case A_QuickKey1:
|
||||||
|
quickKey(1);
|
||||||
|
break;
|
||||||
|
case A_QuickKey2:
|
||||||
|
quickKey(2);
|
||||||
|
break;
|
||||||
|
case A_QuickKey3:
|
||||||
|
quickKey(3);
|
||||||
|
break;
|
||||||
|
case A_QuickKey4:
|
||||||
|
quickKey(4);
|
||||||
|
break;
|
||||||
|
case A_QuickKey5:
|
||||||
|
quickKey(5);
|
||||||
|
break;
|
||||||
|
case A_QuickKey6:
|
||||||
|
quickKey(6);
|
||||||
|
break;
|
||||||
|
case A_QuickKey7:
|
||||||
|
quickKey(7);
|
||||||
|
break;
|
||||||
|
case A_QuickKey8:
|
||||||
|
quickKey(8);
|
||||||
|
break;
|
||||||
|
case A_QuickKey9:
|
||||||
|
quickKey(9);
|
||||||
|
break;
|
||||||
|
case A_QuickKey10:
|
||||||
|
quickKey(10);
|
||||||
|
break;
|
||||||
|
case A_QuickKeysMenu:
|
||||||
|
showQuickKeysMenu();
|
||||||
|
break;
|
||||||
|
case A_ToggleHUD:
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleHud();
|
||||||
|
break;
|
||||||
|
case A_ToggleDebug:
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
|
||||||
|
break;
|
||||||
|
// Does not apply in VR
|
||||||
|
//case A_ZoomIn:
|
||||||
|
// if (mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"] && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
// MWBase::Environment::get().getWorld()->setCameraDistance(ZOOM_SCALE, true, true);
|
||||||
|
// break;
|
||||||
|
//case A_ZoomOut:
|
||||||
|
// if (mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"] && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
// MWBase::Environment::get().getWorld()->setCameraDistance(-ZOOM_SCALE, true, true);
|
||||||
|
// break;
|
||||||
|
case A_QuickSave:
|
||||||
|
quickSave();
|
||||||
|
break;
|
||||||
|
case A_QuickLoad:
|
||||||
|
quickLoad();
|
||||||
|
break;
|
||||||
|
case A_CycleSpellLeft:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
|
||||||
|
break;
|
||||||
|
case A_CycleSpellRight:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponLeft:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponRight:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
|
||||||
|
break;
|
||||||
|
case A_Sneak:
|
||||||
|
if (mSneakToggles)
|
||||||
|
{
|
||||||
|
toggleSneaking();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case A_LookLeftRight:
|
||||||
|
mInputBinder->getChannel(A_LookLeftRight)->setValue(event.value / 2.f + 0.5f);
|
||||||
|
break;
|
||||||
|
case A_MoveLeftRight:
|
||||||
|
mInputBinder->getChannel(A_MoveLeftRight)->setValue(event.value / 2.f + 0.5f);
|
||||||
|
break;
|
||||||
|
case A_MoveForwardBackward:
|
||||||
|
mInputBinder->getChannel(A_MoveForwardBackward)->setValue(-event.value / 2.f + 0.5f);
|
||||||
|
break;
|
||||||
|
case A_Jump:
|
||||||
|
mAttemptJump = true;
|
||||||
|
break;
|
||||||
|
case A_Use:
|
||||||
|
//MWMechanics::DrawState_ state = MWBase::Environment::get().getWorld()->getPlayer().getDrawState();
|
||||||
|
//mPlayer->setAttackingOrSpell(currentValue != 0 && state != MWMechanics::DrawState_Nothing);
|
||||||
|
mInputBinder->getChannel(A_Use)->setValue(event.onPress);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log(Debug::Warning) << "Unhandled XR action " << event.action;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef OPENXR_INPUT_MANAGER_HPP
|
#ifndef OPENXR_INPUT_MANAGER_HPP
|
||||||
#define OPENXR_INPUT_MANAGER_HPP
|
#define OPENXR_INPUT_MANAGER_HPP
|
||||||
|
|
||||||
#include "openxrmanager.hpp"
|
#include "openxrviewer.hpp"
|
||||||
#include "../mwinput/inputmanagerimp.hpp"
|
#include "../mwinput/inputmanagerimp.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -10,27 +10,37 @@
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
struct OpenXRActionEvent
|
struct OpenXRInput;
|
||||||
{
|
struct OpenXRActionEvent;
|
||||||
MWInput::InputManager::Actions action;
|
|
||||||
bool onPress;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OpenXRInputManagerImpl;
|
/// As far as I can tell, SDL does not support VR controllers.
|
||||||
struct OpenXRInputManager
|
/// So I subclass the input manager and insert VR controls.
|
||||||
|
class OpenXRInputManager : public MWInput::InputManager
|
||||||
{
|
{
|
||||||
OpenXRInputManager(osg::ref_ptr<OpenXRManager> XR);
|
public:
|
||||||
~OpenXRInputManager();
|
OpenXRInputManager(
|
||||||
|
SDL_Window* window,
|
||||||
|
osg::ref_ptr<OpenXRViewer> viewer,
|
||||||
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
|
const std::string& userFile, bool userFileExists,
|
||||||
|
const std::string& userControllerBindingsFile,
|
||||||
|
const std::string& controllerBindingsFile, bool grab);
|
||||||
|
|
||||||
void updateControls();
|
virtual ~OpenXRInputManager();
|
||||||
|
|
||||||
|
/// Overriden to always disallow mouselook and similar.
|
||||||
|
virtual void changeInputMode(bool guiMode);
|
||||||
|
|
||||||
|
/// Overriden to update XR inputs
|
||||||
|
virtual void update(float dt, bool disableControls = false, bool disableEvents = false);
|
||||||
|
|
||||||
|
void processEvent(const OpenXRActionEvent& event);
|
||||||
|
|
||||||
PoseSet getHandPoses(int64_t time, TrackedSpace space);
|
PoseSet getHandPoses(int64_t time, TrackedSpace space);
|
||||||
|
|
||||||
bool nextActionEvent(OpenXRActionEvent& action);
|
osg::ref_ptr<OpenXRViewer> mXRViewer;
|
||||||
|
std::unique_ptr<OpenXRInput> mXRInput;
|
||||||
OpenXRInputManagerImpl& impl() { return *mPrivate; }
|
|
||||||
|
|
||||||
std::unique_ptr<OpenXRInputManagerImpl> mPrivate;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ namespace MWVR
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||||
bool isMale = ref->mBase->isMale();
|
bool isMale = ref->mBase->isMale();
|
||||||
float charHeightFactor = isMale ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
|
float charHeightFactor = isMale ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
|
||||||
float charHeightBase = 1.9f;
|
float charHeightBase = 2.f;
|
||||||
float charHeight = charHeightBase * charHeightFactor;
|
float charHeight = charHeightBase * charHeightFactor;
|
||||||
// TODO: Player height should be configurable
|
// TODO: Player height should be configurable
|
||||||
// For now i'm just using my own
|
// For now i'm just using my own
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace MWVR
|
||||||
|
|
||||||
if (mPositionNeedsUpdate)
|
if (mPositionNeedsUpdate)
|
||||||
{
|
{
|
||||||
// Menus are position one meter in front of the player, facing the player.
|
// I position menus half a meter in front of the player, facing the player.
|
||||||
mPose = predictedPose();
|
mPose = predictedPose();
|
||||||
mPose.position += mPose.orientation * osg::Vec3(0, 0, -1);
|
mPose.position += mPose.orientation * osg::Vec3(0, 0, -0.5);
|
||||||
mPose.orientation = -mPose.orientation;
|
mPose.orientation = -mPose.orientation;
|
||||||
|
|
||||||
Log(Debug::Verbose) << "Menu pose updated to: " << mPose;
|
Log(Debug::Verbose) << "Menu pose updated to: " << mPose;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "openxrmanager.hpp"
|
#include "openxrmanager.hpp"
|
||||||
#include "openxrmanagerimpl.hpp"
|
#include "openxrmanagerimpl.hpp"
|
||||||
|
#include "openxrinputmanager.hpp"
|
||||||
#include "openxrswapchain.hpp"
|
#include "openxrswapchain.hpp"
|
||||||
#include "../mwinput/inputmanagerimp.hpp"
|
#include "../mwinput/inputmanagerimp.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||||
|
@ -27,7 +29,7 @@ namespace MWVR
|
||||||
OpenXRSession::OpenXRSession(
|
OpenXRSession::OpenXRSession(
|
||||||
osg::ref_ptr<OpenXRManager> XR)
|
osg::ref_ptr<OpenXRManager> XR)
|
||||||
: mXR(XR)
|
: mXR(XR)
|
||||||
, mInputManager(new OpenXRInputManager(mXR))
|
// , mInputManager(new OpenXRInput(mXR))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,39 +73,108 @@ namespace MWVR
|
||||||
Timer timer("OpenXRSession::waitFrame");
|
Timer timer("OpenXRSession::waitFrame");
|
||||||
mXR->waitFrame();
|
mXR->waitFrame();
|
||||||
timer.checkpoint("waitFrame");
|
timer.checkpoint("waitFrame");
|
||||||
mInputManager->updateControls();
|
// mInputManager->updateControls();
|
||||||
predictNext(0);
|
predictNext(0);
|
||||||
|
|
||||||
OpenXRActionEvent event{};
|
//OpenXRActionEvent event{};
|
||||||
while (mInputManager->nextActionEvent(event))
|
//while (mInputManager->nextActionEvent(event))
|
||||||
{
|
//{
|
||||||
Log(Debug::Verbose) << "ActionEvent action=" << event.action << " onPress=" << event.onPress;
|
// Log(Debug::Verbose) << "ActionEvent action=" << event.action << " onPress=" << event.onPress;
|
||||||
if (event.action == MWInput::InputManager::A_GameMenu)
|
// if (event.action == MWInput::InputManager::A_GameMenu)
|
||||||
{
|
// {
|
||||||
Log(Debug::Verbose) << "A_GameMenu";
|
// Log(Debug::Verbose) << "A_GameMenu";
|
||||||
auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
// auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
||||||
if (menuLayer)
|
// if (menuLayer)
|
||||||
{
|
// {
|
||||||
menuLayer->setVisible(!menuLayer->isVisible());
|
// menuLayer->setVisible(!menuLayer->isVisible());
|
||||||
menuLayer->updatePosition();
|
// menuLayer->updatePosition();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
mPredictionsReady = true;
|
mPredictionsReady = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenXRSession::showMenu(bool show)
|
||||||
|
{
|
||||||
|
auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
||||||
|
if (menuLayer)
|
||||||
|
{
|
||||||
|
bool change = show != menuLayer->isVisible();
|
||||||
|
menuLayer->setVisible(show);
|
||||||
|
|
||||||
|
// Automatically update position of menu whenever the menu opens.
|
||||||
|
// This ensures menus are always opened near the player.
|
||||||
|
if(change)
|
||||||
|
menuLayer->updatePosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRSession::updateMenuPosition(void)
|
||||||
|
{
|
||||||
|
auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
||||||
|
if (menuLayer)
|
||||||
|
{
|
||||||
|
menuLayer->updatePosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// OSG doesn't provide API to extract yaw from a quat, but i need it.
|
||||||
|
// Credits goes to Dennis Bunfield, i just copied his formula https://narkive.com/v0re6547.4
|
||||||
|
static float getYaw(const osg::Quat& quat)
|
||||||
|
{
|
||||||
|
osg::Matrixd m2(osg::Matrixd::rotate(quat));
|
||||||
|
double* mat = (double*)m2.ptr();
|
||||||
|
double angle_x = 0.0;
|
||||||
|
double angle_y = 0.0;
|
||||||
|
double angle_z = 0.0;
|
||||||
|
double D, C, tr_x, tr_y;
|
||||||
|
angle_y = D = asin(mat[2]); /* Calculate Y-axis angle */
|
||||||
|
C = cos(angle_y);
|
||||||
|
if (fabs(C) > 0.005) /* Test for Gimball lock? */
|
||||||
|
{
|
||||||
|
tr_x = mat[10] / C; /* No, so get X-axis angle */
|
||||||
|
tr_y = -mat[6] / C;
|
||||||
|
angle_x = atan2(tr_y, tr_x);
|
||||||
|
tr_x = mat[0] / C; /* Get Z-axis angle */
|
||||||
|
tr_y = -mat[1] / C;
|
||||||
|
angle_z = atan2(tr_y, tr_x);
|
||||||
|
}
|
||||||
|
else /* Gimball lock has occurred */
|
||||||
|
{
|
||||||
|
angle_x = 0; /* Set X-axis angle to zero
|
||||||
|
*/
|
||||||
|
tr_x = mat[5]; /* And calculate Z-axis angle
|
||||||
|
*/
|
||||||
|
tr_y = mat[4];
|
||||||
|
angle_z = atan2(tr_y, tr_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return angle_z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float OpenXRSession::movementYaw(void)
|
||||||
|
{
|
||||||
|
osg::Matrix lookAt;
|
||||||
|
lookAt.makeLookAt(osg::Vec3(0, 0, 0), osg::Vec3(0, 1, 0), osg::Vec3(0, 0, 1));
|
||||||
|
lookAt = osg::Matrix::inverse(lookAt);
|
||||||
|
auto lhandquat = predictedPoses().hands[(int)MWVR::TrackedSpace::STAGE][(int)MWVR::Chirality::LEFT_HAND].orientation * lookAt.getRotate();
|
||||||
|
return getYaw(lhandquat);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenXRSession::predictNext(int extraPeriods)
|
void OpenXRSession::predictNext(int extraPeriods)
|
||||||
{
|
{
|
||||||
auto mPredictedDisplayTime = mXR->impl().frameState().predictedDisplayTime;
|
auto mPredictedDisplayTime = mXR->impl().frameState().predictedDisplayTime;
|
||||||
|
|
||||||
|
auto input = MWBase::Environment::get().getXRInputManager();
|
||||||
|
|
||||||
// Update pose predictions
|
// Update pose predictions
|
||||||
mPredictedPoses.head[(int)TrackedSpace::STAGE] = mXR->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::STAGE);
|
mPredictedPoses.head[(int)TrackedSpace::STAGE] = mXR->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] = mXR->impl().getPredictedLimbPose(mPredictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::VIEW);
|
||||||
mPredictedPoses.hands[(int)TrackedSpace::STAGE] = mInputManager->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE);
|
mPredictedPoses.hands[(int)TrackedSpace::STAGE] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE);
|
||||||
mPredictedPoses.hands[(int)TrackedSpace::VIEW] = mInputManager->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW);
|
mPredictedPoses.hands[(int)TrackedSpace::VIEW] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW);
|
||||||
auto stageViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::STAGE);
|
auto stageViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::STAGE);
|
||||||
auto hmdViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::VIEW);
|
auto hmdViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::VIEW);
|
||||||
mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Chirality::LEFT_HAND] = fromXR(stageViews[(int)Chirality::LEFT_HAND].pose);
|
mPredictedPoses.eye[(int)TrackedSpace::STAGE][(int)Chirality::LEFT_HAND] = fromXR(stageViews[(int)Chirality::LEFT_HAND].pose);
|
||||||
|
|
|
@ -11,42 +11,46 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include "openxrmanager.hpp"
|
#include "openxrmanager.hpp"
|
||||||
#include "openxrlayer.hpp"
|
#include "openxrlayer.hpp"
|
||||||
#include "openxrinputmanager.hpp"
|
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class OpenXRSession
|
||||||
|
{
|
||||||
|
using seconds = std::chrono::duration<double>;
|
||||||
|
using nanoseconds = std::chrono::nanoseconds;
|
||||||
|
using clock = std::chrono::steady_clock;
|
||||||
|
using time_point = clock::time_point;
|
||||||
|
|
||||||
class OpenXRSession
|
public:
|
||||||
{
|
OpenXRSession(osg::ref_ptr<OpenXRManager> XR);
|
||||||
using seconds = std::chrono::duration<double>;
|
~OpenXRSession();
|
||||||
using nanoseconds = std::chrono::nanoseconds;
|
|
||||||
using clock = std::chrono::steady_clock;
|
|
||||||
using time_point = clock::time_point;
|
|
||||||
|
|
||||||
public:
|
void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer);
|
||||||
OpenXRSession(osg::ref_ptr<OpenXRManager> XR);
|
void swapBuffers(osg::GraphicsContext* gc);
|
||||||
~OpenXRSession();
|
|
||||||
|
|
||||||
void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer);
|
PoseSets& predictedPoses() { return mPredictedPoses; };
|
||||||
void swapBuffers(osg::GraphicsContext* gc);
|
|
||||||
|
|
||||||
PoseSets& predictedPoses() { return mPredictedPoses; };
|
//! Call before updating poses and other inputs
|
||||||
|
void waitFrame();
|
||||||
|
|
||||||
//! Call before updating poses
|
//! Update predictions
|
||||||
void waitFrame();
|
void predictNext(int extraPeriods);
|
||||||
|
|
||||||
//! Update predictions
|
void showMenu(bool show);
|
||||||
void predictNext(int extraPeriods);
|
|
||||||
|
|
||||||
osg::ref_ptr<OpenXRManager> mXR;
|
void updateMenuPosition(void);
|
||||||
std::unique_ptr<OpenXRInputManager> mInputManager = nullptr;
|
|
||||||
OpenXRLayerStack mLayerStack{};
|
|
||||||
|
|
||||||
PoseSets mPredictedPoses{};
|
//! Yaw the movement if a tracking limb is configured
|
||||||
|
float movementYaw(void);
|
||||||
|
|
||||||
bool mPredictionsReady{ false };
|
osg::ref_ptr<OpenXRManager> mXR;
|
||||||
};
|
OpenXRLayerStack mLayerStack{};
|
||||||
|
|
||||||
|
PoseSets mPredictedPoses{};
|
||||||
|
|
||||||
|
bool mPredictionsReady{ false };
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "openxrviewer.hpp"
|
#include "openxrviewer.hpp"
|
||||||
|
#include "openxrsession.hpp"
|
||||||
#include "openxrmanagerimpl.hpp"
|
#include "openxrmanagerimpl.hpp"
|
||||||
#include "Windows.h"
|
#include "Windows.h"
|
||||||
#include "../mwrender/vismask.hpp"
|
#include "../mwrender/vismask.hpp"
|
||||||
|
@ -20,14 +21,13 @@ namespace MWVR
|
||||||
float metersPerUnit)
|
float metersPerUnit)
|
||||||
: osg::Group()
|
: osg::Group()
|
||||||
, mXR(XR)
|
, mXR(XR)
|
||||||
|
, mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW})
|
||||||
, mRealizeOperation(new RealizeOperation(XR, this))
|
, mRealizeOperation(new RealizeOperation(XR, this))
|
||||||
, mViewer(viewer)
|
, mViewer(viewer)
|
||||||
, mMetersPerUnit(metersPerUnit)
|
|
||||||
, mConfigured(false)
|
|
||||||
, mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW})
|
|
||||||
, mXRSession(nullptr)
|
|
||||||
, mPreDraw(new PredrawCallback(this))
|
, mPreDraw(new PredrawCallback(this))
|
||||||
, mPostDraw(new PostdrawCallback(this))
|
, mPostDraw(new PostdrawCallback(this))
|
||||||
|
, mMetersPerUnit(metersPerUnit)
|
||||||
|
, mConfigured(false)
|
||||||
{
|
{
|
||||||
mViewer->setRealizeOperation(mRealizeOperation);
|
mViewer->setRealizeOperation(mRealizeOperation);
|
||||||
mCompositionLayerProjectionViews[0].pose.orientation.w = 1;
|
mCompositionLayerProjectionViews[0].pose.orientation.w = 1;
|
||||||
|
@ -160,16 +160,16 @@ namespace MWVR
|
||||||
menuCamera->setPreDrawCallback(mPreDraw);
|
menuCamera->setPreDrawCallback(mPreDraw);
|
||||||
menuCamera->setPostDrawCallback(mPostDraw);
|
menuCamera->setPostDrawCallback(mPostDraw);
|
||||||
|
|
||||||
mViewer->addSlave(menuCamera, true);
|
auto* session = MWBase::Environment::get().getXRSession();
|
||||||
|
|
||||||
mXRSession.reset(new OpenXRSession(mXR));
|
mViewer->addSlave(menuCamera, true);
|
||||||
mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, mXRSession.get(), leftView, context);
|
mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, leftView, context);
|
||||||
mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, mXRSession.get(), rightView, context);
|
mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, rightView, context);
|
||||||
|
|
||||||
mainCamera->getGraphicsContext()->setSwapCallback(new OpenXRViewer::SwapBuffersCallback(this));
|
mainCamera->getGraphicsContext()->setSwapCallback(new OpenXRViewer::SwapBuffersCallback(this));
|
||||||
mainCamera->setGraphicsContext(nullptr);
|
mainCamera->setGraphicsContext(nullptr);
|
||||||
mXRSession->setLayer(OpenXRLayerStack::WORLD_VIEW_LAYER, this);
|
session->setLayer(OpenXRLayerStack::WORLD_VIEW_LAYER, this);
|
||||||
mXRSession->setLayer(OpenXRLayerStack::MENU_VIEW_LAYER, dynamic_cast<OpenXRLayer*>(mViews["MenuView"].get()));
|
session->setLayer(OpenXRLayerStack::MENU_VIEW_LAYER, dynamic_cast<OpenXRLayer*>(mViews["MenuView"].get()));
|
||||||
mConfigured = true;
|
mConfigured = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ namespace MWVR
|
||||||
OpenXRViewer::SwapBuffersCallback::swapBuffersImplementation(
|
OpenXRViewer::SwapBuffersCallback::swapBuffersImplementation(
|
||||||
osg::GraphicsContext* gc)
|
osg::GraphicsContext* gc)
|
||||||
{
|
{
|
||||||
mViewer->mXRSession->swapBuffers(gc);
|
MWBase::Environment::get().getXRSession()->swapBuffers(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRViewer::swapBuffers(osg::GraphicsContext* gc)
|
void OpenXRViewer::swapBuffers(osg::GraphicsContext* gc)
|
||||||
|
@ -220,7 +220,6 @@ namespace MWVR
|
||||||
mViews["RightEye"]->swapBuffers(gc);
|
mViews["RightEye"]->swapBuffers(gc);
|
||||||
timer.checkpoint("Views");
|
timer.checkpoint("Views");
|
||||||
|
|
||||||
auto eyePoses = mXRSession->predictedPoses().eye;
|
|
||||||
auto leftEyePose = toXR(mViews["LeftEye"]->predictedPose());
|
auto leftEyePose = toXR(mViews["LeftEye"]->predictedPose());
|
||||||
auto rightEyePose = toXR(mViews["RightEye"]->predictedPose());
|
auto rightEyePose = toXR(mViews["RightEye"]->predictedPose());
|
||||||
mCompositionLayerProjectionViews[0].pose = leftEyePose;
|
mCompositionLayerProjectionViews[0].pose = leftEyePose;
|
||||||
|
@ -273,7 +272,7 @@ namespace MWVR
|
||||||
if (mXR->sessionRunning())
|
if (mXR->sessionRunning())
|
||||||
{
|
{
|
||||||
mXR->beginFrame();
|
mXR->beginFrame();
|
||||||
auto& poses = mXRSession->predictedPoses();
|
auto& poses = MWBase::Environment::get().getXRSession()->predictedPoses();
|
||||||
auto menuPose = poses.head[(int)TrackedSpace::STAGE];
|
auto menuPose = poses.head[(int)TrackedSpace::STAGE];
|
||||||
mViews["MenuView"]->setPredictedPose(menuPose);
|
mViews["MenuView"]->setPredictedPose(menuPose);
|
||||||
}
|
}
|
||||||
|
@ -307,7 +306,7 @@ namespace MWVR
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& poses = mXRSession->predictedPoses();
|
auto& poses = MWBase::Environment::get().getXRSession()->predictedPoses();
|
||||||
auto handPosesView = poses.hands[(int)TrackedSpace::VIEW];
|
auto handPosesView = poses.hands[(int)TrackedSpace::VIEW];
|
||||||
auto handPosesStage = poses.hands[(int)TrackedSpace::STAGE];
|
auto handPosesStage = poses.hands[(int)TrackedSpace::STAGE];
|
||||||
int chirality = (int)Chirality::LEFT_HAND;
|
int chirality = (int)Chirality::LEFT_HAND;
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "openxrlayer.hpp"
|
#include "openxrlayer.hpp"
|
||||||
#include "openxrworldview.hpp"
|
#include "openxrworldview.hpp"
|
||||||
#include "openxrmenu.hpp"
|
#include "openxrmenu.hpp"
|
||||||
#include "openxrinputmanager.hpp"
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
|
||||||
struct XrCompositionLayerProjection;
|
struct XrCompositionLayerProjection;
|
||||||
|
@ -109,12 +108,11 @@ 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::observer_ptr<OpenXRManager> mXR = nullptr;
|
|
||||||
osg::ref_ptr<OpenXRManager::RealizeOperation> mRealizeOperation = nullptr;
|
osg::ref_ptr<OpenXRManager::RealizeOperation> mRealizeOperation = nullptr;
|
||||||
osg::observer_ptr<osgViewer::Viewer> mViewer = nullptr;
|
osg::ref_ptr<osgViewer::Viewer> mViewer = nullptr;
|
||||||
std::unique_ptr<OpenXRSession> mXRSession = nullptr;
|
|
||||||
std::map<std::string, osg::ref_ptr<OpenXRView> > mViews{};
|
std::map<std::string, osg::ref_ptr<OpenXRView> > mViews{};
|
||||||
std::map<std::string, osg::ref_ptr<osg::Camera> > mCameras{};
|
std::map<std::string, osg::ref_ptr<osg::Camera> > mCameras{};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue