Skip to content

Commit

Permalink
Add xr::DispatchTable for XrUtility (#104)
Browse files Browse the repository at this point in the history
* Add xr::DispatchTable for XrUtility

Add xr::DispatchTable for XrUtility to support libraries that lazily loads openxr_loader without static link to xrFunctions.

Also simplify how to call extension functions through global dispatch table.

* Add all XrUtility headers to solutions
  • Loading branch information
Darryl Gough authored Mar 26, 2022
1 parent e8089f3 commit aad27c8
Show file tree
Hide file tree
Showing 44 changed files with 807 additions and 397 deletions.
22 changes: 19 additions & 3 deletions BasicXrApp.sln
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.421
# Visual Studio Version 16
VisualStudioVersion = 16.0.32228.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicXrApp_uwp", "samples\BasicXrApp\BasicXrApp_uwp.vcxproj", "{1B09B21C-2D7A-4278-81C8-84A47D5834A7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicXrApp_win32", "samples\BasicXrApp\BasicXrApp_win32.vcxproj", "{A75A907B-8952-4ED2-BC2D-A68F09CEBD83}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xrUtility", "xrUtility", "{D71728CE-842F-4FA7-94AE-01AEA60BC45A}"
ProjectSection(SolutionItems) = preProject
shared\XrUtility\XrDispatchTable.h = shared\XrUtility\XrDispatchTable.h
shared\XrUtility\XrEnumerate.h = shared\XrUtility\XrEnumerate.h
shared\XrUtility\XrError.h = shared\XrUtility\XrError.h
shared\XrUtility\XrExtensions.h = shared\XrUtility\XrExtensions.h
shared\XrUtility\XrExtensionContext.h = shared\XrUtility\XrExtensionContext.h
shared\XrUtility\XrExtensionDefined.h = shared\XrUtility\XrExtensionDefined.h
shared\XrUtility\XrGuid.h = shared\XrUtility\XrGuid.h
shared\XrUtility\XrHandle.h = shared\XrUtility\XrHandle.h
shared\XrUtility\XrListFunctions.h = shared\XrUtility\XrListFunctions.h
shared\XrUtility\XrMath.h = shared\XrUtility\XrMath.h
shared\XrUtility\XrPlatformDependencies.h = shared\XrUtility\XrPlatformDependencies.h
shared\XrUtility\XrSceneUnderstanding.h = shared\XrUtility\XrSceneUnderstanding.h
shared\XrUtility\XrSceneUnderstanding.hpp = shared\XrUtility\XrSceneUnderstanding.hpp
shared\XrUtility\XrSceneUnderstandingSerialization.hpp = shared\XrUtility\XrSceneUnderstandingSerialization.hpp
shared\XrUtility\XrSide.h = shared\XrUtility\XrSide.h
shared\XrUtility\XrSpatialGraphBridge.h = shared\XrUtility\XrSpatialGraphBridge.h
shared\XrUtility\XrStereoView.h = shared\XrUtility\XrStereoView.h
shared\XrUtility\XrString.h = shared\XrUtility\XrString.h
shared\XrUtility\XrStruct.h = shared\XrUtility\XrStruct.h
shared\XrUtility\XrToString.h = shared\XrUtility\XrToString.h
shared\XrUtility\XrUuid.h = shared\XrUtility\XrUuid.h
shared\XrUtility\XrViewConfiguration.h = shared\XrUtility\XrViewConfiguration.h
EndProjectSection
EndProject
Global
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ over the coming months.

- **The core OpenXR API usage patterns** <br/>
can be found in the [BasicXrApp/OpenXRProgram.cpp](https://github.com/microsoft/OpenXR-MixedReality/blob/main/samples/BasicXrApp/OpenXrProgram.cpp) file.
The [Run() function](https://github.com/microsoft/OpenXR-MixedReality/blob/main/samples/BasicXrApp/OpenXrProgram.cpp#L15)
The [Run() function](https://github.com/microsoft/OpenXR-MixedReality/blob/main/samples/BasicXrApp/OpenXrProgram.cpp#L28)
captures a typical OpenXR app code flow for session initialization, event handling, the frame loop and input actions.

- **Hand tracking** <br/>
Expand Down
9 changes: 8 additions & 1 deletion Samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,30 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XrUtility", "XrUtility", "{AF0F6DD8-1BC3-4818-919E-9B239B544B5E}"
ProjectSection(SolutionItems) = preProject
shared\XrUtility\XrActionContext.h = shared\XrUtility\XrActionContext.h
shared\XrUtility\XrDispatchTable.h = shared\XrUtility\XrDispatchTable.h
shared\XrUtility\XrEnumerate.h = shared\XrUtility\XrEnumerate.h
shared\XrUtility\XrError.h = shared\XrUtility\XrError.h
shared\XrUtility\XrExtensionContext.h = shared\XrUtility\XrExtensionContext.h
shared\XrUtility\XrExtensions.h = shared\XrUtility\XrExtensions.h
shared\XrUtility\XrExtensionDefined.h = shared\XrUtility\XrExtensionDefined.h
shared\XrUtility\XrGuid.h = shared\XrUtility\XrGuid.h
shared\XrUtility\XrHandle.h = shared\XrUtility\XrHandle.h
shared\XrUtility\XrInstanceContext.h = shared\XrUtility\XrInstanceContext.h
shared\XrUtility\XrListFunctions.h = shared\XrUtility\XrListFunctions.h
shared\XrUtility\XrMath.h = shared\XrUtility\XrMath.h
shared\XrUtility\XrPlatformDependencies.h = shared\XrUtility\XrPlatformDependencies.h
shared\XrUtility\XrSceneUnderstanding.h = shared\XrUtility\XrSceneUnderstanding.h
shared\XrUtility\XrSceneUnderstanding.hpp = shared\XrUtility\XrSceneUnderstanding.hpp
shared\XrUtility\XrSceneUnderstandingSerialization.h = shared\XrUtility\XrSceneUnderstandingSerialization.h
shared\XrUtility\XrSceneUnderstandingSerialization.hpp = shared\XrUtility\XrSceneUnderstandingSerialization.hpp
shared\XrUtility\XrSessionContext.h = shared\XrUtility\XrSessionContext.h
shared\XrUtility\XrSide.h = shared\XrUtility\XrSide.h
shared\XrUtility\XrSpatialGraphBridge.h = shared\XrUtility\XrSpatialGraphBridge.h
shared\XrUtility\XrStereoView.h = shared\XrUtility\XrStereoView.h
shared\XrUtility\XrString.h = shared\XrUtility\XrString.h
shared\XrUtility\XrStruct.h = shared\XrUtility\XrStruct.h
shared\XrUtility\XrSystemContext.h = shared\XrUtility\XrSystemContext.h
shared\XrUtility\XrToString.h = shared\XrUtility\XrToString.h
shared\XrUtility\XrUuid.h = shared\XrUtility\XrUuid.h
shared\XrUtility\XrViewConfiguration.h = shared\XrUtility\XrViewConfiguration.h
EndProjectSection
EndProject
Expand Down
40 changes: 18 additions & 22 deletions samples/BasicXrApp/OpenXrProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ namespace {

createInfo.applicationInfo = {"BasicXrApp", 1, "", 1, XR_CURRENT_API_VERSION};
strcpy_s(createInfo.applicationInfo.applicationName, m_applicationName.c_str());
CHECK_XRCMD(xrCreateInstance(&createInfo, m_instance.Put()));
CHECK_XRCMD(xrCreateInstance(&createInfo, m_instance.Put(xrDestroyInstance)));

m_extensions.PopulateDispatchTable(m_instance.Get());
xr::g_dispatchTable.Initialize(m_instance.Get(), xrGetInstanceProcAddr);
}

std::vector<const char*> SelectExtensions() {
Expand Down Expand Up @@ -109,7 +109,7 @@ namespace {
XrActionSetCreateInfo actionSetInfo{XR_TYPE_ACTION_SET_CREATE_INFO};
strcpy_s(actionSetInfo.actionSetName, "place_hologram_action_set");
strcpy_s(actionSetInfo.localizedActionSetName, "Placement");
CHECK_XRCMD(xrCreateActionSet(m_instance.Get(), &actionSetInfo, m_actionSet.Put()));
CHECK_XRCMD(xrCreateActionSet(m_instance.Get(), &actionSetInfo, m_actionSet.Put(xrDestroyActionSet)));
}

// Create actions.
Expand All @@ -126,7 +126,7 @@ namespace {
strcpy_s(actionInfo.localizedActionName, "Place Hologram");
actionInfo.countSubactionPaths = (uint32_t)m_subactionPaths.size();
actionInfo.subactionPaths = m_subactionPaths.data();
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_placeAction.Put()));
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_placeAction.Put(xrDestroyAction)));
}

// Create an input action getting the left and right hand poses.
Expand All @@ -137,7 +137,7 @@ namespace {
strcpy_s(actionInfo.localizedActionName, "Hand Pose");
actionInfo.countSubactionPaths = (uint32_t)m_subactionPaths.size();
actionInfo.subactionPaths = m_subactionPaths.data();
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_poseAction.Put()));
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_poseAction.Put(xrDestroyAction)));
}

// Create an output action for vibrating the left and right controller.
Expand All @@ -148,7 +148,7 @@ namespace {
strcpy_s(actionInfo.localizedActionName, "Vibrate");
actionInfo.countSubactionPaths = (uint32_t)m_subactionPaths.size();
actionInfo.subactionPaths = m_subactionPaths.data();
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_vibrateAction.Put()));
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_vibrateAction.Put(xrDestroyAction)));
}

// Create an input action to exit the session.
Expand All @@ -159,7 +159,7 @@ namespace {
strcpy_s(actionInfo.localizedActionName, "Exit session");
actionInfo.countSubactionPaths = (uint32_t)m_subactionPaths.size();
actionInfo.subactionPaths = m_subactionPaths.data();
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_exitAction.Put()));
CHECK_XRCMD(xrCreateAction(m_actionSet.Get(), &actionInfo, m_exitAction.Put(xrDestroyAction)));
}
}

Expand All @@ -183,8 +183,7 @@ namespace {
}

// Set up suggested bindings for the hp/mixed_reality_controller profile.
if (m_optionalExtensions.HPMRControllerSupported)
{
if (m_optionalExtensions.HPMRControllerSupported) {
std::vector<XrActionSuggestedBinding> bindings;
bindings.push_back({m_placeAction.Get(), GetXrPath("/user/hand/right/input/trigger/value")});
bindings.push_back({m_placeAction.Get(), GetXrPath("/user/hand/left/input/trigger/value")});
Expand All @@ -203,8 +202,7 @@ namespace {
}

// Set up suggested bindings for the microsoft/hand_interaction profile.
if (m_optionalExtensions.MsftHandInteractionSupported)
{
if (m_optionalExtensions.MsftHandInteractionSupported) {
std::vector<XrActionSuggestedBinding> bindings;
bindings.push_back({m_placeAction.Get(), GetXrPath("/user/hand/right/input/select/value")});
bindings.push_back({m_placeAction.Get(), GetXrPath("/user/hand/left/input/select/value")});
Expand Down Expand Up @@ -267,7 +265,7 @@ namespace {

// Create the D3D11 device for the adapter associated with the system.
XrGraphicsRequirementsD3D11KHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
CHECK_XRCMD(m_extensions.xrGetD3D11GraphicsRequirementsKHR(m_instance.Get(), m_systemId, &graphicsRequirements));
CHECK_XRCMD(xrGetD3D11GraphicsRequirementsKHR(m_instance.Get(), m_systemId, &graphicsRequirements));

// Create a list of feature levels which are both supported by the OpenXR runtime and this application.
std::vector<D3D_FEATURE_LEVEL> featureLevels = {D3D_FEATURE_LEVEL_12_1,
Expand All @@ -290,7 +288,7 @@ namespace {
XrSessionCreateInfo createInfo{XR_TYPE_SESSION_CREATE_INFO};
createInfo.next = &graphicsBinding;
createInfo.systemId = m_systemId;
CHECK_XRCMD(xrCreateSession(m_instance.Get(), &createInfo, m_session.Put()));
CHECK_XRCMD(xrCreateSession(m_instance.Get(), &createInfo, m_session.Put(xrDestroySession)));

XrSessionActionSetsAttachInfo attachInfo{XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO};
std::vector<XrActionSet> actionSets = {m_actionSet.Get()};
Expand Down Expand Up @@ -318,7 +316,7 @@ namespace {
XrReferenceSpaceCreateInfo spaceCreateInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
spaceCreateInfo.referenceSpaceType = m_appSpaceType;
spaceCreateInfo.poseInReferenceSpace = xr::math::Pose::Identity();
CHECK_XRCMD(xrCreateReferenceSpace(m_session.Get(), &spaceCreateInfo, m_appSpace.Put()));
CHECK_XRCMD(xrCreateReferenceSpace(m_session.Get(), &spaceCreateInfo, m_appSpace.Put(xrDestroySpace)));
}

// Create a space for each hand pointer pose.
Expand All @@ -327,7 +325,7 @@ namespace {
createInfo.action = m_poseAction.Get();
createInfo.poseInActionSpace = xr::math::Pose::Identity();
createInfo.subactionPath = m_subactionPaths[side];
CHECK_XRCMD(xrCreateActionSpace(m_session.Get(), &createInfo, m_cubesInHand[side].Space.Put()));
CHECK_XRCMD(xrCreateActionSpace(m_session.Get(), &createInfo, m_cubesInHand[side].Space.Put(xrDestroySpace)));
}
}

Expand Down Expand Up @@ -450,7 +448,7 @@ namespace {
swapchainCreateInfo.createFlags = createFlags;
swapchainCreateInfo.usageFlags = usageFlags;

CHECK_XRCMD(xrCreateSwapchain(session, &swapchainCreateInfo, swapchain.Handle.Put()));
CHECK_XRCMD(xrCreateSwapchain(session, &swapchainCreateInfo, swapchain.Handle.Put(xrDestroySwapchain)));

uint32_t chainLength;
CHECK_XRCMD(xrEnumerateSwapchainImages(swapchain.Handle.Get(), 0, &chainLength, nullptr));
Expand Down Expand Up @@ -535,13 +533,12 @@ namespace {
createInfo.pose = poseInAppSpace;
createInfo.time = placementTime;

XrResult result = m_extensions.xrCreateSpatialAnchorMSFT(
m_session.Get(), &createInfo, hologram.Anchor.Put(m_extensions.xrDestroySpatialAnchorMSFT));
XrResult result = xrCreateSpatialAnchorMSFT(m_session.Get(), &createInfo, hologram.Anchor.Put(xrDestroySpatialAnchorMSFT));
if (XR_SUCCEEDED(result)) {
XrSpatialAnchorSpaceCreateInfoMSFT createSpaceInfo{XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT};
createSpaceInfo.anchor = hologram.Anchor.Get();
createSpaceInfo.poseInAnchorSpace = xr::math::Pose::Identity();
CHECK_XRCMD(m_extensions.xrCreateSpatialAnchorSpaceMSFT(m_session.Get(), &createSpaceInfo, hologram.Cube.Space.Put()));
CHECK_XRCMD(xrCreateSpatialAnchorSpaceMSFT(m_session.Get(), &createSpaceInfo, hologram.Cube.Space.Put(xrDestroySpace)));
} else if (result == XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT) {
DEBUG_PRINT("Anchor cannot be created, likely due to lost positional tracking.");
} else {
Expand All @@ -553,7 +550,7 @@ namespace {
XrReferenceSpaceCreateInfo createInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
createInfo.referenceSpaceType = m_appSpaceType;
createInfo.poseInReferenceSpace = poseInAppSpace;
CHECK_XRCMD(xrCreateReferenceSpace(m_session.Get(), &createInfo, hologram.Cube.Space.Put()));
CHECK_XRCMD(xrCreateReferenceSpace(m_session.Get(), &createInfo, hologram.Cube.Space.Put(xrDestroySpace)));
}
return hologram;
}
Expand Down Expand Up @@ -707,7 +704,7 @@ namespace {
XrReferenceSpaceCreateInfo createInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
createInfo.referenceSpaceType = referenceSpaceType;
createInfo.poseInReferenceSpace = poseInReferenceSpace;
CHECK_XRCMD(xrCreateReferenceSpace(session, &createInfo, space.Put()));
CHECK_XRCMD(xrCreateReferenceSpace(session, &createInfo, space.Put(xrDestroySpace)));
return space;
};

Expand Down Expand Up @@ -890,7 +887,6 @@ namespace {
xr::InstanceHandle m_instance;
xr::SessionHandle m_session;
uint64_t m_systemId{XR_NULL_SYSTEM_ID};
xr::ExtensionDispatchTable m_extensions;

struct {
bool DepthExtensionSupported{false};
Expand Down
4 changes: 3 additions & 1 deletion samples/BasicXrApp/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
#define XR_USE_GRAPHICS_API_D3D11
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_reflection.h>

#define ENABLE_GLOBAL_XR_DISPATCH_TABLE
#include <XrUtility/XrDispatchTable.h>
#include <XrUtility/XrError.h>
#include <XrUtility/XrHandle.h>
#include <XrUtility/XrMath.h>
#include <XrUtility/XrString.h>
#include <XrUtility/XrExtensions.h>

#include <winrt/base.h> // winrt::com_ptr
24 changes: 18 additions & 6 deletions samples/EyeGazeInteractionUwp/Scene_EyeGazeInteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ namespace {

struct EyeGazeInteractionScene : public engine::Scene {
EyeGazeInteractionScene(engine::Context& context)
: Scene(context) {
const bool supportsEyeGazeAction =
context.Extensions.SupportsEyeGazeInteraction && context.System.EyeGazeInteractionProperties.supportsEyeGazeInteraction;
if (supportsEyeGazeAction) {
: Scene(context)
, m_supportsEyeGazeAction(context.Extensions.SupportsEyeGazeInteraction &&
context.System.EyeGazeInteractionProperties.supportsEyeGazeInteraction) {
if (m_supportsEyeGazeAction) {
sample::ActionSet& actionSet =
ActionContext().CreateActionSet("eye_gaze_interaction_scene_actions", "Eye Gaze Interaction Scene Actions");

Expand All @@ -47,13 +47,13 @@ namespace {
XrActionSpaceCreateInfo createInfo{XR_TYPE_ACTION_SPACE_CREATE_INFO};
createInfo.action = gazeAction;
createInfo.poseInActionSpace = Pose::Identity();
CHECK_XRCMD(xrCreateActionSpace(m_context.Session.Handle, &createInfo, m_gazeSpace.Put()));
CHECK_XRCMD(xrCreateActionSpace(m_context.Session.Handle, &createInfo, m_gazeSpace.Put(xrDestroySpace)));
} else {
// Use VIEW reference space to simulate eye gaze when the system doesn't support
XrReferenceSpaceCreateInfo createInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
createInfo.poseInReferenceSpace = Pose::Identity();
CHECK_XRCMD(xrCreateReferenceSpace(m_context.Session.Handle, &createInfo, m_gazeSpace.Put()));
CHECK_XRCMD(xrCreateReferenceSpace(m_context.Session.Handle, &createInfo, m_gazeSpace.Put(xrDestroySpace)));
}

m_gazeObject = AddObject(engine::CreateObject());
Expand Down Expand Up @@ -83,6 +83,17 @@ namespace {
XrSpaceLocation location{XR_TYPE_SPACE_LOCATION};
CHECK_XRCMD(xrLocateSpace(m_gazeSpace.Get(), m_context.AppSpace, frameTime.PredictedDisplayTime, &location));

// eye gaze sample time validation
if (m_supportsEyeGazeAction) {
XrEyeGazeSampleTimeEXT eyeGazeSampleTime{XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT};
XrSpaceLocation testLocation{XR_TYPE_SPACE_LOCATION, &eyeGazeSampleTime};
CHECK_XRCMD(xrLocateSpace(m_gazeSpace.Get(), m_context.AppSpace, frameTime.PredictedDisplayTime, &testLocation));
CHECK_XRCMD(xrLocateSpace(m_context.AppSpace, m_gazeSpace.Get(), frameTime.PredictedDisplayTime, &testLocation));
CHECK_XRCMD(xrLocateSpace(m_gazeSpace.Get(), m_gazeSpace.Get(), frameTime.PredictedDisplayTime, &testLocation));
assert(XR_ERROR_VALIDATION_FAILURE ==
xrLocateSpace(m_context.AppSpace, m_context.AppSpace, frameTime.PredictedDisplayTime, &testLocation));
}

if (Pose::IsPoseValid(location)) {
m_gazeObject->SetVisible(true);
m_gazeObject->Pose() = location.pose;
Expand All @@ -100,6 +111,7 @@ namespace {
}

private:
const bool m_supportsEyeGazeAction{false};
xr::SpaceHandle m_gazeSpace;
std::shared_ptr<engine::Object> m_gazeObject;
std::shared_ptr<engine::Object> m_gazeLookAtAxis;
Expand Down
3 changes: 3 additions & 0 deletions samples/EyeGazeInteractionUwp/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
#define XR_USE_GRAPHICS_API_D3D11
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr/openxr_reflection.h>

#define ENABLE_GLOBAL_XR_DISPATCH_TABLE
#include <XrUtility/XrDispatchTable.h>
#include <XrUtility/XrError.h>
#include <XrUtility/XrMath.h>
#include <SampleShared/Trace.h>
Expand Down
1 change: 1 addition & 0 deletions samples/SampleSceneUwp/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace {
appConfig.RequestedExtensions.push_back(XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME);
appConfig.RequestedExtensions.push_back(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME);
appConfig.RequestedExtensions.push_back(XR_EXT_HAND_TRACKING_EXTENSION_NAME);
appConfig.RequestedExtensions.push_back(XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME);
appConfig.RequestedExtensions.push_back(XR_MSFT_HAND_TRACKING_MESH_EXTENSION_NAME);

// NOTE: Uncomment a filter below to test specific action binding of given profile.
Expand Down
Loading

0 comments on commit aad27c8

Please sign in to comment.