HighInstanceExampleComponent.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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 <HighInstanceExampleComponent.h>
  9. #include <SampleComponentManager.h>
  10. #include <SampleComponentConfig.h>
  11. #include <Atom/Component/DebugCamera/NoClipControllerBus.h>
  12. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  13. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  14. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  15. #include <Automation/ScriptRunnerBus.h>
  16. #include <AzCore/Serialization/SerializeContext.h>
  17. #include <AzFramework/Windowing/WindowBus.h>
  18. #include <RHI/BasicRHIComponent.h>
  19. #include <HighInstanceTestComponent_Traits_Platform.h>
  20. AZ_DECLARE_BUDGET(AtomSampleViewer);
  21. namespace AtomSampleViewer
  22. {
  23. using namespace AZ;
  24. void HighInstanceTestComponent::Reflect(AZ::ReflectContext* context)
  25. {
  26. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  27. {
  28. serializeContext->Class<HighInstanceTestComponent, EntityLatticeTestComponent>()
  29. ->Version(0)
  30. ;
  31. }
  32. }
  33. HighInstanceTestComponent::HighInstanceTestComponent()
  34. : m_materialBrowser("@user@/HighInstanceTestComponent/material_browser.xml")
  35. , m_modelBrowser("@user@/HighInstanceTestComponent/model_browser.xml")
  36. , m_imguiSidebar("@user@/HighInstanceTestComponent/sidebar.xml")
  37. {
  38. m_sampleName = "HighInstanceTest";
  39. m_materialBrowser.SetFilter([](const AZ::Data::AssetInfo& assetInfo)
  40. {
  41. return assetInfo.m_assetType == azrtti_typeid<AZ::RPI::MaterialAsset>();
  42. });
  43. m_modelBrowser.SetFilter([](const AZ::Data::AssetInfo& assetInfo)
  44. {
  45. return assetInfo.m_assetType == azrtti_typeid<AZ::RPI::ModelAsset>();
  46. });
  47. const AZStd::vector<AZStd::string> materialAllowlist =
  48. {
  49. "materials/presets/pbr/metal_aluminum.azmaterial",
  50. "materials/presets/pbr/metal_aluminum_matte.azmaterial",
  51. "materials/presets/pbr/metal_aluminum_polished.azmaterial",
  52. "materials/presets/pbr/metal_brass.azmaterial",
  53. "materials/presets/pbr/metal_brass_matte.azmaterial",
  54. "materials/presets/pbr/metal_brass_polished.azmaterial",
  55. "materials/presets/pbr/metal_chrome.azmaterial",
  56. "materials/presets/pbr/metal_chrome_matte.azmaterial",
  57. "materials/presets/pbr/metal_chrome_polished.azmaterial",
  58. "materials/presets/pbr/metal_cobalt.azmaterial",
  59. "materials/presets/pbr/metal_cobalt_matte.azmaterial",
  60. "materials/presets/pbr/metal_cobalt_polished.azmaterial",
  61. "materials/presets/pbr/metal_copper.azmaterial",
  62. "materials/presets/pbr/metal_copper_matte.azmaterial",
  63. "materials/presets/pbr/metal_copper_polished.azmaterial",
  64. "materials/presets/pbr/metal_gold.azmaterial",
  65. "materials/presets/pbr/metal_gold_matte.azmaterial",
  66. "materials/presets/pbr/metal_gold_polished.azmaterial",
  67. "materials/presets/pbr/metal_iron.azmaterial",
  68. "materials/presets/pbr/metal_iron_matte.azmaterial",
  69. "materials/presets/pbr/metal_iron_polished.azmaterial",
  70. "materials/presets/pbr/metal_mercury.azmaterial",
  71. "materials/presets/pbr/metal_nickel.azmaterial",
  72. "materials/presets/pbr/metal_nickel_matte.azmaterial",
  73. "materials/presets/pbr/metal_nickel_polished.azmaterial",
  74. "materials/presets/pbr/metal_palladium.azmaterial",
  75. "materials/presets/pbr/metal_palladium_matte.azmaterial",
  76. "materials/presets/pbr/metal_palladium_polished.azmaterial",
  77. "materials/presets/pbr/metal_platinum.azmaterial",
  78. "materials/presets/pbr/metal_platinum_matte.azmaterial",
  79. "materials/presets/pbr/metal_platinum_polished.azmaterial",
  80. "materials/presets/pbr/metal_silver.azmaterial",
  81. "materials/presets/pbr/metal_silver_matte.azmaterial",
  82. "materials/presets/pbr/metal_silver_polished.azmaterial",
  83. "materials/presets/pbr/metal_titanium.azmaterial",
  84. "materials/presets/pbr/metal_titanium_matte.azmaterial",
  85. "materials/presets/pbr/metal_titanium_polished.azmaterial",
  86. };
  87. m_materialBrowser.SetDefaultPinnedAssets(materialAllowlist);
  88. m_pinnedMaterialCount = static_cast<uint32_t>(m_materialBrowser.GetPinnedAssets().size());
  89. const AZStd::vector<AZStd::string> modelAllowlist =
  90. {
  91. "materialeditor/viewportmodels/cone.azmodel",
  92. "materialeditor/viewportmodels/cube.azmodel",
  93. "materialeditor/viewportmodels/cylinder.azmodel",
  94. "materialeditor/viewportmodels/platonicsphere.azmodel",
  95. "materialeditor/viewportmodels/polarsphere.azmodel",
  96. "materialeditor/viewportmodels/quadsphere.azmodel",
  97. "materialeditor/viewportmodels/torus.azmodel",
  98. "objects/cube.azmodel",
  99. "objects/cylinder.azmodel",
  100. };
  101. m_modelBrowser.SetDefaultPinnedAssets(modelAllowlist);
  102. }
  103. void HighInstanceTestComponent::Activate()
  104. {
  105. AZ::TickBus::Handler::BusConnect();
  106. m_imguiSidebar.Activate();
  107. m_imguiSidebar.SetHideSidebar(true);
  108. m_materialBrowser.Activate();
  109. m_modelBrowser.Activate();
  110. m_materialBrowser.ResetPinnedAssetsToDefault();
  111. m_modelBrowser.ResetPinnedAssetsToDefault();
  112. SetLatticeDimensions(
  113. ATOMSAMPLEVIEWER_TRAIT_HIGH_INSTANCE_COUNT_TEST_COMPONENT_LATTICE_SIZE_X,
  114. ATOMSAMPLEVIEWER_TRAIT_HIGH_INSTANCE_COUNT_TEST_COMPONENT_LATTICE_SIZE_Y,
  115. ATOMSAMPLEVIEWER_TRAIT_HIGH_INSTANCE_COUNT_TEST_COMPONENT_LATTICE_SIZE_Z);
  116. Base::Activate();
  117. AzFramework::NativeWindowHandle windowHandle = nullptr;
  118. AzFramework::WindowSystemRequestBus::BroadcastResult(
  119. windowHandle,
  120. &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  121. AzFramework::WindowRequestBus::EventResult(
  122. m_preActivateVSyncInterval,
  123. windowHandle,
  124. &AzFramework::WindowRequestBus::Events::GetSyncInterval);
  125. AzFramework::WindowRequestBus::Event(
  126. windowHandle,
  127. &AzFramework::WindowRequestBus::Events::SetSyncInterval,
  128. 0);
  129. SaveCameraConfiguration();
  130. ResetNoClipController();
  131. }
  132. void HighInstanceTestComponent::Deactivate()
  133. {
  134. RestoreCameraConfiguration();
  135. AzFramework::NativeWindowHandle windowHandle = nullptr;
  136. AzFramework::WindowSystemRequestBus::BroadcastResult(
  137. windowHandle,
  138. &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  139. AzFramework::WindowRequestBus::Event(
  140. windowHandle,
  141. &AzFramework::WindowRequestBus::Events::SetSyncInterval,
  142. m_preActivateVSyncInterval);
  143. m_materialBrowser.Deactivate();
  144. m_modelBrowser.Deactivate();
  145. AZ::TickBus::Handler::BusDisconnect();
  146. m_imguiSidebar.Deactivate();
  147. Base::Deactivate();
  148. }
  149. void HighInstanceTestComponent::PrepareCreateLatticeInstances(uint32_t instanceCount)
  150. {
  151. m_modelInstanceData.reserve(instanceCount);
  152. }
  153. void HighInstanceTestComponent::CreateLatticeInstance(const AZ::Transform& transform)
  154. {
  155. m_modelInstanceData.emplace_back<ModelInstanceData>({});
  156. ModelInstanceData& data = m_modelInstanceData.back();
  157. data.m_modelAssetId = GetRandomModelId();
  158. data.m_materialAssetId = GetRandomMaterialId();
  159. data.m_transform = transform;
  160. }
  161. void HighInstanceTestComponent::FinalizeLatticeInstances()
  162. {
  163. AZStd::set<AZ::Data::AssetId> assetIds;
  164. for (ModelInstanceData& instanceData : m_modelInstanceData)
  165. {
  166. if (instanceData.m_materialAssetId.IsValid())
  167. {
  168. assetIds.insert(instanceData.m_materialAssetId);
  169. }
  170. if (instanceData.m_modelAssetId.IsValid())
  171. {
  172. assetIds.insert(instanceData.m_modelAssetId);
  173. }
  174. }
  175. AZStd::vector<AZ::AssetCollectionAsyncLoader::AssetToLoadInfo> assetList;
  176. for (auto& assetId : assetIds)
  177. {
  178. AZ::Data::AssetInfo assetInfo;
  179. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId);
  180. if (assetInfo.m_assetId.IsValid())
  181. {
  182. AZ::AssetCollectionAsyncLoader::AssetToLoadInfo info;
  183. info.m_assetPath = assetInfo.m_relativePath;
  184. info.m_assetType = assetInfo.m_assetType;
  185. assetList.push_back(info);
  186. }
  187. }
  188. PreloadAssets(assetList);
  189. // pause script and tick until assets are ready
  190. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScriptWithTimeout, 120.0f);
  191. AZ::TickBus::Handler::BusDisconnect();
  192. }
  193. void HighInstanceTestComponent::OnAllAssetsReadyActivate()
  194. {
  195. AZ::Render::MaterialAssignmentMap materials;
  196. for (ModelInstanceData& instanceData : m_modelInstanceData)
  197. {
  198. AZ::Render::MaterialAssignment& defaultAssignment = materials[AZ::Render::DefaultMaterialAssignmentId];
  199. defaultAssignment = {};
  200. if (instanceData.m_materialAssetId.IsValid())
  201. {
  202. defaultAssignment.m_materialAsset.Create(instanceData.m_materialAssetId);
  203. defaultAssignment.m_materialInstance = AZ::RPI::Material::FindOrCreate(defaultAssignment.m_materialAsset);
  204. // cache the material when its loaded
  205. m_cachedMaterials.insert(defaultAssignment.m_materialAsset);
  206. }
  207. if (instanceData.m_modelAssetId.IsValid())
  208. {
  209. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset;
  210. modelAsset.Create(instanceData.m_modelAssetId);
  211. instanceData.m_meshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, materials);
  212. GetMeshFeatureProcessor()->SetTransform(instanceData.m_meshHandle, instanceData.m_transform);
  213. }
  214. }
  215. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  216. AZ::TickBus::Handler::BusConnect();
  217. }
  218. void HighInstanceTestComponent::DestroyLatticeInstances()
  219. {
  220. DestroyHandles();
  221. m_modelInstanceData.clear();
  222. }
  223. void HighInstanceTestComponent::DestroyHandles()
  224. {
  225. for (ModelInstanceData& instanceData : m_modelInstanceData)
  226. {
  227. GetMeshFeatureProcessor()->ReleaseMesh(instanceData.m_meshHandle);
  228. instanceData.m_meshHandle = {};
  229. }
  230. }
  231. AZ::Data::AssetId HighInstanceTestComponent::GetRandomModelId() const
  232. {
  233. auto& modelAllowlist = m_modelBrowser.GetPinnedAssets();
  234. if (modelAllowlist.size())
  235. {
  236. const size_t randomModelIndex = rand() % modelAllowlist.size();
  237. return modelAllowlist[randomModelIndex].m_assetId;
  238. }
  239. else
  240. {
  241. return AZ::RPI::AssetUtils::GetAssetIdForProductPath("testdata/objects/cube/cube.azmodel", AZ::RPI::AssetUtils::TraceLevel::Error);
  242. }
  243. }
  244. AZ::Data::AssetId HighInstanceTestComponent::GetRandomMaterialId() const
  245. {
  246. auto& materialAllowlist = m_materialBrowser.GetPinnedAssets();
  247. if (materialAllowlist.size())
  248. {
  249. const size_t randomMaterialIndex = rand() % materialAllowlist.size();
  250. return materialAllowlist[randomMaterialIndex].m_assetId;
  251. }
  252. else
  253. {
  254. return AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultPbrMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error);
  255. }
  256. }
  257. void HighInstanceTestComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint scriptTime)
  258. {
  259. AZ_PROFILE_FUNCTION(AtomSampleViewer);
  260. if (m_updateTransformEnabled)
  261. {
  262. float radians = static_cast<float>(fmod(scriptTime.GetSeconds(), AZ::Constants::TwoPi));
  263. AZ::Vector3 rotation(radians, radians, radians);
  264. AZ::Transform rotationTransform;
  265. rotationTransform.SetFromEulerRadians(rotation);
  266. for (ModelInstanceData& instanceData : m_modelInstanceData)
  267. {
  268. GetMeshFeatureProcessor()->SetTransform(instanceData.m_meshHandle, instanceData.m_transform * rotationTransform);
  269. }
  270. }
  271. if (m_imguiSidebar.Begin())
  272. {
  273. ImGui::Checkbox("Update Transforms Every Frame", &m_updateTransformEnabled);
  274. ImGui::Spacing();
  275. ImGui::Separator();
  276. ImGui::Spacing();
  277. RenderImGuiLatticeControls();
  278. m_imguiSidebar.End();
  279. }
  280. }
  281. void HighInstanceTestComponent::ResetNoClipController()
  282. {
  283. using namespace AZ;
  284. using namespace AZ::Debug;
  285. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, 2000.0f);
  286. NoClipControllerRequestBus::Event(GetCameraEntityId(), &NoClipControllerRequestBus::Events::SetHeading, AZ::DegToRad(-44.722542));
  287. NoClipControllerRequestBus::Event(GetCameraEntityId(), &NoClipControllerRequestBus::Events::SetPitch, AZ::DegToRad(24.987326));
  288. }
  289. void HighInstanceTestComponent::SaveCameraConfiguration()
  290. {
  291. Camera::CameraRequestBus::EventResult(m_originalFarClipDistance, GetCameraEntityId(), &Camera::CameraRequestBus::Events::GetFarClipDistance);
  292. }
  293. void HighInstanceTestComponent::RestoreCameraConfiguration()
  294. {
  295. Camera::CameraRequestBus::Event(GetCameraEntityId(), &Camera::CameraRequestBus::Events::SetFarClipDistance, m_originalFarClipDistance);
  296. }
  297. } // namespace AtomSampleViewer