From 0fa00a117c688c40a88dbf6aeb99b27e5d4abf15 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Fri, 23 Apr 2021 18:33:00 +0200 Subject: [PATCH] [ATOM-14477] Add clone function to model and/or model asset (#135) * Added clone methods for the buffer, model lod and model assets. * Cloning works via the creators. * Mesh handle/instance now knows about the model asset it originated from as well as the cloned model asset that we need for instancing until instancing works without the dependencies to the asset ids. * MeshComponentRequestBus returns the original asset id and the model asset. If you need access to the clone, go by the model. * Cloth component mesh now gettings its model asset from the model as it needs to work on the clone. * Moved the requires cloning function from the mesh loader in the mesh feature processor to the mesh component controller. * As we need the model asset to be loaded before we can check if it requires cloning or not, we couldn't pass in a bool from the controller but had to use a callback. * Using asset hint instead of asset id for the model lod asset creator error. * Storing a map of source buffer asset ids and the actual cloned buffer assets rather than just their ids. * Using the buffer assets from the new map directly and removed the search process in the mesh loop where the asset views are created. * Fixed the vegetation mocks. * Using the actor's mesh asset when emitting the on model ready event for the mesh component notification bus. * Mesh components notifications connection policy changed to adapt to cloned model asset. * Handling empty meshes in model lod asset creator. * Removed the requires cloning callback from the mesh feature processor and made it a parameter to the acquire mesh function * Fixing mocks and unit tests --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 13 +- .../Mesh/MeshFeatureProcessorInterface.h | 16 +- .../Code/Mocks/MockMeshFeatureProcessor.h | 12 +- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 60 +- .../RPI.Reflect/Buffer/BufferAssetCreator.h | 9 +- .../RPI.Reflect/Model/ModelAssetCreator.h | 7 + .../RPI.Reflect/Model/ModelLodAssetCreator.h | 8 + .../RPI.Reflect/Buffer/BufferAssetCreator.cpp | 16 + .../RPI.Reflect/Model/ModelAssetCreator.cpp | 35 +- .../Model/ModelLodAssetCreator.cpp | 85 +++ .../CommonFeatures/Mesh/MeshComponentBus.h | 11 +- .../Source/Mesh/MeshComponentController.cpp | 35 +- .../Source/Mesh/MeshComponentController.h | 12 +- .../Code/Source/AtomActorInstance.cpp | 8 +- .../Code/Source/AtomActorInstance.h | 4 +- .../Code/Tests/ActorRenderManagerTest.cpp | 2 +- .../cloth/Chicken/Actor/chicken.fbx.assetinfo | 602 +++++++++++------- Gems/Vegetation/Code/Tests/VegetationMocks.h | 4 +- 18 files changed, 651 insertions(+), 288 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 675984ce00..7875e38fc0 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -40,7 +40,6 @@ namespace AZ const RPI::Cullable& GetCullable() { return m_cullable; } private: - class MeshLoader : private Data::AssetBus::Handler { @@ -84,6 +83,11 @@ namespace AZ MaterialAssignmentMap m_materialAssignments; Data::Instance m_model; + + //! A reference to the original model asset in case it got cloned before creating the model instance. + Data::Asset m_originalModelAsset; + MeshFeatureProcessorInterface::RequiresCloneCallback m_requiresCloningCallback; + Data::Instance m_shaderResourceGroup; AZStd::unique_ptr m_meshLoader; RPI::Scene* m_scene = nullptr; @@ -131,16 +135,19 @@ namespace AZ const Data::Asset& modelAsset, const MaterialAssignmentMap& materials = {}, bool skinnedMeshWithMotion = false, - bool rayTracingEnabled = true) override; + bool rayTracingEnabled = true, + RequiresCloneCallback requiresCloneCallback = {}) override; MeshHandle AcquireMesh( const Data::Asset &modelAsset, const Data::Instance& material, bool skinnedMeshWithMotion = false, - bool rayTracingEnabled = true) override; + bool rayTracingEnabled = true, + RequiresCloneCallback requiresCloneCallback = {}) override; bool ReleaseMesh(MeshHandle& meshHandle) override; MeshHandle CloneMesh(const MeshHandle& meshHandle) override; Data::Instance GetModel(const MeshHandle& meshHandle) const override; + Data::Asset GetModelAsset(const MeshHandle& meshHandle) const override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override; const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 05f2a408b8..c2360068de 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -12,9 +12,12 @@ #pragma once #include +#include +#include #include #include #include +#include #include namespace AZ @@ -32,19 +35,23 @@ namespace AZ using MeshHandle = StableDynamicArrayHandle; using ModelChangedEvent = Event>; + using RequiresCloneCallback = AZStd::function& modelAsset)>; //! Acquires a model with an optional collection of material assignments. + //! @param requiresCloneCallback The callback indicates whether cloning is required for a given model asset. virtual MeshHandle AcquireMesh( const Data::Asset& modelAsset, const MaterialAssignmentMap& materials = {}, bool skinnedMeshWithMotion = false, - bool rayTracingEnabled = true) = 0; + bool rayTracingEnabled = true, + RequiresCloneCallback requiresCloneCallback = {}) = 0; //! Acquires a model with a single material applied to all its meshes. virtual MeshHandle AcquireMesh( const Data::Asset& modelAsset, const Data::Instance& material, bool skinnedMeshWithMotion = false, - bool rayTracingEnabled = true) = 0; + bool rayTracingEnabled = true, + RequiresCloneCallback requiresCloneCallback = {}) = 0; //! Releases the mesh handle virtual bool ReleaseMesh(MeshHandle& meshHandle) = 0; //! Creates a new instance and handle of a mesh using an existing MeshId. Currently, this will reset the new mesh to default materials. @@ -52,6 +59,8 @@ namespace AZ //! Gets the underlying RPI::Model instance for a meshHandle. May be null if the model has not loaded. virtual Data::Instance GetModel(const MeshHandle& meshHandle) const = 0; + //! Gets the underlying RPI::ModelAsset for a meshHandle. + virtual Data::Asset GetModelAsset(const MeshHandle& meshHandle) const = 0; //! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId. //! Note if there is already a material assignment map, this will replace the entire map with just a single material. virtual void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) = 0; @@ -61,6 +70,7 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const = 0; //! Connects a handler to any changes to an RPI::Model. Changes include loading and reloading. virtual void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) = 0; + //! Sets the transform for a given mesh handle. virtual void SetTransform(const MeshHandle& meshHandle, const Transform& transform, const Vector3& nonUniformScale = Vector3::CreateOne()) = 0; @@ -72,7 +82,7 @@ namespace AZ virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. virtual RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) = 0; - //! Sets an LOD override for a given mesh handle. This LOD will always be rendered instead being automatitcally determined. + //! Sets an LOD override for a given mesh handle. This LOD will always be rendered instead being automatically determined. virtual void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) = 0; //! Gets the LOD override for a given mesh handle. virtual RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) = 0; diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index a1a7e94cb0..39fd7b4380 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -19,16 +19,10 @@ namespace UnitTest class MockMeshFeatureProcessor : public AZ::Render::MeshFeatureProcessorInterface { public: - MOCK_METHOD3( - AcquireMesh, - MeshHandle(const AZ::Data::Asset&, const AZ::Render::MaterialAssignmentMap&, bool)); - MOCK_METHOD3( - AcquireMesh, - MeshHandle( - const AZ::Data::Asset&, const AZStd::intrusive_ptr&, bool)); MOCK_METHOD1(ReleaseMesh, bool(MeshHandle&)); MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&)); MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&)); + MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); MOCK_METHOD3(SetTransform, void(const MeshHandle&, const AZ::Transform&, const AZ::Vector3&)); @@ -41,8 +35,8 @@ namespace UnitTest MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); MOCK_METHOD1(GetLodOverride, AZ::RPI::Cullable::LodOverride(const MeshHandle&)); - MOCK_METHOD4(AcquireMesh, MeshHandle (const AZ::Data::Asset&, const AZ::Render::MaterialAssignmentMap&, bool, bool)); - MOCK_METHOD4(AcquireMesh, MeshHandle (const AZ::Data::Asset&, const AZ::Data::Instance&, bool, bool)); + MOCK_METHOD5(AcquireMesh, MeshHandle (const AZ::Data::Asset&, const AZ::Render::MaterialAssignmentMap&, bool, bool, AZ::Render::MeshFeatureProcessorInterface::RequiresCloneCallback)); + MOCK_METHOD5(AcquireMesh, MeshHandle (const AZ::Data::Asset&, const AZ::Data::Instance&, bool, bool, AZ::Render::MeshFeatureProcessorInterface::RequiresCloneCallback)); MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool)); MOCK_METHOD2(SetVisible, void (const MeshHandle&, bool)); MOCK_METHOD2(SetUseForwardPassIblSpecular, void (const MeshHandle&, bool)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 3fcdd8206d..29f0636e9e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include #include @@ -150,7 +152,8 @@ namespace AZ const Data::Asset& modelAsset, const MaterialAssignmentMap& materials, bool skinnedMeshWithMotion, - bool rayTracingEnabled) + bool rayTracingEnabled, + RequiresCloneCallback requiresCloneCallback) { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); @@ -166,8 +169,9 @@ namespace AZ meshDataHandle->m_scene = GetParentScene(); meshDataHandle->m_materialAssignments = materials; - meshDataHandle->m_objectId = m_transformService->ReserveObjectId(); + meshDataHandle->m_originalModelAsset = modelAsset; + meshDataHandle->m_requiresCloningCallback = requiresCloneCallback; meshDataHandle->m_meshLoader = AZStd::make_unique(modelAsset, &*meshDataHandle); return meshDataHandle; @@ -177,13 +181,14 @@ namespace AZ const Data::Asset& modelAsset, const Data::Instance& material, bool skinnedMeshWithMotion, - bool rayTracingEnabled) + bool rayTracingEnabled, + RequiresCloneCallback requiresCloneCallback) { Render::MaterialAssignmentMap materials; Render::MaterialAssignment& defaultMaterial = materials[AZ::Render::DefaultMaterialAssignmentId]; defaultMaterial.m_materialInstance = material; - return AcquireMesh(modelAsset, materials, skinnedMeshWithMotion, rayTracingEnabled); + return AcquireMesh(modelAsset, materials, skinnedMeshWithMotion, rayTracingEnabled, requiresCloneCallback); } bool MeshFeatureProcessor::ReleaseMesh(MeshHandle& meshHandle) @@ -205,7 +210,7 @@ namespace AZ { if (meshHandle.IsValid()) { - MeshHandle clone = AcquireMesh(meshHandle->m_model->GetModelAsset(), meshHandle->m_materialAssignments); + MeshHandle clone = AcquireMesh(meshHandle->m_originalModelAsset, meshHandle->m_materialAssignments); return clone; } return MeshFeatureProcessor::MeshHandle(); @@ -216,6 +221,16 @@ namespace AZ return meshHandle.IsValid() ? meshHandle->m_model : nullptr; } + Data::Asset MeshFeatureProcessor::GetModelAsset(const MeshHandle& meshHandle) const + { + if (meshHandle.IsValid()) + { + return meshHandle->m_originalModelAsset; + } + + return {}; + } + void MeshFeatureProcessor::SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) { Render::MaterialAssignmentMap materials; @@ -430,7 +445,6 @@ namespace AZ } // MeshDataInstance::MeshLoader... - MeshDataInstance::MeshLoader::MeshLoader(const Data::Asset& modelAsset, MeshDataInstance* parent) : m_modelAsset(modelAsset) , m_parent(parent) @@ -443,10 +457,13 @@ namespace AZ return; } - // Check if the model is in the instance database + // Check if the model is in the instance database and skip the loading process in this case. + // The model asset id is used as instance id to indicate that it is a static and shared. Data::Instance model = Data::InstanceDatabase::Instance().Find(Data::InstanceId::CreateFromAssetId(m_modelAsset.GetId())); if (model) { + // In case the mesh asset requires instancing (e.g. when containing a cloth buffer), the model will always be cloned and there will not be a + // model instance with the asset id as instance id as searched above. m_parent->Init(model); m_modelChangedEvent.Signal(AZStd::move(model)); return; @@ -470,8 +487,35 @@ namespace AZ void MeshDataInstance::MeshLoader::OnAssetReady(Data::Asset asset) { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); + Data::Asset modelAsset = asset; + + // Assign the fully loaded asset back to the mesh handle to not only hold asset id, but the actual data as well. + m_parent->m_originalModelAsset = asset; - Data::Instance model = RPI::Model::FindOrCreate(asset); + Data::Instance model; + // Check if a requires cloning callback got set and if so check if cloning the model asset is requested. + if (m_parent->m_requiresCloningCallback && + m_parent->m_requiresCloningCallback(modelAsset)) + { + // Clone the model asset to force create another model instance. + AZ::Data::AssetId newId(AZ::Uuid::CreateRandom(), /*subId=*/0); + Data::Asset clonedAsset; + if (AZ::RPI::ModelAssetCreator::Clone(modelAsset, clonedAsset, newId)) + { + model = RPI::Model::FindOrCreate(clonedAsset); + } + else + { + AZ_Error("MeshDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr()); + model = RPI::Model::FindOrCreate(modelAsset); + } + } + else + { + // Static mesh, no cloth buffer present. + model = RPI::Model::FindOrCreate(modelAsset); + } + if (model) { m_parent->Init(model); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Buffer/BufferAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Buffer/BufferAssetCreator.h index 81370b4e15..a79c691ed0 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Buffer/BufferAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Buffer/BufferAssetCreator.h @@ -61,8 +61,15 @@ namespace AZ //! Otherwise false is returned and result is left untouched. bool End(Data::Asset& result); - private: + //! Clone the given source buffer asset. + //! @param sourceAsset The source buffer asset to clone. + //! @param clonedResult The resulting, cloned buffer asset. + //! @param inOutLastCreatedAssetId The asset id from the model lod asset that owns the cloned buffer asset. The sub id will be increased and + //! used as the asset id for the cloned asset. + //! @result True in case the asset got cloned successfully, false in case an error happened and the clone process got cancelled. + static bool Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, Data::AssetId& inOutLastCreatedAssetId); + private: bool ValidateBuffer(); }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h index 73f74c1648..b3b2fd4774 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelAssetCreator.h @@ -41,6 +41,13 @@ namespace AZ //! Otherwise false is returned and result is left untouched. bool End(Data::Asset& result); + //! Clone the given source model asset. + //! @param sourceAsset The source model asset to clone. + //! @param clonedResult The resulting, cloned model lod asset. + //! @param cloneAssetId The asset id to assign to the cloned model asset + //! @result True in case the asset got cloned successfully, false in case an error happened and the clone process got cancelled. + static bool Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, const Data::AssetId& cloneAssetId); + private: AZ::Aabb m_modelAabb; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h index 50e4f769f2..471607bb34 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelLodAssetCreator.h @@ -75,6 +75,14 @@ namespace AZ //! Finalizes the ModelLodAsset and assigns ownership of the asset to result if successful, otherwise returns false and result is left untouched. bool End(Data::Asset& result); + //! Clone the given source model lod asset. + //! @param sourceAsset The source model lod asset to clone. + //! @param clonedResult The resulting, cloned model lod asset. + //! @param inOutLastCreatedAssetId The asset id from the model asset that owns the cloned model lod asset. The sub id will be increased and + //! used as the asset id for the cloned asset. + //! @result True in case the asset got cloned successfully, false in case an error happened and the clone process got cancelled. + static bool Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, Data::AssetId& inOutLastCreatedAssetId); + private: bool m_meshBegan = false; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp index 78fc47891b..486be9860e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp @@ -155,5 +155,21 @@ namespace AZ m_asset.SetHint(name); } + bool BufferAssetCreator::Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, Data::AssetId& inOutLastCreatedAssetId) + { + BufferAssetCreator creator; + inOutLastCreatedAssetId.m_subId = inOutLastCreatedAssetId.m_subId + 1; + creator.Begin(inOutLastCreatedAssetId); + + creator.SetBufferName(sourceAsset.GetHint()); + creator.SetUseCommonPool(sourceAsset->GetCommonPoolType()); + creator.SetPoolAsset(sourceAsset->GetPoolAsset()); + creator.SetBufferViewDescriptor(sourceAsset->GetBufferViewDescriptor()); + + const AZStd::array_view sourceBuffer = sourceAsset->GetBuffer(); + creator.SetBuffer(sourceBuffer.data(), sourceBuffer.size(), sourceAsset->GetBufferDescriptor()); + + return creator.End(clonedResult); + } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp index b3f4fc30a4..65fb08b52b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAssetCreator.cpp @@ -11,6 +11,7 @@ */ #include +#include #include @@ -64,5 +65,37 @@ namespace AZ m_asset->SetReady(); return EndCommon(result); } + + bool ModelAssetCreator::Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, const Data::AssetId& cloneAssetId) + { + if (!sourceAsset.IsReady()) + { + return false; + } + + ModelAssetCreator creator; + creator.Begin(cloneAssetId); + creator.SetName(sourceAsset->GetName().GetStringView()); + + AZ::Data::AssetId lastUsedId = cloneAssetId; + const AZStd::array_view> sourceLodAssets = sourceAsset->GetLodAssets(); + for (const Data::Asset& sourceLodAsset : sourceLodAssets) + { + Data::Asset lodAsset; + if (!ModelLodAssetCreator::Clone(sourceLodAsset, lodAsset, lastUsedId)) + { + AZ_Error("ModelAssetCreator", false, + "Cannot clone model lod asset for '%s'.", sourceLodAsset.GetHint().c_str()); + return false; + } + + if (lodAsset.IsReady()) + { + creator.AddLodAsset(AZStd::move(lodAsset)); + } + } + + return creator.End(clonedResult); + } } // namespace RPI -} // namespace AZ \ No newline at end of file +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp index 8a0db38ee6..db2eebf84d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelLodAssetCreator.cpp @@ -10,6 +10,8 @@ * */ +#include +#include #include #include @@ -240,5 +242,88 @@ namespace AZ return true; } + + bool ModelLodAssetCreator::Clone(const Data::Asset& sourceAsset, Data::Asset& clonedResult, Data::AssetId& inOutLastCreatedAssetId) + { + AZStd::array_view sourceMeshes = sourceAsset->GetMeshes(); + if (sourceMeshes.empty()) + { + return true; + } + + ModelLodAssetCreator creator; + inOutLastCreatedAssetId.m_subId = inOutLastCreatedAssetId.m_subId + 1; + creator.Begin(inOutLastCreatedAssetId); + + // Add the index buffer + const Data::Asset sourceIndexBufferAsset = sourceMeshes[0].GetIndexBufferAssetView().GetBufferAsset(); + Data::Asset clonedIndexBufferAsset; + BufferAssetCreator::Clone(sourceIndexBufferAsset, clonedIndexBufferAsset, inOutLastCreatedAssetId); + creator.SetLodIndexBuffer(clonedIndexBufferAsset); + + // Add meshes + AZStd::unordered_map> oldToNewBufferAssets; + for (const ModelLodAsset::Mesh& sourceMesh : sourceMeshes) + { + // Add stream buffers + for (const AZ::RPI::ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo : sourceMesh.GetStreamBufferInfoList()) + { + const Data::Asset& sourceStreamBuffer = streamBufferInfo.m_bufferAssetView.GetBufferAsset(); + const AZ::Data::AssetId sourceBufferAssetId = sourceStreamBuffer.GetId(); + + // In case the buffer asset id is not part of our old to new asset id mapping, we did not convert and add it yet. + if (oldToNewBufferAssets.find(sourceBufferAssetId) == oldToNewBufferAssets.end()) + { + Data::Asset streamBufferAsset; + if (!BufferAssetCreator::Clone(sourceStreamBuffer, streamBufferAsset, inOutLastCreatedAssetId)) + { + AZ_Error("ModelLodAssetCreator", false, + "Cannot clone buffer asset for '%s'.", sourceBufferAssetId.ToString().c_str()); + return false; + } + + oldToNewBufferAssets[sourceBufferAssetId] = streamBufferAsset; + creator.AddLodStreamBuffer(streamBufferAsset); + } + } + + // Add mesh + creator.BeginMesh(); + creator.SetMeshName(sourceMesh.GetName()); + AZ::Aabb aabb = sourceMesh.GetAabb(); + creator.SetMeshAabb(AZStd::move(aabb)); + creator.SetMeshMaterialAsset(sourceMesh.GetMaterialAsset()); + + // Mesh index buffer view + const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView(); + BufferAssetView indexBufferAssetView(clonedIndexBufferAsset, sourceIndexBufferView.GetBufferViewDescriptor()); + creator.SetMeshIndexBuffer(indexBufferAssetView); + + // Mesh stream buffer views + for (const AZ::RPI::ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo : sourceMesh.GetStreamBufferInfoList()) + { + // Get the corresponding new buffer asset id from the source buffer. + const AZ::Data::AssetId sourceBufferAssetId = streamBufferInfo.m_bufferAssetView.GetBufferAsset().GetId(); + const auto assetIdIterator = oldToNewBufferAssets.find(sourceBufferAssetId); + if (assetIdIterator != oldToNewBufferAssets.end()) + { + const Data::Asset& clonedBufferAsset = assetIdIterator->second; + BufferAssetView bufferAssetView(clonedBufferAsset, streamBufferInfo.m_bufferAssetView.GetBufferViewDescriptor()); + creator.AddMeshStreamBuffer(streamBufferInfo.m_semantic, streamBufferInfo.m_customName, bufferAssetView); + } + else + { + AZ_Error("ModelLodAssetCreator", false, + "Cannot find cloned buffer asset for source buffer asset '%s'.", + sourceBufferAssetId.ToString().c_str()); + return false; + } + } + + creator.EndMesh(); + } + + return creator.End(clonedResult); + } } // namespace RPI } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h index f12db2ec9d..65233a4847 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h @@ -27,7 +27,7 @@ namespace AZ { public: virtual void SetModelAsset(Data::Asset modelAsset) = 0; - virtual const Data::Asset& GetModelAsset() const = 0; + virtual Data::Asset GetModelAsset() const = 0; virtual void SetModelAssetId(Data::AssetId modelAssetId) = 0; virtual Data::AssetId GetModelAssetId() const = 0; @@ -35,7 +35,7 @@ namespace AZ virtual void SetModelAssetPath(const AZStd::string& path) = 0; virtual AZStd::string GetModelAssetPath() const = 0; - virtual const Data::Instance GetModel() const = 0; + virtual Data::Instance GetModel() const = 0; virtual void SetSortKey(RHI::DrawItemSortKey sortKey) = 0; virtual RHI::DrawItemSortKey GetSortKey() const = 0; @@ -78,12 +78,15 @@ namespace AZ { AZ::EBusConnectionPolicy::Connect(busPtr, context, handler, connectLock, id); + Data::Asset modelAsset; + MeshComponentRequestBus::EventResult(modelAsset, id, &MeshComponentRequestBus::Events::GetModelAsset); Data::Instance model; MeshComponentRequestBus::EventResult(model, id, &MeshComponentRequestBus::Events::GetModel); + if (model && - model->GetModelAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready) + modelAsset.GetStatus() == AZ::Data::AssetData::AssetStatus::Ready) { - handler->OnModelReady(model->GetModelAsset(), model); + handler->OnModelReady(modelAsset, model); } } }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index b0315fdf9c..9d2196de2b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -268,12 +268,32 @@ namespace AZ } } + bool MeshComponentController::RequiresCloning(const Data::Asset& modelAsset) + { + // Is the model asset containing a cloth buffer? If yes, we need to clone the model asset for instancing. + const AZStd::array_view> lodAssets = modelAsset->GetLodAssets(); + for (const AZ::Data::Asset& lodAsset : lodAssets) + { + const AZStd::array_view meshes = lodAsset->GetMeshes(); + for (const AZ::RPI::ModelLodAsset::Mesh& mesh : meshes) + { + if (mesh.GetSemanticBufferAssetView(AZ::Name("CLOTH_DATA")) != nullptr) + { + return true; + } + } + } + + return false; + } + void MeshComponentController::HandleModelChange(Data::Instance model) { - if (model) + Data::Asset modelAsset = m_meshFeatureProcessor->GetModelAsset(m_meshHandle); + if (model && modelAsset) { - m_configuration.m_modelAsset = model->GetModelAsset(); - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, model->GetModelAsset(), model); + m_configuration.m_modelAsset = modelAsset; + MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model); MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged); AzFramework::EntityBoundsUnionRequestBus::Broadcast( &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, m_entityId); @@ -288,7 +308,8 @@ namespace AZ MaterialComponentRequestBus::EventResult(materials, m_entityId, &MaterialComponentRequests::GetMaterialOverrides); m_meshFeatureProcessor->ReleaseMesh(m_meshHandle); - m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); + m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials, + /*skinnedMeshWithMotion=*/false, /*rayTracingEnabled=*/true, RequiresCloning); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : AZ::Transform::CreateIdentity(); @@ -345,9 +366,9 @@ namespace AZ } } - const Data::Asset& MeshComponentController::GetModelAsset() const + Data::Asset MeshComponentController::GetModelAsset() const { - return GetModel() ? GetModel()->GetModelAsset() : m_configuration.m_modelAsset; + return m_configuration.m_modelAsset; } Data::AssetId MeshComponentController::GetModelAssetId() const @@ -369,7 +390,7 @@ namespace AZ return assetPathString; } - const Data::Instance MeshComponentController::GetModel() const + Data::Instance MeshComponentController::GetModel() const { return m_meshFeatureProcessor ? m_meshFeatureProcessor->GetModel(m_meshHandle) : Data::Instance(); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index afdcfa25c7..0cda34ea42 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -83,17 +83,16 @@ namespace AZ const MeshComponentConfig& GetConfiguration() const; private: - AZ_DISABLE_COPY(MeshComponentController); // MeshComponentRequestBus::Handler overrides ... void SetModelAsset(Data::Asset modelAsset) override; - const Data::Asset& GetModelAsset() const override; + Data::Asset 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; - const AZ::Data::Instance GetModel() const override; + AZ::Data::Instance GetModel() const override; void SetSortKey(RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey() const override; @@ -118,6 +117,13 @@ namespace AZ // 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& modelAsset); + void HandleModelChange(Data::Instance model); void RegisterModel(); void UnregisterModel(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index cd5f3bb6c5..1aaf88c25d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -219,7 +219,7 @@ namespace AZ AZ_Assert(false, "AtomActorInstance::SetModelAsset not supported"); } - const Data::Asset& AtomActorInstance::GetModelAsset() const + Data::Asset AtomActorInstance::GetModelAsset() const { AZ_Assert(GetActor(), "Expecting a Atom Actor Instance having a valid Actor."); return GetActor()->GetMeshAsset(); @@ -253,7 +253,7 @@ namespace AZ return GetModelAsset().GetHint(); } - const AZ::Data::Instance AtomActorInstance::GetModel() const + AZ::Data::Instance AtomActorInstance::GetModel() const { return m_skinnedMeshInstance->m_model; } @@ -459,7 +459,7 @@ namespace AZ MeshComponentRequestBus::Handler::BusConnect(m_entityId); const Data::Instance model = m_meshFeatureProcessor->GetModel(*m_meshHandle); - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, model->GetModelAsset(), model); + MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, GetModelAsset(), model); } void AtomActorInstance::UnregisterActor() @@ -485,7 +485,7 @@ namespace AZ { // Last boolean parameter indicates if motion vector is enabled m_meshHandle = AZStd::make_shared( - m_meshFeatureProcessor->AcquireMesh(m_skinnedMeshInstance->m_model->GetModelAsset(), materials, true)); + m_meshFeatureProcessor->AcquireMesh(m_skinnedMeshInstance->m_model->GetModelAsset(), materials, /*skinnedMeshWithMotion=*/true)); } // If render proxies already exist, they will be auto-freed diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index a2cf042efa..b31091681e 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -128,12 +128,12 @@ namespace AZ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MeshComponentRequestBus::Handler overrides... void SetModelAsset(Data::Asset modelAsset) override; - const Data::Asset& GetModelAsset() const override; + Data::Asset 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; - const AZ::Data::Instance GetModel() const override; + AZ::Data::Instance GetModel() const override; void SetSortKey(RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey() const override; void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override; diff --git a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp index 114721a095..6db4adbab3 100644 --- a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp +++ b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp @@ -98,7 +98,7 @@ namespace Blast // ActorRenderManager::OnActorCreated { EXPECT_CALL( - *m_mockMeshFeatureProcessor, AcquireMesh(_, testing::A(), _, _)) + *m_mockMeshFeatureProcessor, AcquireMesh(_, testing::A(), _, _, _)) .Times(aznumeric_cast(m_actorFactory->m_mockActors[0]->GetChunkIndices().size())) .WillOnce(Return(testing::ByMove(AZ::Render::MeshFeatureProcessorInterface::MeshHandle()))) .WillOnce(Return(testing::ByMove(AZ::Render::MeshFeatureProcessorInterface::MeshHandle()))); diff --git a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo index 92c20c02ac..808b024189 100644 --- a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo +++ b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo @@ -1,240 +1,362 @@ -{ - "values": [ - { - "$type": "ActorGroup", - "name": "chicken", - "id": "{C086F309-EE7E-5AFD-A9C2-69DE5BA48461}", - "rules": { - "rules": [ - { - "$type": "MetaDataRule", - "metaData": "AdjustActor -actorID $(ACTORID) -name \"chicken\"\nActorSetCollisionMeshes -actorID $(ACTORID) -lod 0 -nodeList \"\"\nAdjustActor -actorID $(ACTORID) -nodesExcludedFromBounds \"\" -nodeAction \"select\"\nAdjustActor -actorID $(ACTORID) -nodeAction \"replace\" -attachmentNodes \"\"\nAdjustActor -actorID $(ACTORID) -mirrorSetup \"\"\n" - }, - { - "$type": "ActorPhysicsSetupRule", - "data": { - "config": { - "clothConfig": { - "nodes": [ - { - "name": "def_c_head_joint", - "shapes": [ - [ - { - "Visible": true, - "Position": [ - -0.08505599945783615, - 0.0, - 0.009370899759232998 - ], - "Rotation": [ - 0.7071437239646912, - 0.0, - 0.0, - 0.708984375 - ], - "propertyVisibilityFlags": 248 - }, - { - "$type": "CapsuleShapeConfiguration", - "Height": 0.191273495554924, - "Radius": 0.05063670128583908 - } - ] - ] - }, - { - "name": "def_c_neck_joint", - "shapes": [ - [ - { - "Visible": true, - "Position": [ - 0.08189810067415238, - -2.4586914726398847e-9, - -0.4713243842124939 - ], - "propertyVisibilityFlags": 248 - }, - { - "$type": "SphereShapeConfiguration", - "Radius": 0.2406993955373764 - } - ] - ] - }, - { - "name": "def_c_spine_end", - "shapes": [ - [ - { - "Visible": true, - "Position": [ - -2.0000000233721949e-7, - 0.012646200135350228, - -0.24104370176792146 - ], - "propertyVisibilityFlags": 248 - }, - { - "$type": "SphereShapeConfiguration", - "Radius": 0.24875959753990174 - } - ] - ] - }, - { - "name": "def_c_feather2_joint", - "shapes": [ - [ - { - "Visible": true, - "Position": [ - 0.06151500344276428, - 0.1300000101327896, - 7.729977369308472e-8 - ], - "Rotation": [ - 0.0, - 0.7071062922477722, - 0.0, - 0.7071072459220886 - ], - "propertyVisibilityFlags": 248 - }, - { - "$type": "CapsuleShapeConfiguration", - "Height": 0.5730299949645996, - "Radius": 0.06151498109102249 - } - ] - ] - } - ] - } - } - } - } - ] - } - }, - { - "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup", - "name": "chicken", - "nodeSelectionList": { - "selectedNodes": [ - "RootNode", - "RootNode.chicken_skeleton", - "RootNode.chicken_feet_skin", - "RootNode.chicken_eyes_skin", - "RootNode.chicken_body_skin", - "RootNode.chicken_mohawk", - "RootNode.chicken_skeleton.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint", - "RootNode.chicken_feet_skin.SkinWeight_0", - "RootNode.chicken_feet_skin.map1", - "RootNode.chicken_feet_skin.chicken_body_mat", - "RootNode.chicken_eyes_skin.SkinWeight_0", - "RootNode.chicken_eyes_skin.uvSet1", - "RootNode.chicken_eyes_skin.chicken_eye_mat", - "RootNode.chicken_body_skin.SkinWeight_0", - "RootNode.chicken_body_skin.map1", - "RootNode.chicken_body_skin.chicken_body_mat", - "RootNode.chicken_mohawk.SkinWeight_0", - "RootNode.chicken_mohawk.colorSet1", - "RootNode.chicken_mohawk.map1", - "RootNode.chicken_mohawk.mohawkMat", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint.def_l_ball_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint.def_r_ball_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint.def_c_tail2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint.def_l_wing_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint.def_r_wing_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint.def_l_ball_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint.def_r_ball_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint.def_c_tail2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint.def_l_wing_end.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint.def_r_wing_end.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint.def_c_mouth_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint.def_c_mouth_end.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint.def_c_waddle_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint.def_c_feather_end", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint.def_c_waddle_end.transform", - "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint.def_c_feather_end.transform" - ] - }, - "rules": { - "rules": [ - { - "$type": "SkinRule" - }, - { - "$type": "StaticMeshAdvancedRule", - "vertexColorStreamName": "Disabled" - }, - { - "$type": "MaterialRule" - }, - { - "$type": "ClothRule", - "meshNodeName": "RootNode.chicken_mohawk", - "inverseMassesStreamName": "colorSet1", - "motionConstraintsStreamName": "Default: 1.0", - "backstopStreamName": "None" - } - ] - }, - "id": "{55E26F74-B35F-4BC1-87BB-83E3DE85C346}" - } - ] -} \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/Vegetation/Code/Tests/VegetationMocks.h b/Gems/Vegetation/Code/Tests/VegetationMocks.h index 449e5284bb..4e3d7250e1 100644 --- a/Gems/Vegetation/Code/Tests/VegetationMocks.h +++ b/Gems/Vegetation/Code/Tests/VegetationMocks.h @@ -511,7 +511,7 @@ namespace UnitTest } AZ::Data::Asset m_GetMeshAssetOutput; - const AZ::Data::Asset& GetModelAsset() const override + AZ::Data::Asset GetModelAsset() const override { return m_GetMeshAssetOutput; } @@ -546,7 +546,7 @@ namespace UnitTest return m_modelAssetPathOutput; } - const AZ::Data::Instance GetModel() const override + AZ::Data::Instance GetModel() const override { return AZ::Data::Instance(); }