void BlendPosePerBone(const TArray<FBoneIndexType> &RequiredBoneIndices, const TArray<int32>& PerBoneIndices, const FBlendSampleData& BlendSampleDataCache, FTransformArrayA2 &ResultAtoms, const FTransformArrayA2& SourceAtoms) { const float BlendWeight = BlendSampleDataCache.GetWeight(); TArray<float> PerBoneBlends; for (int32 i = 0; i < BlendSampleDataCache.PerBoneBlendData.Num(); ++i) { PerBoneBlends.Add(FMath::Clamp<float>(BlendSampleDataCache.PerBoneBlendData[i], 0.f, 1.f)); } for (int32 i = 0; i < RequiredBoneIndices.Num(); ++i) { const int32 BoneIndex = RequiredBoneIndices[i]; int32 PerBoneIndex = PerBoneIndices[i]; if (PerBoneIndex == INDEX_NONE || !BlendSampleDataCache.PerBoneBlendData.IsValidIndex(PerBoneIndex)) { BlendTransform<TRANSFORM_BLEND_MODE>(SourceAtoms[BoneIndex], ResultAtoms[BoneIndex], BlendWeight); } else { BlendTransform<TRANSFORM_BLEND_MODE>(SourceAtoms[BoneIndex], ResultAtoms[BoneIndex], PerBoneBlends[PerBoneIndex]); } } }
void BlendPosePerBone(const TArray<int32>& PerBoneIndices, const FBlendSampleData& BlendSampleDataCache, FCompactPose& ResultPose, const FCompactPose& SourcePose) { const float BlendWeight = BlendSampleDataCache.GetWeight(); TArray<float> PerBoneBlends; for (int32 i = 0; i < BlendSampleDataCache.PerBoneBlendData.Num(); ++i) { PerBoneBlends.Add(FMath::Clamp<float>(BlendSampleDataCache.PerBoneBlendData[i], 0.f, 1.f)); } for (FCompactPoseBoneIndex BoneIndex : SourcePose.ForEachBoneIndex()) { int32 PerBoneIndex = PerBoneIndices[BoneIndex.GetInt()]; if (PerBoneIndex == INDEX_NONE || !BlendSampleDataCache.PerBoneBlendData.IsValidIndex(PerBoneIndex)) { BlendTransform<TRANSFORM_BLEND_MODE>(SourcePose[BoneIndex], ResultPose[BoneIndex], BlendWeight); } else { BlendTransform<TRANSFORM_BLEND_MODE>(SourcePose[BoneIndex], ResultPose[BoneIndex], PerBoneBlends[PerBoneIndex]); } } }
bool UBlendSpaceBase::InterpolateWeightOfSampleData(float DeltaTime, const TArray<FBlendSampleData> & OldSampleDataList, const TArray<FBlendSampleData> & NewSampleDataList, TArray<FBlendSampleData> & FinalSampleDataList) const { check (TargetWeightInterpolationSpeedPerSec > 0.f); float TotalFinalWeight = 0.f; // now interpolate from old to new target, this is brute-force for (auto OldIt=OldSampleDataList.CreateConstIterator(); OldIt; ++OldIt) { // Now need to modify old sample, so copy it FBlendSampleData OldSample = *OldIt; bool bTargetSampleExists = false; if (OldSample.PerBoneBlendData.Num()!=PerBoneBlend.Num()) { OldSample.PerBoneBlendData.Init(OldSample.TotalWeight, PerBoneBlend.Num()); } // i'd like to change this later for (auto NewIt=NewSampleDataList.CreateConstIterator(); NewIt; ++NewIt) { const FBlendSampleData& NewSample = *NewIt; // if same sample is found, interpolate if (NewSample.SampleDataIndex == OldSample.SampleDataIndex) { FBlendSampleData InterpData = NewSample; InterpData.TotalWeight = FMath::FInterpConstantTo(OldSample.TotalWeight, NewSample.TotalWeight, DeltaTime, TargetWeightInterpolationSpeedPerSec); InterpData.PerBoneBlendData = OldSample.PerBoneBlendData; // now interpolate the per bone weights for (int32 Iter = 0; Iter<InterpData.PerBoneBlendData.Num(); ++Iter) { if (PerBoneBlend[Iter].InterpolationSpeedPerSec > 0.f) { InterpData.PerBoneBlendData[Iter] = FMath::FInterpConstantTo(OldSample.PerBoneBlendData[Iter], NewSample.TotalWeight, DeltaTime, PerBoneBlend[Iter].InterpolationSpeedPerSec); } else { InterpData.PerBoneBlendData[Iter] = NewSample.TotalWeight; } } FinalSampleDataList.Add(InterpData); TotalFinalWeight += InterpData.GetWeight(); bTargetSampleExists = true; break; } } // if new target isn't found, interpolate to 0.f, this is gone if (bTargetSampleExists == false) { FBlendSampleData InterpData = OldSample; InterpData.TotalWeight = FMath::FInterpConstantTo(OldSample.TotalWeight, 0.f, DeltaTime, TargetWeightInterpolationSpeedPerSec); // now interpolate the per bone weights for (int32 Iter = 0; Iter<InterpData.PerBoneBlendData.Num(); ++Iter) { if (PerBoneBlend[Iter].InterpolationSpeedPerSec > 0.f) { InterpData.PerBoneBlendData[Iter] = FMath::FInterpConstantTo(OldSample.PerBoneBlendData[Iter], 0.f, DeltaTime, PerBoneBlend[Iter].InterpolationSpeedPerSec); } else { InterpData.PerBoneBlendData[Iter] = 0.f; } } // add it if it's not zero if ( InterpData.TotalWeight > ZERO_ANIMWEIGHT_THRESH ) { FinalSampleDataList.Add(InterpData); TotalFinalWeight += InterpData.GetWeight(); } } } // now find new samples that are not found from old samples for (auto OldIt=NewSampleDataList.CreateConstIterator(); OldIt; ++OldIt) { // Now need to modify old sample, so copy it FBlendSampleData OldSample = *OldIt; bool bOldSampleExists = false; if (OldSample.PerBoneBlendData.Num()!=PerBoneBlend.Num()) { OldSample.PerBoneBlendData.Init(OldSample.TotalWeight, PerBoneBlend.Num()); } for (auto NewIt=FinalSampleDataList.CreateConstIterator(); NewIt; ++NewIt) { const FBlendSampleData& NewSample = *NewIt; if (NewSample.SampleDataIndex == OldSample.SampleDataIndex) { bOldSampleExists = true; break; } } // add those new samples if (bOldSampleExists == false) { FBlendSampleData InterpData = OldSample; InterpData.TotalWeight = FMath::FInterpConstantTo(0.f, OldSample.TotalWeight, DeltaTime, TargetWeightInterpolationSpeedPerSec); // now interpolate the per bone weights for (int32 Iter = 0; Iter<InterpData.PerBoneBlendData.Num(); ++Iter) { if (PerBoneBlend[Iter].InterpolationSpeedPerSec > 0.f) { InterpData.PerBoneBlendData[Iter] = FMath::FInterpConstantTo(0.f, OldSample.PerBoneBlendData[Iter], DeltaTime, PerBoneBlend[Iter].InterpolationSpeedPerSec); } else { InterpData.PerBoneBlendData[Iter] = OldSample.PerBoneBlendData[Iter]; } } FinalSampleDataList.Add(InterpData); TotalFinalWeight += InterpData.GetWeight(); } } return (TotalFinalWeight > ZERO_ANIMWEIGHT_THRESH); }