try an alternate implementation for copying animation data in order to remedy the virtual hand crash

This commit is contained in:
Mamadou Babaei
2023-02-23 20:14:43 +01:00
parent 97458b4c9e
commit 6bfb67cd5b
4 changed files with 164 additions and 93 deletions
@@ -35,6 +35,45 @@
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
#include "SenseGlove/GameFramework/SGVirtualHand.h"
#include "SGCore/SGHandPose.h"
struct USGVirtualHandAnimInstance::FImpl
{
/************************
* Static methods
************************/
static const FName& GetLeftHandBoneName(int32 Finger, int32 Joint);
static const FName& GetRightHandBoneName(int32 Finger, int32 Joint);
/************************
* Member variables
************************/
TMap<FName, FRotator> BoneMap;
/************************
* Owner object
************************/
USGVirtualHandAnimInstance* Owner;
/************************
* Constructor / Destructor
************************/
explicit FImpl(USGVirtualHandAnimInstance* InOwner);
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
};
USGVirtualHandAnimInstance::USGVirtualHandAnimInstance(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
@@ -43,6 +82,40 @@ USGVirtualHandAnimInstance::USGVirtualHandAnimInstance(const FObjectInitializer&
void USGVirtualHandAnimInstance::NativeInitializeAnimation()
{
Super::NativeInitializeAnimation();
ASGVirtualHand* Hand(Cast<ASGVirtualHand>(GetOwningActor()));
if (!IsValid(Hand))
{
return;
}
const USGHandPose* HandPose = Hand->GetHandPose();
if (!IsValid(HandPose))
{
return;
}
TArray<TArray<FRotator>> JointRotations = HandPose->GetJointRotations();
int32 FingerIndex = 0;
for (const TArray<FRotator>& FingerJointRotations: JointRotations)
{
int32 JointIndex = 0;
for (FRotator JointRotation: FingerJointRotations)
{
FName BoneName(Hand->IsRight()
? FImpl::GetRightHandBoneName(FingerIndex, JointIndex)
: FImpl::GetLeftHandBoneName(FingerIndex, JointIndex));
Pimpl->BoneMap.Empty();
Pimpl->BoneMap.Emplace(MoveTemp(BoneName), MoveTemp(JointRotation));
++JointIndex;
}
++FingerIndex;
}
}
void USGVirtualHandAnimInstance::NativeUpdateAnimation(const float DeltaSeconds)
@@ -69,3 +142,69 @@ FSGVirtualHandAnimInstanceProxy* USGVirtualHandAnimInstance::CreateAnimInstanceP
{
return new FSGVirtualHandAnimInstanceProxy();
}
TMap<FName, FRotator> USGVirtualHandAnimInstance::GetBoneMap() const
{
TMap<FName, FRotator> BoneMap;
if (Pimpl->BoneMap.Num() <= 0)
{
return MoveTemp(BoneMap);
}
for (const TTuple<FName, FRotator>& Bone: Pimpl->BoneMap)
{
FName BoneName(Bone.Key);
FRotator BoneRotation(Bone.Value);
BoneMap.Emplace(MoveTemp(BoneName), MoveTemp(BoneRotation));
}
return MoveTemp(BoneMap);
}
const FName& USGVirtualHandAnimInstance::FImpl::GetLeftHandBoneName(const int32 Finger, const int32 Joint)
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_l")), FName(TEXT("thumb_02_l")), FName(TEXT("thumb_03_l"))},
{FName(TEXT("index_01_l")), FName(TEXT("index_02_l")), FName(TEXT("index_03_l"))},
{FName(TEXT("middle_01_l")), FName(TEXT("middle_02_l")), FName(TEXT("middle_03_l"))},
{FName(TEXT("ring_01_l")), FName(TEXT("ring_02_l")), FName(TEXT("ring_03_l"))},
{FName(TEXT("pinky_01_l")), FName(TEXT("pinky_02_l")), FName(TEXT("pinky_03_l"))},
};
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName = BoneNames[Finger][Joint];
return BoneName;
}
const FName& USGVirtualHandAnimInstance::FImpl::GetRightHandBoneName(const int32 Finger, const int32 Joint)
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_r")), FName(TEXT("thumb_02_r")), FName(TEXT("thumb_03_r"))},
{FName(TEXT("index_01_r")), FName(TEXT("index_02_r")), FName(TEXT("index_03_r"))},
{FName(TEXT("middle_01_r")), FName(TEXT("middle_02_r")), FName(TEXT("middle_03_r"))},
{FName(TEXT("ring_01_r")), FName(TEXT("ring_02_r")), FName(TEXT("ring_03_r"))},
{FName(TEXT("pinky_01_r")), FName(TEXT("pinky_02_r")), FName(TEXT("pinky_03_r"))},
};
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName = BoneNames[Finger][Joint];
return BoneName;
}
USGVirtualHandAnimInstance::FImpl::FImpl(USGVirtualHandAnimInstance* InOwner)
: Owner(InOwner)
{
}
USGVirtualHandAnimInstance::FImpl::~FImpl() = default;
void USGVirtualHandAnimInstance::FImplDeleter::operator()(const FImpl* P) const
{
delete P;
}
@@ -44,54 +44,7 @@
#include "Engine/SkeletalMesh.h"
#include "Math/Rotator.h"
#include "SenseGlove/GameFramework/SGVirtualHand.h"
#include "SGCore/SGHandPose.h"
#include "SGLog/SGLog.h"
const FName& FSGVirtualHandAnimInstanceProxy::GetLeftHandBoneName(const int32 Finger, const int32 Joint)
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_l")), FName(TEXT("thumb_02_l")), FName(TEXT("thumb_03_l"))},
{FName(TEXT("index_01_l")), FName(TEXT("index_02_l")), FName(TEXT("index_03_l"))},
{FName(TEXT("middle_01_l")), FName(TEXT("middle_02_l")), FName(TEXT("middle_03_l"))},
{FName(TEXT("ring_01_l")), FName(TEXT("ring_02_l")), FName(TEXT("ring_03_l"))},
{FName(TEXT("pinky_01_l")), FName(TEXT("pinky_02_l")), FName(TEXT("pinky_03_l"))},
};
// FIXME / REMOVE
// Debug code
int32 JointCount = BoneNames[Finger].Num();
//ensureAlwaysMsgf(Joint < JointCount, TEXT("Joint index is out of bound!"));
if (Joint >= 3)
{
const FName& BoneName = BoneNames[Finger][0];
return BoneName;
}
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName = BoneNames[Finger][Joint];
return BoneName;
}
const FName& FSGVirtualHandAnimInstanceProxy::GetRightHandBoneName(const int32 Finger, const int32 Joint)
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_r")), FName(TEXT("thumb_02_r")), FName(TEXT("thumb_03_r"))},
{FName(TEXT("index_01_r")), FName(TEXT("index_02_r")), FName(TEXT("index_03_r"))},
{FName(TEXT("middle_01_r")), FName(TEXT("middle_02_r")), FName(TEXT("middle_03_r"))},
{FName(TEXT("ring_01_r")), FName(TEXT("ring_02_r")), FName(TEXT("ring_03_r"))},
{FName(TEXT("pinky_01_r")), FName(TEXT("pinky_02_r")), FName(TEXT("pinky_03_r"))},
};
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName = BoneNames[Finger][Joint];
return BoneName;
}
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
FSGVirtualHandAnimInstanceProxy::FSGVirtualHandAnimInstanceProxy()
: FAnimInstanceProxy()
@@ -127,55 +80,18 @@ void FSGVirtualHandAnimInstanceProxy::PreEvaluateAnimation(UAnimInstance* InAnim
{
FAnimInstanceProxy::PreEvaluateAnimation(InAnimInstance);
if (!IsValid(InAnimInstance))
const USGVirtualHandAnimInstance* VirtualHandAnimInstance = Cast<USGVirtualHandAnimInstance>(InAnimInstance);
if (!IsValid(VirtualHandAnimInstance))
{
return;
}
ASGVirtualHand* Hand(Cast<ASGVirtualHand>(InAnimInstance->GetOwningActor()));
if (!IsValid(Hand))
{
return;
}
const USGHandPose* HandPose = Hand->GetHandPose();
if (!IsValid(HandPose))
{
return;
}
TArray<TArray<FRotator>> JointRotations = HandPose->GetJointRotations();
int32 FingerIndex = 0;
for (const TArray<FRotator>& FingerJointRotations: JointRotations)
{
int32 JointIndex = 0;
// FIXME / REMOVE
// This should not be necessary
if (JointIndex >= 3)
{
continue;;
}
for (FRotator JointRotation: FingerJointRotations)
{
FName BoneName(Hand->IsRight()
? GetRightHandBoneName(FingerIndex, JointIndex)
: GetLeftHandBoneName(FingerIndex, JointIndex));
BoneMap.Emplace(MoveTemp(BoneName), MoveTemp(JointRotation));
++JointIndex;
}
++FingerIndex;
}
BoneMap = VirtualHandAnimInstance->GetBoneMap();
}
bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
{
const USkeletalMeshComponent* HandMeshComponent = GetSkelMeshComponent();
USkeletalMeshComponent* HandMeshComponent = GetSkelMeshComponent();
if (!IsValid(HandMeshComponent))
{
return FAnimInstanceProxy::Evaluate(Output);
@@ -229,6 +145,8 @@ bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
}
}
HandMeshComponent->MarkRenderStateDirty();
return true;
}
@@ -36,6 +36,10 @@
#pragma once
#include "Animation/AnimInstance.h"
#include "Containers/Map.h"
#include "Math/Rotator.h"
#include "Templates/UniquePtr.h"
#include "UObject/NameTypes.h"
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
@@ -46,6 +50,17 @@ class SENSEGLOVE_API USGVirtualHandAnimInstance : public UAnimInstance
{
GENERATED_UCLASS_BODY()
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
public:
// the below functions are the native overrides for each phase
// Native initialization override point
@@ -66,4 +81,7 @@ public:
protected:
virtual FSGVirtualHandAnimInstanceProxy* CreateAnimInstanceProxy() override;
public:
TMap<FName, FRotator> GetBoneMap() const;
};
@@ -46,10 +46,6 @@ struct SENSEGLOVE_API FSGVirtualHandAnimInstanceProxy : public FAnimInstanceProx
{
GENERATED_USTRUCT_BODY()
public:
static const FName& GetLeftHandBoneName(int32 Finger, int32 Joint);
static const FName& GetRightHandBoneName(int32 Finger, int32 Joint);
public:
TMap<FName, FRotator> BoneMap;