|
@@ -6,30 +6,40 @@
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+#include <AzCore/Console/IConsole.h>
|
|
#include <AzCore/Debug/Timer.h>
|
|
#include <AzCore/Debug/Timer.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
|
|
|
|
#include <EMotionFX/Source/ActorInstance.h>
|
|
#include <EMotionFX/Source/ActorInstance.h>
|
|
-#include <Allocators.h>
|
|
|
|
#include <EMotionFX/Source/EMotionFXManager.h>
|
|
#include <EMotionFX/Source/EMotionFXManager.h>
|
|
#include <EMotionFX/Source/Motion.h>
|
|
#include <EMotionFX/Source/Motion.h>
|
|
#include <EMotionFX/Source/MotionInstance.h>
|
|
#include <EMotionFX/Source/MotionInstance.h>
|
|
#include <EMotionFX/Source/MotionInstancePool.h>
|
|
#include <EMotionFX/Source/MotionInstancePool.h>
|
|
-#include <MotionMatchingData.h>
|
|
|
|
-#include <MotionMatchingInstance.h>
|
|
|
|
|
|
+#include <EMotionFX/Source/Pose.h>
|
|
|
|
+#include <EMotionFX/Source/TransformData.h>
|
|
|
|
+
|
|
|
|
+#include <Allocators.h>
|
|
#include <Feature.h>
|
|
#include <Feature.h>
|
|
#include <FeatureSchema.h>
|
|
#include <FeatureSchema.h>
|
|
#include <FeatureTrajectory.h>
|
|
#include <FeatureTrajectory.h>
|
|
-#include <KdTree.h>
|
|
|
|
|
|
+#include <FeatureVelocity.h>
|
|
#include <ImGuiMonitorBus.h>
|
|
#include <ImGuiMonitorBus.h>
|
|
-#include <EMotionFX/Source/Pose.h>
|
|
|
|
-#include <EMotionFX/Source/TransformData.h>
|
|
|
|
|
|
+#include <KdTree.h>
|
|
|
|
+#include <MotionMatchingData.h>
|
|
|
|
+#include <MotionMatchingInstance.h>
|
|
#include <PoseDataJointVelocities.h>
|
|
#include <PoseDataJointVelocities.h>
|
|
|
|
|
|
|
|
+
|
|
namespace EMotionFX::MotionMatching
|
|
namespace EMotionFX::MotionMatching
|
|
{
|
|
{
|
|
|
|
+ AZ_CVAR_EXTERNED(bool, mm_debugDraw);
|
|
|
|
+ AZ_CVAR_EXTERNED(float, mm_debugDrawVelocityScale);
|
|
|
|
+ AZ_CVAR_EXTERNED(bool, mm_debugDrawQueryPose);
|
|
|
|
+ AZ_CVAR_EXTERNED(bool, mm_debugDrawQueryVelocities);
|
|
|
|
+ AZ_CVAR_EXTERNED(bool, mm_useKdTree);
|
|
|
|
+
|
|
AZ_CLASS_ALLOCATOR_IMPL(MotionMatchingInstance, MotionMatchAllocator, 0)
|
|
AZ_CLASS_ALLOCATOR_IMPL(MotionMatchingInstance, MotionMatchAllocator, 0)
|
|
|
|
|
|
MotionMatchingInstance::~MotionMatchingInstance()
|
|
MotionMatchingInstance::~MotionMatchingInstance()
|
|
@@ -118,6 +128,11 @@ namespace EMotionFX::MotionMatching
|
|
|
|
|
|
void MotionMatchingInstance::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay)
|
|
void MotionMatchingInstance::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay)
|
|
{
|
|
{
|
|
|
|
+ if (!mm_debugDraw)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
AZ_PROFILE_SCOPE(Animation, "MotionMatchingInstance::DebugDraw");
|
|
AZ_PROFILE_SCOPE(Animation, "MotionMatchingInstance::DebugDraw");
|
|
|
|
|
|
// Get the lowest cost frame index from the last search. As we're searching the feature database with a much lower
|
|
// Get the lowest cost frame index from the last search. As we're searching the feature database with a much lower
|
|
@@ -153,6 +168,42 @@ namespace EMotionFX::MotionMatching
|
|
|
|
|
|
// Draw the trajectory history starting after the sampled version of the past trajectory.
|
|
// Draw the trajectory history starting after the sampled version of the past trajectory.
|
|
m_trajectoryHistory.DebugDraw(debugDisplay, trajectoryQueryColor, m_cachedTrajectoryFeature->GetPastTimeRange());
|
|
m_trajectoryHistory.DebugDraw(debugDisplay, trajectoryQueryColor, m_cachedTrajectoryFeature->GetPastTimeRange());
|
|
|
|
+
|
|
|
|
+ // Draw the input for the motion matching search.
|
|
|
|
+ DebugDrawQueryPose(debugDisplay, mm_debugDrawQueryPose, mm_debugDrawQueryVelocities);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void MotionMatchingInstance::DebugDrawQueryPose(AzFramework::DebugDisplayRequests& debugDisplay, bool drawPose, bool drawVelocities) const
|
|
|
|
+ {
|
|
|
|
+ const AZ::Color color = AZ::Color::CreateOne();
|
|
|
|
+
|
|
|
|
+ if (drawPose)
|
|
|
|
+ {
|
|
|
|
+ m_queryPose.DebugDraw(debugDisplay, color);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (drawVelocities)
|
|
|
|
+ {
|
|
|
|
+ PoseDataJointVelocities* velocityPoseData = m_queryPose.GetPoseData<PoseDataJointVelocities>();
|
|
|
|
+ if (velocityPoseData)
|
|
|
|
+ {
|
|
|
|
+ const Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton();
|
|
|
|
+ for (const Feature* feature : m_data->GetFeatureSchema().GetFeatures())
|
|
|
|
+ {
|
|
|
|
+ if (const FeatureVelocity* velocityFeature = azdynamic_cast<const FeatureVelocity*>(feature))
|
|
|
|
+ {
|
|
|
|
+ Node* joint = skeleton->FindNodeByName(velocityFeature->GetJointName());
|
|
|
|
+ if (joint)
|
|
|
|
+ {
|
|
|
|
+ const size_t jointIndex = joint->GetNodeIndex();
|
|
|
|
+ const size_t relativeToJointIndex = feature->GetRelativeToNodeIndex();
|
|
|
|
+ const AZ::Vector3& velocity = velocityPoseData->GetVelocities()[jointIndex];
|
|
|
|
+ velocityFeature->DebugDraw(debugDisplay, m_queryPose, velocity, jointIndex, relativeToJointIndex, color);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void MotionMatchingInstance::SamplePose(MotionInstance* motionInstance, Pose& outputPose)
|
|
void MotionMatchingInstance::SamplePose(MotionInstance* motionInstance, Pose& outputPose)
|
|
@@ -432,6 +483,7 @@ namespace EMotionFX::MotionMatching
|
|
const FeatureTrajectory* trajectoryFeature = m_cachedTrajectoryFeature;
|
|
const FeatureTrajectory* trajectoryFeature = m_cachedTrajectoryFeature;
|
|
|
|
|
|
// 1. Broad-phase search using KD-tree
|
|
// 1. Broad-phase search using KD-tree
|
|
|
|
+ if (mm_useKdTree)
|
|
{
|
|
{
|
|
// Build the input query features that will be compared to every entry in the feature database in the motion matching search.
|
|
// Build the input query features that will be compared to every entry in the feature database in the motion matching search.
|
|
size_t startOffset = 0;
|
|
size_t startOffset = 0;
|
|
@@ -455,12 +507,10 @@ namespace EMotionFX::MotionMatching
|
|
float minTrajectoryFutureCost = 0.0f;
|
|
float minTrajectoryFutureCost = 0.0f;
|
|
|
|
|
|
// Iterate through the frames filtered by the broad-phase search.
|
|
// Iterate through the frames filtered by the broad-phase search.
|
|
-#ifdef SEARCH_THROUGH_WHOLE_MOTIONDATABASE
|
|
|
|
- for (size_t frameIndex = 0; frameIndex < frameDatabase.GetNumFrames(); ++frameIndex)
|
|
|
|
-#else
|
|
|
|
- for (const size_t frameIndex : m_nearestFrames)
|
|
|
|
-#endif
|
|
|
|
|
|
+ const size_t numFrames = mm_useKdTree ? m_nearestFrames.size() : frameDatabase.GetNumFrames();
|
|
|
|
+ for (size_t i = 0; i < numFrames; ++i)
|
|
{
|
|
{
|
|
|
|
+ const size_t frameIndex = mm_useKdTree ? m_nearestFrames[i] : i;
|
|
const Frame& frame = frameDatabase.GetFrame(frameIndex);
|
|
const Frame& frame = frameDatabase.GetFrame(frameIndex);
|
|
|
|
|
|
// TODO: This shouldn't be there, we should be discarding the frames when extracting the features and not at runtime when checking the cost.
|
|
// TODO: This shouldn't be there, we should be discarding the frames when extracting the features and not at runtime when checking the cost.
|