XRRPIExampleComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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(
  78. AZ::Render::MeshHandleDescriptor(modelAsset, AZ::RPI::Material::FindOrCreate(materialAsset)));
  79. GetMeshFeatureProcessor()->SetTransform(m_statueMeshHandle, transform);
  80. }
  81. // cube
  82. {
  83. AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("materials/ssrexample/cube.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  84. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cube.fbx.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  85. AZ::Transform transform = AZ::Transform::CreateIdentity();
  86. transform.SetTranslation(-4.5f, 0.0f, 0.49f);
  87. m_boxMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(
  88. AZ::Render::MeshHandleDescriptor(modelAsset, AZ::RPI::Material::FindOrCreate(materialAsset)));
  89. GetMeshFeatureProcessor()->SetTransform(m_boxMeshHandle, transform);
  90. }
  91. // shader ball
  92. {
  93. 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);
  94. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/ShaderBall_simple.fbx.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  95. AZ::Transform transform = AZ::Transform::CreateIdentity();
  96. transform *= AZ::Transform::CreateRotationZ(AZ::Constants::Pi);
  97. transform.SetTranslation(4.5f, 0.0f, 0.89f);
  98. m_shaderBallMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(
  99. AZ::Render::MeshHandleDescriptor(modelAsset, AZ::RPI::Material::FindOrCreate(materialAsset)));
  100. GetMeshFeatureProcessor()->SetTransform(m_shaderBallMeshHandle, transform);
  101. }
  102. // controller meshes
  103. {
  104. 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);
  105. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/left_hand_controller.fbx.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  106. AZ::Transform transform = AZ::Transform::CreateIdentity();
  107. m_leftControllerMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(
  108. AZ::Render::MeshHandleDescriptor(modelAsset, AZ::RPI::Material::FindOrCreate(materialAsset)));
  109. m_rightControllerMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(
  110. AZ::Render::MeshHandleDescriptor(modelAsset, AZ::RPI::Material::FindOrCreate(materialAsset)));
  111. GetMeshFeatureProcessor()->SetTransform(m_leftControllerMeshHandle, transform);
  112. GetMeshFeatureProcessor()->SetTransform(m_rightControllerMeshHandle, transform);
  113. }
  114. }
  115. void XRRPIExampleComponent::CreateGroundPlane()
  116. {
  117. AZ::Render::MeshFeatureProcessorInterface* meshFeatureProcessor = GetMeshFeatureProcessor();
  118. if (m_groundMeshHandle.IsValid())
  119. {
  120. meshFeatureProcessor->ReleaseMesh(m_groundMeshHandle);
  121. }
  122. // load material
  123. AZStd::string materialName;
  124. switch (m_groundPlaneMaterial)
  125. {
  126. case 0:
  127. materialName = "materials/ssrexample/groundplanechrome.azmaterial";
  128. break;
  129. case 1:
  130. materialName = "materials/ssrexample/groundplanealuminum.azmaterial";
  131. break;
  132. case 2:
  133. materialName = "materials/presets/pbr/default_grid.azmaterial";
  134. break;
  135. default:
  136. materialName = "materials/ssrexample/groundplanemirror.azmaterial";
  137. break;
  138. }
  139. AZ::Data::AssetId groundMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(materialName.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error);
  140. m_groundMaterialAsset.Create(groundMaterialAssetId);
  141. // load mesh
  142. AZ::Data::Asset<AZ::RPI::ModelAsset> planeModel = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/plane.fbx.azmodel", AZ::RPI::AssetUtils::TraceLevel::Error);
  143. m_groundMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(
  144. AZ::Render::MeshHandleDescriptor(planeModel, AZ::RPI::Material::FindOrCreate(m_groundMaterialAsset)));
  145. AZ::Transform transform = AZ::Transform::CreateIdentity();
  146. const AZ::Vector3 nonUniformScale(15.0f, 15.0f, 1.0f);
  147. GetMeshFeatureProcessor()->SetTransform(m_groundMeshHandle, transform, nonUniformScale);
  148. }
  149. void XRRPIExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  150. {
  151. if (m_resetCamera)
  152. {
  153. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Reset);
  154. AZ::TransformBus::Event(GetCameraEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(7.5f, -10.5f, 3.0f));
  155. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  156. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetHeading, AZ::DegToRad(22.5f));
  157. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetPitch, AZ::DegToRad(-10.0f));
  158. m_resetCamera = false;
  159. }
  160. if (m_xrSystem && m_xrSystem->ShouldRender())
  161. {
  162. AZ::RPI::PoseData frontPoseData;
  163. AZ::RHI::ResultCode resultCode = m_xrSystem->GetViewLocalPose(frontPoseData);
  164. for (AZ::u32 i = 0; i < m_numXrViews; i++)
  165. {
  166. //Pose data for the controller
  167. AZ::RPI::PoseData controllerPose;
  168. resultCode = m_xrSystem->GetControllerPose(i, controllerPose);
  169. if(resultCode == AZ::RHI::ResultCode::Success && !controllerPose.m_orientation.IsZero())
  170. {
  171. AZ::Vector3 camPosition;
  172. AZ::TransformBus::EventResult(camPosition, GetCameraEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
  173. AZ::Vector3 controllerPositionOffset = controllerPose.m_position * ControllerOffsetScale;
  174. AZ::Vector3 newControllerPos = camPosition + AZ::Vector3(controllerPositionOffset.GetX(), -controllerPositionOffset.GetZ(), controllerPositionOffset.GetY());
  175. // Go from y up to z up as a right handed coord system
  176. AZ::Quaternion controllerOrientation = controllerPose.m_orientation;
  177. controllerOrientation.SetX(controllerPose.m_orientation.GetX());
  178. controllerOrientation.SetY(-controllerPose.m_orientation.GetZ());
  179. controllerOrientation.SetZ(controllerPose.m_orientation.GetY());
  180. //Apply a Rotation of 90 deg around X axis in order to orient the model to face away from you as default pose
  181. AZ::Transform controllerTransform = AZ::Transform::CreateFromQuaternionAndTranslation(
  182. controllerOrientation * AZ::Quaternion::CreateRotationX(-AZ::Constants::Pi / 2), AZ::Vector3(newControllerPos.GetX(), newControllerPos.GetY(),newControllerPos.GetZ()));
  183. AZ::Render::MeshFeatureProcessorInterface::MeshHandle* controllerMeshhandle = &m_leftControllerMeshHandle;
  184. if (i == 1)
  185. {
  186. controllerMeshhandle = &m_rightControllerMeshHandle;
  187. }
  188. GetMeshFeatureProcessor()->SetTransform(*controllerMeshhandle, controllerTransform, AZ::Vector3(m_xrSystem->GetControllerScale(i)));
  189. }
  190. }
  191. //Update Camera movement (left, right forward, back) based on left JoyStick controller
  192. float m_xJoyStickValue = m_xrSystem->GetXJoyStickState(0);
  193. float m_yJoyStickValue = m_xrSystem->GetYJoyStickState(0);
  194. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateForward, m_yJoyStickValue);
  195. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateBack, m_yJoyStickValue);
  196. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateLeft, m_xJoyStickValue);
  197. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateRight, m_xJoyStickValue);
  198. //Update Camera movement (Up, Down) based on X,Y button presses on the left controller
  199. float yButtonState = m_xrSystem->GetYButtonState();
  200. float xButtonState = m_xrSystem->GetXButtonState();
  201. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateUp, yButtonState);
  202. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetCameraStateDown, xButtonState);
  203. // Switch to updating the view using right joystick controller if the Trigger button on the right controller is pressed
  204. m_rightTriggerButtonPressed = (m_xrSystem->GetTriggerState(1) > 0.1f);
  205. if (m_rightTriggerButtonPressed)
  206. {
  207. //Update Camera view based on right JoyStick controller
  208. float m_xRightJoyStickValue = m_xrSystem->GetXJoyStickState(1);
  209. float m_yRightJoyStickValue = m_xrSystem->GetYJoyStickState(1);
  210. float heading, pitch = 0.0f;
  211. AZ::Debug::NoClipControllerRequestBus::EventResult(heading, GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::GetHeading);
  212. AZ::Debug::NoClipControllerRequestBus::EventResult(pitch, GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::GetPitch);
  213. heading -= m_xRightJoyStickValue * PixelToDegree * ViewOrientationScale;
  214. pitch += m_yRightJoyStickValue * PixelToDegree * ViewOrientationScale;
  215. pitch = AZStd::max(pitch, -AZ::Constants::HalfPi);
  216. pitch = AZStd::min(pitch, AZ::Constants::HalfPi);
  217. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetHeading, heading);
  218. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequests::SetPitch, pitch);
  219. }
  220. else
  221. {
  222. //Convert to O3de's coordinate system and update the camera orientation for the correct eye view
  223. AZ::Quaternion viewLocalPoseOrientation = frontPoseData.m_orientation;
  224. viewLocalPoseOrientation.SetX(-frontPoseData.m_orientation.GetX());
  225. viewLocalPoseOrientation.SetY(frontPoseData.m_orientation.GetZ());
  226. viewLocalPoseOrientation.SetZ(-frontPoseData.m_orientation.GetY());
  227. for (AZ::u32 i = 0; i < m_numXrViews; i++)
  228. {
  229. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetXRViewQuaternion, viewLocalPoseOrientation, i);
  230. }
  231. }
  232. // Switch to the next lighting preset using the B-button
  233. if (m_xrSystem->GetBButtonState() > 0.0f)
  234. {
  235. if (!m_bButtonPressed)
  236. {
  237. m_bButtonPressed = true;
  238. IterateToNextLightingPreset();
  239. }
  240. }
  241. else
  242. {
  243. m_bButtonPressed = false;
  244. }
  245. // Switch to the next ground floor using the A-button
  246. if (m_xrSystem->GetAButtonState() > 0.0f)
  247. {
  248. if (!m_aButtonPressed)
  249. {
  250. m_aButtonPressed = true;
  251. m_groundPlaneMaterial = (m_groundPlaneMaterial + 1) % 4;
  252. CreateGroundPlane();
  253. }
  254. }
  255. else
  256. {
  257. m_aButtonPressed = false;
  258. }
  259. }
  260. }
  261. }