3
0

DrawableMeshEntity.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 <Draw/DrawableMeshEntity.h>
  9. #include <Atom/RPI.Public/Model/Model.h>
  10. #include <Atom/RPI.Public/Model/ModelLodUtils.h>
  11. #include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
  12. #include <Atom/RPI.Public/Scene.h>
  13. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  14. #include <Atom/RPI.Public/ViewportContext.h>
  15. #include <Atom/RPI.Public/ViewportContextBus.h>
  16. #include <AzCore/Component/TransformBus.h>
  17. #include <AzToolsFramework/Entity/EditorEntityHelpers.h>
  18. namespace AZ::Render
  19. {
  20. // Gets the view for the specified scene
  21. static const RPI::ViewPtr GetViewFromScene(const RPI::Scene* scene)
  22. {
  23. const auto viewportContextRequests = RPI::ViewportContextRequests::Get();
  24. const auto viewportContext = viewportContextRequests->GetViewportContextByScene(scene);
  25. const RPI::ViewPtr viewPtr = viewportContext->GetDefaultView();
  26. return viewPtr;
  27. }
  28. // Utility class for common drawable data
  29. class DrawableMetaData
  30. {
  31. public:
  32. DrawableMetaData(EntityId entityId);
  33. RPI::Scene* GetScene() const;
  34. const RPI::ViewPtr GetView() const;
  35. const MeshFeatureProcessorInterface* GetFeatureProcessor() const;
  36. private:
  37. RPI::Scene* m_scene = nullptr;
  38. RPI::ViewPtr m_view = nullptr;
  39. MeshFeatureProcessorInterface* m_featureProcessor = nullptr;
  40. };
  41. DrawableMetaData::DrawableMetaData(EntityId entityId)
  42. {
  43. m_scene = RPI::Scene::GetSceneForEntityId(entityId);
  44. m_view = GetViewFromScene(m_scene);
  45. m_featureProcessor = m_scene->GetFeatureProcessor<MeshFeatureProcessorInterface>();
  46. }
  47. RPI::Scene* DrawableMetaData::GetScene() const
  48. {
  49. return m_scene;
  50. }
  51. const RPI::ViewPtr DrawableMetaData::GetView() const
  52. {
  53. return m_view;
  54. }
  55. const MeshFeatureProcessorInterface* DrawableMetaData::GetFeatureProcessor() const
  56. {
  57. return m_featureProcessor;
  58. }
  59. DrawableMeshEntity::DrawableMeshEntity(EntityId entityId, Data::Instance<RPI::Material> maskMaterial, Name drawList)
  60. : m_entityId(entityId)
  61. , m_maskMaterial(maskMaterial)
  62. , m_drawList(drawList)
  63. {
  64. AZ::Render::MeshHandleStateNotificationBus::Handler::BusConnect(m_entityId);
  65. }
  66. DrawableMeshEntity::~DrawableMeshEntity()
  67. {
  68. AZ::Render::MeshHandleStateNotificationBus::Handler::BusDisconnect();
  69. }
  70. void DrawableMeshEntity::ClearDrawData()
  71. {
  72. m_modelLodIndex = RPI::ModelLodIndex::Null;
  73. m_meshDrawPackets.clear();
  74. }
  75. bool DrawableMeshEntity::CanDraw() const
  76. {
  77. return !m_meshDrawPackets.empty();
  78. }
  79. void DrawableMeshEntity::Draw()
  80. {
  81. if (!CanDraw())
  82. {
  83. AZ_Warning(
  84. "EditorModeFeedbackSystemComponent",
  85. false,
  86. "Attempted to draw entity '%s' but entity has no draw data!",
  87. m_entityId.ToString().c_str());
  88. return;
  89. }
  90. const DrawableMetaData drawabaleMetaData(m_entityId);
  91. // If the mesh level of detail index has changed, rebuild the mesh draw packets with the new index
  92. if (!m_meshHandle || !m_meshHandle->IsValid())
  93. {
  94. return;
  95. }
  96. const auto model = drawabaleMetaData.GetFeatureProcessor()->GetModel(*m_meshHandle);
  97. if (!model)
  98. {
  99. return;
  100. }
  101. if (const auto modelLodIndex = GetModelLodIndex(drawabaleMetaData.GetView(), model);
  102. m_modelLodIndex != modelLodIndex)
  103. {
  104. CreateOrUpdateMeshDrawPackets(drawabaleMetaData.GetFeatureProcessor(), modelLodIndex, model);
  105. }
  106. AZ::RPI::DynamicDrawInterface* dynamicDraw = AZ::RPI::GetDynamicDraw();
  107. for (auto& drawPacket : m_meshDrawPackets)
  108. {
  109. drawPacket.Update(*drawabaleMetaData.GetScene());
  110. if (auto* rhiDrawPacket = drawPacket.GetRHIDrawPacket();
  111. rhiDrawPacket != nullptr)
  112. {
  113. dynamicDraw->AddDrawPacket(drawabaleMetaData.GetScene(), rhiDrawPacket);
  114. }
  115. }
  116. }
  117. RPI::ModelLodIndex DrawableMeshEntity::GetModelLodIndex(const RPI::ViewPtr view, Data::Instance<RPI::Model> model) const
  118. {
  119. const auto worldTM = AzToolsFramework::GetWorldTransform(m_entityId);
  120. return RPI::ModelLodUtils::SelectLod(view.get(), worldTM, *model);
  121. }
  122. void DrawableMeshEntity::OnMeshHandleSet(const MeshFeatureProcessorInterface::MeshHandle* meshHandle)
  123. {
  124. m_meshHandle = meshHandle;
  125. if (!m_meshHandle || !m_meshHandle->IsValid())
  126. {
  127. ClearDrawData();
  128. return;
  129. }
  130. const DrawableMetaData drawabaleMetaData(m_entityId);
  131. if (const auto model = drawabaleMetaData.GetFeatureProcessor()->GetModel(*m_meshHandle))
  132. {
  133. const auto modelLodIndex = GetModelLodIndex(drawabaleMetaData.GetView(), model);
  134. CreateOrUpdateMeshDrawPackets(drawabaleMetaData.GetFeatureProcessor(), modelLodIndex, model);
  135. }
  136. }
  137. void DrawableMeshEntity::CreateOrUpdateMeshDrawPackets(
  138. const MeshFeatureProcessorInterface* featureProcessor, const RPI::ModelLodIndex modelLodIndex, Data::Instance<RPI::Model> model)
  139. {
  140. ClearDrawData();
  141. if (!m_meshHandle || !m_meshHandle->IsValid())
  142. {
  143. return;
  144. }
  145. if (m_meshHandle->IsValid())
  146. {
  147. const auto maskMeshObjectSrg = CreateMaskShaderResourceGroup(featureProcessor);
  148. m_modelLodIndex = modelLodIndex;
  149. BuildMeshDrawPackets(model->GetModelAsset(), maskMeshObjectSrg);
  150. }
  151. }
  152. void DrawableMeshEntity::BuildMeshDrawPackets(
  153. const Data::Asset<RPI::ModelAsset> modelAsset, Data::Instance<RPI::ShaderResourceGroup> meshObjectSrg)
  154. {
  155. const auto modelLodAssets = modelAsset->GetLodAssets();
  156. const Data::Asset<RPI::ModelLodAsset>& modelLodAsset = modelLodAssets[m_modelLodIndex.m_index];
  157. Data::Instance<RPI::ModelLod> modelLod = RPI::ModelLod::FindOrCreate(modelLodAsset, modelAsset).get();
  158. for (size_t i = 0; i < modelLod->GetMeshes().size(); i++)
  159. {
  160. EditorStateMeshDrawPacket drawPacket(*modelLod, i, m_maskMaterial, m_drawList, meshObjectSrg);
  161. m_meshDrawPackets.emplace_back(drawPacket);
  162. }
  163. }
  164. Data::Instance<RPI::ShaderResourceGroup> DrawableMeshEntity::CreateMaskShaderResourceGroup(
  165. const MeshFeatureProcessorInterface* featureProcessor) const
  166. {
  167. const auto& shaderAsset = m_maskMaterial->GetAsset()->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg();
  168. const auto& objectSrgLayout = m_maskMaterial->GetAsset()->GetObjectSrgLayout();
  169. const auto maskMeshObjectSrg = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName());
  170. // Set the object id so the correct MVP matrices can be selected in the shader
  171. const auto objectId = featureProcessor->GetObjectId(*m_meshHandle).GetIndex();
  172. RHI::ShaderInputNameIndex objectIdIndex = "m_objectId";
  173. maskMeshObjectSrg->SetConstant(objectIdIndex, objectId);
  174. maskMeshObjectSrg->Compile();
  175. return maskMeshObjectSrg;
  176. }
  177. } // namespace AZ::Render