XRRPIExampleComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 <XRRPIExampleComponent.h>
  9. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  10. #include <Atom/RPI.Public/Scene.h>
  11. #include <Atom/RPI.Public/RPISystem.h>
  12. #include <Atom/RPI.Public/RPISystemInterface.h>
  13. #include <Atom/RPI.Public/Pass/PassFilter.h>
  14. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  15. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  16. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  17. #include <Automation/ScriptableImGui.h>
  18. #include <Automation/ScriptRunnerBus.h>
  19. #include <Utils/Utils.h>
  20. #include <SSRExampleComponent_Traits_Platform.h>
  21. namespace AtomSampleViewer
  22. {
  23. static const float ControllerOffsetScale = 2.0f;
  24. static const float ViewOrientationScale = 10.0f;
  25. static const float PixelToDegree = 1.0 / 360.0f;
  26. void XRRPIExampleComponent::Reflect(AZ::ReflectContext* context)
  27. {
  28. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  29. {
  30. serializeContext->Class<XRRPIExampleComponent, AZ::Component>()
  31. ->Version(0);
  32. }
  33. }
  34. void XRRPIExampleComponent::Activate()
  35. {
  36. if (m_xrSystem = AZ::RPI::RPISystemInterface::Get()->GetXRSystem();
  37. m_xrSystem == nullptr)
  38. {
  39. return;
  40. }
  41. AZ::TickBus::Handler::BusConnect();
  42. // setup the camera
  43. Camera::CameraRequestBus::EventResult(m_originalFarClipDistance, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance);
  44. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, 180.f);
  45. m_numXrViews = m_xrSystem->GetNumViews();
  46. // create scene
  47. CreateModels();
  48. CreateGroundPlane();
  49. InitLightingPresets(true);
  50. }
  51. void XRRPIExampleComponent::Deactivate()
  52. {
  53. if (!m_xrSystem)
  54. {
  55. return;
  56. }
  57. ShutdownLightingPresets();
  58. GetMeshFeatureProcessor()->ReleaseMesh(m_statueMeshHandle);
  59. GetMeshFeatureProcessor()->ReleaseMesh(m_boxMeshHandle);
  60. GetMeshFeatureProcessor()->ReleaseMesh(m_shaderBallMeshHandle);
  61. GetMeshFeatureProcessor()->ReleaseMesh(m_groundMeshHandle);
  62. GetMeshFeatureProcessor()->ReleaseMesh(m_leftControllerMeshHandle);
  63. GetMeshFeatureProcessor()->ReleaseMesh(m_rightControllerMeshHandle);
  64. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, m_originalFarClipDistance);
  65. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  66. AZ::TickBus::Handler::BusDisconnect();
  67. }
  68. void XRRPIExampleComponent::CreateModels()
  69. {
  70. GetMeshFeatureProcessor();
  71. // statue
  72. {
  73. AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("objects/hermanubis/hermanubis_stone.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  74. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>(ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_HERMANUBIS_MODEL_NAME, AZ::RPI::AssetUtils::TraceLevel::Assert);
  75. AZ::Transform transform = AZ::Transform::CreateIdentity();
  76. transform.SetTranslation(0.0f, 0.0f, -0.05f);
  77. m_statueMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, AZ::RPI::Material::FindOrCreate(materialAsset));
  78. GetMeshFeatureProcessor()->SetTransform(m_statueMeshHandle, transform);
  79. }
  80. // cube
  81. {
  82. AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("materials/ssrexample/cube.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  83. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cube.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  84. AZ::Transform transform = AZ::Transform::CreateIdentity();
  85. transform.SetTranslation(-4.5f, 0.0f, 0.49f);
  86. m_boxMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, AZ::RPI::Material::FindOrCreate(materialAsset));
  87. GetMeshFeatureProcessor()->SetTransform(m_boxMeshHandle, transform);
  88. }
  89. // shader ball
  90. {
  91. AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("Materials/Presets/PBR/default_grid.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  92. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/ShaderBall_simple.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  93. AZ::Transform transform = AZ::Transform::CreateIdentity();
  94. transform *= AZ::Transform::CreateRotationZ(AZ::Constants::Pi);
  95. transform.SetTranslation(4.5f, 0.0f, 0.89f);
  96. m_shaderBallMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, AZ::RPI::Material::FindOrCreate(materialAsset));
  97. GetMeshFeatureProcessor()->SetTransform(m_shaderBallMeshHandle, transform);
  98. }
  99. // controller meshes
  100. {
  101. AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("Materials/XR/XR_Hand_Controller_ControlerMAT.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  102. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/left_hand_controller.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  103. AZ::Transform transform = AZ::Transform::CreateIdentity();
  104. m_leftControllerMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, AZ::RPI::Material::FindOrCreate(materialAsset));
  105. m_rightControllerMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, AZ::RPI::Material::FindOrCreate(materialAsset));
  106. GetMeshFeatureProcessor()->SetTransform(m_leftControllerMeshHandle, transform);
  107. GetMeshFeatureProcessor()->SetTransform(m_rightControllerMeshHandle, transform);
  108. }
  109. }
  110. void XRRPIExampleComponent::CreateGroundPlane()
  111. {
  112. AZ::Render::MeshFeatureProcessorInterface* meshFeatureProcessor = GetMeshFeatureProcessor();
  113. if (m_groundMeshHandle.IsValid())
  114. {
  115. meshFeatureProcessor->ReleaseMesh(m_groundMeshHandle);
  116. }
  117. // load material
  118. AZStd::string materialName;
  119. switch (m_groundPlaneMaterial)
  120. {
  121. case 0:
  122. materialName = "materials/ssrexample/groundplanechrome.azmaterial";
  123. break;
  124. case 1:
  125. materialName = "materials/ssrexample/groundplanealuminum.azmaterial";
  126. break;
  127. case 2:
  128. materialName = "materials/presets/pbr/default_grid.azmaterial";
  129. break;
  130. default:
  131. materialName = "materials/ssrexample/groundplanemirror.azmaterial";
  132. break;
  133. }
  134. AZ::Data::AssetId groundMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(materialName.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error);
  135. m_groundMaterialAsset.Create(groundMaterialAssetId);
  136. // load mesh
  137. AZ::Data::Asset<AZ::RPI::ModelAsset> planeModel = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/plane.azmodel", AZ::RPI::AssetUtils::TraceLevel::Error);
  138. m_groundMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ planeModel }, AZ::RPI::Material::FindOrCreate(m_groundMaterialAsset));
  139. AZ::Transform transform = AZ::Transform::CreateIdentity();
  140. const AZ::Vector3 nonUniformScale(15.0f, 15.0f, 1.0f);
  141. GetMeshFeatureProcessor()->SetTransform(m_groundMeshHandle, transform, nonUniformScale);
  142. }
  143. void XRRPIExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  144. {
  145. if (m_resetCamera)
  146. {
  147. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Reset);
  148. AZ::TransformBus::Event(GetCameraEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(7.5f, -10.5f, 3.0f));
  149. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  150. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetHeading, AZ::DegToRad(22.5f));
  151. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetPitch, AZ::DegToRad(-10.0f));
  152. m_resetCamera = false;
  153. }
  154. if (m_xrSystem && m_xrSystem->ShouldRender())
  155. {
  156. AZ::RPI::PoseData frontPoseData;
  157. AZ::RHI::ResultCode resultCode = m_xrSystem->GetViewLocalPose(frontPoseData);
  158. for (AZ::u32 i = 0; i < m_numXrViews; i++)
  159. {
  160. //Pose data for the controller
  161. AZ::RPI::PoseData controllerPose;
  162. resultCode = m_xrSystem->GetControllerPose(i, controllerPose);
  163. if(resultCode == AZ::RHI::ResultCode::Success && !controllerPose.m_orientation.IsZero())
  164. {
  165. AZ::Vector3 camPosition;
  166. AZ::TransformBus::EventResult(camPosition, GetCameraEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
  167. AZ::Vector3 controllerPositionOffset = controllerPose.m_position * ControllerOffsetScale;
  168. AZ::Vector3 newControllerPos = camPosition + AZ::Vector3(controllerPositionOffset.GetX(), -controllerPositionOffset.GetZ(), controllerPositionOffset.GetY());
  169. // Go from y up to z up as a right handed coord system
  170. AZ::Quaternion controllerOrientation = controllerPose.m_orientation;
  171. controllerOrientation.SetX(controllerPose.m_orientation.GetX());
  172. controllerOrientation.SetY(-controllerPose.m_orientation.GetZ());
  173. controllerOrientation.SetZ(controllerPose.m_orientation.GetY());
  174. //Apply a Rotation of 90 deg around X axis in order to orient the model to face away from you as default pose
  175. AZ::Transform controllerTransform = AZ::Transform::CreateFromQuaternionAndTranslation(
  176. controllerOrientation * AZ::Quaternion::CreateRotationX(-AZ::Constants::Pi / 2), AZ::Vector3(newControllerPos.GetX(), newControllerPos.GetY(),newControllerPos.GetZ()));
  177. AZ::Render::MeshFeatureProcessorInterface::MeshHandle* controllerMeshhandle = &m_leftControllerMeshHandle;
  178. if (i == 1)
  179. {
  180. controllerMeshhandle = &m_rightControllerMeshHandle;
  181. }
  182. GetMeshFeatureProcessor()->SetTransform(*controllerMeshhandle, controllerTransform, AZ::Vector3(m_xrSystem->GetControllerScale(i)));
  183. }
  184. }
  185. //Update Camera movement (left, right forward, back) based on left JoyStick controller
  186. float m_xJoyStickValue = m_xrSystem->GetXJoyStickState(0);
  187. float m_yJoyStickValue = m_xrSystem->GetYJoyStickState(0);
  188. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateForward, m_yJoyStickValue);
  189. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateBack, m_yJoyStickValue);
  190. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateLeft, m_xJoyStickValue);
  191. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateRight, m_xJoyStickValue);
  192. //Update Camera movement (Up, Down) based on X,Y button presses on the left controller
  193. float yButtonState = m_xrSystem->GetYButtonState();
  194. float xButtonState = m_xrSystem->GetXButtonState();
  195. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateUp, yButtonState);
  196. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateDown, xButtonState);
  197. // Switch to updating the view using right joystick controller if the Trigger button on the right controller is pressed
  198. m_rightTriggerButtonPressed = (m_xrSystem->GetTriggerState(1) > 0.1f);
  199. if (m_rightTriggerButtonPressed)
  200. {
  201. //Update Camera view based on right JoyStick controller
  202. float m_xRightJoyStickValue = m_xrSystem->GetXJoyStickState(1);
  203. float m_yRightJoyStickValue = m_xrSystem->GetYJoyStickState(1);
  204. float heading, pitch = 0.0f;
  205. AZ::Debug::NoClipControllerRequestBus::EventResult(heading, GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::GetHeading);
  206. AZ::Debug::NoClipControllerRequestBus::EventResult(pitch, GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::GetPitch);
  207. heading -= m_xRightJoyStickValue * PixelToDegree * ViewOrientationScale;
  208. pitch += m_yRightJoyStickValue * PixelToDegree * ViewOrientationScale;
  209. pitch = AZStd::max(pitch, -AZ::Constants::HalfPi);
  210. pitch = AZStd::min(pitch, AZ::Constants::HalfPi);
  211. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetHeading, heading);
  212. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetPitch, pitch);
  213. }
  214. else
  215. {
  216. //Convert to O3de's coordinate system and update the camera orientation for the correct eye view
  217. AZ::Quaternion viewLocalPoseOrientation = frontPoseData.m_orientation;
  218. viewLocalPoseOrientation.SetX(-frontPoseData.m_orientation.GetX());
  219. viewLocalPoseOrientation.SetY(frontPoseData.m_orientation.GetZ());
  220. viewLocalPoseOrientation.SetZ(-frontPoseData.m_orientation.GetY());
  221. for (AZ::u32 i = 0; i < m_numXrViews; i++)
  222. {
  223. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetXRViewQuaternion, viewLocalPoseOrientation, i);
  224. }
  225. }
  226. // Switch to the next lighting preset using the B-button
  227. if (m_xrSystem->GetBButtonState() > 0.0f)
  228. {
  229. if (!m_bButtonPressed)
  230. {
  231. m_bButtonPressed = true;
  232. IterateToNextLightingPreset();
  233. }
  234. }
  235. else
  236. {
  237. m_bButtonPressed = false;
  238. }
  239. // Switch to the next ground floor using the A-button
  240. if (m_xrSystem->GetAButtonState() > 0.0f)
  241. {
  242. if (!m_aButtonPressed)
  243. {
  244. m_aButtonPressed = true;
  245. m_groundPlaneMaterial = (m_groundPlaneMaterial + 1) % 4;
  246. CreateGroundPlane();
  247. }
  248. }
  249. else
  250. {
  251. m_aButtonPressed = false;
  252. }
  253. }
  254. }
  255. }