145 lines
5.8 KiB
C++
145 lines
5.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "PoseSearch/PoseSearchAssetSamplerLibrary.h"
|
|
#include "Animation/AnimInstance.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
#include "DrawDebugHelpers.h"
|
|
#include "Engine/SkinnedAsset.h"
|
|
#include "PoseSearch/PoseSearchDefines.h"
|
|
#include "PoseSearch/PoseSearchMirrorDataCache.h"
|
|
|
|
FPoseSearchAssetSamplerPose UPoseSearchAssetSamplerLibrary::SamplePose(const UAnimInstance* AnimInstance, const FPoseSearchAssetSamplerInput Input)
|
|
{
|
|
FPoseSearchAssetSamplerPose AssetSamplerPose;
|
|
using namespace UE::PoseSearch;
|
|
if (!Input.Animation)
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::SamplePose invalid Input.Animation"));
|
|
}
|
|
else if (!AnimInstance)
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::SamplePose invalid AnimInstance"));
|
|
}
|
|
else if (Input.bMirrored && !Input.MirrorDataTable)
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::SamplePose unable to mirror the pose from %s at time %f because of invalid MirrorDataTable"), *Input.Animation->GetName(), Input.AnimationTime);
|
|
}
|
|
else
|
|
{
|
|
const FBoneContainer& BoneContainer = AnimInstance->GetRequiredBonesOnAnyThread();
|
|
|
|
FMemMark Mark(FMemStack::Get());
|
|
|
|
bool bPreProcessRootTransform = true;
|
|
const FAnimationAssetSampler Sampler(Input.Animation, Input.RootTransformOrigin, Input.BlendParameters, Input.RootTransformSamplingRate, bPreProcessRootTransform);
|
|
|
|
FBlendedCurve Curve;
|
|
FCompactPose Pose;
|
|
Pose.SetBoneContainer(&BoneContainer);
|
|
|
|
Sampler.ExtractPose(Input.AnimationTime, Pose, Curve);
|
|
AssetSamplerPose.RootTransform = Sampler.ExtractRootTransform(Input.AnimationTime);
|
|
|
|
if (Input.bMirrored)
|
|
{
|
|
const FMirrorDataCache MirrorDataCache(Input.MirrorDataTable, BoneContainer);
|
|
MirrorDataCache.MirrorPose(Pose);
|
|
AssetSamplerPose.RootTransform = MirrorDataCache.MirrorTransform(AssetSamplerPose.RootTransform);
|
|
}
|
|
|
|
AssetSamplerPose.Pose.CopyBonesFrom(Pose);
|
|
AssetSamplerPose.ComponentSpacePose.InitPose(AssetSamplerPose.Pose);
|
|
}
|
|
return AssetSamplerPose;
|
|
}
|
|
|
|
FTransform UPoseSearchAssetSamplerLibrary::GetTransform(FPoseSearchAssetSamplerPose& AssetSamplerPose, FCompactPoseBoneIndex CompactPoseBoneIndex, EPoseSearchAssetSamplerSpace Space)
|
|
{
|
|
return GetTransform(AssetSamplerPose.ComponentSpacePose, AssetSamplerPose.RootTransform, CompactPoseBoneIndex, Space);
|
|
}
|
|
|
|
FTransform UPoseSearchAssetSamplerLibrary::GetTransformByName(UPARAM(ref) FPoseSearchAssetSamplerPose& AssetSamplerPose, FName BoneName, EPoseSearchAssetSamplerSpace Space)
|
|
{
|
|
if (!AssetSamplerPose.Pose.IsValid())
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::GetTransformByName invalid AssetSamplerPose.Pose"));
|
|
return FTransform::Identity;
|
|
}
|
|
|
|
const FBoneContainer& BoneContainer = AssetSamplerPose.Pose.GetBoneContainer();
|
|
const USkeleton* Skeleton = BoneContainer.GetSkeletonAsset();
|
|
|
|
FBoneReference BoneReference;
|
|
BoneReference.BoneName = BoneName;
|
|
BoneReference.Initialize(Skeleton);
|
|
if (!BoneReference.HasValidSetup())
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::GetTransformByName invalid BoneName %s for Skeleton %s"), *BoneName.ToString(), *GetNameSafe(Skeleton));
|
|
return FTransform::Identity;
|
|
}
|
|
|
|
const FCompactPoseBoneIndex CompactPoseBoneIndex = BoneContainer.GetCompactPoseIndexFromSkeletonPoseIndex(FSkeletonPoseBoneIndex(BoneReference.BoneIndex));
|
|
if (!CompactPoseBoneIndex.IsValid())
|
|
{
|
|
UE_LOG(LogPoseSearch, Error, TEXT("UPoseSearchAssetSamplerLibrary::GetTransformByName invalid FCompactPoseBoneIndex for BoneName %s for Skeleton %s"), *BoneName.ToString(), *GetNameSafe(Skeleton));
|
|
return FTransform::Identity;
|
|
}
|
|
|
|
return GetTransform(AssetSamplerPose, CompactPoseBoneIndex, Space);
|
|
}
|
|
|
|
void UPoseSearchAssetSamplerLibrary::Draw(const UAnimInstance* AnimInstance, UPARAM(ref) FPoseSearchAssetSamplerPose& AssetSamplerPose)
|
|
{
|
|
check(IsInGameThread());
|
|
|
|
#if ENABLE_DRAW_DEBUG
|
|
static float DebugDrawSamplerRootAxisLength = 20.f;
|
|
static float DebugDrawSamplerSize = 6.f;
|
|
|
|
if (AnimInstance)
|
|
{
|
|
Draw(AnimInstance->GetWorld(), AssetSamplerPose.ComponentSpacePose, AssetSamplerPose.RootTransform);
|
|
}
|
|
#endif // ENABLE_DRAW_DEBUG
|
|
}
|
|
|
|
#if ENABLE_VISUAL_LOG
|
|
void UPoseSearchAssetSamplerLibrary::VLogDraw(const UObject* VLogContext, const USkeletalMeshComponent* Mesh, const TCHAR* VLogName, const FColor Color, float DebugDrawSamplerRootAxisLength)
|
|
{
|
|
check(IsInGameThread());
|
|
|
|
if (!Mesh)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const USkinnedAsset* SkinnedAsset = Mesh->GetSkinnedAsset();
|
|
if (!SkinnedAsset)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (DebugDrawSamplerRootAxisLength > 0.f)
|
|
{
|
|
const FTransform& AxisWorldTransform = Mesh->GetComponentTransform();
|
|
UE_VLOG_SEGMENT(VLogContext, VLogName, Display, AxisWorldTransform.GetTranslation(), AxisWorldTransform.GetTranslation() + AxisWorldTransform.GetScaledAxis(EAxis::X) * DebugDrawSamplerRootAxisLength, FColor::Red, TEXT(""));
|
|
UE_VLOG_SEGMENT(VLogContext, VLogName, Display, AxisWorldTransform.GetTranslation(), AxisWorldTransform.GetTranslation() + AxisWorldTransform.GetScaledAxis(EAxis::Y) * DebugDrawSamplerRootAxisLength, FColor::Green, TEXT(""));
|
|
UE_VLOG_SEGMENT(VLogContext, VLogName, Display, AxisWorldTransform.GetTranslation(), AxisWorldTransform.GetTranslation() + AxisWorldTransform.GetScaledAxis(EAxis::Z) * DebugDrawSamplerRootAxisLength, FColor::Blue, TEXT(""));
|
|
}
|
|
|
|
const int NumBones = Mesh->GetNumBones();
|
|
for (int32 BoneIndex = 0; BoneIndex < NumBones; ++BoneIndex)
|
|
{
|
|
const int32 ParentBoneIndex = SkinnedAsset->GetRefSkeleton().GetParentIndex(BoneIndex);
|
|
if (ParentBoneIndex != INDEX_NONE)
|
|
{
|
|
const FTransform BoneWorldTransform = Mesh->GetBoneTransform(BoneIndex);
|
|
const FTransform ParentBoneWorldTransform = Mesh->GetBoneTransform(ParentBoneIndex);
|
|
UE_VLOG_SEGMENT(VLogContext, VLogName, Display, BoneWorldTransform.GetTranslation(), ParentBoneWorldTransform.GetTranslation(), Color, TEXT(""));
|
|
}
|
|
}
|
|
}
|
|
#endif // ENABLE_VISUAL_LOG
|
|
|
|
|