void FAnimNode_AbilityAnimPlayer::Evaluate_AnyThread(FPoseContext& Output) { check(Output.AnimInstanceProxy); FAnimInstanceProxy* Proxy = Output.AnimInstanceProxy; if (m_SequenceToPlay && Proxy->IsSkeletonCompatible(m_SequenceToPlay->GetSkeleton())) { if (m_NextSequence && Proxy->IsSkeletonCompatible(m_NextSequence->GetSkeleton())) { FCompactPose Poses[2]; FBlendedCurve Curves[2]; float Weights[2]; const FBoneContainer& RequiredBone = Proxy->GetRequiredBones(); Poses[0].SetBoneContainer(&RequiredBone); Poses[1].SetBoneContainer(&RequiredBone); Curves[0].InitFrom(RequiredBone); Curves[1].InitFrom(RequiredBone); Weights[0] = 1.0f - m_NextSequenceBlendIn.GetBlendedValue(); Weights[1] = m_NextSequenceBlendIn.GetBlendedValue(); m_SequenceToPlay->GetAnimationPose(Poses[0], Curves[0], FAnimExtractContext(InternalTimeAccumulator, Proxy->ShouldExtractRootMotion())); m_NextSequence->GetAnimationPose(Poses[1], Curves[1], FAnimExtractContext(m_NextSequenceInternalTimeAccumulator, Proxy->ShouldExtractRootMotion())); FAnimationRuntime::BlendPosesTogether(Poses, Curves, Weights, Output.Pose, Output.Curve); } else { m_SequenceToPlay->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(InternalTimeAccumulator, Output.AnimInstanceProxy->ShouldExtractRootMotion())); } m_CachedOutputSequence = m_SequenceToPlay; } else if (m_CachedOutputSequence) { m_CachedOutputSequence->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(InternalTimeAccumulator, Output.AnimInstanceProxy->ShouldExtractRootMotion())); } else { Output.ResetToRefPose(); } }
void FAnimNode_SequencePlayer::Evaluate(FPoseContext& Output) { if ((Sequence != NULL) && (Output.AnimInstance->CurrentSkeleton->IsCompatible(Sequence->GetSkeleton()))) { Sequence->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(InternalTimeAccumulator, Output.AnimInstance->ShouldExtractRootMotion())); } else { Output.ResetToRefPose(); } }
void UAnimSingleNodeInstance::InternalBlendSpaceEvaluatePose(class UBlendSpaceBase* BlendSpace, TArray<FBlendSampleData>& BlendSampleDataCache, struct FA2Pose& Pose, bool bIsLooping) { USkeletalMeshComponent* Component = GetSkelMeshComponent(); if (BlendSpace->IsValidAdditive()) { FA2Pose BasePose; FA2Pose AdditivePose; BasePose.Bones.AddUninitialized(Pose.Bones.Num()); AdditivePose.Bones.AddUninitialized(Pose.Bones.Num()); #if WITH_EDITORONLY_DATA if (BlendSpace->PreviewBasePose) { BlendSpace->PreviewBasePose->GetBonePose(/*out*/ BasePose.Bones, RequiredBones, FAnimExtractContext(PreviewPoseCurrentTime, bIsLooping)); } else #endif // WITH_EDITORONLY_DATA { // otherwise, get ref pose FAnimationRuntime::FillWithRefPose(BasePose.Bones, RequiredBones); } FAnimationRuntime::GetPoseFromBlendSpace( BlendSpace, BlendSampleDataCache, bIsLooping, RequiredBones, /*out*/ AdditivePose.Bones); if (BlendSpace->IsA(UAimOffsetBlendSpace::StaticClass()) || BlendSpace->IsA(UAimOffsetBlendSpace1D::StaticClass()) ) { BlendRotationOffset(BasePose, AdditivePose, 1.f, Pose); } else { ApplyAdditiveSequence(BasePose, AdditivePose, 1.f, Pose); } } else { FAnimationRuntime::GetPoseFromBlendSpace( BlendSpace, BlendSampleDataCache, bIsLooping, RequiredBones, /*out*/ Pose.Bones); } }
void UAnimSingleNodeInstance::InternalBlendSpaceEvaluatePose(class UBlendSpaceBase* BlendSpace, TArray<FBlendSampleData>& BlendSampleDataCache, FPoseContext& OutContext) { USkeletalMeshComponent* Component = GetSkelMeshComponent(); if (BlendSpace->IsValidAdditive()) { FCompactPose& OutPose = OutContext.Pose; FBlendedCurve& OutCurve = OutContext.Curve; FCompactPose AdditivePose; FBlendedCurve AdditiveCurve; AdditivePose.SetBoneContainer(&OutPose.GetBoneContainer()); AdditiveCurve.InitFrom(OutCurve); #if WITH_EDITORONLY_DATA if (BlendSpace->PreviewBasePose) { BlendSpace->PreviewBasePose->GetBonePose(/*out*/ OutPose, /*out*/OutCurve, FAnimExtractContext(PreviewPoseCurrentTime)); } else #endif // WITH_EDITORONLY_DATA { // otherwise, get ref pose OutPose.ResetToRefPose(); } BlendSpace->GetAnimationPose(BlendSampleDataCache, AdditivePose, AdditiveCurve); enum EAdditiveAnimationType AdditiveType = BlendSpace->bRotationBlendInMeshSpace? AAT_RotationOffsetMeshSpace : AAT_LocalSpaceBase; FAnimationRuntime::AccumulateAdditivePose(OutPose, AdditivePose, OutCurve, AdditiveCurve, 1.f, AdditiveType); } else { BlendSpace->GetAnimationPose(BlendSampleDataCache, OutContext.Pose, OutContext.Curve); } }
void UDebugSkelMeshComponent::RefreshBoneTransforms(FActorComponentTickFunction* TickFunction) { // Run regular update first so we get RequiredBones up to date. Super::RefreshBoneTransforms(NULL); // Pass NULL so we force non threaded work const bool bIsPreviewInstance = (PreviewInstance && PreviewInstance == AnimScriptInstance); BakedAnimationPoses.Empty(); if(bDisplayBakedAnimation && bIsPreviewInstance && PreviewInstance->RequiredBones.IsValid()) { if(UAnimSequence* Sequence = Cast<UAnimSequence>(PreviewInstance->CurrentAsset)) { BakedAnimationPoses.AddUninitialized(PreviewInstance->RequiredBones.GetNumBones()); bool bSavedUseSourceData = AnimScriptInstance->RequiredBones.ShouldUseSourceData(); AnimScriptInstance->RequiredBones.SetUseRAWData(true); AnimScriptInstance->RequiredBones.SetUseSourceData(false); PreviewInstance->EnableControllers(false); GenSpaceBases(BakedAnimationPoses); AnimScriptInstance->RequiredBones.SetUseRAWData(false); AnimScriptInstance->RequiredBones.SetUseSourceData(bSavedUseSourceData); PreviewInstance->EnableControllers(true); } } SourceAnimationPoses.Empty(); if(bDisplaySourceAnimation && bIsPreviewInstance && PreviewInstance->RequiredBones.IsValid()) { if(UAnimSequence* Sequence = Cast<UAnimSequence>(PreviewInstance->CurrentAsset)) { SourceAnimationPoses.AddUninitialized(PreviewInstance->RequiredBones.GetNumBones()); bool bSavedUseSourceData = AnimScriptInstance->RequiredBones.ShouldUseSourceData(); AnimScriptInstance->RequiredBones.SetUseSourceData(true); PreviewInstance->EnableControllers(false); GenSpaceBases(SourceAnimationPoses); AnimScriptInstance->RequiredBones.SetUseSourceData(bSavedUseSourceData); PreviewInstance->EnableControllers(true); } } UncompressedSpaceBases.Empty(); if (bDisplayRawAnimation && AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid()) { UncompressedSpaceBases.AddUninitialized(AnimScriptInstance->RequiredBones.GetNumBones()); AnimScriptInstance->RequiredBones.SetUseRAWData(true); GenSpaceBases(UncompressedSpaceBases); AnimScriptInstance->RequiredBones.SetUseRAWData(false); } // Non retargeted pose. NonRetargetedSpaceBases.Empty(); if( bDisplayNonRetargetedPose && AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid() ) { NonRetargetedSpaceBases.AddUninitialized(AnimScriptInstance->RequiredBones.GetNumBones()); AnimScriptInstance->RequiredBones.SetDisableRetargeting(true); GenSpaceBases(NonRetargetedSpaceBases); AnimScriptInstance->RequiredBones.SetDisableRetargeting(false); } // Only works in PreviewInstance, and not for anim blueprint. This is intended. AdditiveBasePoses.Empty(); if( bDisplayAdditiveBasePose && bIsPreviewInstance && PreviewInstance->RequiredBones.IsValid() ) { if (UAnimSequence* Sequence = Cast<UAnimSequence>(PreviewInstance->CurrentAsset)) { if (Sequence->IsValidAdditive()) { FCSPose<FCompactPose> CSAdditiveBasePose; { FCompactPose AdditiveBasePose; FBlendedCurve AdditiveCurve(PreviewInstance); AdditiveBasePose.SetBoneContainer(&PreviewInstance->RequiredBones); Sequence->GetAdditiveBasePose(AdditiveBasePose, AdditiveCurve, FAnimExtractContext(PreviewInstance->CurrentTime)); CSAdditiveBasePose.InitPose(AdditiveBasePose); } for (int32 i = 0; i < AdditiveBasePoses.Num(); ++i) { FCompactPoseBoneIndex CompactIndex = PreviewInstance->RequiredBones.MakeCompactPoseIndex(FMeshPoseBoneIndex(i)); AdditiveBasePoses[i] = CSAdditiveBasePose.GetComponentSpaceTransform(CompactIndex); } } } } }
bool UAnimSingleNodeInstance::NativeEvaluateAnimation(FPoseContext& Output) { if (CurrentAsset != NULL) { //@TODO: animrefactor: Seems like more code duplication than we need if (UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(CurrentAsset)) { InternalBlendSpaceEvaluatePose(BlendSpace, BlendSampleData, Output.Pose); } else if (UAnimSequence* Sequence = Cast<UAnimSequence>(CurrentAsset)) { if (Sequence->IsValidAdditive()) { FA2Pose BasePose; FA2Pose AdditivePose; BasePose.Bones.AddUninitialized(Output.Pose.Bones.Num()); AdditivePose.Bones.AddUninitialized(Output.Pose.Bones.Num()); FAnimExtractContext ExtractionContext(CurrentTime); Sequence->GetAdditiveBasePose(BasePose.Bones, RequiredBones, ExtractionContext); Sequence->GetAnimationPose(AdditivePose.Bones, RequiredBones, ExtractionContext); if (Sequence->AdditiveAnimType == AAT_LocalSpaceBase) { ApplyAdditiveSequence(BasePose, AdditivePose, 1.0f, Output.Pose); } else { BlendRotationOffset(BasePose, AdditivePose, 1.0f, Output.Pose); } } else { // if sekeltalmesh isn't there, we'll need to use skeleton FAnimationRuntime::GetPoseFromSequence(Sequence, RequiredBones, Output.Pose.Bones, FAnimExtractContext(CurrentTime, Sequence->bEnableRootMotion)); } } else if (UAnimComposite* Composite = Cast<UAnimComposite>(CurrentAsset)) { const FAnimTrack& AnimTrack = Composite->AnimationTrack; // find out if this is additive animation EAdditiveAnimationType AdditiveAnimType = AAT_None; if (AnimTrack.IsAdditive()) { FA2Pose AdditivePose; FA2Pose BasePose; BasePose.Bones.AddUninitialized(Output.Pose.Bones.Num()); AdditivePose.Bones.AddUninitialized(Output.Pose.Bones.Num()); AdditiveAnimType = AnimTrack.IsRotationOffsetAdditive()? AAT_RotationOffsetMeshSpace : AAT_LocalSpaceBase; // get base pose - for now we only support ref pose as base FAnimationRuntime::FillWithRefPose(BasePose.Bones, RequiredBones); //get the additive pose FAnimationRuntime::GetPoseFromAnimTrack(AnimTrack, RequiredBones, AdditivePose.Bones, FAnimExtractContext(CurrentTime, RootMotionMode == ERootMotionMode::RootMotionFromEverything)); // if additive, we should blend with source to make it fullbody if (AdditiveAnimType == AAT_LocalSpaceBase) { ApplyAdditiveSequence(BasePose,AdditivePose,1.f,Output.Pose); } else if (AdditiveAnimType == AAT_RotationOffsetMeshSpace) { BlendRotationOffset(BasePose,AdditivePose,1.f,Output.Pose); } } else { //doesn't handle additive yet FAnimationRuntime::GetPoseFromAnimTrack(AnimTrack, RequiredBones, Output.Pose.Bones, FAnimExtractContext(CurrentTime, RootMotionMode == ERootMotionMode::RootMotionFromEverything)); } } else if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { // for now only update first slot // in the future, add option to see which slot to see if (Montage->SlotAnimTracks.Num() > 0) { FA2Pose SourcePose; SourcePose.Bones.AddUninitialized(Output.Pose.Bones.Num()); if (Montage->IsValidAdditive()) { #if WITH_EDITORONLY_DATA // if montage is additive, we need to have base pose for the slot pose evaluate if (Montage->PreviewBasePose && Montage->SequenceLength > 0.f) { Montage->PreviewBasePose->GetBonePose(SourcePose.Bones, RequiredBones, FAnimExtractContext(CurrentTime)); } else #endif // WITH_EDITORONLY_DATA { FAnimationRuntime::FillWithRefPose(SourcePose.Bones, RequiredBones); } } else { FAnimationRuntime::FillWithRefPose(SourcePose.Bones, RequiredBones); } SlotEvaluatePose(Montage->SlotAnimTracks[0].SlotName, SourcePose, Output.Pose, 1.f); } } } if(CurrentVertexAnim != NULL) { VertexAnims.Add(FActiveVertexAnim(CurrentVertexAnim, 1.f, CurrentTime)); } return true; }
void UDebugSkelMeshComponent::RefreshBoneTransforms(FActorComponentTickFunction* TickFunction) { // Run regular update first so we get RequiredBones up to date. Super::RefreshBoneTransforms(NULL); // Pass NULL so we force non threaded work // Non retargeted pose. NonRetargetedSpaceBases.Empty(); if( bDisplayNonRetargetedPose && AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid() ) { TArray<FTransform> BackupSpaceBases = SpaceBases; AnimScriptInstance->RequiredBones.SetDisableRetargeting(true); Super::RefreshBoneTransforms(NULL); AnimScriptInstance->RequiredBones.SetDisableRetargeting(false); NonRetargetedSpaceBases = SpaceBases; SpaceBases = BackupSpaceBases; } if( bDisplayRawAnimation ) { // save the transform in CompressedSpaceBases CompressedSpaceBases = SpaceBases; // use raw data now if( AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid() ) { AnimScriptInstance->RequiredBones.SetUseRAWData(true); Super::RefreshBoneTransforms(NULL); AnimScriptInstance->RequiredBones.SetUseRAWData(false); } // Otherwise we'll just get ref pose. else { Super::RefreshBoneTransforms(NULL); } } else { CompressedSpaceBases.Empty(); } const bool bIsPreviewInstance = (PreviewInstance && PreviewInstance == AnimScriptInstance); // Only works in PreviewInstance, and not for anim blueprint. This is intended. AdditiveBasePoses.Empty(); if( bDisplayAdditiveBasePose && bIsPreviewInstance && PreviewInstance->RequiredBones.IsValid() ) { if (UAnimSequence* Sequence = Cast<UAnimSequence>(PreviewInstance->CurrentAsset)) { if (Sequence->IsValidAdditive()) { AdditiveBasePoses.AddUninitialized(PreviewInstance->RequiredBones.GetNumBones()); Sequence->GetAdditiveBasePose(AdditiveBasePoses, PreviewInstance->RequiredBones, FAnimExtractContext(PreviewInstance->CurrentTime)); FA2CSPose CSPose; CSPose.AllocateLocalPoses(AnimScriptInstance->RequiredBones, AdditiveBasePoses); for(int32 i=0; i<AdditiveBasePoses.Num(); ++i) { AdditiveBasePoses[i] = CSPose.GetComponentSpaceTransform(i); } } } } }
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(); }
bool UAnimSingleNodeInstance::NativeEvaluateAnimation(FPoseContext& Output) { if (CurrentAsset != NULL) { //@TODO: animrefactor: Seems like more code duplication than we need if (UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(CurrentAsset)) { InternalBlendSpaceEvaluatePose(BlendSpace, BlendSampleData, Output); } else if (UAnimSequence* Sequence = Cast<UAnimSequence>(CurrentAsset)) { if (Sequence->IsValidAdditive()) { FAnimExtractContext ExtractionContext(CurrentTime, Sequence->bEnableRootMotion); Sequence->GetAdditiveBasePose(Output.Pose, Output.Curve, ExtractionContext); FCompactPose AdditivePose; FBlendedCurve AdditiveCurve; AdditivePose.SetBoneContainer(&Output.Pose.GetBoneContainer()); AdditiveCurve.InitFrom(Output.Curve); Sequence->GetAnimationPose(AdditivePose, AdditiveCurve, ExtractionContext); FAnimationRuntime::AccumulateAdditivePose(Output.Pose, AdditivePose, Output.Curve, AdditiveCurve, 1.f, Sequence->AdditiveAnimType); Output.Pose.NormalizeRotations(); } else { // if SkeletalMesh isn't there, we'll need to use skeleton Sequence->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(CurrentTime, Sequence->bEnableRootMotion)); } } else if (UAnimComposite* Composite = Cast<UAnimComposite>(CurrentAsset)) { FAnimExtractContext ExtractionContext(CurrentTime, ShouldExtractRootMotion()); const FAnimTrack& AnimTrack = Composite->AnimationTrack; // find out if this is additive animation if (AnimTrack.IsAdditive()) { #if WITH_EDITORONLY_DATA if (Composite->PreviewBasePose) { Composite->PreviewBasePose->GetAdditiveBasePose(Output.Pose, Output.Curve, ExtractionContext); } else #endif { // get base pose - for now we only support ref pose as base Output.Pose.ResetToRefPose(); } EAdditiveAnimationType AdditiveAnimType = AnimTrack.IsRotationOffsetAdditive()? AAT_RotationOffsetMeshSpace : AAT_LocalSpaceBase; FCompactPose AdditivePose; FBlendedCurve AdditiveCurve; AdditivePose.SetBoneContainer(&Output.Pose.GetBoneContainer()); AdditiveCurve.InitFrom(Output.Curve); Composite->GetAnimationPose(AdditivePose, AdditiveCurve, ExtractionContext); FAnimationRuntime::AccumulateAdditivePose(Output.Pose, AdditivePose, Output.Curve, AdditiveCurve, 1.f, AdditiveAnimType); } else { //doesn't handle additive yet Composite->GetAnimationPose(Output.Pose, Output.Curve, ExtractionContext); } } else if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { // for now only update first slot // in the future, add option to see which slot to see if (Montage->SlotAnimTracks.Num() > 0) { FCompactPose SourcePose; FBlendedCurve SourceCurve; SourcePose.SetBoneContainer(&Output.Pose.GetBoneContainer()); SourceCurve.InitFrom(Output.Curve); if (Montage->IsValidAdditive()) { #if WITH_EDITORONLY_DATA // if montage is additive, we need to have base pose for the slot pose evaluate if (Montage->PreviewBasePose && Montage->SequenceLength > 0.f) { Montage->PreviewBasePose->GetBonePose(SourcePose, SourceCurve, FAnimExtractContext(CurrentTime)); } else #endif // WITH_EDITORONLY_DATA { SourcePose.ResetToRefPose(); } } else { SourcePose.ResetToRefPose(); } SlotEvaluatePose(Montage->SlotAnimTracks[0].SlotName, SourcePose, SourceCurve, Output.Pose, Output.Curve, 1.f); } } } if(CurrentVertexAnim != NULL) { VertexAnims.Add(FActiveVertexAnim(CurrentVertexAnim, 1.f, CurrentTime)); } return true; }