OpenXRVkInput.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <OpenXRVk/OpenXRVkInput.h>
  9. #include <OpenXRVk/OpenXRVkInstance.h>
  10. #include <OpenXRVk/OpenXRVkSession.h>
  11. #include <OpenXRVk/OpenXRVkDevice.h>
  12. #include <OpenXRVk/OpenXRVkSpace.h>
  13. #include <OpenXRVk/OpenXRVkUtils.h>
  14. #include <AzCore/Casting/numeric_cast.h>
  15. namespace OpenXRVk
  16. {
  17. XR::Ptr<Input> Input::Create()
  18. {
  19. const auto newInput = aznew Input;
  20. newInput->m_xrController.SetImplementation(&AzFramework::InputDeviceXRController::Implementation::Create);
  21. newInput->m_xrControllerImpl = newInput->m_xrController.GetImplementation();
  22. return newInput;
  23. }
  24. AZ::RHI::ResultCode Input::InitInternal()
  25. {
  26. const auto xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  27. const XrInstance xrInstance = xrVkInstance->GetXRInstance();
  28. // Create an action set.
  29. CreateActionSet(xrInstance);
  30. // Create all the XrActions
  31. CreateAllActions(xrInstance);
  32. // Bindings for the Oculus Touch.
  33. XrPath oculusTouchInteractionProfilePath;
  34. AZStd::string controllerProfilePath{ m_xrControllerImpl->GetInputDeviceProfilePath() };
  35. [[maybe_unused]] XrResult result = xrStringToPath(xrInstance, controllerProfilePath.data(), &oculusTouchInteractionProfilePath);
  36. WARN_IF_UNSUCCESSFUL(result);
  37. XrInteractionProfileSuggestedBinding suggestedBindings{};
  38. suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
  39. suggestedBindings.interactionProfile = oculusTouchInteractionProfilePath;
  40. suggestedBindings.suggestedBindings = m_xrActionPaths.data();
  41. suggestedBindings.countSuggestedBindings = aznumeric_cast<AZ::u32>(m_xrActionPaths.size());
  42. result = xrSuggestInteractionProfileBindings(xrInstance, &suggestedBindings);
  43. WARN_IF_UNSUCCESSFUL(result);
  44. //Init the location data so we dont read bad data when the device is in a bad state at start
  45. for (int i = 0; i < AZ::RPI::XRMaxNumControllers; i++)
  46. {
  47. m_handSpaceLocation[i].pose.orientation.x = 0.0f;
  48. m_handSpaceLocation[i].pose.orientation.y = 0.0f;
  49. m_handSpaceLocation[i].pose.orientation.z = 0.0f;
  50. m_handSpaceLocation[i].pose.orientation.w = 0.0f;
  51. m_handSpaceLocation[i].pose.position.x = 0.0f;
  52. m_handSpaceLocation[i].pose.position.y = 0.0f;
  53. m_handSpaceLocation[i].pose.position.z = 0.0f;
  54. }
  55. for (int i = 0; i < SpaceType::Count; i++)
  56. {
  57. m_xrVisualizedSpaceLocations[i].pose.orientation.x = 0.0f;
  58. m_xrVisualizedSpaceLocations[i].pose.orientation.y = 0.0f;
  59. m_xrVisualizedSpaceLocations[i].pose.orientation.z = 0.0f;
  60. m_xrVisualizedSpaceLocations[i].pose.orientation.w = 0.0f;
  61. m_xrVisualizedSpaceLocations[i].pose.position.x = 0.0f;
  62. m_xrVisualizedSpaceLocations[i].pose.position.y = 0.0f;
  63. m_xrVisualizedSpaceLocations[i].pose.position.z = 0.0f;
  64. }
  65. return ConvertResult(result);
  66. }
  67. void Input::CreateAction(XrAction& action, XrActionType actionType,
  68. const char* actionName, const char* localizedActionName,
  69. uint32_t countSubactionPathCount, const XrPath* subActionPaths) const
  70. {
  71. XrActionCreateInfo actionInfo{};
  72. actionInfo.type = XR_TYPE_ACTION_CREATE_INFO;
  73. actionInfo.actionType = actionType;
  74. azstrcpy(actionInfo.actionName, sizeof(actionInfo.actionName), actionName);
  75. azstrcpy(actionInfo.localizedActionName, sizeof(actionInfo.localizedActionName), localizedActionName);
  76. actionInfo.countSubactionPaths = countSubactionPathCount;
  77. actionInfo.subactionPaths = subActionPaths;
  78. [[maybe_unused]] const XrResult result = xrCreateAction(m_actionSet, &actionInfo, &action);
  79. WARN_IF_UNSUCCESSFUL(result);
  80. }
  81. void Input::CreateActionSet(const XrInstance& xrInstance)
  82. {
  83. // Create an action set.
  84. XrActionSetCreateInfo actionSetInfo{};
  85. actionSetInfo.type = XR_TYPE_ACTION_SET_CREATE_INFO;
  86. azstrcpy(actionSetInfo.actionSetName, sizeof(actionSetInfo.actionSetName), "gameplay");
  87. azstrcpy(actionSetInfo.localizedActionSetName, sizeof(actionSetInfo.localizedActionSetName), "Gameplay");
  88. actionSetInfo.priority = 0;
  89. [[maybe_unused]] const XrResult result = xrCreateActionSet(xrInstance, &actionSetInfo, &m_actionSet);
  90. WARN_IF_UNSUCCESSFUL(result);
  91. }
  92. void Input::CreateAllActions(const XrInstance& xrInstance)
  93. {
  94. // Get the XrPath for the left and right hands - we will use them as subaction paths.
  95. const AZStd::string leftHandPath{ m_xrControllerImpl->GetLeftHandSubPath() };
  96. const AZStd::string rightHandPath{ m_xrControllerImpl->GetRightHandSubPath() };
  97. XrResult result = xrStringToPath(xrInstance, leftHandPath.data(), &m_handSubactionPath[static_cast<uint32_t>(XR::Side::Left)]);
  98. WARN_IF_UNSUCCESSFUL(result);
  99. result = xrStringToPath(xrInstance, rightHandPath.data(), &m_handSubactionPath[static_cast<uint32_t>(XR::Side::Right)]);
  100. WARN_IF_UNSUCCESSFUL(result);
  101. // Lambda to create an action and path, store them in m_xrActionPaths
  102. using namespace AzFramework;
  103. auto createXrAction = [this, &xrInstance](const InputChannelId& channelId, const XrActionType actionType)
  104. {
  105. m_xrActionIndices[channelId] = m_xrActionPaths.size();
  106. m_xrActionPaths.push_back({});
  107. CreateAction(m_xrActionPaths.back().action, actionType, channelId.GetName(), channelId.GetName(),
  108. aznumeric_cast<AZ::u32>(AZStd::size(m_handSubactionPath)), m_handSubactionPath.data());
  109. const AZStd::string xrPathStr{ m_xrControllerImpl->GetInputChannelPath(channelId) };
  110. [[maybe_unused]] const XrResult pathResult = xrStringToPath(xrInstance, xrPathStr.data(), &m_xrActionPaths.back().binding);
  111. WARN_IF_UNSUCCESSFUL(pathResult);
  112. };
  113. for (const InputChannelId& channelId : InputDeviceXRController::Button::All)
  114. {
  115. createXrAction(channelId, XR_ACTION_TYPE_BOOLEAN_INPUT);
  116. }
  117. for (const InputChannelId& channelId : InputDeviceXRController::Trigger::All)
  118. {
  119. createXrAction(channelId, XR_ACTION_TYPE_FLOAT_INPUT);
  120. }
  121. for (const InputChannelId& channelId : InputDeviceXRController::ThumbStickAxis1D::All)
  122. {
  123. createXrAction(channelId, XR_ACTION_TYPE_FLOAT_INPUT);
  124. }
  125. for (const InputChannelId& channelId : InputDeviceXRController::ControllerPosePosition::All)
  126. {
  127. createXrAction(channelId, XR_ACTION_TYPE_POSE_INPUT);
  128. }
  129. for (const InputChannelId& channelId : InputDeviceXRController::ControllerPoseOrientation::All)
  130. {
  131. createXrAction(channelId, XR_ACTION_TYPE_POSE_INPUT); // is this correct?
  132. }
  133. m_xrControllerImpl->RegisterTickCallback([this](){ PollActions(); });
  134. }
  135. AZ::RHI::ResultCode Input::InitializeActionSpace(XrSession xrSession)
  136. {
  137. XrActionSpaceCreateInfo actionSpaceInfo{};
  138. actionSpaceInfo.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
  139. actionSpaceInfo.action = GetAction(AzFramework::InputDeviceXRController::ControllerPosePosition::LPos);
  140. actionSpaceInfo.poseInActionSpace.orientation.w = 1.f;
  141. actionSpaceInfo.subactionPath = m_handSubactionPath[static_cast<uint32_t>(XR::Side::Left)];
  142. XrResult result = xrCreateActionSpace(xrSession, &actionSpaceInfo, &m_handSpace[static_cast<uint32_t>(XR::Side::Left)]);
  143. WARN_IF_UNSUCCESSFUL(result);
  144. RETURN_RESULTCODE_IF_UNSUCCESSFUL(ConvertResult(result));
  145. actionSpaceInfo.action = GetAction(AzFramework::InputDeviceXRController::ControllerPosePosition::RPos);
  146. actionSpaceInfo.subactionPath = m_handSubactionPath[static_cast<uint32_t>(XR::Side::Right)];
  147. result = xrCreateActionSpace(xrSession, &actionSpaceInfo, &m_handSpace[static_cast<uint32_t>(XR::Side::Right)]);
  148. WARN_IF_UNSUCCESSFUL(result);
  149. return ConvertResult(result);
  150. }
  151. AZ::RHI::ResultCode Input::InitializeActionSets(XrSession xrSession) const
  152. {
  153. XrSessionActionSetsAttachInfo attachInfo{};
  154. attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
  155. attachInfo.countActionSets = 1;
  156. attachInfo.actionSets = &m_actionSet;
  157. const XrResult result = xrAttachSessionActionSets(xrSession, &attachInfo);
  158. WARN_IF_UNSUCCESSFUL(result);
  159. return ConvertResult(result);
  160. }
  161. void Input::ShutdownInternal()
  162. {
  163. if (m_actionSet != XR_NULL_HANDLE)
  164. {
  165. for (const auto hand : { XR::Side::Left, XR::Side::Right })
  166. {
  167. xrDestroySpace(m_handSpace[static_cast<AZ::u32>(hand)]);
  168. }
  169. xrDestroyActionSet(m_actionSet);
  170. }
  171. // Turn off the tick callback and reset the (non-owning) impl pointer back to null
  172. m_xrControllerImpl->RegisterTickCallback(nullptr);
  173. m_xrControllerImpl = nullptr;
  174. }
  175. XrAction Input::GetAction(const AzFramework::InputChannelId& channelId) const
  176. {
  177. // this is a private function and only input channel ids that were used to
  178. // initialize structures in this class should be passed.
  179. // "at" will assert if the channelId is something unexpected for xr controller
  180. const auto index = m_xrActionIndices.at(channelId);
  181. return m_xrActionPaths[index].action;
  182. }
  183. void Input::PollActions()
  184. {
  185. const auto session = static_cast<Session*>(GetDescriptor().m_session.get());
  186. XrSession xrSession = session->GetXrSession();
  187. const auto device = static_cast<Device*>(GetDescriptor().m_device.get());
  188. m_handActive = { XR_FALSE, XR_FALSE };
  189. auto& rawControllerData = m_xrControllerImpl->GetRawState();
  190. // Might not need to reset if we're constantly refreshing all raw values.
  191. // In the future we may want to store off a couple ticks of data in a history
  192. // so that derivatives and edge detection can be computed.
  193. rawControllerData.Reset();
  194. // Sync actions
  195. const XrActiveActionSet activeActionSet{ m_actionSet, XR_NULL_PATH };
  196. XrActionsSyncInfo syncInfo{};
  197. syncInfo.type = XR_TYPE_ACTIONS_SYNC_INFO;
  198. syncInfo.countActiveActionSets = 1;
  199. syncInfo.activeActionSets = &activeActionSet;
  200. XrResult result = xrSyncActions(xrSession, &syncInfo);
  201. if (result != XR_SUCCESS)
  202. {
  203. // This will hit when the device gets put down / goes idle.
  204. // So to avoid spam, just return here.
  205. return;
  206. }
  207. using namespace AzFramework;
  208. using xrc = InputDeviceXRController;
  209. // Updating digital buttons is somewhat unique, because it compacts and combines them all to a u32 with bit masks...
  210. for (const auto& [channelId, bitMask] : rawControllerData.m_buttonIdsToBitMasks)
  211. {
  212. XrActionStateGetInfo getButtonInfo{};
  213. getButtonInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
  214. getButtonInfo.next = nullptr;
  215. getButtonInfo.action = GetAction(channelId);
  216. getButtonInfo.subactionPath = XR_NULL_PATH;
  217. XrActionStateBoolean buttonValue{};
  218. buttonValue.type = XR_TYPE_ACTION_STATE_BOOLEAN;
  219. result = xrGetActionStateBoolean(xrSession, &getButtonInfo, &buttonValue);
  220. WARN_IF_UNSUCCESSFUL(result);
  221. rawControllerData.m_digitalButtonStates |= (
  222. (buttonValue.isActive == XR_TRUE && buttonValue.currentState == XR_TRUE)
  223. ? bitMask
  224. : 0
  225. );
  226. }
  227. // lambda that obtains a float state from an action...
  228. auto getActionStateFloat = [&xrSession, this](const InputChannelId& channelId) -> float
  229. {
  230. XrActionStateGetInfo getAnalogInfo{};
  231. getAnalogInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
  232. getAnalogInfo.next = nullptr;
  233. getAnalogInfo.action = GetAction(channelId);
  234. getAnalogInfo.subactionPath = XR_NULL_PATH;
  235. XrActionStateFloat analogValue{};
  236. analogValue.type = XR_TYPE_ACTION_STATE_FLOAT;
  237. const XrResult result = xrGetActionStateFloat(xrSession, &getAnalogInfo, &analogValue);
  238. WARN_IF_UNSUCCESSFUL(result);
  239. if (analogValue.isActive == XR_TRUE)
  240. {
  241. return analogValue.currentState;
  242. }
  243. return 0.f;
  244. };
  245. // Update Analog values...
  246. rawControllerData.m_leftTriggerState = getActionStateFloat(xrc::Trigger::LTrigger);
  247. rawControllerData.m_rightTriggerState = getActionStateFloat(xrc::Trigger::RTrigger);
  248. rawControllerData.m_leftGripState = getActionStateFloat(xrc::Trigger::LGrip);
  249. rawControllerData.m_rightGripState = getActionStateFloat(xrc::Trigger::RGrip);
  250. rawControllerData.m_leftThumbStickXState = getActionStateFloat(xrc::ThumbStickAxis1D::LX);
  251. rawControllerData.m_leftThumbStickYState = getActionStateFloat(xrc::ThumbStickAxis1D::LY);
  252. rawControllerData.m_rightThumbStickXState = getActionStateFloat(xrc::ThumbStickAxis1D::RX);
  253. rawControllerData.m_rightThumbStickYState = getActionStateFloat(xrc::ThumbStickAxis1D::RY);
  254. // Scale the rendered hand by 1.0f (open) to 0.5f (fully squeezed).
  255. m_handScale[static_cast<AZ::u32>(XR::Side::Left)] = 1.f - 0.5f * rawControllerData.m_leftGripState;
  256. m_handScale[static_cast<AZ::u32>(XR::Side::Right)] = 1.f - 0.5f * rawControllerData.m_rightGripState;
  257. // lambda that outputs vibration amount to a particular side
  258. auto setHapticVibration = [this, &xrSession](AZ::u32 side, float amount)
  259. {
  260. if (amount > 0.f)
  261. {
  262. XrHapticVibration hapticVibration{};
  263. hapticVibration.type = XR_TYPE_HAPTIC_VIBRATION;
  264. hapticVibration.amplitude = amount;
  265. hapticVibration.duration = XR_MIN_HAPTIC_DURATION;
  266. hapticVibration.frequency = XR_FREQUENCY_UNSPECIFIED;
  267. XrHapticActionInfo hapticActionInfo{};
  268. hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
  269. hapticActionInfo.action = m_hapticAction;
  270. hapticActionInfo.subactionPath = m_handSubactionPath[side];
  271. [[maybe_unused]] const XrResult result = xrApplyHapticFeedback(
  272. xrSession, &hapticActionInfo, reinterpret_cast<XrHapticBaseHeader*>(&hapticVibration));
  273. WARN_IF_UNSUCCESSFUL(result);
  274. }
  275. };
  276. setHapticVibration(static_cast<AZ::u32>(XR::Side::Left), rawControllerData.m_leftMotorVibrationValue);
  277. setHapticVibration(static_cast<AZ::u32>(XR::Side::Right), rawControllerData.m_rightMotorVibrationValue);
  278. // after the vibration values have been used, reset them
  279. rawControllerData.m_leftMotorVibrationValue = 0.f;
  280. rawControllerData.m_rightMotorVibrationValue = 0.f;
  281. // Update poses
  282. for (const auto hand : { XR::Side::Left, XR::Side::Right })
  283. {
  284. XrActionStateGetInfo getInfo{};
  285. getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
  286. getInfo.action = GetPoseAction(static_cast<AZ::u32>(hand));
  287. XrActionStatePose poseState{};
  288. poseState.type = XR_TYPE_ACTION_STATE_POSE;
  289. result = xrGetActionStatePose(xrSession, &getInfo, &poseState);
  290. WARN_IF_UNSUCCESSFUL(result);
  291. m_handActive[static_cast<AZ::u32>(hand)] = poseState.isActive;
  292. LocateControllerSpace(device->GetPredictedDisplayTime(), session->GetXrSpace(OpenXRVk::SpaceType::View), static_cast<AZ::u32>(hand));
  293. }
  294. // Cache 3d location information
  295. for (AZ::u32 i = 0; i < static_cast<AZ::u32>(SpaceType::Count); i++)
  296. {
  297. const auto spaceType = static_cast<SpaceType>(i);
  298. LocateVisualizedSpace(device->GetPredictedDisplayTime(), session->GetXrSpace(spaceType),
  299. session->GetXrSpace(OpenXRVk::SpaceType::View), spaceType);
  300. }
  301. // XR to AZ vector conversion...
  302. // Goes from y-up to z-up configuration (keeping Right Handed system)
  303. const auto convertVector3 = [](const XrVector3f& xrVec3) -> AZ::Vector3
  304. {
  305. return AZ::Vector3{ xrVec3.x, -xrVec3.z, xrVec3.y };
  306. };
  307. // XR to AZ quaternion conversion...
  308. // Goes from y-up to z-up configuration (keeping Right Handed system)
  309. const auto convertQuat = [](const XrQuaternionf& xrQuat) -> AZ::Quaternion
  310. {
  311. return AZ::Quaternion{ xrQuat.x, -xrQuat.z, xrQuat.y, xrQuat.w };
  312. };
  313. rawControllerData.m_leftPositionState = convertVector3(m_handSpaceLocation[static_cast<AZ::u32>(XR::Side::Left)].pose.position);
  314. rawControllerData.m_rightPositionState = convertVector3(m_handSpaceLocation[static_cast<AZ::u32>(XR::Side::Right)].pose.position);
  315. rawControllerData.m_leftOrientationState = convertQuat(m_handSpaceLocation[static_cast<AZ::u32>(XR::Side::Left)].pose.orientation);
  316. rawControllerData.m_rightOrientationState = convertQuat(m_handSpaceLocation[static_cast<AZ::u32>(XR::Side::Right)].pose.orientation);
  317. // Check if the Quit (Home) button was pressed this sync...
  318. const bool quitPressed = GetButtonState(InputDeviceXRController::Button::Home);
  319. if (quitPressed && !m_wasQuitPressedLastSync)
  320. {
  321. result = xrRequestExitSession(xrSession);
  322. WARN_IF_UNSUCCESSFUL(result);
  323. }
  324. m_wasQuitPressedLastSync = quitPressed;
  325. }
  326. void Input::LocateControllerSpace(XrTime predictedDisplayTime, XrSpace baseSpace, AZ::u32 handIndex)
  327. {
  328. XrSpaceLocation spaceLocation{};
  329. spaceLocation.type = XR_TYPE_SPACE_LOCATION;
  330. if (const XrResult result = xrLocateSpace(m_handSpace[handIndex], baseSpace, predictedDisplayTime, &spaceLocation);
  331. result == XR_SUCCESS)
  332. {
  333. if ((spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
  334. (spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0)
  335. {
  336. m_handSpaceLocation[handIndex] = spaceLocation;
  337. }
  338. }
  339. }
  340. void Input::LocateVisualizedSpace(XrTime predictedDisplayTime, XrSpace space, XrSpace baseSpace, OpenXRVk::SpaceType visualizedSpaceType)
  341. {
  342. XrSpaceLocation spaceLocation{};
  343. spaceLocation.type = XR_TYPE_SPACE_LOCATION;
  344. if (const XrResult result = xrLocateSpace(space, baseSpace, predictedDisplayTime, &spaceLocation);
  345. result == XR_SUCCESS)
  346. {
  347. if ((spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
  348. (spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0)
  349. {
  350. m_xrVisualizedSpaceLocations[static_cast<uint32_t>(visualizedSpaceType)] = spaceLocation;
  351. }
  352. }
  353. }
  354. AZ::RHI::ResultCode Input::GetControllerPose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const
  355. {
  356. if (handIndex < AZStd::size(m_handSpaceLocation))
  357. {
  358. const XrQuaternionf& orientation = m_handSpaceLocation[handIndex].pose.orientation;
  359. const XrVector3f& position = m_handSpaceLocation[handIndex].pose.position;
  360. outPoseData.m_orientation.Set(orientation.x, orientation.y, orientation.z, orientation.w);
  361. outPoseData.m_position.Set(position.x, position.y, position.z);
  362. return AZ::RHI::ResultCode::Success;
  363. }
  364. return AZ::RHI::ResultCode::Fail;
  365. }
  366. AZ::RHI::ResultCode Input::GetVisualizedSpacePose(OpenXRVk::SpaceType visualizedSpaceType, AZ::RPI::PoseData& outPoseData) const
  367. {
  368. const auto spaceIndex = static_cast<AZ::u32>(visualizedSpaceType);
  369. if (spaceIndex < AZStd::size(m_xrVisualizedSpaceLocations))
  370. {
  371. const XrQuaternionf& orientation = m_xrVisualizedSpaceLocations[spaceIndex].pose.orientation;
  372. const XrVector3f& position = m_xrVisualizedSpaceLocations[spaceIndex].pose.position;
  373. outPoseData.m_orientation.Set(orientation.x, orientation.y, orientation.z, orientation.w);
  374. outPoseData.m_position.Set(position.x, position.y, position.z);
  375. return AZ::RHI::ResultCode::Success;
  376. }
  377. return AZ::RHI::ResultCode::Fail;
  378. }
  379. float Input::GetControllerScale(AZ::u32 handIndex) const
  380. {
  381. return m_handScale[handIndex];
  382. }
  383. XrAction Input::GetSqueezeAction(AZ::u32 handIndex) const
  384. {
  385. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  386. ? GetAction(AzFramework::InputDeviceXRController::Trigger::LGrip)
  387. : GetAction(AzFramework::InputDeviceXRController::Trigger::RGrip);
  388. }
  389. XrAction Input::GetPoseAction(AZ::u32 handIndex) const
  390. {
  391. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  392. ? GetAction(AzFramework::InputDeviceXRController::ControllerPosePosition::LPos)
  393. : GetAction(AzFramework::InputDeviceXRController::ControllerPosePosition::RPos);
  394. }
  395. XrAction Input::GetVibrationAction() const
  396. {
  397. return m_hapticAction;
  398. }
  399. XrAction Input::GetQuitAction() const
  400. {
  401. return GetAction(AzFramework::InputDeviceXRController::Button::Home);
  402. }
  403. bool Input::GetButtonState(const AzFramework::InputChannelId& channelId) const
  404. {
  405. const auto& state = m_xrControllerImpl->GetRawState();
  406. return state.GetDigitalButtonState(channelId);
  407. }
  408. bool Input::GetXButtonState() const
  409. {
  410. return GetButtonState(AzFramework::InputDeviceXRController::Button::X);
  411. }
  412. bool Input::GetYButtonState() const
  413. {
  414. return GetButtonState(AzFramework::InputDeviceXRController::Button::Y);
  415. }
  416. bool Input::GetAButtonState() const
  417. {
  418. return GetButtonState(AzFramework::InputDeviceXRController::Button::A);
  419. }
  420. bool Input::GetBButtonState() const
  421. {
  422. return GetButtonState(AzFramework::InputDeviceXRController::Button::B);
  423. }
  424. float Input::GetXJoyStickState(AZ::u32 handIndex) const
  425. {
  426. const auto& state = m_xrControllerImpl->GetRawState();
  427. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  428. ? state.m_leftThumbStickXState
  429. : state.m_rightThumbStickXState;
  430. }
  431. float Input::GetYJoyStickState(AZ::u32 handIndex) const
  432. {
  433. const auto& state = m_xrControllerImpl->GetRawState();
  434. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  435. ? state.m_leftThumbStickYState
  436. : state.m_rightThumbStickYState;
  437. }
  438. float Input::GetSqueezeState(AZ::u32 handIndex) const
  439. {
  440. const auto& state = m_xrControllerImpl->GetRawState();
  441. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  442. ? state.m_leftGripState
  443. : state.m_rightGripState;
  444. }
  445. float Input::GetTriggerState(AZ::u32 handIndex) const
  446. {
  447. const auto& state = m_xrControllerImpl->GetRawState();
  448. return (handIndex == static_cast<AZ::u32>(XR::Side::Left))
  449. ? state.m_leftTriggerState
  450. : state.m_rightTriggerState;
  451. }
  452. } // namespace OpenXRVk