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"
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
#include "mwvr/openxrinputmanager.hpp"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void checkSDLError(int ret)
|
||||
|
@ -542,8 +546,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
gameControllerdb = globaldefault;
|
||||
else
|
||||
gameControllerdb = ""; //if it doesn't exist, pass in an empty string
|
||||
|
||||
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||
MWInput::InputManager* input =
|
||||
#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);
|
||||
|
||||
std::string myguiResources = (mResDir / "mygui").string();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "engine.hpp"
|
||||
#include "mwbase/environment.hpp"
|
||||
#include "mwvr/openxrmanager.hpp"
|
||||
#include "mwvr/openxrsession.hpp"
|
||||
|
||||
#ifndef USE_OPENXR
|
||||
#error "USE_OPENXR not defined"
|
||||
|
@ -11,6 +13,7 @@ void OMW::Engine::initVr()
|
|||
throw std::logic_error("mViewer must be initialized before calling initVr()");
|
||||
|
||||
mXR = new MWVR::OpenXRManager();
|
||||
mEnvironment.setXRSession(new MWVR::OpenXRSession(mXR));
|
||||
|
||||
// Ref: https://wiki.openmw.org/index.php?title=Measurement_Units
|
||||
float unitsPerYard = 64.f;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "windowmanager.hpp"
|
||||
#include "statemanager.hpp"
|
||||
|
||||
|
||||
MWBase::Environment *MWBase::Environment::sThis = 0;
|
||||
|
||||
MWBase::Environment::Environment()
|
||||
|
@ -198,3 +199,27 @@ const MWBase::Environment& MWBase::Environment::get()
|
|||
assert (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
|
||||
#define GAME_BASE_ENVIRONMENT_H
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
namespace MWVR
|
||||
{
|
||||
class OpenXRInputManager;
|
||||
class OpenXRSession;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
class World;
|
||||
|
@ -21,82 +29,94 @@ namespace MWBase
|
|||
/// the set* functions.
|
||||
class Environment
|
||||
{
|
||||
static Environment *sThis;
|
||||
|
||||
World *mWorld;
|
||||
SoundManager *mSoundManager;
|
||||
ScriptManager *mScriptManager;
|
||||
WindowManager *mWindowManager;
|
||||
MechanicsManager *mMechanicsManager;
|
||||
DialogueManager *mDialogueManager;
|
||||
Journal *mJournal;
|
||||
InputManager *mInputManager;
|
||||
StateManager *mStateManager;
|
||||
float mFrameDuration;
|
||||
float mFrameRateLimit;
|
||||
static Environment *sThis;
|
||||
|
||||
Environment (const Environment&);
|
||||
///< not implemented
|
||||
World *mWorld;
|
||||
SoundManager *mSoundManager;
|
||||
ScriptManager *mScriptManager;
|
||||
WindowManager *mWindowManager;
|
||||
MechanicsManager *mMechanicsManager;
|
||||
DialogueManager *mDialogueManager;
|
||||
Journal *mJournal;
|
||||
InputManager *mInputManager;
|
||||
StateManager *mStateManager;
|
||||
float mFrameDuration;
|
||||
float mFrameRateLimit;
|
||||
|
||||
Environment& operator= (const Environment&);
|
||||
///< not implemented
|
||||
Environment (const Environment&);
|
||||
///< 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);
|
||||
///< Set length of current frame in seconds.
|
||||
void setStateManager (StateManager *stateManager);
|
||||
|
||||
void setFrameRateLimit(float frameRateLimit);
|
||||
float getFrameRateLimit() const;
|
||||
void limitFrameRate(double dt) const;
|
||||
void setFrameDuration (float duration);
|
||||
///< Set length of current frame in seconds.
|
||||
|
||||
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();
|
||||
///< Delete all mw*-subsystems.
|
||||
StateManager *getStateManager() const;
|
||||
|
||||
static const Environment& get();
|
||||
///< Return instance of this class.
|
||||
float getFrameDuration() const;
|
||||
|
||||
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
|
||||
int numSticks = SDL_NumJoysticks();
|
||||
Log(Debug::Info) << "Detected " << numSticks << " joysticks";
|
||||
for(int i = 0; i < numSticks; i++)
|
||||
{
|
||||
if(SDL_IsGameController(i))
|
||||
|
|
|
@ -161,7 +161,7 @@ namespace MWInput
|
|||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
private:
|
||||
protected:
|
||||
SDL_Window* mWindow;
|
||||
bool mWindowVisible;
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
|
@ -218,7 +218,7 @@ namespace MWInput
|
|||
float mInvUiScalingFactor;
|
||||
float mGamepadCursorSpeed;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void convertMousePosForMyGUI(int& x, int& y);
|
||||
|
||||
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
||||
|
@ -239,7 +239,7 @@ namespace MWInput
|
|||
|
||||
bool checkAllowedToUseItems() const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void toggleMainMenu();
|
||||
void toggleSpell();
|
||||
void toggleWeapon();
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#ifdef USE_OPENXR
|
||||
#include "../mwvr/openxrsession.hpp"
|
||||
#endif
|
||||
|
||||
#include "collisiontype.hpp"
|
||||
#include "actor.hpp"
|
||||
#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,
|
||||
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
|
||||
// (Not sure if gravity should still apply?)
|
||||
if (!ptr.getClass().isMobile(ptr))
|
||||
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
|
||||
physicActor->setWalkingOnWater(false);
|
||||
// Anything to collide with?
|
||||
|
@ -1275,6 +1294,7 @@ namespace MWPhysics
|
|||
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
||||
for(;iter != mMovementQueue.end();++iter)
|
||||
{
|
||||
bool isPlayer = iter->first == MWMechanics::getPlayer();
|
||||
ActorMap::iterator foundActor = mActors.find(iter->first);
|
||||
if (foundActor == mActors.end()) // actor was already removed from the scene
|
||||
continue;
|
||||
|
@ -1314,7 +1334,7 @@ namespace MWPhysics
|
|||
for (int i=0; i<numSteps; ++i)
|
||||
{
|
||||
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())
|
||||
positionChanged = true;
|
||||
physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct
|
||||
|
|
|
@ -1,11 +1,34 @@
|
|||
#include "openxrinputmanager.hpp"
|
||||
#include "openxrmanager.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "../mwinput/inputmanagerimp.hpp"
|
||||
|
||||
#include <components/debug/debuglog.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 <osg/Camera>
|
||||
|
@ -17,6 +40,13 @@
|
|||
|
||||
namespace MWVR
|
||||
{
|
||||
struct OpenXRActionEvent
|
||||
{
|
||||
MWInput::InputManager::Actions action;
|
||||
bool onPress;
|
||||
float value = 0.f;
|
||||
};
|
||||
|
||||
struct OpenXRAction
|
||||
{
|
||||
|
||||
|
@ -86,7 +116,7 @@ namespace MWVR
|
|||
float mValue = 0.f;
|
||||
};
|
||||
|
||||
struct OpenXRInputManagerImpl
|
||||
struct OpenXRInput
|
||||
{
|
||||
using Actions = MWInput::InputManager::Actions;
|
||||
|
||||
|
@ -112,18 +142,16 @@ namespace MWVR
|
|||
|
||||
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 = {});
|
||||
|
||||
XrActionSet createActionSet(void);
|
||||
|
||||
void updateHandTracking();
|
||||
|
||||
XrPath subactionPath(SubAction subAction);
|
||||
|
||||
void updateControls();
|
||||
void updateHead();
|
||||
bool nextActionEvent(OpenXRActionEvent& action);
|
||||
PoseSet getHandPoses(int64_t time, TrackedSpace space);
|
||||
|
||||
osg::ref_ptr<OpenXRManager> mXR;
|
||||
|
@ -226,7 +254,7 @@ namespace MWVR
|
|||
};
|
||||
|
||||
XrActionSet
|
||||
OpenXRInputManagerImpl::createActionSet()
|
||||
OpenXRInput::createActionSet()
|
||||
{
|
||||
XrActionSet actionSet = XR_NULL_HANDLE;
|
||||
XrActionSetCreateInfo createInfo{ XR_TYPE_ACTION_SET_CREATE_INFO };
|
||||
|
@ -353,8 +381,8 @@ namespace MWVR
|
|||
mAction.getFloat(0, mValue);
|
||||
}
|
||||
|
||||
OpenXRInputManagerImpl::ControllerActionPaths
|
||||
OpenXRInputManagerImpl::generateControllerActionPaths(
|
||||
OpenXRInput::ControllerActionPaths
|
||||
OpenXRInput::generateControllerActionPaths(
|
||||
const std::string& controllerAction)
|
||||
{
|
||||
ControllerActionPaths actionPaths;
|
||||
|
@ -370,7 +398,7 @@ namespace MWVR
|
|||
return actionPaths;
|
||||
}
|
||||
|
||||
OpenXRInputManagerImpl::OpenXRInputManagerImpl(
|
||||
OpenXRInput::OpenXRInput(
|
||||
osg::ref_ptr<OpenXRManager> XR)
|
||||
: mXR(XR)
|
||||
, mSubactionPath{ {
|
||||
|
@ -430,8 +458,8 @@ namespace MWVR
|
|||
{mLookLeftRight, mThumbstickXPath[RIGHT_HAND]},
|
||||
{mMoveLeftRight, mThumbstickXPath[LEFT_HAND]},
|
||||
{mMoveForwardBackward, mThumbstickYPath[LEFT_HAND]},
|
||||
{mActivate, mSqueezeClickPath[RIGHT_HAND]},
|
||||
{mUse, mTriggerClickPath[RIGHT_HAND]},
|
||||
{mActivate, mSqueezeValuePath[RIGHT_HAND]},
|
||||
{mUse, mTriggerValuePath[RIGHT_HAND]},
|
||||
{mJump, mTriggerValuePath[LEFT_HAND]},
|
||||
{mWeapon, mAPath[RIGHT_HAND]},
|
||||
{mSpell, mAPath[RIGHT_HAND]},
|
||||
|
@ -442,7 +470,7 @@ namespace MWVR
|
|||
{mSneak, mXPath[LEFT_HAND]},
|
||||
{mInventory, mBPath[RIGHT_HAND]},
|
||||
{mQuickMenu, mYPath[LEFT_HAND]},
|
||||
{mSpellModifier, mSqueezeClickPath[LEFT_HAND]},
|
||||
{mSpellModifier, mSqueezeValuePath[LEFT_HAND]},
|
||||
{mGameMenu, mMenuClickPath[LEFT_HAND]},
|
||||
} };
|
||||
XrInteractionProfileSuggestedBinding suggestedBindings{ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING };
|
||||
|
@ -490,7 +518,7 @@ namespace MWVR
|
|||
};
|
||||
|
||||
OpenXRAction
|
||||
OpenXRInputManagerImpl::createAction(
|
||||
OpenXRInput::createAction(
|
||||
XrActionType actionType,
|
||||
const std::string& actionName,
|
||||
const std::string& localName,
|
||||
|
@ -515,17 +543,8 @@ namespace MWVR
|
|||
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
|
||||
OpenXRInputManagerImpl::subactionPath(
|
||||
OpenXRInput::subactionPath(
|
||||
SubAction subAction)
|
||||
{
|
||||
if (subAction == NONE)
|
||||
|
@ -534,7 +553,7 @@ namespace MWVR
|
|||
}
|
||||
|
||||
void
|
||||
OpenXRInputManagerImpl::updateControls()
|
||||
OpenXRInput::updateControls()
|
||||
{
|
||||
if (!mXR->impl().mSessionRunning)
|
||||
return;
|
||||
|
@ -546,9 +565,24 @@ namespace MWVR
|
|||
syncInfo.activeActionSets = &activeActionSet;
|
||||
CHECK_XRCMD(xrSyncActions(mXR->impl().mSession, &syncInfo));
|
||||
|
||||
updateHead();
|
||||
|
||||
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
|
||||
if (mActionsMenu.actionOnPress())
|
||||
|
@ -567,9 +601,9 @@ namespace MWVR
|
|||
{
|
||||
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())
|
||||
{
|
||||
|
@ -591,7 +625,7 @@ namespace MWVR
|
|||
// Weapon/Spell actions
|
||||
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())
|
||||
{
|
||||
|
@ -603,7 +637,7 @@ namespace MWVR
|
|||
}
|
||||
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())
|
||||
{
|
||||
|
@ -619,97 +653,33 @@ namespace MWVR
|
|||
float moveLeftRight = mMoveLeftRight.value();
|
||||
float moveForwardBackward = mMoveForwardBackward.value();
|
||||
|
||||
// Until i implement the rest
|
||||
(void)lookLeftRight;
|
||||
(void)moveLeftRight;
|
||||
(void)moveForwardBackward;
|
||||
|
||||
// TODO: Propagate movement to openmw
|
||||
|
||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_LookLeftRight, false, lookLeftRight });
|
||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_MoveLeftRight, false, moveLeftRight });
|
||||
mActionEvents.emplace_back(OpenXRActionEvent{ MWInput::InputManager::A_MoveForwardBackward, false, moveForwardBackward });
|
||||
}
|
||||
|
||||
void OpenXRInputManagerImpl::updateHead()
|
||||
{
|
||||
//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 OpenXRInput::generateXrPath(const std::string& path)
|
||||
{
|
||||
XrPath xrpath = 0;
|
||||
CHECK_XRCMD(xrStringToPath(mXR->impl().mInstance, path.c_str(), &xrpath));
|
||||
return xrpath;
|
||||
}
|
||||
|
||||
OpenXRInputManager::OpenXRInputManager(
|
||||
osg::ref_ptr<OpenXRManager> XR)
|
||||
: mPrivate(new OpenXRInputManagerImpl(XR))
|
||||
bool OpenXRInput::nextActionEvent(OpenXRActionEvent& action)
|
||||
{
|
||||
action = {};
|
||||
|
||||
}
|
||||
|
||||
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())
|
||||
if (mActionEvents.empty())
|
||||
return false;
|
||||
|
||||
action = mPrivate->mActionEvents.front();
|
||||
mPrivate->mActionEvents.pop_front();
|
||||
action = mActionEvents.front();
|
||||
mActionEvents.pop_front();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
PoseSet
|
||||
OpenXRInputManagerImpl::getHandPoses(
|
||||
OpenXRInput::getHandPoses(
|
||||
int64_t time,
|
||||
TrackedSpace space)
|
||||
{
|
||||
|
@ -724,8 +694,7 @@ namespace MWVR
|
|||
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
||||
location.next = &velocity;
|
||||
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{
|
||||
osg::fromXR(location.pose.position),
|
||||
osg::fromXR(location.pose.orientation),
|
||||
|
@ -741,4 +710,220 @@ namespace MWVR
|
|||
|
||||
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
|
||||
#define OPENXR_INPUT_MANAGER_HPP
|
||||
|
||||
#include "openxrmanager.hpp"
|
||||
#include "openxrviewer.hpp"
|
||||
#include "../mwinput/inputmanagerimp.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
@ -10,27 +10,37 @@
|
|||
|
||||
namespace MWVR
|
||||
{
|
||||
struct OpenXRActionEvent
|
||||
{
|
||||
MWInput::InputManager::Actions action;
|
||||
bool onPress;
|
||||
};
|
||||
struct OpenXRInput;
|
||||
struct OpenXRActionEvent;
|
||||
|
||||
struct OpenXRInputManagerImpl;
|
||||
struct OpenXRInputManager
|
||||
/// As far as I can tell, SDL does not support VR controllers.
|
||||
/// So I subclass the input manager and insert VR controls.
|
||||
class OpenXRInputManager : public MWInput::InputManager
|
||||
{
|
||||
OpenXRInputManager(osg::ref_ptr<OpenXRManager> XR);
|
||||
~OpenXRInputManager();
|
||||
public:
|
||||
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);
|
||||
|
||||
bool nextActionEvent(OpenXRActionEvent& action);
|
||||
|
||||
OpenXRInputManagerImpl& impl() { return *mPrivate; }
|
||||
|
||||
std::unique_ptr<OpenXRInputManagerImpl> mPrivate;
|
||||
osg::ref_ptr<OpenXRViewer> mXRViewer;
|
||||
std::unique_ptr<OpenXRInput> mXRInput;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -504,7 +504,7 @@ namespace MWVR
|
|||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||
bool isMale = ref->mBase->isMale();
|
||||
float charHeightFactor = isMale ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
|
||||
float charHeightBase = 1.9f;
|
||||
float charHeightBase = 2.f;
|
||||
float charHeight = charHeightBase * charHeightFactor;
|
||||
// TODO: Player height should be configurable
|
||||
// For now i'm just using my own
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace MWVR
|
|||
|
||||
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.position += mPose.orientation * osg::Vec3(0, 0, -1);
|
||||
mPose.position += mPose.orientation * osg::Vec3(0, 0, -0.5);
|
||||
mPose.orientation = -mPose.orientation;
|
||||
|
||||
Log(Debug::Verbose) << "Menu pose updated to: " << mPose;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "openxrmanager.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "openxrinputmanager.hpp"
|
||||
#include "openxrswapchain.hpp"
|
||||
#include "../mwinput/inputmanagerimp.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/sdlutil/sdlgraphicswindow.hpp>
|
||||
|
@ -27,7 +29,7 @@ namespace MWVR
|
|||
OpenXRSession::OpenXRSession(
|
||||
osg::ref_ptr<OpenXRManager> XR)
|
||||
: mXR(XR)
|
||||
, mInputManager(new OpenXRInputManager(mXR))
|
||||
// , mInputManager(new OpenXRInput(mXR))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -71,39 +73,108 @@ namespace MWVR
|
|||
Timer timer("OpenXRSession::waitFrame");
|
||||
mXR->waitFrame();
|
||||
timer.checkpoint("waitFrame");
|
||||
mInputManager->updateControls();
|
||||
// mInputManager->updateControls();
|
||||
predictNext(0);
|
||||
|
||||
OpenXRActionEvent event{};
|
||||
while (mInputManager->nextActionEvent(event))
|
||||
{
|
||||
Log(Debug::Verbose) << "ActionEvent action=" << event.action << " onPress=" << event.onPress;
|
||||
if (event.action == MWInput::InputManager::A_GameMenu)
|
||||
{
|
||||
Log(Debug::Verbose) << "A_GameMenu";
|
||||
auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
||||
if (menuLayer)
|
||||
{
|
||||
menuLayer->setVisible(!menuLayer->isVisible());
|
||||
menuLayer->updatePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
//OpenXRActionEvent event{};
|
||||
//while (mInputManager->nextActionEvent(event))
|
||||
//{
|
||||
// Log(Debug::Verbose) << "ActionEvent action=" << event.action << " onPress=" << event.onPress;
|
||||
// if (event.action == MWInput::InputManager::A_GameMenu)
|
||||
// {
|
||||
// Log(Debug::Verbose) << "A_GameMenu";
|
||||
// auto* menuLayer = dynamic_cast<OpenXRMenu*>(mLayerStack.layerObjects()[OpenXRLayerStack::MENU_VIEW_LAYER]);
|
||||
// if (menuLayer)
|
||||
// {
|
||||
// menuLayer->setVisible(!menuLayer->isVisible());
|
||||
// menuLayer->updatePosition();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
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)
|
||||
{
|
||||
auto mPredictedDisplayTime = mXR->impl().frameState().predictedDisplayTime;
|
||||
|
||||
auto input = MWBase::Environment::get().getXRInputManager();
|
||||
|
||||
// Update pose predictions
|
||||
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.hands[(int)TrackedSpace::STAGE] = mInputManager->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE);
|
||||
mPredictedPoses.hands[(int)TrackedSpace::VIEW] = mInputManager->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW);
|
||||
mPredictedPoses.hands[(int)TrackedSpace::STAGE] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::STAGE);
|
||||
mPredictedPoses.hands[(int)TrackedSpace::VIEW] = input->getHandPoses(mPredictedDisplayTime, TrackedSpace::VIEW);
|
||||
auto stageViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::STAGE);
|
||||
auto hmdViews = mXR->impl().getPredictedViews(mPredictedDisplayTime, TrackedSpace::VIEW);
|
||||
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 "openxrmanager.hpp"
|
||||
#include "openxrlayer.hpp"
|
||||
#include "openxrinputmanager.hpp"
|
||||
|
||||
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
|
||||
{
|
||||
using seconds = std::chrono::duration<double>;
|
||||
using nanoseconds = std::chrono::nanoseconds;
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
public:
|
||||
OpenXRSession(osg::ref_ptr<OpenXRManager> XR);
|
||||
~OpenXRSession();
|
||||
|
||||
public:
|
||||
OpenXRSession(osg::ref_ptr<OpenXRManager> XR);
|
||||
~OpenXRSession();
|
||||
void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer);
|
||||
void swapBuffers(osg::GraphicsContext* gc);
|
||||
|
||||
void setLayer(OpenXRLayerStack::Layer layerType, OpenXRLayer* layer);
|
||||
void swapBuffers(osg::GraphicsContext* gc);
|
||||
PoseSets& predictedPoses() { return mPredictedPoses; };
|
||||
|
||||
PoseSets& predictedPoses() { return mPredictedPoses; };
|
||||
//! Call before updating poses and other inputs
|
||||
void waitFrame();
|
||||
|
||||
//! Call before updating poses
|
||||
void waitFrame();
|
||||
//! Update predictions
|
||||
void predictNext(int extraPeriods);
|
||||
|
||||
//! Update predictions
|
||||
void predictNext(int extraPeriods);
|
||||
void showMenu(bool show);
|
||||
|
||||
osg::ref_ptr<OpenXRManager> mXR;
|
||||
std::unique_ptr<OpenXRInputManager> mInputManager = nullptr;
|
||||
OpenXRLayerStack mLayerStack{};
|
||||
void updateMenuPosition(void);
|
||||
|
||||
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 "openxrsession.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "Windows.h"
|
||||
#include "../mwrender/vismask.hpp"
|
||||
|
@ -20,14 +21,13 @@ namespace MWVR
|
|||
float metersPerUnit)
|
||||
: osg::Group()
|
||||
, mXR(XR)
|
||||
, mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW})
|
||||
, mRealizeOperation(new RealizeOperation(XR, this))
|
||||
, mViewer(viewer)
|
||||
, mMetersPerUnit(metersPerUnit)
|
||||
, mConfigured(false)
|
||||
, mCompositionLayerProjectionViews(2, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW})
|
||||
, mXRSession(nullptr)
|
||||
, mPreDraw(new PredrawCallback(this))
|
||||
, mPostDraw(new PostdrawCallback(this))
|
||||
, mMetersPerUnit(metersPerUnit)
|
||||
, mConfigured(false)
|
||||
{
|
||||
mViewer->setRealizeOperation(mRealizeOperation);
|
||||
mCompositionLayerProjectionViews[0].pose.orientation.w = 1;
|
||||
|
@ -160,16 +160,16 @@ namespace MWVR
|
|||
menuCamera->setPreDrawCallback(mPreDraw);
|
||||
menuCamera->setPostDrawCallback(mPostDraw);
|
||||
|
||||
mViewer->addSlave(menuCamera, true);
|
||||
auto* session = MWBase::Environment::get().getXRSession();
|
||||
|
||||
mXRSession.reset(new OpenXRSession(mXR));
|
||||
mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, mXRSession.get(), leftView, context);
|
||||
mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, mXRSession.get(), rightView, context);
|
||||
mViewer->addSlave(menuCamera, true);
|
||||
mViewer->getSlave(0)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, leftView, context);
|
||||
mViewer->getSlave(1)._updateSlaveCallback = new OpenXRWorldView::UpdateSlaveCallback(mXR, session, rightView, context);
|
||||
|
||||
mainCamera->getGraphicsContext()->setSwapCallback(new OpenXRViewer::SwapBuffersCallback(this));
|
||||
mainCamera->setGraphicsContext(nullptr);
|
||||
mXRSession->setLayer(OpenXRLayerStack::WORLD_VIEW_LAYER, this);
|
||||
mXRSession->setLayer(OpenXRLayerStack::MENU_VIEW_LAYER, dynamic_cast<OpenXRLayer*>(mViews["MenuView"].get()));
|
||||
session->setLayer(OpenXRLayerStack::WORLD_VIEW_LAYER, this);
|
||||
session->setLayer(OpenXRLayerStack::MENU_VIEW_LAYER, dynamic_cast<OpenXRLayer*>(mViews["MenuView"].get()));
|
||||
mConfigured = true;
|
||||
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ namespace MWVR
|
|||
OpenXRViewer::SwapBuffersCallback::swapBuffersImplementation(
|
||||
osg::GraphicsContext* gc)
|
||||
{
|
||||
mViewer->mXRSession->swapBuffers(gc);
|
||||
MWBase::Environment::get().getXRSession()->swapBuffers(gc);
|
||||
}
|
||||
|
||||
void OpenXRViewer::swapBuffers(osg::GraphicsContext* gc)
|
||||
|
@ -220,7 +220,6 @@ namespace MWVR
|
|||
mViews["RightEye"]->swapBuffers(gc);
|
||||
timer.checkpoint("Views");
|
||||
|
||||
auto eyePoses = mXRSession->predictedPoses().eye;
|
||||
auto leftEyePose = toXR(mViews["LeftEye"]->predictedPose());
|
||||
auto rightEyePose = toXR(mViews["RightEye"]->predictedPose());
|
||||
mCompositionLayerProjectionViews[0].pose = leftEyePose;
|
||||
|
@ -273,7 +272,7 @@ namespace MWVR
|
|||
if (mXR->sessionRunning())
|
||||
{
|
||||
mXR->beginFrame();
|
||||
auto& poses = mXRSession->predictedPoses();
|
||||
auto& poses = MWBase::Environment::get().getXRSession()->predictedPoses();
|
||||
auto menuPose = poses.head[(int)TrackedSpace::STAGE];
|
||||
mViews["MenuView"]->setPredictedPose(menuPose);
|
||||
}
|
||||
|
@ -307,7 +306,7 @@ namespace MWVR
|
|||
return;
|
||||
}
|
||||
|
||||
auto& poses = mXRSession->predictedPoses();
|
||||
auto& poses = MWBase::Environment::get().getXRSession()->predictedPoses();
|
||||
auto handPosesView = poses.hands[(int)TrackedSpace::VIEW];
|
||||
auto handPosesStage = poses.hands[(int)TrackedSpace::STAGE];
|
||||
int chirality = (int)Chirality::LEFT_HAND;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "openxrlayer.hpp"
|
||||
#include "openxrworldview.hpp"
|
||||
#include "openxrmenu.hpp"
|
||||
#include "openxrinputmanager.hpp"
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
|
||||
struct XrCompositionLayerProjection;
|
||||
|
@ -109,12 +108,11 @@ namespace MWVR
|
|||
|
||||
public:
|
||||
|
||||
osg::observer_ptr<OpenXRManager> mXR = nullptr;
|
||||
std::unique_ptr<XrCompositionLayerProjection> mLayer = nullptr;
|
||||
std::vector<XrCompositionLayerProjectionView> mCompositionLayerProjectionViews;
|
||||
osg::observer_ptr<OpenXRManager> mXR = nullptr;
|
||||
osg::ref_ptr<OpenXRManager::RealizeOperation> mRealizeOperation = nullptr;
|
||||
osg::observer_ptr<osgViewer::Viewer> mViewer = nullptr;
|
||||
std::unique_ptr<OpenXRSession> mXRSession = nullptr;
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer = nullptr;
|
||||
std::map<std::string, osg::ref_ptr<OpenXRView> > mViews{};
|
||||
std::map<std::string, osg::ref_ptr<osg::Camera> > mCameras{};
|
||||
|
||||
|
|
Loading…
Reference in a new issue