/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace EMotionFX { class Actor; class ActorInstance; } namespace AZ::RPI { class AuxGeomDraw; class AuxGeomFeatureProcessorInterface; class Model; class Buffer; class StreamingImage; } namespace AZ { namespace Render { class SkinnedMeshFeatureProcessorInterface; class SkinnedMeshInputBuffers; class MeshFeatureProcessorInterface; class AtomActor; //! Render node for managing and rendering actor instances. Each Actor Component //! creates an ActorRenderNode. The render node is responsible for drawing meshes and //! passing skinning transforms to the skinning pipeline. class AtomActorInstance : public EMotionFX::Integration::RenderActorInstance , public AZ::TransformNotificationBus::Handler , public AZ::Render::MaterialReceiverRequestBus::Handler , public AzFramework::BoundsRequestBus::Handler , public AZ::Render::MaterialComponentNotificationBus::Handler , public AZ::Render::MeshComponentRequestBus::Handler , private AZ::Render::SkinnedMeshFeatureProcessorNotificationBus::Handler , private AZ::Render::SkinnedMeshOutputStreamNotificationBus::Handler , private LmbrCentral::SkeletalHierarchyRequestBus::Handler , private Data::AssetBus::MultiHandler { public: AZ_CLASS_ALLOCATOR_DECL; AZ_RTTI(AZ::Render::AtomActorInstance, "{6C933B44-8D4A-43B0-9F0F-C1932A257ABC}", EMotionFX::Integration::RenderActorInstance) AZ_DISABLE_COPY_MOVE(AtomActorInstance); AtomActorInstance() = delete; AtomActorInstance(AZ::EntityId entityId, const EMotionFX::Integration::EMotionFXPtr& actorInstance, const AZ::Data::Asset& asset, const AZ::Transform& worldTransform, EMotionFX::Integration::SkinningMethod skinningMethod); ~AtomActorInstance() override; // RenderActorInstance overrides ... void OnTick(float timeDelta) override; void UpdateBounds() override; void DebugDraw(const DebugOptions& debugOptions) override; void SetMaterials(const EMotionFX::Integration::ActorAsset::MaterialList& materialPerLOD) override { AZ_UNUSED(materialPerLOD); }; void SetSkinningMethod(EMotionFX::Integration::SkinningMethod emfxSkinningMethod); SkinningMethod GetAtomSkinningMethod() const; void SetIsVisible(bool isVisible) override; // BoundsRequestBus overrides ... AZ::Aabb GetWorldBounds() override; AZ::Aabb GetLocalBounds() override; AtomActor* GetRenderActor() const; ///////////////////////////////////////////// void Activate(); void Deactivate(); // Create all the buffers necessary for a skinned mesh render proxy and mesh render proxy, then register it with Atom void Create(); // Release render proxies and destroy all the buffers void Destroy(); // Acquire render proxies from Atom. Assumes the input buffers already exist. void RegisterActor(); // Release render proxies, but don't destroy the buffers used to create them. Can be used to hide the actor while keeping its resources around for later. void UnregisterActor(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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 GetModelUvNames() const override; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MaterialComponentNotificationBus::Handler overrides... void OnMaterialsUpdated(const MaterialAssignmentMap& materials) override; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MeshComponentRequestBus::Handler overrides... void SetModelAsset(Data::Asset modelAsset) 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; AZ::Data::Instance 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; // GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SkeletalHierarchyRequestBus::Handler overrides... AZ::u32 GetJointCount() override; const char* GetJointNameByIndex(AZ::u32 jointIndex) override; AZ::s32 GetJointIndexByName(const char* jointName) override; AZ::Transform GetJointTransformCharacterRelative(AZ::u32 jointIndex) override; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Data::AssetBus::MultiHandler::Handler overrides... void OnAssetReady(AZ::Data::Asset asset) override; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SkinnedMeshFeatureProcessorNotificationBus void OnUpdateSkinningMatrices() override; void CreateRenderProxy(const MaterialAssignmentMap& materials); private: void CreateSkinnedMeshInstance(); // Copies input buffers to output skinned buffers when the skinned mesh instance is created. void FillSkinnedMeshInstanceBuffers(); // SkinnedMeshOutputStreamNotificationBus void OnSkinnedMeshOutputStreamMemoryAvailable() override; // Check to see if the skin material is being used, // and if there are blend shapes with wrinkle masks that should be applied to it void InitWrinkleMasks(); void UpdateWrinkleMasks(); // Helper and debug geometry rendering void RenderSkeleton(RPI::AuxGeomDraw* auxGeom); void RenderEMFXDebugDraw(RPI::AuxGeomDraw* auxGeom); RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr; AZStd::vector m_auxVertices; AZStd::vector m_auxColors; AZStd::intrusive_ptr m_skinnedMeshInputBuffers = nullptr; AZStd::intrusive_ptr m_skinnedMeshInstance; AZ::Data::Instance m_boneTransforms = nullptr; AZ::Render::SkinnedMeshRenderProxyInterfaceHandle m_skinnedMeshRenderProxy; AZ::Render::SkinnedMeshFeatureProcessorInterface* m_skinnedMeshFeatureProcessor = nullptr; AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; //m_meshHandle is wrapped in a shared pointer so that it can be shared between this and the SkinnedMeshRenderProxy (the handle itself cannot be copied) AZStd::shared_ptr m_meshHandle; AZ::TransformInterface* m_transformInterface = nullptr; AZStd::set m_waitForMaterialLoadIds; AZStd::vector m_morphTargetWeights; typedef AZStd::unordered_map> MorphTargetWrinkleMaskMap; AZStd::vector m_morphTargetWrinkleMaskMapsByLod; AZStd::vector> m_wrinkleMasks; AZStd::vector m_wrinkleMaskWeights; }; } // namespace Render } // namespace AZ