diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp index 4ecd1c0117..864c193a9a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp @@ -6,7 +6,6 @@ * */ -// include the required headers #include "EMotionFXConfig.h" #include "EMotionFXManager.h" #include "Importer/Importer.h" @@ -29,6 +28,7 @@ #include #include #include +#include #include namespace EMotionFX @@ -76,6 +76,7 @@ namespace EMotionFX gEMFX.Get()->SetRecorder (Recorder::Create()); gEMFX.Get()->SetMotionInstancePool (MotionInstancePool::Create()); gEMFX.Get()->SetDebugDraw (aznew DebugDraw()); + gEMFX.Get()->SetPoseDataFactory (aznew PoseDataFactory()); gEMFX.Get()->SetGlobalSimulationSpeed (1.0f); // set the number of threads @@ -124,6 +125,7 @@ namespace EMotionFX m_recorder = nullptr; m_motionInstancePool = nullptr; m_debugDraw = nullptr; + m_poseDataFactory = nullptr; m_unitType = MCore::Distance::UNITTYPE_METERS; m_globalSimulationSpeed = 1.0f; m_isInEditorMode = false; @@ -170,6 +172,9 @@ namespace EMotionFX delete m_debugDraw; m_debugDraw = nullptr; + delete m_poseDataFactory; + m_poseDataFactory = nullptr; + m_renderActorSettings.reset(); m_eventManager->Destroy(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h index 4d55143b2f..7276516739 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h @@ -37,6 +37,7 @@ namespace EMotionFX class MotionInstancePool; class EventDataFactory; class DebugDraw; + class PoseDataFactory; // versions #define EMFX_HIGHVERSION 4 @@ -188,6 +189,8 @@ namespace EMotionFX */ MCORE_INLINE DebugDraw* GetDebugDraw() const { return m_debugDraw; } + MCORE_INLINE PoseDataFactory* GetPoseDataFactory() const { return m_poseDataFactory; } + /** * Get the render actor settings * @result A pointer to global render actor settings. @@ -357,6 +360,7 @@ namespace EMotionFX EventManager* m_eventManager; /**< The motion event manager. */ SoftSkinManager* m_softSkinManager; /**< The softskin manager. */ AnimGraphManager* m_animGraphManager; /**< The animgraph manager. */ + PoseDataFactory* m_poseDataFactory; Recorder* m_recorder; /**< The recorder. */ MotionInstancePool* m_motionInstancePool; /**< The motion instance pool. */ DebugDraw* m_debugDraw; /**< The debug drawing system. */ @@ -433,6 +437,8 @@ namespace EMotionFX */ void SetMotionInstancePool(MotionInstancePool* pool); + void SetPoseDataFactory(PoseDataFactory* poseDataFactory) { m_poseDataFactory = poseDataFactory; } + /** * Set the number of threads to use. * @param numThreads The number of threads to use internally. This must be a value of 1 or above. @@ -520,5 +526,6 @@ namespace EMotionFX MCORE_INLINE Recorder& GetRecorder() { return *GetEMotionFX().GetRecorder(); } /**< Get the recorder. */ MCORE_INLINE MotionInstancePool& GetMotionInstancePool() { return *GetEMotionFX().GetMotionInstancePool(); } /**< Get the motion instance pool. */ MCORE_INLINE DebugDraw& GetDebugDraw() { return *GetEMotionFX().GetDebugDraw(); } /**< Get the debug drawing. */ + MCORE_INLINE PoseDataFactory& GetPoseDataFactory() { return *GetEMotionFX().GetPoseDataFactory(); } MCORE_INLINE AZ::Render::RenderActorSettings& GetRenderActorSettings() { return *GetEMotionFX().GetRenderActorSettings(); }/**< Get the render actor settings. */ } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index e2bff677ad..232bdacfd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -1428,4 +1428,38 @@ namespace EMotionFX GetEMotionFX().GetThreadData(m_actorInstance->GetThreadIndex())->GetPosePool().FreePose(tempPose); } -} // namespace EMotionFX + + void Pose::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Color& color, bool drawPoseDatas) const + { + debugDisplay.SetColor(color); + debugDisplay.DepthTestOff(); + + const Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); + const size_t numEnabledJoints = m_actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabledJoints; ++i) + { + const size_t jointIndex = m_actorInstance->GetEnabledNode(i); + const size_t parentIndex = skeleton->GetNode(jointIndex)->GetParentIndex(); + if (parentIndex != InvalidIndex) + { + const AZ::Vector3 startPos = GetWorldSpaceTransform(jointIndex).m_position; + const AZ::Vector3 endPos = GetWorldSpaceTransform(parentIndex).m_position; + + debugDisplay.DrawSolidCylinder(/*center=*/(startPos + endPos) * 0.5f, + /*direction=*/(endPos - startPos).GetNormalizedSafe(), + /*radius=*/0.005f, + /*height=*/(endPos - startPos).GetLength(), + /*drawShaded=*/false); + } + } + + if (drawPoseDatas) + { + for (const auto& poseDataItem : m_poseDatas) + { + PoseData* poseData = poseDataItem.second.get(); + poseData->DebugDraw(debugDisplay, color); + } + } + } +} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index b7844276be..451e855150 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -10,10 +10,10 @@ #include #include +#include #include #include - namespace EMotionFX { // forward declarations @@ -25,10 +25,6 @@ namespace EMotionFX class Skeleton; class MotionLinkData; - /** - * - * - */ class EMFX_API Pose { MCORE_MEMORYOBJECTCATEGORY(Pose, EMFX_DEFAULT_ALIGNMENT, EMFX_MEMCATEGORY_POSE); @@ -192,6 +188,14 @@ namespace EMotionFX template T* GetAndPreparePoseData(ActorInstance* linkToActorInstance) { return azdynamic_cast(GetAndPreparePoseData(azrtti_typeid(), linkToActorInstance)); } + /** + * Draw debug visualization for the given pose. + * @param[in] debugDisplay Debug display request bus to spawn the render commands. + * @param[in] color The color the skeletal pose should be in. + * @param[in] drawPoseDatas Draw the pose data debug visualizations (e.g. joint velocities) along with the actual skeletal pose. [Default = false] + */ + void DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Color& color, bool drawPoseDatas = false) const; + private: mutable AZStd::vector m_localSpaceTransforms; mutable AZStd::vector m_modelSpaceTransforms; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PoseData.h b/Gems/EMotionFX/Code/EMotionFX/Source/PoseData.h index 31c22a3839..69e8800c0a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PoseData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PoseData.h @@ -12,9 +12,9 @@ #include #include #include +#include #include - namespace EMotionFX { class Actor; @@ -40,6 +40,8 @@ namespace EMotionFX virtual void Blend(const Pose* destPose, float weight) = 0; + virtual void DebugDraw([[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay, [[maybe_unused]] const AZ::Color& color) const {} + bool IsUsed() const { return m_isUsed; } void SetIsUsed(bool isUsed) { m_isUsed = isUsed; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.cpp index c1c2627c8d..857cc7da7e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.cpp @@ -8,13 +8,20 @@ #include #include +#include #include #include #include - namespace EMotionFX { + AZ_CLASS_ALLOCATOR_IMPL(PoseDataFactory, PoseAllocator, 0) + + PoseDataFactory::PoseDataFactory() + { + AddPoseDataType(azrtti_typeid()); + } + PoseData* PoseDataFactory::Create(Pose* pose, const AZ::TypeId& type) { AZ::SerializeContext* context = nullptr; @@ -34,13 +41,13 @@ namespace EMotionFX return result; } - const AZStd::unordered_set& PoseDataFactory::GetTypeIds() + void PoseDataFactory::AddPoseDataType(const AZ::TypeId& poseDataType) { - static AZStd::unordered_set typeIds = - { - azrtti_typeid() - }; + m_poseDataTypeIds.emplace(poseDataType); + } - return typeIds; + const AZStd::unordered_set& PoseDataFactory::GetTypeIds() const + { + return m_poseDataTypeIds; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.h b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.h index 31bc3e0d3f..624f0aeebf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataFactory.h @@ -25,7 +25,18 @@ namespace EMotionFX class EMFX_API PoseDataFactory { public: + AZ_RTTI(PoseDataFactory, "{F10014A0-2B6A-44E5-BA53-0E11ED566701}") + AZ_CLASS_ALLOCATOR_DECL + + PoseDataFactory(); + virtual ~PoseDataFactory() = default; + static PoseData* Create(Pose* pose, const AZ::TypeId& type); - static const AZStd::unordered_set& GetTypeIds(); + + void AddPoseDataType(const AZ::TypeId& poseDataType); + const AZStd::unordered_set& GetTypeIds() const; + + private: + AZStd::unordered_set m_poseDataTypeIds; }; } // namespace EMotionFX