void FAnimationRuntime::BlendPosesTogetherPerBone(const TArray<FCompactPose>& SourcePoses, const TArray<FBlendedCurve>& SourceCurves, const UBlendSpaceBase* BlendSpace, const TArray<FBlendSampleData>& BlendSampleDataCache, /*out*/ FCompactPose& ResultPose, /*out*/ FBlendedCurve& ResultCurve) { check(SourcePoses.Num() > 0); const TArray<FBoneIndexType> & RequiredBoneIndices = ResultPose.GetBoneContainer().GetBoneIndicesArray(); TArray<int32> PerBoneIndices; PerBoneIndices.AddUninitialized(ResultPose.GetNumBones()); for (int32 BoneIndex = 0; BoneIndex < PerBoneIndices.Num(); ++BoneIndex) { PerBoneIndices[BoneIndex] = BlendSpace->GetPerBoneInterpolationIndex(RequiredBoneIndices[BoneIndex], ResultPose.GetBoneContainer()); } BlendPosePerBone<ETransformBlendMode::Overwrite>(PerBoneIndices, BlendSampleDataCache[0], ResultPose, SourcePoses[0]); for (int32 i = 1; i < SourcePoses.Num(); ++i) { BlendPosePerBone<ETransformBlendMode::Accumulate>(PerBoneIndices, BlendSampleDataCache[i], ResultPose, SourcePoses[i]); } // Ensure that all of the resulting rotations are normalized ResultPose.NormalizeRotations(); if (SourceCurves.Num() > 0) { TArray<float> SourceWeights; SourceWeights.AddUninitialized(BlendSampleDataCache.Num()); for (int32 CacheIndex=0; CacheIndex<BlendSampleDataCache.Num(); ++CacheIndex) { SourceWeights[CacheIndex] = BlendSampleDataCache[CacheIndex].TotalWeight; } BlendCurves(SourceCurves, SourceWeights, ResultCurve); } }
void FAnimationRuntime::FillWithRetargetBaseRefPose(FCompactPose& OutPose, const USkeletalMesh* Mesh) { // Copy Target Asset's ref pose. if (Mesh) { for (FCompactPoseBoneIndex BoneIndex : OutPose.ForEachBoneIndex()) { FMeshPoseBoneIndex PoseIndex = OutPose.GetBoneContainer().MakeMeshPoseIndex(BoneIndex); OutPose[BoneIndex] = Mesh->RetargetBasePose[PoseIndex.GetInt()]; } } }
void UBlendSpaceBase::GetAnimationPose(TArray<FBlendSampleData>& BlendSampleDataCache, /*out*/ FCompactPose& OutPose, /*out*/ FBlendedCurve& OutCurve) { SCOPE_CYCLE_COUNTER(STAT_BlendSpace_GetAnimPose); FScopeCycleCounterUObject BlendSpaceScope(this); if(BlendSampleDataCache.Num() == 0) { OutPose.ResetToRefPose(); return; } const int32 NumPoses = BlendSampleDataCache.Num(); TArray<FCompactPose, TInlineAllocator<8>> ChildrenPoses; ChildrenPoses.AddZeroed(NumPoses); TArray<FBlendedCurve, TInlineAllocator<8>> ChildrenCurves; ChildrenCurves.AddZeroed(NumPoses); TArray<float, TInlineAllocator<8>> ChildrenWeights; ChildrenWeights.AddZeroed(NumPoses); for(int32 ChildrenIdx=0; ChildrenIdx<ChildrenPoses.Num(); ++ChildrenIdx) { ChildrenPoses[ChildrenIdx].SetBoneContainer(&OutPose.GetBoneContainer()); ChildrenCurves[ChildrenIdx].InitFrom(OutCurve); } // get all child atoms we interested in for(int32 I = 0; I < BlendSampleDataCache.Num(); ++I) { FCompactPose& Pose = ChildrenPoses[I]; if(SampleData.IsValidIndex(BlendSampleDataCache[I].SampleDataIndex)) { const FBlendSample& Sample = SampleData[BlendSampleDataCache[I].SampleDataIndex]; ChildrenWeights[I] = BlendSampleDataCache[I].GetWeight(); if(Sample.Animation) { const float Time = FMath::Clamp<float>(BlendSampleDataCache[I].Time, 0.f, Sample.Animation->SequenceLength); // first one always fills up the source one Sample.Animation->GetAnimationPose(Pose, ChildrenCurves[I], FAnimExtractContext(Time, true)); } else { Pose.ResetToRefPose(); } } else { Pose.ResetToRefPose(); } } TArrayView<FCompactPose> ChildrenPosesView(ChildrenPoses); if (PerBoneBlend.Num() > 0) { if (IsValidAdditive()) { if (bRotationBlendInMeshSpace) { FAnimationRuntime::BlendPosesTogetherPerBoneInMeshSpace(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve); } else { FAnimationRuntime::BlendPosesTogetherPerBone(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve); } } else { FAnimationRuntime::BlendPosesTogetherPerBone(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve); } } else { FAnimationRuntime::BlendPosesTogether(ChildrenPosesView, ChildrenCurves, ChildrenWeights, OutPose, OutCurve); } // Once all the accumulation and blending has been done, normalize rotations. OutPose.NormalizeRotations(); }