Skip to content

Commit c3def0c

Browse files
author
Khasreto
authored
Merge branch 'o3de:development' into development
2 parents 2044499 + a30927e commit c3def0c

File tree

59 files changed

+1306
-550
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1306
-550
lines changed

Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkDevice.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,5 @@ namespace OpenXRVk
7979
XrCompositionLayerProjection m_xrLayer{ XR_TYPE_COMPOSITION_LAYER_PROJECTION };
8080
AZStd::vector<XrCompositionLayerProjectionView> m_projectionLayerViews;
8181
AZStd::vector<XrView> m_views;
82-
uint32_t m_viewCountOutput = 0;
8382
};
8483
}

Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkInput.h

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
namespace OpenXRVk
1818
{
19+
class Device;
20+
1921
// Class that will help manage XrActionSet/XrAction
2022
class Input final
2123
: public XR::Input
@@ -24,10 +26,25 @@ namespace OpenXRVk
2426
AZ_CLASS_ALLOCATOR(Input, AZ::SystemAllocator);
2527
AZ_RTTI(Input, "{97ADD1FE-27DF-4F36-9F61-683F881F9477}", XR::Input);
2628

29+
static constexpr char LogName[] = "OpenXRVkInput";
30+
2731
static XR::Ptr<Input> Create();
2832

29-
//! Sync all the actions and update controller
30-
//! as well as various tracked space poses
33+
//! Called by the session when the predicted display time has been updated (typically
34+
//! the device updates the predicted display time during BeginFrame).
35+
//! \param[in] device The device that emitted this event.
36+
//! \param[in] predictedTime The predicted display time for the current frame.
37+
//! \param[out] xrViews Vector where each Eye Pose will be stored. Eye poses are always relative to the VIEW space.
38+
//! The VIEW pose typically represents the pose of the Head (The Head is typically centered
39+
//! between both eyes). Subscript 0 is the left eye, while subscript 1 is the right eye.
40+
//! Returns true if the number of Eye Poses matches the size of @xrViews.
41+
bool UpdateXrSpaceLocations(const OpenXRVk::Device& device, XrTime predictedDisplayTime, AZStd::vector<XrView>& xrViews);
42+
43+
//! Sync all the actions and update controller.
44+
//! REMARK: XrPoses are not updated in this function. Instead, poses are updated upon UpdateXrSpaceLocations().
45+
//! Why? Because PollActions() is called on the main thread outside of the BeginFrame()/EndFrame() loop.
46+
//! This means the if Poses are updated during PollActions(), those poses would be using the predicted display time
47+
//! of the previous frame instead of the current frame.
3148
void PollActions();
3249

3350
//! Initialize various actions/actions sets and add support for Oculus touch bindings
@@ -39,20 +56,30 @@ namespace OpenXRVk
3956
//! Attach action sets
4057
AZ::RHI::ResultCode InitializeActionSets(XrSession xrSession) const;
4158

42-
//! Update Controller space information
59+
//! Updates a Controller/Joystick pose.
4360
void LocateControllerSpace(XrTime predictedDisplayTime, XrSpace baseSpace, AZ::u32 handIndex);
4461

45-
//! Update information for a specific tracked space type (i.e visualizedSpaceType)
62+
//! Update pose information for the view.
4663
void LocateVisualizedSpace(XrTime predictedDisplayTime, XrSpace space, XrSpace baseSpace, OpenXRVk::SpaceType visualizedSpaceType);
4764

4865
//! Return Pose data for a controller attached to a hand index
49-
AZ::RHI::ResultCode GetControllerPose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const;
66+
//! By default the pose data is converted per O3DE convention: Xright, Yfront, Zup.
67+
//! You can read the raw XR Pose data by setting @convertToO3de to false (Not recommended, but useful for debugging).
68+
AZ::RHI::ResultCode GetControllerPose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData, bool convertToO3de = true) const;
69+
70+
//! Same as above but returns the pose data as an AZ::Transform. The AZ::Transform also includes the controller scale.
71+
AZ::RHI::ResultCode GetControllerTransform(AZ::u32 handIndex, AZ::Transform& outTransform, bool convertToO3de = true) const;
5072

51-
//! Return scale for a controller attached to a hand index
73+
//! Returns scale for a controller attached to a hand index
5274
float GetControllerScale(AZ::u32 handIndex) const;
5375

54-
//! Return Pose data for a tracked space type (i.e visualizedSpaceType)
55-
AZ::RHI::ResultCode GetVisualizedSpacePose(OpenXRVk::SpaceType visualizedSpaceType, AZ::RPI::PoseData& outPoseData) const;
76+
//! Return Pose data for a tracked space type (i.e visualizedSpaceType).
77+
//! By default the pose data is converted per O3DE convention: Xright, Yfront, Zup.
78+
//! You can read the raw XR Pose data by setting @convertToO3de to false (Not recommended, but useful for debugging).
79+
AZ::RHI::ResultCode GetVisualizedSpacePose(OpenXRVk::SpaceType visualizedSpaceType, AZ::RPI::PoseData& outPoseData, bool convertToO3de = true) const;
80+
81+
//! Same as above but returns the pose data as an AZ::Transform
82+
AZ::RHI::ResultCode GetVisualizedSpaceTransform(OpenXRVk::SpaceType visualizedSpaceType, AZ::Transform& outTransform, bool convertToO3de = true) const;
5683

5784
//! Get the Squeeze action
5885
XrAction GetSqueezeAction(AZ::u32 handIndex) const;
@@ -107,6 +134,9 @@ namespace OpenXRVk
107134
//! Destroy native objects
108135
void ShutdownInternal() override;
109136

137+
//! Returns true if the number of Eye Poses matches the size of @xrViews.
138+
bool LocateEyeViews(XrTime predictedDisplayTime, AZStd::vector<XrView>& xrViews);
139+
110140
XrActionSet m_actionSet{ XR_NULL_HANDLE };
111141

112142
XrAction m_hapticAction{};

Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSession.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ namespace OpenXRVk
4040
//! Return the Xrspace related to the SpaceType enum
4141
XrSpace GetXrSpace(SpaceType spaceType) const;
4242

43+
////////////////////////////////////////////////////////////////////////////////////////////
44+
//! Called by a Device when the predicted display time has been updated (typically
45+
//! the device updates the predicted display time during BeginFrame).
46+
//! See OpenXRVkInput.h UpdateXrSpaceLocations(...) for more details.
47+
void UpdateXrSpaceLocations(const OpenXRVk::Device& device, XrTime predictedDisplayTime, AZStd::vector<XrView>& xrViews);
48+
49+
//! Setters and Getters for the base spaces that will be used
50+
//! when calling xrLocateSpace().
51+
//! By default, the base space for visualization is SpaceType::Local
52+
//! and the base space for Joysticks/controllers is SpaceType::View (aka the Head)
53+
void SetBaseSpaceTypeForVisualization(SpaceType spaceType);
54+
void SetBaseSpaceTypeForControllers(SpaceType spaceType);
55+
SpaceType GetBaseSpaceTypeForVisualization() const;
56+
SpaceType GetBaseSpaceTypeForControllers() const;
57+
4358
//////////////////////////////////////////////////////////////////////////
4459
// XR::Session overrides
4560
AZ::RHI::ResultCode InitInternal(AZ::RHI::XRSessionDescriptor* descriptor) override;
@@ -50,6 +65,7 @@ namespace OpenXRVk
5065
void PollEvents() override;
5166
void LocateControllerSpace(AZ::u32 handIndex) override;
5267
AZ::RHI::ResultCode GetControllerPose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const override;
68+
AZ::RHI::ResultCode GetControllerTransform(AZ::u32 handIndex, AZ::Transform& outTransform) const override;
5369
AZ::RHI::ResultCode GetControllerStagePose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const override;
5470
AZ::RHI::ResultCode GetViewFrontPose(AZ::RPI::PoseData& outPoseData) const override;
5571
AZ::RHI::ResultCode GetViewLocalPose(AZ::RPI::PoseData& outPoseData) const override;
@@ -68,12 +84,25 @@ namespace OpenXRVk
6884
void ShutdownInternal() override;
6985
void LogActionSourceName(XrAction action, const AZStd::string_view actionName) const;
7086
Input* GetNativeInput() const;
87+
// Spaces are reset every time the proximity sensor turns off, or the user wears the headset
88+
// when the proximity sensor is ON.
89+
void ResetSpaces();
7190

7291
XrSession m_session = XR_NULL_HANDLE;
7392
XrSessionState m_sessionState = XR_SESSION_STATE_UNKNOWN;
7493
XrEventDataBuffer m_eventDataBuffer;
7594
XrInstance m_xrInstance = XR_NULL_HANDLE;
7695
XrGraphicsBindingVulkan2KHR m_graphicsBinding{ XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR };
96+
97+
// Application defined base space that will used to calculate
98+
// the relative pose of all other spaces.
99+
// Typically SpaceType::Local or SpaceType::Stage.
100+
SpaceType m_baseSpaceTypeForVisualization = SpaceType::Local;
101+
102+
// Application defined base space that will use to calculate
103+
// the relative pose of the joysticks (aka XR Controllers).
104+
// Typically SpaceType::View, but could be SpaceType::Local or SpaceType::Stage.
105+
SpaceType m_baseSpaceTypeForControllers = SpaceType::View;
77106

78107
bool m_sessionRunning = false;
79108
bool m_exitRenderLoop = false;

Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkUtils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
#pragma once
1010

11+
#include <AzCore/Math/Transform.h>
1112
#include <OpenXRVk_Platform.h>
1213
#include <XR/XRBase.h>
1314

15+
1416
// Macro to generate stringify functions for OpenXR enumerations based data provided in openxr_reflection.h
1517
#define ENUM_CASE_STR(name, val) case name: return #name;
1618
#define MAKE_XR_TO_STRING_FUNC(enumType) \
@@ -63,4 +65,10 @@ namespace OpenXRVk
6365
//! Iterate through the characters while caching the starting pointer to a string
6466
//! and every time ' ' is encountered replace it with '\0' to indicate the end of a string.
6567
AZStd::vector<const char*> ParseExtensionString(char* names);
68+
69+
AZ::Quaternion AzQuaternionFromXrPose(const XrPosef& pose, bool convertCoordinates = true);
70+
AZ::Vector3 AzPositionFromXrPose(const XrPosef& pose, bool convertCoordinates = true);
71+
AZ::Transform AzTransformFromXrPose(const XrPosef& pose, bool convertCoordinates = true);
72+
XrPosef XrPoseFromAzTransform(const AZ::Transform& tm, bool convertCoordinates = true);
73+
6674
}

Gems/OpenXRVk/Code/Source/OpenXRVkDevice.cpp

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ namespace OpenXRVk
5252
{
5353
WARN_IF_UNSUCCESSFUL(result);
5454
}
55+
56+
// Notify the input system that we have a new predicted display time.
57+
// The new predicted display time will be used to calculate XrPoses for the current frame.
58+
session->UpdateXrSpaceLocations(*this, m_frameState.predictedDisplayTime, m_views);
59+
5560
//Always return true as we want EndFrame to always be called.
5661
return true;
5762
}
@@ -112,36 +117,10 @@ namespace OpenXRVk
112117
{
113118
XR::SwapChain::View* baseSwapChainView = baseSwapChain->GetView(viewIndex);
114119
SwapChain::View* swapChainView = static_cast<SwapChain::View*>(baseSwapChainView);
115-
Space* xrSpace = static_cast<Space*>(GetSession()->GetSpace());
116-
Instance* instance = static_cast<Instance*>(GetDescriptor().m_instance.get());
117-
Session* session = static_cast<Session*>(GetSession().get());
118-
XrSession xrSession = session->GetXrSession();
119120
XrSwapchain swapChainHandle = swapChainView->GetSwapChainHandle();
120121

121-
XrViewState viewState{ XR_TYPE_VIEW_STATE };
122-
uint32_t viewCapacityInput = aznumeric_cast<uint32_t>(m_views.size());
123-
124-
XrViewLocateInfo viewLocateInfo{ XR_TYPE_VIEW_LOCATE_INFO };
125-
viewLocateInfo.viewConfigurationType = instance->GetViewConfigType();
126-
viewLocateInfo.displayTime = m_frameState.predictedDisplayTime;
127-
viewLocateInfo.space = xrSpace->GetXrSpace(OpenXRVk::SpaceType::View);
128-
129-
XrResult result = xrLocateViews(xrSession, &viewLocateInfo, &viewState, viewCapacityInput, &m_viewCountOutput, m_views.data());
130-
ASSERT_IF_UNSUCCESSFUL(result);
131-
132-
if ((viewState.viewStateFlags & XR_VIEW_STATE_POSITION_VALID_BIT) == 0 ||
133-
(viewState.viewStateFlags & XR_VIEW_STATE_ORIENTATION_VALID_BIT) == 0)
134-
{
135-
//There is no valid tracking poses for the views
136-
return false;
137-
}
138-
139-
AZ_Assert(m_viewCountOutput == viewCapacityInput, "Size mismatch between xrLocateViews %i and xrEnumerateViewConfigurationViews %i", m_viewCountOutput, viewCapacityInput);
140-
AZ_Assert(m_viewCountOutput == static_cast<SwapChain*>(baseSwapChain)->GetViewConfigs().size(), "Size mismatch between xrLocateViews %i and xrEnumerateViewConfigurationViews %i", m_viewCountOutput, static_cast<SwapChain*>(baseSwapChain)->GetViewConfigs().size());
141-
142-
m_projectionLayerViews.resize(m_viewCountOutput);
143122
XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
144-
result = xrAcquireSwapchainImage(swapChainHandle, &acquireInfo, &baseSwapChainView->m_activeImageIndex);
123+
auto result = xrAcquireSwapchainImage(swapChainHandle, &acquireInfo, &baseSwapChainView->m_activeImageIndex);
145124
baseSwapChainView->m_isImageAcquired = (result == XR_SUCCESS);
146125
WARN_IF_UNSUCCESSFUL(result);
147126

@@ -150,6 +129,9 @@ namespace OpenXRVk
150129
result = xrWaitSwapchainImage(swapChainHandle, &waitInfo);
151130
ASSERT_IF_UNSUCCESSFUL(result);
152131

132+
// REMARK: The data in m_views was updated during BeginFrameInternal(), which
133+
// calls session->UpdateXrSpaceLocations(...).
134+
m_projectionLayerViews.resize(m_views.size());
153135
m_projectionLayerViews[viewIndex] = { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW };
154136
m_projectionLayerViews[viewIndex].pose = m_views[viewIndex].pose;
155137
m_projectionLayerViews[viewIndex].fov = m_views[viewIndex].fov;
@@ -189,30 +171,23 @@ namespace OpenXRVk
189171

190172
AZ::RHI::ResultCode Device::GetViewFov(AZ::u32 viewIndex, AZ::RPI::FovData& outFovData) const
191173
{
192-
if(viewIndex < m_projectionLayerViews.size())
174+
if(viewIndex < m_views.size())
193175
{
194-
outFovData.m_angleLeft = m_projectionLayerViews[viewIndex].fov.angleLeft;
195-
outFovData.m_angleRight = m_projectionLayerViews[viewIndex].fov.angleRight;
196-
outFovData.m_angleUp = m_projectionLayerViews[viewIndex].fov.angleUp;
197-
outFovData.m_angleDown = m_projectionLayerViews[viewIndex].fov.angleDown;
176+
outFovData.m_angleLeft = m_views[viewIndex].fov.angleLeft;
177+
outFovData.m_angleRight = m_views[viewIndex].fov.angleRight;
178+
outFovData.m_angleUp = m_views[viewIndex].fov.angleUp;
179+
outFovData.m_angleDown = m_views[viewIndex].fov.angleDown;
198180
return AZ::RHI::ResultCode::Success;
199181
}
200182
return AZ::RHI::ResultCode::Fail;
201183
}
202184

203185
AZ::RHI::ResultCode Device::GetViewPose(AZ::u32 viewIndex, AZ::RPI::PoseData& outPoseData) const
204186
{
205-
if (viewIndex < m_projectionLayerViews.size())
187+
if (viewIndex < m_views.size())
206188
{
207-
const XrQuaternionf& orientation = m_projectionLayerViews[viewIndex].pose.orientation;
208-
const XrVector3f& position = m_projectionLayerViews[viewIndex].pose.position;
209-
outPoseData.m_orientation.Set(orientation.x,
210-
orientation.y,
211-
orientation.z,
212-
orientation.w);
213-
outPoseData.m_position.Set(position.x,
214-
position.y,
215-
position.z);
189+
outPoseData.m_orientation = AzQuaternionFromXrPose(m_views[viewIndex].pose);
190+
outPoseData.m_position = AzPositionFromXrPose(m_views[viewIndex].pose);
216191
return AZ::RHI::ResultCode::Success;
217192
}
218193
return AZ::RHI::ResultCode::Fail;
@@ -231,4 +206,5 @@ namespace OpenXRVk
231206
m_xrVkDevice = VK_NULL_HANDLE;
232207
m_xrVkPhysicalDevice = VK_NULL_HANDLE;
233208
}
209+
234210
}

0 commit comments

Comments
 (0)