1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 07:53:51 +00:00

Squashed commit of the following:

commit d8564b8e501c98fa2e3cde582b8d06d7c78ba6ce
Author: Mads Buvik Sandvei <madssandvei@protonmail.com>
Date:   Fri Oct 16 23:43:39 2020 +0200

    bad assignment

commit 84f66e4bf1050ce8a316a27f8b10dc2243e35406
Author: Mads Buvik Sandvei <madssandvei@protonmail.com>
Date:   Fri Oct 16 21:08:27 2020 +0200

    Removed the approach of abstracting xr paths with enums. It is not turning out to be useful. Use the explicit paths instead. Added some default bindings for most currently available controllers, except the xbox controller.

commit ae525d0a239c087a7344528634a078e0812af66d
Author: Mads Buvik Sandvei <madssandvei@protonmail.com>
Date:   Fri Oct 16 21:05:37 2020 +0200

    Cleaned up openxr extensions code. Upgraded openxr to version 1.0.12 to enable support for certain controllers.

commit 2d71a5ecbf699c59f1fcdbebcad867fd28552929
Author: Mads Buvik Sandvei <madssandvei@protonmail.com>
Date:   Thu Sep 24 22:18:25 2020 +0200

    simple_controller
This commit is contained in:
Mads Buvik Sandvei 2020-10-17 12:33:46 +02:00
parent bd4093bbcb
commit c3a312f80d
13 changed files with 375 additions and 275 deletions

View file

@ -266,7 +266,7 @@ if(BUILD_OPENMW_VR)
FetchContent_Declare(
OpenXR
GIT_REPOSITORY https://github.com/KhronosGroup/OpenXR-SDK.git
GIT_TAG release-1.0.9
GIT_TAG release-1.0.12
)
FetchContent_MakeAvailable(OpenXR)

View file

@ -25,24 +25,6 @@ namespace MWVR
// Currently the set of action paths was determined using the oculus touch (i know nothing about the vive and the index).
// The set of action paths may therefore need expansion. E.g. /click vs /value may vary with controllers.
// To fit more actions onto controllers i created a system of short and long press actions. Allowing one action to activate
// on a short press, and another on long. Here, what actions are short press and what actions are long press is simply
// hardcoded at init, rather than interpreted from bindings. That's bad, and should be fixed, but that's hard to do
// while staying true to openxr's binding system, so if the system i wrote for the oculus touch isn't a good fit for
// the vive/index, we might want to rewrite this to handle bindings ourselves.
generateControllerActionPaths(ActionPath::Select, "/input/select/click");
generateControllerActionPaths(ActionPath::Squeeze, "/input/squeeze/value");
generateControllerActionPaths(ActionPath::Pose, "/input/aim/pose");
generateControllerActionPaths(ActionPath::Haptic, "/output/haptic");
generateControllerActionPaths(ActionPath::Menu, "/input/menu/click");
generateControllerActionPaths(ActionPath::ThumbstickX, "/input/thumbstick/x");
generateControllerActionPaths(ActionPath::ThumbstickY, "/input/thumbstick/y");
generateControllerActionPaths(ActionPath::ThumbstickClick, "/input/thumbstick/click");
generateControllerActionPaths(ActionPath::X, "/input/x/click");
generateControllerActionPaths(ActionPath::Y, "/input/y/click");
generateControllerActionPaths(ActionPath::A, "/input/a/click");
generateControllerActionPaths(ActionPath::B, "/input/b/click");
generateControllerActionPaths(ActionPath::Trigger, "/input/trigger/value");
/*
// Applicable actions not (yet) included
@ -65,6 +47,12 @@ namespace MWVR
A_Screenshot, // Generate a VR screenshot?
A_Console, // Currently awkward due to a lack of virtual keyboard, but should be included when that's in place
*/
// To fit more actions onto controllers i created a system of short and long press actions. Allowing one action to activate
// on a short press, and another on long. Here, what actions are short press and what actions are long press is simply
// hardcoded at init, rather than interpreted from bindings. That's bad, and should be fixed, but that's hard to do
// while staying true to openxr's binding system, so if the system i wrote for the oculus touch isn't a good fit for
// the vive/index, we might want to rewrite this to handle bindings ourselves.
createMWAction<ButtonPressAction>(MWInput::A_GameMenu, "game_menu", "Game Menu");
createMWAction<ButtonLongPressAction>(A_Recenter, "reposition_menu", "Reposition Menu");
createMWAction<ButtonPressAction>(MWInput::A_Inventory, "inventory", "Inventory");
@ -147,10 +135,10 @@ namespace MWVR
{
std::vector<XrActionSuggestedBinding> suggestedBindings =
{
{*mTrackerMap[TrackedLimb::LEFT_HAND], getXrPath(ActionPath::Pose, Side::LEFT_SIDE)},
{*mTrackerMap[TrackedLimb::RIGHT_HAND], getXrPath(ActionPath::Pose, Side::RIGHT_SIDE)},
{*mHapticsMap[TrackedLimb::LEFT_HAND], getXrPath(ActionPath::Haptic, Side::LEFT_SIDE)},
{*mHapticsMap[TrackedLimb::RIGHT_HAND], getXrPath(ActionPath::Haptic, Side::RIGHT_SIDE)},
{*mTrackerMap[TrackedLimb::LEFT_HAND], getXrPath("/user/hand/left/input/aim/pose")},
{*mTrackerMap[TrackedLimb::RIGHT_HAND], getXrPath("/user/hand/right/input/aim/pose")},
{*mHapticsMap[TrackedLimb::LEFT_HAND], getXrPath("/user/hand/left/output/haptic")},
{*mHapticsMap[TrackedLimb::RIGHT_HAND], getXrPath("/user/hand/right/output/haptic")},
};
for (auto& mwSuggestedBinding : mwSuggestedBindings)
@ -161,29 +149,12 @@ namespace MWVR
Log(Debug::Error) << "OpenXRActionSet: Unknown action " << mwSuggestedBinding.action;
continue;
}
suggestedBindings.push_back({ *xrAction->second, getXrPath(mwSuggestedBinding.path, mwSuggestedBinding.side) });
suggestedBindings.push_back({ *xrAction->second, getXrPath(mwSuggestedBinding.path) });
}
xrSuggestedBindings.insert(xrSuggestedBindings.end(), suggestedBindings.begin(), suggestedBindings.end());
}
void
OpenXRActionSet::generateControllerActionPaths(
ActionPath actionPath,
const std::string& controllerAction)
{
auto* xr = Environment::get().getManager();
ControllerActionPaths actionPaths;
std::string left = std::string("/user/hand/left") + controllerAction;
std::string right = std::string("/user/hand/right") + controllerAction;
CHECK_XRCMD(xrStringToPath(xr->impl().xrInstance(), left.c_str(), &actionPaths[(int)Side::LEFT_SIDE]));
CHECK_XRCMD(xrStringToPath(xr->impl().xrInstance(), right.c_str(), &actionPaths[(int)Side::RIGHT_SIDE]));
mPathMap[actionPath] = actionPaths;
}
std::unique_ptr<OpenXRAction>
OpenXRActionSet::createXRAction(
@ -219,7 +190,7 @@ namespace MWVR
action.second->updateAndQueue(mActionQueue);
}
XrPath OpenXRActionSet::generateXrPath(const std::string& path)
XrPath OpenXRActionSet::getXrPath(const std::string& path)
{
auto* xr = Environment::get().getManager();
XrPath xrpath = 0;
@ -265,13 +236,4 @@ namespace MWVR
it->second->apply(intensity);
}
XrPath OpenXRActionSet::getXrPath(ActionPath actionPath, Side side)
{
auto it = mPathMap.find(actionPath);
if (it == mPathMap.end())
{
Log(Debug::Error) << "OpenXRActionSet: No such path: " << (int)actionPath;
}
return it->second[(int)side];
}
}

View file

@ -13,7 +13,6 @@ namespace MWVR
{
public:
using Actions = MWInput::Actions;
using ControllerActionPaths = std::array<XrPath, 2>;
OpenXRActionSet(const std::string& actionSetName);
@ -38,15 +37,12 @@ namespace MWVR
void createPoseAction(TrackedLimb limb, const std::string& actionName, const std::string& localName);
void createHapticsAction(TrackedLimb limb, const std::string& actionName, const std::string& localName);
std::unique_ptr<OpenXRAction> createXRAction(XrActionType actionType, const std::string& actionName, const std::string& localName);
XrPath generateXrPath(const std::string& path);
void generateControllerActionPaths(ActionPath actionPath, const std::string& controllerAction);
XrPath getXrPath(const std::string& path);
XrActionSet createActionSet(const std::string& name);
XrPath getXrPath(ActionPath actionPath, Side side);
XrActionSet mActionSet{ nullptr };
std::string mLocalizedName{};
std::string mInternalName{};
std::map<ActionPath, ControllerActionPaths> mPathMap;
std::map<int, std::unique_ptr<Action>> mActionMap;
std::map<TrackedLimb, std::unique_ptr<PoseAction>> mTrackerMap;
std::map<TrackedLimb, std::unique_ptr<HapticsAction>> mHapticsMap;

View file

@ -40,7 +40,7 @@ namespace MWVR
// Suggest bindings before attaching
for (auto& profile : mSuggestedBindings)
{
XrPath profilePath;
XrPath profilePath = 0;
CHECK_XRCMD(
xrStringToPath(xr->impl().xrInstance(), profile.first.c_str(), &profilePath));
XrInteractionProfileSuggestedBinding xrProfileSuggestedBindings{ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING };

View file

@ -16,10 +16,10 @@
#include "../mwworld/player.hpp"
#include "../mwworld/esmstore.hpp"
// The OpenXR SDK assumes we've included Windows.h
// The OpenXR SDK's platform headers assume we've included these windows headers
#include <Windows.h>
#include <objbase.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_platform_defines.h>
#include <openxr/openxr_reflection.h>
@ -48,18 +48,17 @@ MAKE_TO_STRING_FUNC(XrResult);
MAKE_TO_STRING_FUNC(XrFormFactor);
MAKE_TO_STRING_FUNC(XrStructureType);
#if !XR_KHR_composition_layer_depth || !XR_KHR_opengl_enable
#error "OpenXR extensions missing. Please upgrade your copy of the OpenXR SDK"
#endif
namespace MWVR
{
OpenXRManagerImpl::OpenXRManagerImpl()
{
std::vector<const char*> extensions = {
XR_KHR_OPENGL_ENABLE_EXTENSION_NAME,
XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME,
};
setupExtensionsAndLayers();
std::vector<const char*> extensions;
for (auto& extension : mEnabledExtensions)
extensions.push_back(extension.c_str());
logLayersAndExtensions();
{ // Create Instance
XrInstanceCreateInfo createInfo{ XR_TYPE_INSTANCE_CREATE_INFO };
@ -68,33 +67,7 @@ namespace MWVR
createInfo.enabledExtensionNames = extensions.data();
strcpy(createInfo.applicationInfo.applicationName, "openmw_vr");
createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
// Iteratively strip extensions until instance creation succeeds.
XrResult result = xrCreateInstance(&createInfo, &mInstance);
while (result == XR_ERROR_EXTENSION_NOT_PRESENT)
{
createInfo.enabledExtensionCount--;
result = xrCreateInstance(&createInfo, &mInstance);
}
mEnabledExtensions.insert(extensions.begin(), extensions.begin() + createInfo.enabledExtensionCount);
if (!xrExtensionIsEnabled(XR_KHR_OPENGL_ENABLE_EXTENSION_NAME))
throw std::runtime_error(std::string("Required OpenXR extension ") + XR_KHR_OPENGL_ENABLE_EXTENSION_NAME + " not supported");
Log(Debug::Verbose) << "OpenXR Extension status:";
for (auto* ext : extensions)
{
if (!xrExtensionIsEnabled(ext))
{
Log(Debug::Verbose) << " " << ext << ": disabled (not supported)";
}
else
{
Log(Debug::Verbose) << " " << ext << ": enabled";
}
}
CHECK_XRCMD(xrCreateInstance(&createInfo, &mInstance));
assert(mInstance);
}
@ -142,32 +115,24 @@ namespace MWVR
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
auto XRGLRC = wglCreateContext(DC);
auto USERGLRC = wglCreateContext(DC);
wglShareLists(GLRC, XRGLRC);
wglShareLists(GLRC, USERGLRC);
mGraphicsBindingXr.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
mGraphicsBindingXr.next = nullptr;
mGraphicsBindingXr.hDC = DC;
mGraphicsBindingXr.hGLRC = XRGLRC;
mGraphicsBindingUser.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
mGraphicsBindingUser.next = nullptr;
mGraphicsBindingUser.hDC = DC;
mGraphicsBindingUser.hGLRC = USERGLRC;
XrGraphicsBindingOpenGLWin32KHR graphicsBindings;
graphicsBindings.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
graphicsBindings.next = nullptr;
graphicsBindings.hDC = DC;
graphicsBindings.hGLRC = XRGLRC;
if (!mGraphicsBindingXr.hDC)
if (!graphicsBindings.hDC)
Log(Debug::Warning) << "Missing DC";
if (!mGraphicsBindingXr.hGLRC)
Log(Debug::Warning) << "Missing GLRC";
XrSessionCreateInfo createInfo{ XR_TYPE_SESSION_CREATE_INFO };
createInfo.next = &mGraphicsBindingXr;
createInfo.next = &graphicsBindings;
createInfo.systemId = mSystemId;
CHECK_XRCMD(xrCreateSession(mInstance, &createInfo, &mSession));
assert(mSession);
}
LogLayersAndExtensions();
LogInstanceInfo();
LogReferenceSpaces();
LogSwapchainFormats();
@ -254,9 +219,67 @@ namespace MWVR
}
#if !XR_KHR_composition_layer_depth \
|| !XR_KHR_opengl_enable \
|| !XR_EXT_hp_mixed_reality_controller
#error "OpenXR extensions missing. Please upgrade your copy of the OpenXR SDK to 1.0.12 minimum"
#endif
std::vector<std::string> OpenXRManagerImpl::enumerateExtensions(const char* layerName)
{
uint32_t extensionCount = 0;
std::vector<XrExtensionProperties> availableExtensions;
xrEnumerateInstanceExtensionProperties(nullptr, 0, &extensionCount, nullptr);
availableExtensions.resize(extensionCount, XrExtensionProperties{ XR_TYPE_EXTENSION_PROPERTIES });
xrEnumerateInstanceExtensionProperties(nullptr, availableExtensions.size(), &extensionCount, availableExtensions.data());
std::vector<std::string> extensionNames;
for (auto& extension : availableExtensions)
extensionNames.push_back(extension.extensionName);
return extensionNames;
}
void OpenXRManagerImpl::setupExtensionsAndLayers()
{
std::vector<const char*> requiredExtensions = {
XR_KHR_OPENGL_ENABLE_EXTENSION_NAME,
};
std::vector<const char*> optionalExtensions = {
XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME,
XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME
};
for (auto& extension : enumerateExtensions())
mAvailableExtensions.insert(extension);
for (auto requiredExtension : requiredExtensions)
enableExtension(requiredExtension, false);
for (auto optionalExtension : optionalExtensions)
enableExtension(optionalExtension, true);
}
void OpenXRManagerImpl::enableExtension(const std::string& extension, bool optional)
{
if (mAvailableExtensions.count(extension) > 0)
{
Log(Debug::Verbose) << " " << extension << ": enabled";
mEnabledExtensions.insert(extension);
}
else
{
Log(Debug::Verbose) << " " << extension << ": disabled (not supported)";
if (!optional)
{
throw std::runtime_error(std::string("Required OpenXR extension ") + extension + " not supported by the runtime");
}
}
}
void
OpenXRManagerImpl::LogLayersAndExtensions() {
OpenXRManagerImpl::logLayersAndExtensions() {
// Write out extension properties for a given layer.
const auto logExtensions = [](const char* layerName, int indent = 0) {
uint32_t instanceExtensionCount;
@ -283,9 +306,6 @@ namespace MWVR
Log(Debug::Verbose) << ss.str();
};
// Log non-layer extensions (layerName==nullptr).
logExtensions(nullptr);
// Log layers and any of their extensions.
{
uint32_t layerCount;
@ -382,15 +402,8 @@ namespace MWVR
void
OpenXRManagerImpl::beginFrame()
{
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
wglMakeCurrent(mGraphicsBindingUser.hDC, mGraphicsBindingUser.hGLRC);
clearGlErrors();
XrFrameBeginInfo frameBeginInfo{ XR_TYPE_FRAME_BEGIN_INFO };
CHECK_XRCMD(xrBeginFrame(mSession, &frameBeginInfo));
wglMakeCurrent(DC, GLRC);
}
XrCompositionLayerProjectionView toXR(MWVR::CompositionLayerProjectionView layer)
@ -408,11 +421,6 @@ namespace MWVR
void
OpenXRManagerImpl::endFrame(FrameInfo frameInfo, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack)
{
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
wglMakeCurrent(mGraphicsBindingUser.hDC, mGraphicsBindingUser.hGLRC);
clearGlErrors();
std::array<XrCompositionLayerProjectionView, 2> compositionLayerProjectionViews{};
compositionLayerProjectionViews[(int)Side::LEFT_SIDE] = toXR(layerStack[(int)Side::LEFT_SIDE]);
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR(layerStack[(int)Side::RIGHT_SIDE]);
@ -449,8 +457,6 @@ namespace MWVR
frameEndInfo.layers = &xrLayerStack;
}
CHECK_XRCMD(xrEndFrame(mSession, &frameEndInfo));
wglMakeCurrent(DC, GLRC);
}
std::array<View, 2>

View file

@ -7,13 +7,7 @@
#include <components/debug/debuglog.hpp>
#include <components/sdlutil/sdlgraphicswindow.hpp>
// The OpenXR SDK assumes we've included Windows.h
#include <Windows.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_platform_defines.h>
#include <openxr/openxr_reflection.h>
#include <vector>
#include <array>
@ -77,7 +71,10 @@ namespace MWVR
void xrResourceReleased();
protected:
void LogLayersAndExtensions();
std::vector<std::string> enumerateExtensions(const char* layerName = nullptr);
void setupExtensionsAndLayers();
void enableExtension(const std::string& extension, bool optional);
void logLayersAndExtensions();
void LogInstanceInfo();
void LogReferenceSpaces();
void LogSwapchainFormats();
@ -100,8 +97,6 @@ namespace MWVR
XrViewConfigurationType mViewConfigType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
XrEnvironmentBlendMode mEnvironmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
XrSystemId mSystemId = XR_NULL_SYSTEM_ID;
XrGraphicsBindingOpenGLWin32KHR mGraphicsBindingXr{ XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR };
XrGraphicsBindingOpenGLWin32KHR mGraphicsBindingUser{ XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR };
XrSystemProperties mSystemProperties{ XR_TYPE_SYSTEM_PROPERTIES };
std::array<XrViewConfigurationView, 2> mConfigViews{ { {XR_TYPE_VIEW_CONFIGURATION_VIEW}, {XR_TYPE_VIEW_CONFIGURATION_VIEW} } };
XrSpace mReferenceSpaceView = XR_NULL_HANDLE;
@ -113,6 +108,7 @@ namespace MWVR
uint32_t mAcquiredResources = 0;
std::mutex mFrameStateMutex{};
std::mutex mEventMutex{};
std::set<std::string> mAvailableExtensions;
std::set<std::string> mEnabledExtensions;
std::queue<XrEventDataBuffer> mEventQueue;

View file

@ -6,13 +6,6 @@
#include <components/debug/debuglog.hpp>
#include <Windows.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_platform_defines.h>
#include <openxr/openxr_reflection.h>
namespace MWVR {
OpenXRSwapchain::OpenXRSwapchain(osg::ref_ptr<osg::State> state, SwapchainConfig config)
: mPrivate(new OpenXRSwapchainImpl(state, config))

View file

@ -5,6 +5,7 @@
#include <components/debug/debuglog.hpp>
#include <Windows.h>
#include <objbase.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>

View file

@ -5,6 +5,7 @@
#include "openxrmanagerimpl.hpp"
struct XrSwapchainSubImage;
struct XrSwapchainImageOpenGLKHR;
namespace MWVR
{

View file

@ -8,8 +8,6 @@
namespace MWVR
{
/// Extension of MWInput's set of actions.
enum VrActions
{
@ -27,34 +25,11 @@ namespace MWVR
A_VrLast
};
/// \brief Enum representation of action paths in openxr.
///
/// OpenXR allows a lot of generics, consequentially this will most likely be changed/expanded
/// in the future as we need it. This set was added based on what the Oculus needed.
enum class ActionPath
{
Pose = 0,
Haptic,
Menu,
ThumbstickX,
ThumbstickY,
ThumbstickClick,
Select,
Squeeze,
Trigger,
X,
Y,
A,
B,
Last
};
/// \brief Suggest a binding by binding an action to a path on a given hand (left or right).
struct SuggestedBinding
{
int action;
ActionPath path;
Side side;
std::string path;
};
using SuggestedBindings = std::vector<SuggestedBinding>;

View file

@ -167,6 +167,261 @@ namespace MWVR
activeActionSet().applyHaptics(TrackedLimb::RIGHT_HAND, intensity);
}
void VRInputManager::suggestBindingsSimple()
{
std::string simpleProfilePath = "/interaction_profiles/khr/simple_controller";
// Set up default bindings for the khronos simple controller.
// Note: The simple controller is the equivalent to a universal "default".
// It has highly reduced functionality. Only poses and two click actions
// are available for each hand, reducing the possible functionality of the profile
// to that of a wonky preview.
// The available click actions are 'select' and 'menu', and i cannot control what
// real buttons this is mapped to. On the Oculus Touch they are X, Y, A, and B.
// In-game character controls
SuggestedBindings simpleGameplayBindings{
{MWInput::A_Use, "/user/hand/left/input/select/click"}, // Touch: X
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"}, // Touch: Y
{A_Recenter, "/user/hand/left/input/menu/click"}, // Touch: Y
{A_ActivateTouch, "/user/hand/right/input/select/click"}, // Touch: A
{MWInput::A_Inventory, "/user/hand/right/input/menu/click"}, // Touch: B
};
// GUI controls
SuggestedBindings simpleGUIBindings{
{MWInput::A_Use, "/user/hand/left/input/select/click"}, // Touch: X
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"}, // Touch: Y
{A_Recenter, "/user/hand/left/input/menu/click"}, // Touch: Y
{A_MenuSelect, "/user/hand/right/input/select/click"}, // Touch: A
{A_MenuBack, "/user/hand/right/input/menu/click"}, // Touch: B
};
mXRInput->suggestBindings(ActionSet::Gameplay, simpleProfilePath, simpleGameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, simpleProfilePath, simpleGUIBindings);
}
void VRInputManager::suggestBindingsOculusTouch()
{
std::string controllerProfilePath = "/interaction_profiles/oculus/touch_controller";
// In-game character controls
SuggestedBindings gameplayBindings{
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
{MWInput::A_Journal, "/user/hand/right/input/b/click"},
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
{MWInput::A_QuickSave, "/user/hand/left/input/y/click"},
{MWInput::A_Rest, "/user/hand/left/input/y/click"},
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
{MWInput::A_ToggleDebug, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_ToggleHUD, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_ToggleSpell, "/user/hand/left/input/x/click"},
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
};
// GUI controls
SuggestedBindings GUIBindings{
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
{A_MenuSelect, "/user/hand/right/input/a/click"},
{A_MenuBack, "/user/hand/right/input/b/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
};
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
}
void VRInputManager::suggestBindingsHpMixedReality()
{
std::string controllerProfilePath = "/interaction_profiles/hp/mixed_reality_controller";
// In-game character controls
SuggestedBindings gameplayBindings{
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
{MWInput::A_Journal, "/user/hand/right/input/b/click"},
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
{MWInput::A_QuickSave, "/user/hand/left/input/y/click"},
{MWInput::A_Rest, "/user/hand/left/input/y/click"},
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
{MWInput::A_ToggleDebug, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_ToggleHUD, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_ToggleSpell, "/user/hand/left/input/x/click"},
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
};
// GUI controls
SuggestedBindings GUIBindings{
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
{A_MenuSelect, "/user/hand/right/input/a/click"},
{A_MenuBack, "/user/hand/right/input/b/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
};
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
}
void VRInputManager::suggestBindingsMicrosoftMixedReality()
{
std::string controllerProfilePath = "/interaction_profiles/microsoft/motion_controller";
// TODO: Slightly better than the vive wands, but still not good.
// In-game character controls
SuggestedBindings gameplayBindings{
//{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
//{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
//{MWInput::A_ToggleDebug, "/user/hand/right/input/thumbstick/click"},
//{MWInput::A_ToggleHUD, "/user/hand/left/input/thumbstick/click"},
{A_ActivateTouch, "/user/hand/right/input/squeeze/click"},
{A_Recenter, "/user/hand/left/input/menu/click"},
{MWInput::A_Activate, "/user/hand/right/input/squeeze/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Inventory, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_Journal, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
{MWInput::A_QuickSave, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_Rest, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/click"},
{MWInput::A_ToggleSpell, "/user/hand/left/input/trackpad/click"},
{MWInput::A_ToggleWeapon, "/user/hand/right/input/trackpad/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
};
// GUI controls
SuggestedBindings GUIBindings{
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
{A_MenuSelect, "/user/hand/right/input/trackpad/click"},
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
};
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
}
void VRInputManager::suggestBindingsIndex()
{
std::string controllerProfilePath = "/interaction_profiles/valve/index_controller";
// In-game character controls
SuggestedBindings gameplayBindings{
{A_ActivateTouch, "/user/hand/right/input/squeeze/value"},
{A_Recenter, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_Activate, "/user/hand/right/input/squeeze/value"},
//{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
//{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
{MWInput::A_Journal, "/user/hand/right/input/b/click"},
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
{MWInput::A_LookLeftRight, "/user/hand/right/input/thumbstick/x"},
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/thumbstick/y"},
{MWInput::A_MoveLeftRight, "/user/hand/left/input/thumbstick/x"},
{MWInput::A_QuickSave, "/user/hand/left/input/b/click"},
{MWInput::A_Rest, "/user/hand/left/input/b/click"},
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/value"},
//{MWInput::A_ToggleDebug, "/user/hand/right/input/thumbstick/click"},
//{MWInput::A_ToggleHUD, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_ToggleSpell, "/user/hand/left/input/a/click"},
{MWInput::A_ToggleWeapon, "/user/hand/right/input/a/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
};
// GUI controls
SuggestedBindings GUIBindings{
{A_MenuUpDown, "/user/hand/right/input/thumbstick/y"},
{A_MenuLeftRight, "/user/hand/right/input/thumbstick/x"},
{A_MenuSelect, "/user/hand/right/input/a/click"},
{A_MenuBack, "/user/hand/right/input/b/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/thumbstick/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
{A_Recenter, "/user/hand/left/input/thumbstick/click"},
};
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
}
void VRInputManager::suggestBindingsVive()
{
std::string controllerProfilePath = "/interaction_profiles/htc/vive_controller";
// TODO: I Didn't realize the vive wands were so bad. We don't have NEARLY enough actions available.
// In-game character controls
SuggestedBindings gameplayBindings{
//{MWInput::A_AlwaysRun, "/user/hand/left/input/thumbstick/click"},
//{MWInput::A_AutoMove, "/user/hand/right/input/thumbstick/click"},
//{MWInput::A_Inventory, "/user/hand/right/input/b/click"},
//{MWInput::A_Journal, "/user/hand/right/input/b/click"},
//{MWInput::A_QuickSave, "/user/hand/left/input/b/click"},
//{MWInput::A_Rest, "/user/hand/left/input/b/click"},
//{MWInput::A_ToggleDebug, "/user/hand/right/input/thumbstick/click"},
//{MWInput::A_ToggleHUD, "/user/hand/left/input/thumbstick/click"},
{A_ActivateTouch, "/user/hand/right/input/squeeze/click"},
{A_Recenter, "/user/hand/left/input/menu/click"},
{MWInput::A_Activate, "/user/hand/right/input/squeeze/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Jump, "/user/hand/left/input/trigger/value"},
{MWInput::A_LookLeftRight, "/user/hand/right/input/trackpad/x"},
{MWInput::A_MoveForwardBackward,"/user/hand/left/input/trackpad/y"},
{MWInput::A_MoveLeftRight, "/user/hand/left/input/trackpad/x"},
{MWInput::A_Sneak, "/user/hand/left/input/squeeze/click"},
{MWInput::A_ToggleSpell, "/user/hand/left/input/trackpad/click"},
{MWInput::A_ToggleWeapon, "/user/hand/right/input/trackpad/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
};
// GUI controls
SuggestedBindings GUIBindings{
{A_MenuUpDown, "/user/hand/right/input/trackpad/y"},
{A_MenuLeftRight, "/user/hand/right/input/trackpad/x"},
{A_MenuSelect, "/user/hand/right/input/trackpad/click"},
{A_MenuBack, "/user/hand/left/input/trackpad/click"},
{MWInput::A_GameMenu, "/user/hand/left/input/menu/click"},
{MWInput::A_Use, "/user/hand/right/input/trigger/value"},
{A_Recenter, "/user/hand/left/input/menu/click"},
};
mXRInput->suggestBindings(ActionSet::Gameplay, controllerProfilePath, gameplayBindings);
mXRInput->suggestBindings(ActionSet::GUI, controllerProfilePath, GUIBindings);
}
void VRInputManager::suggestBindingsXboxController()
{
//TODO
}
void VRInputManager::requestRecenter()
{
mShouldRecenter = true;
@ -193,106 +448,19 @@ namespace MWVR
controllerBindingsFile,
grab)
, mXRInput(new OpenXRInput)
, mHapticsEnabled{Settings::Manager::getBool("haptics enabled", "VR")}
, mHapticsEnabled{ Settings::Manager::getBool("haptics enabled", "VR") }
{
std::string oculusTouchProfilePath = "/interaction_profiles/oculus/touch_controller";
// Set up default bindings for the oculus
auto xr = MWVR::Environment::get().getManager();
/*
Oculus Bindings:
L-Squeeze:
Hold: Sneak
suggestBindingsSimple();
suggestBindingsOculusTouch();
suggestBindingsMicrosoftMixedReality();
suggestBindingsIndex();
suggestBindingsVive();
suggestBindingsXboxController();
R-Squeeze:
Hold: Enable Pointer
L-Trigger:
Press: Jump
R-Trigger:
IF POINTER:
Activate
ELSE:
Use
L-Thumbstick:
X-Axis: MoveForwardBackward
Y-Axis: MoveLeftRight
Button:
Press: AlwaysRun
Long: ToggleHUD
Touch:
R-Thumbstick:
X-Axis: LookLeftRight
Y-Axis:
Button:
Press: AutoMove
Long: ToggleDebug
Touch:
X:
Press: Toggle Spell
Long:
Y:
Press: Rest
Long: Quick Save
A:
Press: Toggle Weapon
Long:
B:
Press: Inventory
Long: Journal
Menu:
Press: GameMenu
Long: Recenter on player and reset GUI
*/
{
// In-game character controls
SuggestedBindings oculusTouchGameplayBindings{
{MWInput::A_LookLeftRight, ActionPath::ThumbstickX, Side::RIGHT_SIDE},
{MWInput::A_MoveLeftRight, ActionPath::ThumbstickX, Side::LEFT_SIDE},
{MWInput::A_MoveForwardBackward, ActionPath::ThumbstickY, Side::LEFT_SIDE},
{MWInput::A_Activate, ActionPath::Squeeze, Side::RIGHT_SIDE},
{MWInput::A_Use, ActionPath::Trigger, Side::RIGHT_SIDE},
{MWInput::A_Jump, ActionPath::Trigger, Side::LEFT_SIDE},
{MWInput::A_ToggleWeapon, ActionPath::A, Side::RIGHT_SIDE},
{MWInput::A_ToggleSpell, ActionPath::X, Side::LEFT_SIDE},
//{*mCycleSpellLeft, mThumbstickClickPath, Side::LEFT_SIDE},
//{*mCycleSpellRight, mThumbstickClickPath, Side::RIGHT_SIDE},
//{*mCycleWeaponLeft, mThumbstickClickPath, Side::LEFT_SIDE},
//{*mCycleWeaponRight, mThumbstickClickPath, Side::RIGHT_SIDE},
{MWInput::A_AlwaysRun, ActionPath::ThumbstickClick, Side::LEFT_SIDE},
{MWInput::A_AutoMove, ActionPath::ThumbstickClick, Side::RIGHT_SIDE},
{MWInput::A_ToggleHUD, ActionPath::ThumbstickClick, Side::LEFT_SIDE},
{MWInput::A_ToggleDebug, ActionPath::ThumbstickClick, Side::RIGHT_SIDE},
{MWInput::A_Sneak, ActionPath::Squeeze, Side::LEFT_SIDE},
{MWInput::A_Inventory, ActionPath::B, Side::RIGHT_SIDE},
{MWInput::A_Rest, ActionPath::Y, Side::LEFT_SIDE},
{MWInput::A_Journal, ActionPath::B, Side::RIGHT_SIDE},
{MWInput::A_QuickSave, ActionPath::Y, Side::LEFT_SIDE},
{MWInput::A_GameMenu, ActionPath::Menu, Side::LEFT_SIDE},
{A_Recenter, ActionPath::Menu, Side::LEFT_SIDE},
{A_ActivateTouch, ActionPath::Squeeze, Side::RIGHT_SIDE},
};
mXRInput->suggestBindings(ActionSet::Gameplay, oculusTouchProfilePath, oculusTouchGameplayBindings);
// GUI controls
SuggestedBindings oculusTouchGUIBindings{
{A_MenuUpDown, ActionPath::ThumbstickY, Side::RIGHT_SIDE},
{A_MenuLeftRight, ActionPath::ThumbstickX, Side::RIGHT_SIDE},
{A_MenuSelect, ActionPath::A, Side::RIGHT_SIDE},
{A_MenuBack, ActionPath::B, Side::RIGHT_SIDE},
{MWInput::A_GameMenu, ActionPath::Menu, Side::LEFT_SIDE},
{MWInput::A_Use, ActionPath::Trigger, Side::RIGHT_SIDE},
{A_Recenter, ActionPath::Menu, Side::LEFT_SIDE},
};
mXRInput->suggestBindings(ActionSet::GUI, oculusTouchProfilePath, oculusTouchGUIBindings);
}
if (xr->xrExtensionIsEnabled(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))
suggestBindingsHpMixedReality();
mXRInput->attachActionSets();
}

View file

@ -73,6 +73,15 @@ namespace MWVR
void applyHapticsLeftHand(float intensity) override;
void applyHapticsRightHand(float intensity) override;
private:
void suggestBindingsSimple();
void suggestBindingsOculusTouch();
void suggestBindingsHpMixedReality();
void suggestBindingsMicrosoftMixedReality();
void suggestBindingsIndex();
void suggestBindingsVive();
void suggestBindingsXboxController();
std::unique_ptr<OpenXRInput> mXRInput;
std::unique_ptr<RealisticCombat::StateMachine> mRealisticCombat;
Pose mHeadPose{};

View file

@ -1,3 +1,5 @@
#include "vrsession.hpp"
#include "vrgui.hpp"
#include "vrenvironment.hpp"
#include "vrinputmanager.hpp"
#include "openxrmanager.hpp"
@ -10,21 +12,12 @@
#include <components/sdlutil/sdlgraphicswindow.hpp>
#include <components/misc/stringops.hpp>
#include <Windows.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_platform_defines.h>
#include <openxr/openxr_reflection.h>
#include <osg/Camera>
#include <algorithm>
#include <vector>
#include <array>
#include <iostream>
#include "vrsession.hpp"
#include "vrgui.hpp"
#include <time.h>
#include <thread>