try an alternate implementation for copying animation data in order to remedy the virtual hand crash
This commit is contained in:
@@ -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)
|
||||
@@ -68,4 +141,70 @@ void USGVirtualHandAnimInstance::NativeBeginPlay()
|
||||
FSGVirtualHandAnimInstanceProxy* USGVirtualHandAnimInstance::CreateAnimInstanceProxy()
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user