示例#1
0
void UAnimInstance::EvaluateAnimation(FPoseContext& Output)
{
	// If bone caches have been invalidated, have AnimNodes refresh those.
	if( bBoneCachesInvalidated && RootNode )
	{
		bBoneCachesInvalidated = false;

		IncrementContextCounter();
		FAnimationCacheBonesContext UpdateContext(this);
		RootNode->CacheBones(UpdateContext);
	}

	// Evaluate native code if implemented, otherwise evaluate the node graph
	if (!NativeEvaluateAnimation(Output))
	{
		if (RootNode != NULL)
		{
			SCOPE_CYCLE_COUNTER(STAT_AnimGraphEvaluate);

			RootNode->Evaluate(Output);
		}
		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 FAnimNode_BlendSpacePlayer::Evaluate(FPoseContext& Output)
{
	if ((BlendSpace != NULL) && (Output.AnimInstanceProxy->IsSkeletonCompatible(BlendSpace->GetSkeleton())))
	{
		BlendSpace->GetAnimationPose(BlendSampleDataCache, Output.Pose, Output.Curve);
	}
	else
	{
		Output.ResetToRefPose();
	}
}
void FAnimNode_BlendSpacePlayer::Evaluate(FPoseContext& Output)
{
	if ((BlendSpace != NULL) && (Output.AnimInstance->CurrentSkeleton->IsCompatible(BlendSpace->GetSkeleton())))
	{
		Output.AnimInstance->BlendSpaceEvaluatePose(BlendSpace, BlendSampleDataCache, Output.Pose);
	}
	else
	{
		Output.ResetToRefPose();
	}
}
void FAnimNode_RefPose::Evaluate(FPoseContext& Output)
{
	// I don't have anything to evaluate. Should this be even here?
	// EvaluateGraphExposedInputs.Execute(Context);

	switch (RefPoseType) 
	{
	case EIT_LocalSpace:
		Output.ResetToRefPose();
		break;

	case EIT_Additive:
	default:
		Output.ResetToIdentity();
		break;
	}
}
示例#6
0
void FAnimNode_BlendListBase::Evaluate(FPoseContext& Output)
{
	SCOPE_CYCLE_COUNTER(STAT_AnimNativeBlendPoses);

	const int32 MaxNumPoses = BlendPose.Num();

	//@TODO: This is currently using O(NumPoses) memory but doesn't need to
	if ((MaxNumPoses > 0) && (BlendPose.Num() == BlendWeights.Num()))
	{
		TArray<FPoseContext> FilteredPoseContexts;
		FilteredPoseContexts.Empty(MaxNumPoses);

		FTransformArrayA2** FilteredPoses = new FTransformArrayA2*[MaxNumPoses];
		float* FilteredWeights = new float[MaxNumPoses];

		int32 NumActivePoses = 0;
		for (int32 i = 0; i < BlendPose.Num(); ++i)
		{
			const float BlendWeight = BlendWeights[i];
			if (BlendWeight > ZERO_ANIMWEIGHT_THRESH)
			{
				FPoseContext& CurrentPoseContext = *(new (FilteredPoseContexts) FPoseContext(Output));

				FPoseLink& CurrentPose = BlendPose[i];
				CurrentPose.Evaluate(CurrentPoseContext);

				FilteredPoses[NumActivePoses] = &(CurrentPoseContext.Pose.Bones);
				FilteredWeights[NumActivePoses] = BlendWeight;
				NumActivePoses++;
			}
		}

		FAnimationRuntime::BlendPosesTogether(NumActivePoses, (const FTransformArrayA2**)FilteredPoses, (const float*)FilteredWeights, Output.AnimInstance->RequiredBones, Output.Pose.Bones);

		delete[] FilteredPoses;
		delete[] FilteredWeights;
	}
	else
	{
		Output.ResetToRefPose();
	}
}
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 FPoseLink::Evaluate(FPoseContext& Output)
{
#if DO_CHECK
	checkf( !bProcessed, TEXT( "Evaluate already in progress, circular link for AnimInstance [%s] Blueprint [%s]" ), \
		*Output.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Output.AnimInstanceProxy->GetAnimClassInterface())));
	TGuardValue<bool> CircularGuard(bProcessed, true);
#endif

#if WITH_EDITOR
	if ((LinkedNode == NULL) && GIsEditor)
	{
		//@TODO: Should only do this when playing back
		AttemptRelink(Output);
	}
#endif

#if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG
	checkf(InitializationCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetInitializationCounter()), TEXT("Calling Evaluate without initialization!"));
	checkf(UpdateCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetUpdateCounter()), TEXT("Calling Evaluate without Update for this node!"));
	checkf(CachedBonesCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetCachedBonesCounter()), TEXT("Calling Evaluate without CachedBones!"));
	EvaluationCounter.SynchronizeWith(Output.AnimInstanceProxy->GetEvaluationCounter());
#endif

	if (LinkedNode != NULL)
	{
#if ENABLE_ANIMNODE_POSE_DEBUG
		CurrentPose.ResetToAdditiveIdentity();
#endif
		LinkedNode->Evaluate(Output);
#if ENABLE_ANIMNODE_POSE_DEBUG
		CurrentPose.CopyBonesFrom(Output.Pose);
#endif

#if WITH_EDITOR
		Output.AnimInstanceProxy->RegisterWatchedPose(Output.Pose, LinkID);
#endif
	}
	else
	{
		//@TODO: Warning here?
		Output.ResetToRefPose();
	}

	// Detect non valid output
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (Output.ContainsNaN())
	{
		// Show bone transform with some useful debug info
		for (const FTransform& Bone : Output.Pose.GetBones())
		{
			if (Bone.ContainsNaN())
			{
				ensureMsgf(!Bone.ContainsNaN(), TEXT("Bone transform contains NaN from AnimInstance:[%s] Node:[%s] Value:[%s]")
					, *Output.AnimInstanceProxy->GetAnimInstanceName(), LinkedNode ? *LinkedNode->StaticStruct()->GetName() : TEXT("NULL"), *Bone.ToString());
			}
		}
	}

	if (!Output.IsNormalized())
	{
		// Show bone transform with some useful debug info
		for (const FTransform& Bone : Output.Pose.GetBones())
		{
			if (!Bone.IsRotationNormalized())
			{
				ensureMsgf(Bone.IsRotationNormalized(), TEXT("Bone Rotation not normalized from AnimInstance:[%s] Node:[%s] Rotation:[%s]")
					, *Output.AnimInstanceProxy->GetAnimInstanceName(), LinkedNode ? *LinkedNode->StaticStruct()->GetName() : TEXT("NULL"), *Bone.GetRotation().ToString());
			}
		}
	}
#endif
}