FTransform UKismetMathLibrary::TLerp(const FTransform& A, const FTransform& B, float Alpha) { FTransform Result; FTransform NA = A; FTransform NB = B; NA.NormalizeRotation(); NB.NormalizeRotation(); Result.Blend(NA, NB, Alpha); return Result; }
void UPhysicsHandleComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); const float Alpha = FMath::Clamp(DeltaTime * InterpolationSpeed, 0.f, 1.f); FTransform C = CurrentTransform; FTransform T = TargetTransform; C.NormalizeRotation(); T.NormalizeRotation(); CurrentTransform.Blend(C, T, Alpha); UpdateHandleTransform(CurrentTransform); }
void FAnimationRuntime::LerpBoneTransforms(TArray<FTransform> & A, const TArray<FTransform> & B, float Alpha, const TArray<FBoneIndexType> & RequiredBonesArray) { if( Alpha >= (1.f - ZERO_ANIMWEIGHT_THRESH) ) { A = B; } else if( Alpha > ZERO_ANIMWEIGHT_THRESH ) { FTransform* ATransformData = A.GetData(); const FTransform* BTransformData = B.GetData(); const ScalarRegister VAlpha(Alpha); const ScalarRegister VOneMinusAlpha(1.f - Alpha); for (int32 Index=0; Index<RequiredBonesArray.Num(); Index++) { const int32& BoneIndex = RequiredBonesArray[Index]; FTransform* TA = ATransformData + BoneIndex; const FTransform* TB = BTransformData + BoneIndex; *TA *= VOneMinusAlpha; TA->AccumulateWithShortestRotation(*TB, VAlpha); TA->NormalizeRotation(); // TA->BlendWith(*TB, Alpha); } } }
void AShip::turnShip(float delta){ if (turnDirection == 0) return; FRotator rot = FRotator(turnDirection * engines->getTurnSpeed() * delta, 0.f, 0.f); FTransform transform = GetTransform(); transform.ConcatenateRotation(rot.Quaternion()); transform.NormalizeRotation(); SetActorTransform(transform); }
void UAnimCompress_RemoveLinearKeys::UpdateWorldBoneTransformTable( UAnimSequence* AnimSeq, const TArray<FBoneData>& BoneData, const TArray<FTransform>& RefPose, int32 BoneIndex, // this bone index should be of skeleton, not mesh bool UseRaw, TArray<FTransform>& OutputWorldBones) { const FBoneData& Bone = BoneData[BoneIndex]; const int32 NumFrames = AnimSeq->NumFrames; const float SequenceLength = AnimSeq->SequenceLength; const int32 FrameStart = (BoneIndex*NumFrames); const int32 TrackIndex = AnimSeq->GetSkeleton()->GetAnimationTrackIndex(BoneIndex, AnimSeq); check(OutputWorldBones.Num() >= (FrameStart+NumFrames)); const float TimePerFrame = SequenceLength / (float)(NumFrames-1); if( TrackIndex != INDEX_NONE ) { // get the local-space bone transforms using the animation solver for ( int32 FrameIndex = 0; FrameIndex < NumFrames; ++FrameIndex ) { float Time = (float)FrameIndex * TimePerFrame; FTransform LocalAtom; AnimSeq->GetBoneTransform(LocalAtom, TrackIndex, Time, UseRaw); FQuat Rot = LocalAtom.GetRotation(); LocalAtom.SetRotation(EnforceShortestArc(FQuat::Identity, Rot)); // Saw some crashes happening with it, so normalize here. LocalAtom.NormalizeRotation(); OutputWorldBones[(BoneIndex*NumFrames) + FrameIndex] = LocalAtom; } } else { // get the default rotation and translation from the reference skeleton FTransform DefaultTransform; FTransform LocalAtom = RefPose[BoneIndex]; LocalAtom.SetRotation(EnforceShortestArc(FQuat::Identity, LocalAtom.GetRotation())); DefaultTransform = LocalAtom; // copy the default transformation into the world bone table for ( int32 FrameIndex = 0; FrameIndex < NumFrames; ++FrameIndex ) { OutputWorldBones[(BoneIndex*NumFrames) + FrameIndex] = DefaultTransform; } } // apply parent transforms to bake into world space. We assume the parent transforms were previously set using this function const int32 ParentIndex = Bone.GetParent(); if (ParentIndex != INDEX_NONE) { check (ParentIndex < BoneIndex); for ( int32 FrameIndex = 0; FrameIndex < NumFrames; ++FrameIndex ) { OutputWorldBones[(BoneIndex*NumFrames) + FrameIndex] = OutputWorldBones[(BoneIndex*NumFrames) + FrameIndex] * OutputWorldBones[(ParentIndex*NumFrames) + FrameIndex]; } } }