Files
o3de/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
T
Chris Santora 14d2e38b90 Refactored how model material slots work in preparation to support more flexible material conversion options for the scene asset pipeline. The material slot IDs are based on the MaterialUid that come from SceneAPI. Since these IDs are also used as the AssetId sub-ID for the converted material assets, the system was just checking the material asset sub-ID to determine the material slot ID. But in order to support certain FBX material conversion options, we needed to break this tie, so the slot ID is separate from the AssetId of the material in that slot. This will allow some other material to be used in the slot, instead of being forced to use one that was generated from the FBX.
Here we inttroduce a new struct ModelMaterialSlot which formalizes the concept of material slot, with an ID, display name, and default material assignment. The ID still comes from the MaterialUid like before. The display name is built-in, rather than being parsed out from the asset file name. And the default material assignment can be any material asset, it doesn't have to come from the FBX (or other scene file).

This commit is just the preliminary set of changes. Cursory testing shows that it works pretty well but more testing is needed (and likely some fixes) before merging.

Here is what's left to do...
Add serialization version converters to preserve prior prefab data.
See if we can get rid of GetLabelByAssetId function only rely on the display name inside ModelMaterialSlot.
I'm not sure if the condition for enabling the "Edit Material Instance..." context menu item is correct.
Test actors
Lots more testing in general

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
2021-07-30 11:40:51 -07:00

156 lines
7.0 KiB
C++

/*
* 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
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Component/ComponentBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Component/NonUniformScaleBus.h>
#include <AtomCore/Instance/InstanceDatabase.h>
#include <AzFramework/Render/GeometryIntersectionBus.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <Atom/RPI.Public/Model/Model.h>
#include <Atom/Feature/Mesh/MeshFeatureProcessorInterface.h>
#include <Atom/Feature/Material/MaterialAssignment.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
namespace AZ
{
namespace Render
{
//! A configuration structure for the MeshComponentController
class MeshComponentConfig final
: public AZ::ComponentConfig
{
public:
AZ_RTTI(AZ::Render::MeshComponentConfig, "{63737345-51B1-472B-9355-98F99993909B}", ComponentConfig);
AZ_CLASS_ALLOCATOR(MeshComponentConfig, SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
// Editor helper functions
bool IsAssetSet();
AZStd::vector<AZStd::pair<RPI::Cullable::LodOverride, AZStd::string>> GetLodOverrideValues();
Data::Asset<RPI::ModelAsset> m_modelAsset = { AZ::Data::AssetLoadBehavior::QueueLoad };
RHI::DrawItemSortKey m_sortKey = 0;
RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride;
bool m_excludeFromReflectionCubeMaps = false;
bool m_useForwardPassIblSpecular = false;
};
class MeshComponentController final
: private MeshComponentRequestBus::Handler
, public AzFramework::BoundsRequestBus::Handler
, public AzFramework::RenderGeometry::IntersectionRequestBus::Handler
, private TransformNotificationBus::Handler
, private MaterialReceiverRequestBus::Handler
, private MaterialComponentNotificationBus::Handler
{
public:
friend class EditorMeshComponent;
AZ_CLASS_ALLOCATOR(MeshComponentController, AZ::SystemAllocator, 0);
AZ_RTTI(AZ::Render::MeshComponentController, "{D0F35FAC-4194-4C89-9487-D000DDB8B272}");
~MeshComponentController();
static void Reflect(AZ::ReflectContext* context);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
MeshComponentController() = default;
MeshComponentController(const MeshComponentConfig& config);
void Activate(const AZ::EntityComponentIdPair& entityComponentIdPair);
void Deactivate();
void SetConfiguration(const MeshComponentConfig& config);
const MeshComponentConfig& GetConfiguration() const;
private:
AZ_DISABLE_COPY(MeshComponentController);
// MeshComponentRequestBus::Handler overrides ...
void SetModelAsset(Data::Asset<RPI::ModelAsset> modelAsset) override;
Data::Asset<const RPI::ModelAsset> GetModelAsset() const override;
void SetModelAssetId(Data::AssetId modelAssetId) override;
Data::AssetId GetModelAssetId() const override;
void SetModelAssetPath(const AZStd::string& modelAssetPath) override;
AZStd::string GetModelAssetPath() const override;
AZ::Data::Instance<RPI::Model> GetModel() const override;
void SetSortKey(RHI::DrawItemSortKey sortKey) override;
RHI::DrawItemSortKey GetSortKey() const override;
void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override;
RPI::Cullable::LodOverride GetLodOverride() const override;
void SetVisibility(bool visible) override;
bool GetVisibility() const override;
// BoundsRequestBus and MeshComponentRequestBus overrides ...
AZ::Aabb GetWorldBounds() override;
AZ::Aabb GetLocalBounds() override;
// IntersectionRequestBus overrides ...
AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override;
// TransformNotificationBus::Handler overrides ...
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
// MaterialReceiverRequestBus::Handler overrides ...
RPI::ModelMaterialSlotMap GetModelMaterialSlots() const override;
MaterialAssignmentMap GetMaterialAssignments() const override;
AZStd::unordered_set<AZ::Name> GetModelUvNames() const override;
// MaterialComponentNotificationBus::Handler overrides ...
void OnMaterialsUpdated(const MaterialAssignmentMap& materials) override;
//! Check if the model asset requires to be cloned (e.g. cloth) for unique model instances.
//! @param modelAsset The model asset to check.
//! @result True in case the model asset needs to be cloned before creating the model. False if there is a 1:1 relationship between
//! the model asset and the model and it is static and shared. In the second case the m_originalModelAsset of the mesh handle is
//! equal to the model asset that the model is linked to.
static bool RequiresCloning(const Data::Asset<RPI::ModelAsset>& modelAsset);
void HandleModelChange(Data::Instance<RPI::Model> model);
void RegisterModel();
void UnregisterModel();
void RefreshModelRegistration();
void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale);
Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr;
Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle;
TransformInterface* m_transformInterface = nullptr;
AZ::EntityComponentIdPair m_entityComponentIdPair;
bool m_isVisible = true;
MeshComponentConfig m_configuration;
AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne();
MeshFeatureProcessorInterface::ModelChangedEvent::Handler m_changeEventHandler
{
[&](Data::Instance<RPI::Model> model) { HandleModelChange(model); }
};
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler
{
[&](const AZ::Vector3& nonUniformScale) { HandleNonUniformScaleChange(nonUniformScale); }
};
};
} // namespace Render
} // namespace AZ