예제 #1
0
float UAnimInstance::GetSlotWeight(FName SlotNodeName)
{
	float TotalSum = 0.f;
#if DEBUGMONTAGEWEIGHT
	float TotalDesiredWeight = 0.f;
#endif
	// first get all the montage instance weight this slot node has
	for (int32 I = 0; I < MontageInstances.Num(); ++I)
	{
		FAnimMontageInstance* MontageInstance = MontageInstances[I];

		if (MontageInstance && MontageInstance->IsValid() && MontageInstance->Montage->IsValidSlot(SlotNodeName))
		{
			TotalSum += MontageInstance->Weight;
#if DEBUGMONTAGEWEIGHT			
			TotalDesiredWeight += MontageInstance->DesiredWeight;
#endif			
		}
	}

	// this can happen when it's blending in OR when newer animation comes in with shorter blendtime
	// say #1 animation was blending out time with current blendtime 1.0 #2 animation was blending in with 1.0 (old) but got blend out with new blendtime 0.2f
	// #3 animation was blending in with the new blendtime 0.2f, you'll have sum of #1, 2, 3 exceeds 1.f
	if (TotalSum > 1.f + ZERO_ANIMWEIGHT_THRESH)
	{
		// first get all the montage instance weight this slot node has
		for (int32 I=0; I<MontageInstances.Num(); ++I)
		{
			FAnimMontageInstance * MontageInstance = MontageInstances[I];

			if (MontageInstance && MontageInstance->IsValid() && MontageInstance->Montage->IsValidSlot(SlotNodeName))
			{
				MontageInstance->Weight/=TotalSum;
			}
		} 
	}
#if DEBUGMONTAGEWEIGHT
	else if (TotalDesiredWeight == 1.f && TotalSum < 1.f - ZERO_ANIMWEIGHT_THRESH)
	{
		// this can happen when it's blending in OR when newer animation comes in with longer blendtime
		// say #1 animation was blending out time with current blendtime 0.2 #2 animation was blending in with 0.2 (old) but got blend out with new blendtime 1.f
		// #3 animation was blending in with the new blendtime 1.f, you'll have sum of #1, 2, 3 doesn't meet 1.f
		UE_LOG(LogAnimation, Warning, TEXT("[%s] Montage has less weight. Blending in?(%f)"), *SlotNodeName.ToString(), TotalSum);
	}
#endif

	return FMath::Clamp<float>(TotalSum, 0.f, 1.f);
}
예제 #2
0
void UAnimInstance::UpdateRootMotionMontageInstance()
{
	FAnimMontageInstance * ActiveMontageInstance = GetActiveMontageInstance();

	const bool bValidRootMotionInstance = (ActiveMontageInstance && ActiveMontageInstance->IsValid() && ActiveMontageInstance->Montage 
		&& (ActiveMontageInstance->Montage->bEnableRootMotionTranslation || ActiveMontageInstance->Montage->bEnableRootMotionRotation) );

	RootMotionMontageInstance = bValidRootMotionInstance ? ActiveMontageInstance : NULL;
}
예제 #3
0
FAnimMontageInstance* UAnimInstance::GetActiveMontageInstance()
{
	if ( MontageInstances.Num() > 0 )
	{
		FAnimMontageInstance * RetVal = MontageInstances.Last();
		if ( RetVal->IsValid() )
		{
			return RetVal;
		}
	}

	return NULL;
}
예제 #4
0
void UAnimInstance::SlotEvaluatePose(FName SlotNodeName, const FA2Pose & SourcePose, FA2Pose & BlendedPose, float SlotNodeWeight)
{
	SCOPE_CYCLE_COUNTER(STAT_AnimNativeEvaluatePoses);
	if ( SlotNodeWeight > ZERO_ANIMWEIGHT_THRESH )
	{
		// final output of slot pose
		FA2Pose SlotPose;
		SlotPose.Bones.AddUninitialized(SourcePose.Bones.Num());

		/// blend helper variables
		TArray<FA2Pose>						MontagePoses;
		TArray<float>						MontageWeights;
		TArray<FAnimMontageInstance *>		ValidMontageInstances;

		// first pass we go through collect weights and valid montages. 
		for (auto Iter = MontageInstances.CreateConstIterator(); Iter; ++Iter)
		{
			FAnimMontageInstance * MontageInstance = (*Iter);

			// @todo make this struct?
			if (MontageInstance->IsValid() && MontageInstance->Montage->IsValidSlot(SlotNodeName))
			{
				int32 NewIndex = MontageWeights.AddUninitialized(1);
				MontagePoses.AddZeroed(1);
				ValidMontageInstances.Add(MontageInstance);

				MontagePoses[NewIndex].Bones.AddUninitialized(BlendedPose.Bones.Num());
				MontageWeights[NewIndex] = MontageInstance->Weight;
			}
		}

		// clean up the MontageWeights to see if they're not summing up correctly
		float TotalSum = 0.f;
		for (int32 I=0; I<MontageWeights.Num(); ++I)
		{
			// normalize I
			TotalSum += MontageWeights[I];
		}

		// if it has any valid weight
		if ( TotalSum > ZERO_ANIMWEIGHT_THRESH )
		{
			// but not 1.f. If 1.f it's useless
			if (FMath::IsNearlyEqual(TotalSum, 1.f) == false)
			{
				for (int32 I=0; I<MontageWeights.Num(); ++I)
				{
					// normalize I
					MontageWeights[I] /= TotalSum;
				}
			}
		}
		else
		{
			FAnimationRuntime::FillWithRefPose(BlendedPose.Bones, RequiredBones);
			// nothing else to do here, there is no weight
			return;
		}

		// if not, something went wrong. It should have something
		check (ValidMontageInstances.Num() > 0);

		// second pass, we fill up MontagePoses with valid data to be full pose
		for (int32 I=0; I<ValidMontageInstances.Num(); ++I)
		{
			FAnimMontageInstance * MontageInstance = ValidMontageInstances[I];
			const FAnimTrack * AnimTrack = MontageInstance->Montage->GetAnimationData(SlotNodeName);

			// find out if this is additive animation
			EAdditiveAnimationType AdditiveAnimType = AAT_None;
			if (AnimTrack->IsAdditive())
			{
				AdditiveAnimType = AnimTrack->IsRotationOffsetAdditive()? AAT_RotationOffsetMeshSpace : AAT_LocalSpaceBase;
			}

			// get the pose data, temporarily use SlotPose
			FAnimExtractContext ExtractionContext(MontageInstance->Position, false, MontageInstance->Montage->bEnableRootMotionTranslation, MontageInstance->Montage->bEnableRootMotionRotation, MontageInstance->Montage->RootMotionRootLock);
			FAnimationRuntime::GetPoseFromAnimTrack(*AnimTrack, RequiredBones, SlotPose.Bones, ExtractionContext);

			// if additive, we should blend with source to make it fullbody
			if (AdditiveAnimType == AAT_LocalSpaceBase)
			{
				ApplyAdditiveSequence(SourcePose,SlotPose,MontageWeights[I],MontagePoses[I]);
			}
			else if (AdditiveAnimType == AAT_RotationOffsetMeshSpace)
			{
				BlendRotationOffset(SourcePose,SlotPose,MontageWeights[I],MontagePoses[I]);
			}
			else 
			{
				CopyPose(SlotPose, MontagePoses[I]);
			}
		}
	
		// allocate for blending
		FTransformArrayA2** BlendingPoses = new FTransformArrayA2*[MontagePoses.Num()];

		for (int32 I=0; I<MontagePoses.Num(); ++I)
		{
			BlendingPoses[I] = &MontagePoses[I].Bones;
		}
		// now time to blend all montages
		FAnimationRuntime::BlendPosesTogether(MontagePoses.Num(), (const FTransformArrayA2**)BlendingPoses, (const float*)MontageWeights.GetData(), RequiredBones, SlotPose.Bones);

		// clean up memory
		delete[] BlendingPoses;

		// now blend with Source
		if ( SlotNodeWeight > 1-ZERO_ANIMWEIGHT_THRESH )
		{
			BlendedPose = SlotPose;
		}
		else
		{
			// normal non-additive animations
			BlendSequences(SourcePose, SlotPose, SlotNodeWeight, BlendedPose);
		}
	}
	else
	{
		BlendedPose = SourcePose;
	}
}