3
0

DescriptorWeightSelectorComponent.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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 "DescriptorWeightSelectorComponent.h"
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/Serialization/SerializeContext.h>
  13. #include <LmbrCentral/Dependency/DependencyNotificationBus.h>
  14. #include <GradientSignal/Ebuses/GradientRequestBus.h>
  15. #include <VegetationProfiler.h>
  16. namespace Vegetation
  17. {
  18. void DescriptorWeightSelectorConfig::Reflect(AZ::ReflectContext* context)
  19. {
  20. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  21. if (serialize)
  22. {
  23. serialize->Class<DescriptorWeightSelectorConfig, AZ::ComponentConfig>()
  24. ->Version(0)
  25. ->Field("SortBehavior", &DescriptorWeightSelectorConfig::m_sortBehavior)
  26. ->Field("Gradient", &DescriptorWeightSelectorConfig::m_gradientSampler)
  27. ;
  28. AZ::EditContext* edit = serialize->GetEditContext();
  29. if (edit)
  30. {
  31. edit->Class<DescriptorWeightSelectorConfig>(
  32. "Vegetation Asset Weight Selector", "")
  33. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  34. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  35. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  36. ->DataElement(AZ::Edit::UIHandlers::ComboBox, &DescriptorWeightSelectorConfig::m_sortBehavior, "Sort By Weight", "Defines how descriptors will be sorted before gradient is used for selection")
  37. ->EnumAttribute(SortBehavior::Unsorted, "Unsorted")
  38. ->EnumAttribute(SortBehavior::Ascending, "Ascending (lowest first)")
  39. ->EnumAttribute(SortBehavior::Descending, "Descending (highest first)")
  40. ->DataElement(0, &DescriptorWeightSelectorConfig::m_gradientSampler, "Gradient", "Gradient mapped to range between 0 and total combined weight of all descriptors.")
  41. ;
  42. }
  43. }
  44. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  45. {
  46. behaviorContext->Class<DescriptorWeightSelectorConfig>()
  47. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  48. ->Constructor()
  49. ->Property("noiseType",
  50. [](DescriptorWeightSelectorConfig* config) { return (AZ::u8&)(config->m_sortBehavior); },
  51. [](DescriptorWeightSelectorConfig* config, const AZ::u8& i) { config->m_sortBehavior = (SortBehavior)i; })
  52. ->Property("gradientSampler", BehaviorValueProperty(&DescriptorWeightSelectorConfig::m_gradientSampler))
  53. ;
  54. }
  55. }
  56. void DescriptorWeightSelectorComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  57. {
  58. services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec));
  59. }
  60. void DescriptorWeightSelectorComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  61. {
  62. services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec));
  63. }
  64. void DescriptorWeightSelectorComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& services)
  65. {
  66. }
  67. void DescriptorWeightSelectorComponent::Reflect(AZ::ReflectContext* context)
  68. {
  69. DescriptorWeightSelectorConfig::Reflect(context);
  70. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  71. if (serialize)
  72. {
  73. serialize->Class<DescriptorWeightSelectorComponent, AZ::Component>()
  74. ->Version(0)
  75. ->Field("Configuration", &DescriptorWeightSelectorComponent::m_configuration)
  76. ;
  77. }
  78. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  79. {
  80. behaviorContext->Constant("DescriptorWeightSelectorComponentTypeId", BehaviorConstant(DescriptorWeightSelectorComponentTypeId));
  81. behaviorContext->Class<DescriptorWeightSelectorComponent>()->RequestBus("DescriptorWeightSelectorRequestBus");
  82. behaviorContext->EBus<DescriptorWeightSelectorRequestBus>("DescriptorWeightSelectorRequestBus")
  83. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  84. ->Event("GetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::GetSortBehavior)
  85. ->Event("SetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::SetSortBehavior)
  86. ->VirtualProperty("SortBehavior", "GetSortBehavior", "SetSortBehavior")
  87. ->Event("GetGradientSampler", &DescriptorWeightSelectorRequestBus::Events::GetGradientSampler)
  88. ;
  89. }
  90. }
  91. DescriptorWeightSelectorComponent::DescriptorWeightSelectorComponent(const DescriptorWeightSelectorConfig& configuration)
  92. : m_configuration(configuration)
  93. {
  94. }
  95. void DescriptorWeightSelectorComponent::Activate()
  96. {
  97. m_dependencyMonitor.Reset();
  98. m_dependencyMonitor.ConnectOwner(GetEntityId());
  99. m_dependencyMonitor.ConnectDependencies({ m_configuration.m_gradientSampler.m_gradientId });
  100. DescriptorSelectorRequestBus::Handler::BusConnect(GetEntityId());
  101. DescriptorWeightSelectorRequestBus::Handler::BusConnect(GetEntityId());
  102. }
  103. void DescriptorWeightSelectorComponent::Deactivate()
  104. {
  105. m_dependencyMonitor.Reset();
  106. DescriptorSelectorRequestBus::Handler::BusDisconnect();
  107. DescriptorWeightSelectorRequestBus::Handler::BusDisconnect();
  108. }
  109. bool DescriptorWeightSelectorComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  110. {
  111. if (auto config = azrtti_cast<const DescriptorWeightSelectorConfig*>(baseConfig))
  112. {
  113. m_configuration = *config;
  114. return true;
  115. }
  116. return false;
  117. }
  118. bool DescriptorWeightSelectorComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
  119. {
  120. if (auto config = azrtti_cast<DescriptorWeightSelectorConfig*>(outBaseConfig))
  121. {
  122. *config = m_configuration;
  123. return true;
  124. }
  125. return false;
  126. }
  127. void DescriptorWeightSelectorComponent::SelectDescriptors(const DescriptorSelectorParams& params, DescriptorPtrVec& descriptors) const
  128. {
  129. VEGETATION_PROFILE_FUNCTION_VERBOSE
  130. switch (m_configuration.m_sortBehavior)
  131. {
  132. default:
  133. case SortBehavior::Unsorted:
  134. //defaulting to no sorting as an optimization since descriptors can be presorted
  135. break;
  136. case SortBehavior::Ascending:
  137. std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight < rhs->m_weight; });
  138. break;
  139. case SortBehavior::Descending:
  140. std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight > rhs->m_weight; });
  141. break;
  142. }
  143. float totalWeight = 0.0f;
  144. for (const auto& descriptor : descriptors)
  145. {
  146. totalWeight += descriptor->m_weight;
  147. }
  148. int count = 0;
  149. const GradientSignal::GradientSampleParams sampleParams(params.m_position);
  150. float minimumWeight = m_configuration.m_gradientSampler.GetValue(sampleParams) * totalWeight;
  151. float currentWeight = 0.0f;
  152. for (const auto& descriptor : descriptors)
  153. {
  154. currentWeight += descriptor->m_weight;
  155. if (currentWeight < minimumWeight)
  156. {
  157. ++count;
  158. }
  159. }
  160. if (count > 0)
  161. {
  162. descriptors.erase(descriptors.begin(), descriptors.begin() + count);
  163. }
  164. }
  165. SortBehavior DescriptorWeightSelectorComponent::GetSortBehavior() const
  166. {
  167. return m_configuration.m_sortBehavior;
  168. }
  169. void DescriptorWeightSelectorComponent::SetSortBehavior(SortBehavior behavior)
  170. {
  171. m_configuration.m_sortBehavior = behavior;
  172. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  173. }
  174. GradientSignal::GradientSampler& DescriptorWeightSelectorComponent::GetGradientSampler()
  175. {
  176. return m_configuration.m_gradientSampler;
  177. }
  178. }