Пример #1
0
void FAnimationRuntime::AccumulateLocalSpaceAdditivePose(FCompactPose& BasePose, const FCompactPose& AdditivePose, FBlendedCurve& BaseCurve, const FBlendedCurve& AdditiveCurve, float Weight)
{
	if (Weight > ZERO_ANIMWEIGHT_THRESH)
	{
		if (Weight >= (1.f - ZERO_ANIMWEIGHT_THRESH))
		{
			// fast path, no need to weight additive.
			for (FCompactPoseBoneIndex BoneIndex : BasePose.ForEachBoneIndex())
			{
				BasePose[BoneIndex].Accumulate(AdditivePose[BoneIndex]);
			}
		}
		else
		{
			// Slower path w/ weighting
			const ScalarRegister VBlendWeight(Weight);
			for (FCompactPoseBoneIndex BoneIndex : BasePose.ForEachBoneIndex())
			{
				// copy additive, because BlendFromIdentityAndAccumulate modifies it.
				FTransform Additive = AdditivePose[BoneIndex];
				FTransform::BlendFromIdentityAndAccumulate(BasePose[BoneIndex], Additive, VBlendWeight);
			}
		}
	}
}
Пример #2
0
FORCEINLINE void BlendPose(const FCompactPose& SourcePose, FCompactPose& ResultPose, const float BlendWeight)
{
	for (FCompactPoseBoneIndex BoneIndex : SourcePose.ForEachBoneIndex())
	{
		BlendTransform<TRANSFORM_BLEND_MODE>(SourcePose[BoneIndex], ResultPose[BoneIndex], BlendWeight);
	}
}
Пример #3
0
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()];
		}
	}
}
Пример #4
0
void FAnimationRuntime::ConvertPoseToAdditive(FCompactPose& TargetPose, const FCompactPose& BasePose)
{
	for (FCompactPoseBoneIndex BoneIndex : BasePose.ForEachBoneIndex())
	{
		FTransform& TargetTransform = TargetPose[BoneIndex];
		const FTransform& BaseTransform = BasePose[BoneIndex];

		TargetTransform.SetRotation(TargetTransform.GetRotation() * BaseTransform.GetRotation().Inverse());
		TargetTransform.SetTranslation(TargetTransform.GetTranslation() - BaseTransform.GetTranslation());
		TargetTransform.SetScale3D(TargetTransform.GetScale3D() * BaseTransform.GetSafeScaleReciprocal(BaseTransform.GetScale3D()));
		TargetTransform.NormalizeRotation();
	}
}
Пример #5
0
void FAnimationRuntime::BlendPosesTogetherPerBoneInMeshSpace(TArray<FCompactPose>& SourcePoses, const TArray<FBlendedCurve>& SourceCurves, const UBlendSpaceBase* BlendSpace, const TArray<FBlendSampleData>& BlendSampleDataCache, FCompactPose& ResultPose, FBlendedCurve& ResultCurve)
{
	FQuat NewRotation;
	USkeleton* Skeleton = BlendSpace->GetSkeleton();

	// all this is going to do is to convert SourcePoses.Rotation to be mesh space, and then once it goes through BlendPosesTogetherPerBone, convert back to local
	for (FCompactPose& Pose : SourcePoses)
	{
		for (const FCompactPoseBoneIndex BoneIndex : Pose.ForEachBoneIndex())
		{
			const FCompactPoseBoneIndex ParentIndex = Pose.GetParentBoneIndex(BoneIndex);
			if (ParentIndex != INDEX_NONE)
			{
				NewRotation = Pose[ParentIndex].GetRotation()*Pose[BoneIndex].GetRotation();
				NewRotation.Normalize();
			}
			else
			{
				NewRotation = Pose[BoneIndex].GetRotation();
			}

			// now copy back to SourcePoses
			Pose[BoneIndex].SetRotation(NewRotation);
		}
	}

	// now we have mesh space rotation, call BlendPosesTogetherPerBone
	BlendPosesTogetherPerBone(SourcePoses, SourceCurves, BlendSpace, BlendSampleDataCache, ResultPose, ResultCurve);

	// now result atoms has the output with mesh space rotation. Convert back to local space, start from back
	for (const FCompactPoseBoneIndex BoneIndex : ResultPose.ForEachBoneIndex())
	{
		const FCompactPoseBoneIndex ParentIndex = ResultPose.GetParentBoneIndex(BoneIndex);
		if (ParentIndex != INDEX_NONE)
		{
			FQuat LocalBlendQuat = ResultPose[ParentIndex].GetRotation().Inverse()*ResultPose[BoneIndex].GetRotation();
			ResultPose[BoneIndex].SetRotation(LocalBlendQuat);
			ResultPose[BoneIndex].NormalizeRotation();
		}
	}
}
Пример #6
0
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]);
		}
	}
}
Пример #7
0
void FAnimationRuntime::BlendLocalPosesPerBoneWeights(
	FCompactPose& BasePose,
	const TArray<FCompactPose>& BlendPoses,
	struct FBlendedCurve& BaseCurve,
	const TArray<struct FBlendedCurve>& BlendedCurves,
	const TArray<FPerBoneBlendWeight> & BoneBlendWeights,
	ECurveBlendOption::Type CurveBlendOption,
	/*out*/ FCompactPose& OutPose, 
	/*out*/ struct FBlendedCurve& OutCurve)
{
	check(BasePose.GetNumBones() == BoneBlendWeights.Num());
	int32 PoseNum = BlendPoses.Num();

	TArray<float> MaxPoseWeights;
	MaxPoseWeights.AddZeroed(PoseNum);

	for (FCompactPoseBoneIndex BoneIndex : BasePose.ForEachBoneIndex())
	{
		const int32 PoseIndex = BoneBlendWeights[BoneIndex.GetInt()].SourceIndex;
		const FTransform& BaseAtom = BasePose[BoneIndex];

		const float BlendWeight = FMath::Clamp(BoneBlendWeights[BoneIndex.GetInt()].BlendWeight, 0.f, 1.f);
		MaxPoseWeights[PoseIndex] = FMath::Max(MaxPoseWeights[PoseIndex], BlendWeight);

		if (BlendWeight < ZERO_ANIMWEIGHT_THRESH)
		{
			OutPose[BoneIndex] = BaseAtom;
		}
		else if ((1.0 - BlendWeight) < ZERO_ANIMWEIGHT_THRESH)
		{
			OutPose[BoneIndex] = BlendPoses[PoseIndex][BoneIndex];
		}
		else // we want blend here
		{
			FTransform BlendAtom = BaseAtom;
			const FTransform& TargetAtom = BlendPoses[PoseIndex][BoneIndex];
			BlendAtom.BlendWith(TargetAtom, BlendWeight);
			OutPose[BoneIndex] = BlendAtom;
		}
	}

	// time to blend curves
	// the way we blend curve per bone
	// is to find out max weight per that pose, and then apply that weight to the curve
	{
		TArray<const FBlendedCurve*> SourceCurves;
		TArray<float> SourceWegihts;

		SourceCurves.SetNumUninitialized(PoseNum+1);
		SourceWegihts.SetNumUninitialized(PoseNum+1);

		SourceCurves[0] = &BaseCurve;
		SourceWegihts[0] = 1.f;

		for (int32 Idx=0; Idx<PoseNum; ++Idx)
		{
			SourceCurves[Idx+1] = &BlendedCurves[Idx];
			SourceWegihts[Idx+1] = MaxPoseWeights[Idx];
		}
		
		BlendCurves(SourceCurves, SourceWegihts, OutCurve, CurveBlendOption);
	}
}