| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "DescriptorWeightSelectorComponent.h"
- #include <AzCore/Component/Entity.h>
- #include <AzCore/RTTI/BehaviorContext.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <LmbrCentral/Dependency/DependencyNotificationBus.h>
- #include <GradientSignal/Ebuses/GradientRequestBus.h>
- #include <VegetationProfiler.h>
- namespace Vegetation
- {
- void DescriptorWeightSelectorConfig::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
- if (serialize)
- {
- serialize->Class<DescriptorWeightSelectorConfig, AZ::ComponentConfig>()
- ->Version(0)
- ->Field("SortBehavior", &DescriptorWeightSelectorConfig::m_sortBehavior)
- ->Field("Gradient", &DescriptorWeightSelectorConfig::m_gradientSampler)
- ;
- AZ::EditContext* edit = serialize->GetEditContext();
- if (edit)
- {
- edit->Class<DescriptorWeightSelectorConfig>(
- "Vegetation Asset Weight Selector", "")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
- ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
- ->DataElement(AZ::Edit::UIHandlers::ComboBox, &DescriptorWeightSelectorConfig::m_sortBehavior, "Sort By Weight", "Defines how descriptors will be sorted before gradient is used for selection")
- ->EnumAttribute(SortBehavior::Unsorted, "Unsorted")
- ->EnumAttribute(SortBehavior::Ascending, "Ascending (lowest first)")
- ->EnumAttribute(SortBehavior::Descending, "Descending (highest first)")
- ->DataElement(0, &DescriptorWeightSelectorConfig::m_gradientSampler, "Gradient", "Gradient mapped to range between 0 and total combined weight of all descriptors.")
- ;
- }
- }
- if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
- {
- behaviorContext->Class<DescriptorWeightSelectorConfig>()
- ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
- ->Constructor()
- ->Property("noiseType",
- [](DescriptorWeightSelectorConfig* config) { return (AZ::u8&)(config->m_sortBehavior); },
- [](DescriptorWeightSelectorConfig* config, const AZ::u8& i) { config->m_sortBehavior = (SortBehavior)i; })
- ->Property("gradientSampler", BehaviorValueProperty(&DescriptorWeightSelectorConfig::m_gradientSampler))
- ;
- }
- }
- void DescriptorWeightSelectorComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
- {
- services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec));
- }
- void DescriptorWeightSelectorComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
- {
- services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec));
- }
- void DescriptorWeightSelectorComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& services)
- {
- }
- void DescriptorWeightSelectorComponent::Reflect(AZ::ReflectContext* context)
- {
- DescriptorWeightSelectorConfig::Reflect(context);
- AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
- if (serialize)
- {
- serialize->Class<DescriptorWeightSelectorComponent, AZ::Component>()
- ->Version(0)
- ->Field("Configuration", &DescriptorWeightSelectorComponent::m_configuration)
- ;
- }
- if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
- {
- behaviorContext->Constant("DescriptorWeightSelectorComponentTypeId", BehaviorConstant(DescriptorWeightSelectorComponentTypeId));
- behaviorContext->Class<DescriptorWeightSelectorComponent>()->RequestBus("DescriptorWeightSelectorRequestBus");
- behaviorContext->EBus<DescriptorWeightSelectorRequestBus>("DescriptorWeightSelectorRequestBus")
- ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
- ->Event("GetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::GetSortBehavior)
- ->Event("SetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::SetSortBehavior)
- ->VirtualProperty("SortBehavior", "GetSortBehavior", "SetSortBehavior")
- ->Event("GetGradientSampler", &DescriptorWeightSelectorRequestBus::Events::GetGradientSampler)
- ;
- }
- }
- DescriptorWeightSelectorComponent::DescriptorWeightSelectorComponent(const DescriptorWeightSelectorConfig& configuration)
- : m_configuration(configuration)
- {
- }
- void DescriptorWeightSelectorComponent::Activate()
- {
- m_dependencyMonitor.Reset();
- m_dependencyMonitor.ConnectOwner(GetEntityId());
- m_dependencyMonitor.ConnectDependencies({ m_configuration.m_gradientSampler.m_gradientId });
- DescriptorSelectorRequestBus::Handler::BusConnect(GetEntityId());
- DescriptorWeightSelectorRequestBus::Handler::BusConnect(GetEntityId());
- }
- void DescriptorWeightSelectorComponent::Deactivate()
- {
- m_dependencyMonitor.Reset();
- DescriptorSelectorRequestBus::Handler::BusDisconnect();
- DescriptorWeightSelectorRequestBus::Handler::BusDisconnect();
- }
- bool DescriptorWeightSelectorComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
- {
- if (auto config = azrtti_cast<const DescriptorWeightSelectorConfig*>(baseConfig))
- {
- m_configuration = *config;
- return true;
- }
- return false;
- }
- bool DescriptorWeightSelectorComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
- {
- if (auto config = azrtti_cast<DescriptorWeightSelectorConfig*>(outBaseConfig))
- {
- *config = m_configuration;
- return true;
- }
- return false;
- }
- void DescriptorWeightSelectorComponent::SelectDescriptors(const DescriptorSelectorParams& params, DescriptorPtrVec& descriptors) const
- {
- VEGETATION_PROFILE_FUNCTION_VERBOSE
- switch (m_configuration.m_sortBehavior)
- {
- default:
- case SortBehavior::Unsorted:
- //defaulting to no sorting as an optimization since descriptors can be presorted
- break;
- case SortBehavior::Ascending:
- std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight < rhs->m_weight; });
- break;
- case SortBehavior::Descending:
- std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight > rhs->m_weight; });
- break;
- }
- float totalWeight = 0.0f;
- for (const auto& descriptor : descriptors)
- {
- totalWeight += descriptor->m_weight;
- }
- int count = 0;
- const GradientSignal::GradientSampleParams sampleParams(params.m_position);
- float minimumWeight = m_configuration.m_gradientSampler.GetValue(sampleParams) * totalWeight;
- float currentWeight = 0.0f;
- for (const auto& descriptor : descriptors)
- {
- currentWeight += descriptor->m_weight;
- if (currentWeight < minimumWeight)
- {
- ++count;
- }
- }
- if (count > 0)
- {
- descriptors.erase(descriptors.begin(), descriptors.begin() + count);
- }
- }
- SortBehavior DescriptorWeightSelectorComponent::GetSortBehavior() const
- {
- return m_configuration.m_sortBehavior;
- }
- void DescriptorWeightSelectorComponent::SetSortBehavior(SortBehavior behavior)
- {
- m_configuration.m_sortBehavior = behavior;
- LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
- }
- GradientSignal::GradientSampler& DescriptorWeightSelectorComponent::GetGradientSampler()
- {
- return m_configuration.m_gradientSampler;
- }
- }
|