本文整理汇总了C++中FCSPose::GetComponentSpaceTransform方法的典型用法代码示例。如果您正苦于以下问题:C++ FCSPose::GetComponentSpaceTransform方法的具体用法?C++ FCSPose::GetComponentSpaceTransform怎么用?C++ FCSPose::GetComponentSpaceTransform使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类FCSPose
的用法示例。
在下文中一共展示了FCSPose::GetComponentSpaceTransform方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: EvaluateBoneTransforms
void FAnimNode_HandIKRetargeting::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
checkSlow(OutBoneTransforms.Num() == 0);
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
// Get component space transforms for all of our IK and FK bones.
const FTransform& RightHandFKTM = MeshBases.GetComponentSpaceTransform(RightHandFK.GetCompactPoseIndex(BoneContainer));
const FTransform& LeftHandFKTM = MeshBases.GetComponentSpaceTransform(LeftHandFK.GetCompactPoseIndex(BoneContainer));
const FTransform& RightHandIKTM = MeshBases.GetComponentSpaceTransform(RightHandIK.GetCompactPoseIndex(BoneContainer));
const FTransform& LeftHandIKTM = MeshBases.GetComponentSpaceTransform(LeftHandIK.GetCompactPoseIndex(BoneContainer));
// Compute weight FK and IK hand location. And translation from IK to FK.
FVector const FKLocation = FMath::Lerp<FVector>(LeftHandFKTM.GetTranslation(), RightHandFKTM.GetTranslation(), HandFKWeight);
FVector const IKLocation = FMath::Lerp<FVector>(LeftHandIKTM.GetTranslation(), RightHandIKTM.GetTranslation(), HandFKWeight);
FVector const IK_To_FK_Translation = FKLocation - IKLocation;
// If we're not translating, don't send any bones to update.
if (!IK_To_FK_Translation.IsNearlyZero())
{
// Move desired bones
for (const FBoneReference& BoneReference : IKBonesToMove)
{
if (BoneReference.IsValid(BoneContainer))
{
FCompactPoseBoneIndex BoneIndex = BoneReference.GetCompactPoseIndex(BoneContainer);
FTransform BoneTransform = MeshBases.GetComponentSpaceTransform(BoneIndex);
BoneTransform.AddToTranslation(IK_To_FK_Translation);
OutBoneTransforms.Add(FBoneTransform(BoneIndex, BoneTransform));
}
}
}
}
示例2: EvaluateBoneTransforms
void FAnimNode_CopyBone::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
// Pass through if we're not doing anything.
if( !bCopyTranslation && !bCopyRotation && !bCopyScale )
{
return;
}
// Get component space transform for source and current bone.
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
FCompactPoseBoneIndex SourceBoneIndex = SourceBone.GetCompactPoseIndex(BoneContainer);
FCompactPoseBoneIndex TargetBoneIndex = TargetBone.GetCompactPoseIndex(BoneContainer);
FTransform SourceBoneTM = MeshBases.GetComponentSpaceTransform(SourceBoneIndex);
FTransform CurrentBoneTM = MeshBases.GetComponentSpaceTransform(TargetBoneIndex);
if(ControlSpace != BCS_ComponentSpace)
{
// Convert out to selected space
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, SourceBoneTM, SourceBoneIndex, ControlSpace);
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, CurrentBoneTM, TargetBoneIndex, ControlSpace);
}
// Copy individual components
if (bCopyTranslation)
{
CurrentBoneTM.SetTranslation( SourceBoneTM.GetTranslation() );
}
if (bCopyRotation)
{
CurrentBoneTM.SetRotation( SourceBoneTM.GetRotation() );
}
if (bCopyScale)
{
CurrentBoneTM.SetScale3D( SourceBoneTM.GetScale3D() );
}
if(ControlSpace != BCS_ComponentSpace)
{
// Convert back out if we aren't operating in component space
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, CurrentBoneTM, TargetBoneIndex, ControlSpace);
}
// Output new transform for current bone.
OutBoneTransforms.Add(FBoneTransform(TargetBoneIndex, CurrentBoneTM));
}
示例3: EvaluateBoneTransforms
void FAnimNode_WheelHandler::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
const TArray<FWheelAnimData>& WheelAnimData = AnimInstanceProxy->GetWheelAnimData();
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
for(const FWheelLookupData& Wheel : Wheels)
{
if (Wheel.BoneReference.IsValid(BoneContainer))
{
FCompactPoseBoneIndex WheelSimBoneIndex = Wheel.BoneReference.GetCompactPoseIndex(BoneContainer);
// the way we apply transform is same as FMatrix or FTransform
// we apply scale first, and rotation, and translation
// if you'd like to translate first, you'll need two nodes that first node does translate and second nodes to rotate.
FTransform NewBoneTM = MeshBases.GetComponentSpaceTransform(WheelSimBoneIndex);
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, WheelSimBoneIndex, BCS_ComponentSpace);
// Apply rotation offset
const FQuat BoneQuat(WheelAnimData[Wheel.WheelIndex].RotOffset);
NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
// Apply loc offset
NewBoneTM.AddToTranslation(WheelAnimData[Wheel.WheelIndex].LocOffset);
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, WheelSimBoneIndex, BCS_ComponentSpace);
// add back to it
OutBoneTransforms.Add(FBoneTransform(WheelSimBoneIndex, NewBoneTM));
}
}
}
示例4: TEXT
/** Convert a BoneSpace FTransform to ComponentSpace. */
void FAnimationRuntime::ConvertBoneSpaceTransformToCS
(
USkeletalMeshComponent * SkelComp,
FCSPose<FCompactPose> & MeshBases,
/*inout*/ FTransform& BoneSpaceTM,
FCompactPoseBoneIndex BoneIndex,
uint8 Space
)
{
switch( Space )
{
case BCS_WorldSpace :
BoneSpaceTM.SetToRelativeTransform(SkelComp->ComponentToWorld);
break;
case BCS_ComponentSpace :
// Component Space, no change.
break;
case BCS_ParentBoneSpace :
if( BoneIndex != INDEX_NONE )
{
const FCompactPoseBoneIndex ParentIndex = MeshBases.GetPose().GetParentBoneIndex(BoneIndex);
if( ParentIndex != INDEX_NONE )
{
const FTransform& ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
BoneSpaceTM *= ParentTM;
}
}
break;
case BCS_BoneSpace :
if( BoneIndex != INDEX_NONE )
{
const FTransform& BoneTM = MeshBases.GetComponentSpaceTransform(BoneIndex);
BoneSpaceTM *= BoneTM;
}
break;
default:
UE_LOG(LogAnimation, Warning, TEXT("ConvertBoneSpaceTransformToCS: Unknown BoneSpace %d for Mesh: %s"), Space, *GetNameSafe(SkelComp->SkeletalMesh));
break;
}
}
示例5: EvaluateBoneTransforms
void FAnimNode_RotationMultiplier::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
if ( Multiplier != 0.f )
{
// Reference bone
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
const FCompactPoseBoneIndex TargetBoneIndex = TargetBone.GetCompactPoseIndex(BoneContainer);
const FCompactPoseBoneIndex SourceBoneIndex = SourceBone.GetCompactPoseIndex(BoneContainer);
const FQuat RefQuat = MeshBases.GetPose().GetRefPose(TargetBoneIndex).GetRotation();
const FTransform& SourceRefPose = MeshBases.GetPose().GetRefPose(SourceBoneIndex);
FQuat NewQuat = MultiplyQuatBasedOnSourceIndex(SourceRefPose, MeshBases.GetLocalSpaceTransform(SourceBoneIndex), RotationAxisToRefer, Multiplier, RefQuat);
FTransform NewLocalTransform = MeshBases.GetLocalSpaceTransform(TargetBoneIndex);
if (bIsAdditive)
{
NewQuat = NewLocalTransform.GetRotation() * NewQuat;
}
NewLocalTransform.SetRotation(NewQuat);
const FCompactPoseBoneIndex ParentIndex = MeshBases.GetPose().GetParentBoneIndex(TargetBoneIndex);
if( ParentIndex != INDEX_NONE )
{
const FTransform& ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
FTransform NewTransform = NewLocalTransform * ParentTM;
OutBoneTransforms.Add( FBoneTransform(TargetBoneIndex, NewTransform) );
}
else
{
OutBoneTransforms.Add( FBoneTransform(TargetBoneIndex, NewLocalTransform) );
}
}
}
示例6: EvaluateOneBoneTransforms
void FAnimNode_ModifyFinger::EvaluateOneBoneTransforms(FBoneReference* BoneToModify, FRotator* Rotation, const FBoneContainer BoneContainer, FCSPose<FCompactPose> &MeshBases, USkeletalMeshComponent* SkelComp, TArray<FBoneTransform> &OutBoneTransforms)
{
FCompactPoseBoneIndex CompactPoseBoneToModify = BoneToModify->GetCompactPoseIndex(BoneContainer);
FTransform NewBoneTM = MeshBases.GetComponentSpaceTransform(CompactPoseBoneToModify);
if (RotationMode != BMM_Ignore)
{
// Convert to Bone Space.
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
const FQuat BoneQuat(*Rotation);
if (RotationMode == BMM_Additive)
{
NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
}
else
{
NewBoneTM.SetRotation(BoneQuat);
}
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
}
if (ScaleMode != BMM_Ignore)
{
// Convert to Bone Space.
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, ScaleSpace);
if (ScaleMode == BMM_Additive)
{
NewBoneTM.SetScale3D(NewBoneTM.GetScale3D() * Scale);
}
else
{
NewBoneTM.SetScale3D(Scale);
}
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, ScaleSpace);
}
if (TranslationMode != BMM_Ignore)
{
// Convert to Bone Space.
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, TranslationSpace);
if (TranslationMode == BMM_Additive)
{
NewBoneTM.AddToTranslation(Translation1);
}
else
{
NewBoneTM.SetTranslation(Translation1);
}
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, TranslationSpace);
}
OutBoneTransforms.Add(FBoneTransform(BoneToModify->GetCompactPoseIndex(BoneContainer), NewBoneTM));
const float BlendWeight = FMath::Clamp<float>(Alpha, 0.f, 1.f);
MeshBases.LocalBlendCSBoneTransforms(OutBoneTransforms, BlendWeight);
OutBoneTransforms.Empty();
}
示例7: EvaluateBoneTransforms
void FAnimNode_CopyBoneDelta::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
if(!bCopyTranslation && !bCopyRotation && !bCopyScale)
{
return;
}
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
FCompactPoseBoneIndex SourceBoneIndex = SourceBone.GetCompactPoseIndex(BoneContainer);
FCompactPoseBoneIndex TargetBoneIndex = TargetBone.GetCompactPoseIndex(BoneContainer);
FTransform SourceTM = MeshBases.GetComponentSpaceTransform(SourceBoneIndex);
FTransform TargetTM = MeshBases.GetComponentSpaceTransform(TargetBoneIndex);
// Convert to parent space
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, SourceTM, SourceBoneIndex, BCS_ParentBoneSpace);
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, TargetTM, TargetBoneIndex, BCS_ParentBoneSpace);
// Ref pose transform
FTransform RefLSTransform = SkelComp->SkeletalMesh->RefSkeleton.GetRefBonePose()[SourceBone.GetMeshPoseIndex().GetInt()];
// Get transform relative to ref pose
SourceTM.SetToRelativeTransform(RefLSTransform);
if(CopyMode == CopyBoneDeltaMode::Accumulate)
{
if(bCopyTranslation)
{
TargetTM.AddToTranslation(SourceTM.GetTranslation() * TranslationMultiplier);
}
if(bCopyRotation)
{
FVector Axis;
float Angle;
SourceTM.GetRotation().ToAxisAndAngle(Axis, Angle);
TargetTM.SetRotation(FQuat(Axis, Angle * RotationMultiplier) * TargetTM.GetRotation());
}
if(bCopyScale)
{
TargetTM.SetScale3D(TargetTM.GetScale3D() * (SourceTM.GetScale3D() * ScaleMultiplier));
}
}
else //CopyMode = CopyBoneDeltaMode::Copy
{
if(bCopyTranslation)
{
TargetTM.SetTranslation(SourceTM.GetTranslation() * TranslationMultiplier);
}
if(bCopyRotation)
{
FVector Axis;
float Angle;
SourceTM.GetRotation().ToAxisAndAngle(Axis, Angle);
TargetTM.SetRotation(FQuat(Axis, Angle * RotationMultiplier));
}
if(bCopyScale)
{
TargetTM.SetScale3D(SourceTM.GetScale3D() * ScaleMultiplier);
}
}
// Back out to component space
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, TargetTM, TargetBoneIndex, BCS_ParentBoneSpace);
OutBoneTransforms.Add(FBoneTransform(TargetBoneIndex, TargetTM));
}
示例8: EvaluateBoneTransforms
void FAnimNode_LookAt::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
const FCompactPoseBoneIndex ModifyBoneIndex = BoneToModify.GetCompactPoseIndex(BoneContainer);
FTransform ComponentBoneTransform = MeshBases.GetComponentSpaceTransform(ModifyBoneIndex);
// get target location
FVector TargetLocationInComponentSpace;
if (LookAtBone.IsValid(BoneContainer))
{
const FTransform& LookAtTransform = MeshBases.GetComponentSpaceTransform(LookAtBone.GetCompactPoseIndex(BoneContainer));
TargetLocationInComponentSpace = LookAtTransform.GetLocation();
}
else
{
TargetLocationInComponentSpace = SkelComp->ComponentToWorld.InverseTransformPosition(LookAtLocation);
}
FVector OldCurrentTargetLocation = CurrentTargetLocation;
FVector NewCurrentTargetLocation = TargetLocationInComponentSpace;
if ((NewCurrentTargetLocation - OldCurrentTargetLocation).SizeSquared() > InterpolationTriggerThreashold*InterpolationTriggerThreashold)
{
if (AccumulatedInterpoolationTime >= InterpolationTime)
{
// reset current Alpha, we're starting to move
AccumulatedInterpoolationTime = 0.f;
}
PreviousTargetLocation = OldCurrentTargetLocation;
CurrentTargetLocation = NewCurrentTargetLocation;
}
else if (InterpolationTriggerThreashold == 0.f)
{
CurrentTargetLocation = NewCurrentTargetLocation;
}
if (InterpolationTime > 0.f)
{
float CurrentAlpha = AccumulatedInterpoolationTime/InterpolationTime;
if (CurrentAlpha < 1.f)
{
float BlendAlpha = AlphaToBlendType(CurrentAlpha, GetInterpolationType());
CurrentLookAtLocation = FMath::Lerp(PreviousTargetLocation, CurrentTargetLocation, BlendAlpha);
}
}
else
{
CurrentLookAtLocation = CurrentTargetLocation;
}
if (bEnableDebug)
{
UWorld* World = SkelComp->GetWorld();
DrawDebugData(World, SkelComp->GetComponentToWorld(), ComponentBoneTransform.GetLocation(), PreviousTargetLocation, FColor(0, 255, 0));
DrawDebugData(World, SkelComp->GetComponentToWorld(), ComponentBoneTransform.GetLocation(), CurrentTargetLocation, FColor(255, 0, 0));
DrawDebugData(World, SkelComp->GetComponentToWorld(), ComponentBoneTransform.GetLocation(), CurrentLookAtLocation, FColor(0, 0, 255));
}
// lookat vector
FVector LookAtVector = GetAlignVector(ComponentBoneTransform, LookAtAxis);
// flip to target vector if it wasnt negative
bool bShouldFlip = LookAtAxis == EAxisOption::X_Neg || LookAtAxis == EAxisOption::Y_Neg || LookAtAxis == EAxisOption::Z_Neg;
FVector ToTarget = CurrentLookAtLocation - ComponentBoneTransform.GetLocation();
ToTarget.Normalize();
if (bShouldFlip)
{
ToTarget *= -1.f;
}
if ( LookAtClamp > ZERO_ANIMWEIGHT_THRESH )
{
float LookAtClampInRadians = FMath::DegreesToRadians(LookAtClamp);
float DiffAngle = FMath::Acos(FVector::DotProduct(LookAtVector, ToTarget));
if (LookAtClampInRadians > 0.f && DiffAngle > LookAtClampInRadians)
{
FVector OldToTarget = ToTarget;
FVector DeltaTarget = ToTarget-LookAtVector;
float Ratio = LookAtClampInRadians/DiffAngle;
DeltaTarget *= Ratio;
ToTarget = LookAtVector + DeltaTarget;
ToTarget.Normalize();
// UE_LOG(LogAnimation, Warning, TEXT("Recalculation required - old target %f, new target %f"),
// FMath::RadiansToDegrees(FMath::Acos(FVector::DotProduct(LookAtVector, OldToTarget))), FMath::RadiansToDegrees(FMath::Acos(FVector::DotProduct(LookAtVector, ToTarget))));
}
}
FQuat DeltaRot;
// if want to use look up,
if (bUseLookUpAxis)
{
// find look up vector in local space
FVector LookUpVector = GetAlignVector(ComponentBoneTransform, LookUpAxis);
//.........这里部分代码省略.........
示例9: RefreshBoneTransforms
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);
}
}
}
}
}
示例10: BoneQuat
//.........这里部分代码省略.........
FRotator CompSpaceRotator = (PostBoneDirAdjustmentRotator.Quaternion()*BoneAdjustments[Bone.JointTypeEnd].BoneNormalAdjustment.Quaternion()).Rotator();
FVector Normal, Binormal, Dir;
UKismetMathLibrary::BreakRotIntoAxes(CompSpaceRotator, Normal, Binormal, Dir);
Dir *= BoneAdjustments[Bone.JointTypeEnd].bInvertDir ? -1 : 1;
Normal *= BoneAdjustments[Bone.JointTypeEnd].bInvertNormal ? -1 : 1;
FVector X, Y, Z;
switch (BoneAdjustments[Bone.JointTypeEnd].BoneDirAxis)
{
case EAxis::X:
X = Dir;
break;
case EAxis::Y:
Y = Dir;
break;
case EAxis::Z:
Z = Dir;
break;
default:
;
}
switch (BoneAdjustments[Bone.JointTypeEnd].BoneBinormalAxis)
{
case EAxis::X:
X = Binormal;
break;
case EAxis::Y:
Y = Binormal;
break;
case EAxis::Z:
Z = Binormal;
break;
default:
;
}
switch (BoneAdjustments[Bone.JointTypeEnd].BoneNormalAxis)
{
case EAxis::X:
X = Normal;
break;
case EAxis::Y:
Y = Normal;
break;
case EAxis::Z:
Z = Normal;
break;
default:
;
}
FRotator SwiveledRot = UKismetMathLibrary::MakeRotationFromAxes(X, Y, Z);
SwiveledRot = (SkelComp->GetBoneTransform(0).Rotator().Quaternion()*SwiveledRot.Quaternion()).Rotator();
//PosableMesh->SetBoneRotationByName(RetargetBoneNames[Bone.JointTypeEnd], (PosableMesh->GetBoneTransform(0).Rotator().Quaternion()*SwiveledRot.Quaternion()).Rotator(), EBoneSpaces::ComponentSpace);
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (BoneAdjustments[i].bDebugDraw)
{
DrawDebugCoordinateSystem(SkelComp->GetWorld(), SkelComp->GetBoneLocation(BonesToRetarget[i].BoneName), SwiveledRot, 100.f, false, 0.1f);
}
#endif
FCompactPoseBoneIndex CompactPoseBoneToModify = BonesToRetarget[i].GetCompactPoseIndex(BoneContainer);
FTransform NewBoneTM = MeshBases.GetComponentSpaceTransform(CompactPoseBoneToModify);
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);
const FQuat BoneQuat(SwiveledRot);
NewBoneTM.SetRotation(BoneQuat);
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);
FAnimationRuntime::SetSpaceTransform(TempPose, BonesToRetarget[i].BoneIndex, NewBoneTM);
OutBoneTransforms.Add(FBoneTransform(BonesToRetarget[i].GetCompactPoseIndex(BoneContainer), NewBoneTM));
}
++i;
}
}
示例11: EvaluateBoneTransforms
void FAnimNode_Trail::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
if( ChainLength < 2 )
{
return;
}
// The incoming BoneIndex is the 'end' of the spline chain. We need to find the 'start' by walking SplineLength bones up hierarchy.
// Fail if we walk past the root bone.
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
FCompactPoseBoneIndex WalkBoneIndex = TrailBone.GetCompactPoseIndex(BoneContainer);
TArray<FCompactPoseBoneIndex> ChainBoneIndices;
ChainBoneIndices.AddZeroed(ChainLength);
ChainBoneIndices[ChainLength - 1] = WalkBoneIndex;
for (int32 i = 1; i < ChainLength; i++)
{
// returns to avoid a crash
// @TODO : shows an error message why failed
if (WalkBoneIndex == 0)
{
return;
}
// Get parent bone.
WalkBoneIndex = BoneContainer.GetParentBoneIndex(WalkBoneIndex);
//Insert indices at the start of array, so that parents are before children in the array.
int32 TransformIndex = ChainLength - (i + 1);
ChainBoneIndices[TransformIndex] = WalkBoneIndex;
}
OutBoneTransforms.AddZeroed(ChainLength);
// If we have >0 this frame, but didn't last time, record positions of all the bones.
// Also do this if number has changed or array is zero.
bool bHasValidStrength = (Alpha > 0.f);
if(TrailBoneLocations.Num() != ChainLength || (bHasValidStrength && !bHadValidStrength))
{
TrailBoneLocations.Empty();
TrailBoneLocations.AddZeroed(ChainLength);
for(int32 i=0; i<ChainBoneIndices.Num(); i++)
{
FCompactPoseBoneIndex ChildIndex = ChainBoneIndices[i];
const FTransform& ChainTransform = MeshBases.GetComponentSpaceTransform(ChildIndex);
TrailBoneLocations[i] = ChainTransform.GetTranslation();
}
OldLocalToWorld = SkelComp->GetTransformMatrix();
}
bHadValidStrength = bHasValidStrength;
// transform between last frame and now.
FMatrix OldToNewTM = OldLocalToWorld * SkelComp->GetTransformMatrix().InverseFast();
// Add fake velocity if present to all but root bone
if(!FakeVelocity.IsZero())
{
FVector FakeMovement = -FakeVelocity * ThisTimstep;
if (bActorSpaceFakeVel && SkelComp->GetOwner())
{
const FTransform BoneToWorld(SkelComp->GetOwner()->GetActorQuat(), SkelComp->GetOwner()->GetActorLocation());
FakeMovement = BoneToWorld.TransformVector(FakeMovement);
}
FakeMovement = SkelComp->GetTransformMatrix().InverseTransformVector(FakeMovement);
// Then add to each bone
for(int32 i=1; i<TrailBoneLocations.Num(); i++)
{
TrailBoneLocations[i] += FakeMovement;
}
}
// Root bone of trail is not modified.
FCompactPoseBoneIndex RootIndex = ChainBoneIndices[0];
const FTransform& ChainTransform = MeshBases.GetComponentSpaceTransform(RootIndex);
OutBoneTransforms[0] = FBoneTransform(RootIndex, ChainTransform);
TrailBoneLocations[0] = ChainTransform.GetTranslation();
// Starting one below head of chain, move bones.
for(int32 i=1; i<ChainBoneIndices.Num(); i++)
{
// Parent bone position in component space.
FCompactPoseBoneIndex ParentIndex = ChainBoneIndices[i - 1];
FVector ParentPos = TrailBoneLocations[i-1];
FVector ParentAnimPos = MeshBases.GetComponentSpaceTransform(ParentIndex).GetTranslation();
// Child bone position in component space.
FCompactPoseBoneIndex ChildIndex = ChainBoneIndices[i];
FVector ChildPos = OldToNewTM.TransformPosition(TrailBoneLocations[i]); // move from 'last frames component' frame to 'this frames component' frame
FVector ChildAnimPos = MeshBases.GetComponentSpaceTransform(ChildIndex).GetTranslation();
// Desired parent->child offset.
FVector TargetDelta = (ChildAnimPos - ParentAnimPos);
//.........这里部分代码省略.........
示例12: UpdateLimits
void FAnimNode_AnimDynamics::UpdateLimits(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases)
{
SCOPE_CYCLE_COUNTER(STAT_AnimDynamicsLimitUpdate);
// We're always going to use the same number so don't realloc
LinearLimits.Empty(LinearLimits.Num());
AngularLimits.Empty(AngularLimits.Num());
Springs.Empty(Springs.Num());
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
for (int32 Idx = 0; Idx < Bodies.Num(); ++Idx)
{
const FBoneReference& CurrentBoneRef = BoundBoneReferences[Idx];
// If our bone isn't valid, move on
if(!CurrentBoneRef.IsValid(BoneContainer))
{
continue;
}
FAnimPhysLinkedBody& ChainBody = Bodies[Idx];
FAnimPhysRigidBody& RigidBody = Bodies[Idx].RigidBody.PhysBody;
FAnimPhysRigidBody* PrevBody = nullptr;
if (ChainBody.ParentBody)
{
PrevBody = &ChainBody.ParentBody->PhysBody;
}
// Get joint transform
FCompactPoseBoneIndex BoneIndex = CurrentBoneRef.GetCompactPoseIndex(BoneContainer);
FTransform BoundBoneTransform = MeshBases.GetComponentSpaceTransform(BoneIndex);
FTransform ShapeTransform = BoundBoneTransform;
// Local offset to joint for Body1
FVector Body1JointOffset = LocalJointOffset;
if (PrevBody)
{
// Get the correct offset
Body1JointOffset = JointOffsets[Idx];
// Modify the shape transform to be correct in Body0 frame
ShapeTransform = FTransform(FQuat::Identity, -Body1JointOffset);
}
if (ConstraintSetup.bLinearFullyLocked)
{
// Rather than calculate prismatic limits, just lock the transform (1 limit instead of 6)
FAnimPhys::ConstrainPositionNailed(NextTimeStep, LinearLimits, PrevBody, ShapeTransform.GetTranslation(), &RigidBody, Body1JointOffset);
}
else
{
if (ConstraintSetup.LinearXLimitType != AnimPhysLinearConstraintType::Free)
{
FAnimPhys::ConstrainAlongDirection(NextTimeStep, LinearLimits, PrevBody, ShapeTransform.GetTranslation(), &RigidBody, Body1JointOffset, ShapeTransform.GetRotation().GetAxisX(), FVector2D(ConstraintSetup.LinearAxesMin.X, ConstraintSetup.LinearAxesMax.X));
}
if (ConstraintSetup.LinearYLimitType != AnimPhysLinearConstraintType::Free)
{
FAnimPhys::ConstrainAlongDirection(NextTimeStep, LinearLimits, PrevBody, ShapeTransform.GetTranslation(), &RigidBody, Body1JointOffset, ShapeTransform.GetRotation().GetAxisY(), FVector2D(ConstraintSetup.LinearAxesMin.Y, ConstraintSetup.LinearAxesMax.Y));
}
if (ConstraintSetup.LinearZLimitType != AnimPhysLinearConstraintType::Free)
{
FAnimPhys::ConstrainAlongDirection(NextTimeStep, LinearLimits, PrevBody, ShapeTransform.GetTranslation(), &RigidBody, Body1JointOffset, ShapeTransform.GetRotation().GetAxisZ(), FVector2D(ConstraintSetup.LinearAxesMin.Z, ConstraintSetup.LinearAxesMax.Z));
}
}
if (ConstraintSetup.AngularConstraintType == AnimPhysAngularConstraintType::Angular)
{
#if WITH_EDITOR
// Check the ranges are valid when running in the editor, log if something is wrong
if(ConstraintSetup.AngularLimitsMin.X > ConstraintSetup.AngularLimitsMax.X ||
ConstraintSetup.AngularLimitsMin.Y > ConstraintSetup.AngularLimitsMax.Y ||
ConstraintSetup.AngularLimitsMin.Z > ConstraintSetup.AngularLimitsMax.Z)
{
UE_LOG(LogAnimation, Warning, TEXT("AnimDynamics: Min/Max angular limits for bone %s incorrect, at least one min axis value is greater than the corresponding max."), *BoundBone.BoneName.ToString());
}
#endif
// Add angular limits. any limit with 360+ degree range is ignored and left free.
FAnimPhys::ConstrainAngularRange(NextTimeStep, AngularLimits, PrevBody, &RigidBody, ShapeTransform.GetRotation(), ConstraintSetup.TwistAxis, ConstraintSetup.AngularLimitsMin, ConstraintSetup.AngularLimitsMax);
}
else
{
FAnimPhys::ConstrainConeAngle(NextTimeStep, AngularLimits, PrevBody, BoundBoneTransform.GetRotation().GetAxisX(), &RigidBody, FVector(1.0f, 0.0f, 0.0f), ConstraintSetup.ConeAngle);
}
if(PlanarLimits.Num() > 0)
{
for(FAnimPhysPlanarLimit& PlanarLimit : PlanarLimits)
{
FTransform LimitPlaneTransform = PlanarLimit.PlaneTransform;
if(PlanarLimit.DrivingBone.IsValid(BoneContainer))
{
FCompactPoseBoneIndex DrivingBoneIndex = PlanarLimit.DrivingBone.GetCompactPoseIndex(BoneContainer);
LimitPlaneTransform *= MeshBases.GetComponentSpaceTransform(DrivingBoneIndex);// * LimitPlaneTransform;
}
//.........这里部分代码省略.........
示例13: InitPhysics
void FAnimNode_AnimDynamics::InitPhysics(USkeletalMeshComponent* Component, FCSPose<FCompactPose>& MeshBases)
{
// Clear up any existing physics data
TermPhysics();
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
// List of bone indices in the chain.
TArray<int32> ChainBoneIndices;
TArray<FName> ChainBoneNames;
if(ChainEnd.IsValid(BoneContainer))
{
// Add the end of the chain. We have to walk from the bottom upwards to find a chain
// as walking downwards doesn't guarantee a single end point.
ChainBoneIndices.Add(ChainEnd.BoneIndex);
ChainBoneNames.Add(ChainEnd.BoneName);
int32 ParentBoneIndex = BoneContainer.GetParentBoneIndex(ChainEnd.BoneIndex);
// Walk up the chain until we either find the top or hit the root bone
while(ParentBoneIndex != 0)
{
ChainBoneIndices.Add(ParentBoneIndex);
ChainBoneNames.Add(Component->GetBoneName(ParentBoneIndex));
if(ParentBoneIndex == BoundBone.BoneIndex)
{
// Found the top of the chain
break;
}
ParentBoneIndex = BoneContainer.GetParentBoneIndex(ParentBoneIndex);
}
// Bail if we can't find a chain, and let the user know
if(ParentBoneIndex != BoundBone.BoneIndex)
{
UE_LOG(LogAnimation, Error, TEXT("AnimDynamics: Attempted to find bone chain starting at %s and ending at %s but failed."), *BoundBone.BoneName.ToString(), *ChainEnd.BoneName.ToString());
return;
}
}
else
{
// No chain specified, just use the bound bone
ChainBoneIndices.Add(BoundBone.BoneIndex);
ChainBoneNames.Add(BoundBone.BoneName);
}
Bodies.Reserve(ChainBoneIndices.Num());
// Walk backwards here as the chain was discovered in reverse order
for (int32 Idx = ChainBoneIndices.Num() - 1; Idx >= 0; --Idx)
{
TArray<FAnimPhysShape> BodyShapes;
BodyShapes.Add(FAnimPhysShape::MakeBox(BoxExtents));
FBoneReference LinkBoneRef;
LinkBoneRef.BoneName = ChainBoneNames[Idx];
LinkBoneRef.Initialize(BoneContainer);
// Calculate joint offsets by looking at the length of the bones and extending the provided offset
if (BoundBoneReferences.Num() > 0)
{
FTransform CurrentBoneTransform = MeshBases.GetComponentSpaceTransform(LinkBoneRef.GetCompactPoseIndex(BoneContainer));
FTransform PreviousBoneTransform = MeshBases.GetComponentSpaceTransform(BoundBoneReferences.Last().GetCompactPoseIndex(BoneContainer));
FVector PreviousAnchor = PreviousBoneTransform.TransformPosition(-LocalJointOffset);
float DistanceToAnchor = (PreviousBoneTransform.GetTranslation() - CurrentBoneTransform.GetTranslation()).Size() * 0.5f;
if(LocalJointOffset.SizeSquared() < SMALL_NUMBER)
{
// No offset, just use the position between chain links as the offset
// This is likely to just look horrible, but at least the bodies will
// be placed correctly and not stack up at the top of the chain.
JointOffsets.Add(PreviousAnchor - CurrentBoneTransform.GetTranslation());
}
else
{
// Extend offset along chain.
JointOffsets.Add(LocalJointOffset.GetSafeNormal() * DistanceToAnchor);
}
}
else
{
// No chain to worry about, just use the specified offset.
JointOffsets.Add(LocalJointOffset);
}
BoundBoneReferences.Add(LinkBoneRef);
FTransform BodyTransform = MeshBases.GetComponentSpaceTransform(LinkBoneRef.GetCompactPoseIndex(BoneContainer));
BodyTransform.SetTranslation(BodyTransform.GetTranslation() + BodyTransform.GetRotation().RotateVector(-LocalJointOffset));
FAnimPhysLinkedBody NewChainBody(BodyShapes, BodyTransform.GetTranslation(), LinkBoneRef);
FAnimPhysRigidBody& PhysicsBody = NewChainBody.RigidBody.PhysBody;
PhysicsBody.Pose.Orientation = BodyTransform.GetRotation();
PhysicsBody.PreviousOrientation = PhysicsBody.Pose.Orientation;
PhysicsBody.NextOrientation = PhysicsBody.Pose.Orientation;
//.........这里部分代码省略.........
示例14: EvaluateBoneTransforms
void FAnimNode_TwoBoneIK::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
// Get indices of the lower and upper limb bones and check validity.
bool bInvalidLimb = false;
FCompactPoseBoneIndex IKBoneCompactPoseIndex = IKBone.GetCompactPoseIndex(BoneContainer);
const FCompactPoseBoneIndex LowerLimbIndex = BoneContainer.GetParentBoneIndex(IKBoneCompactPoseIndex);
if (LowerLimbIndex == INDEX_NONE)
{
bInvalidLimb = true;
}
const FCompactPoseBoneIndex UpperLimbIndex = BoneContainer.GetParentBoneIndex(LowerLimbIndex);
if (UpperLimbIndex == INDEX_NONE)
{
bInvalidLimb = true;
}
const bool bInBoneSpace = (EffectorLocationSpace == BCS_ParentBoneSpace) || (EffectorLocationSpace == BCS_BoneSpace);
const int32 EffectorBoneIndex = bInBoneSpace ? BoneContainer.GetPoseBoneIndexForBoneName(EffectorSpaceBoneName) : INDEX_NONE;
const FCompactPoseBoneIndex EffectorSpaceBoneIndex = BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(EffectorBoneIndex));
if (bInBoneSpace && (EffectorSpaceBoneIndex == INDEX_NONE))
{
bInvalidLimb = true;
}
// If we walked past the root, this controlled is invalid, so return no affected bones.
if( bInvalidLimb )
{
return;
}
// Get Local Space transforms for our bones. We do this first in case they already are local.
// As right after we get them in component space. (And that does the auto conversion).
// We might save one transform by doing local first...
const FTransform EndBoneLocalTransform = MeshBases.GetLocalSpaceTransform(IKBoneCompactPoseIndex);
// Now get those in component space...
FTransform LowerLimbCSTransform = MeshBases.GetComponentSpaceTransform(LowerLimbIndex);
FTransform UpperLimbCSTransform = MeshBases.GetComponentSpaceTransform(UpperLimbIndex);
FTransform EndBoneCSTransform = MeshBases.GetComponentSpaceTransform(IKBoneCompactPoseIndex);
// Get current position of root of limb.
// All position are in Component space.
const FVector RootPos = UpperLimbCSTransform.GetTranslation();
const FVector InitialJointPos = LowerLimbCSTransform.GetTranslation();
const FVector InitialEndPos = EndBoneCSTransform.GetTranslation();
// Transform EffectorLocation from EffectorLocationSpace to ComponentSpace.
FTransform EffectorTransform(EffectorLocation);
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, EffectorTransform, EffectorSpaceBoneIndex, EffectorLocationSpace);
// This is our reach goal.
FVector DesiredPos = EffectorTransform.GetTranslation();
FVector DesiredDelta = DesiredPos - RootPos;
float DesiredLength = DesiredDelta.Size();
// Check to handle case where DesiredPos is the same as RootPos.
FVector DesiredDir;
if (DesiredLength < (float)KINDA_SMALL_NUMBER)
{
DesiredLength = (float)KINDA_SMALL_NUMBER;
DesiredDir = FVector(1,0,0);
}
else
{
DesiredDir = DesiredDelta / DesiredLength;
}
// Get joint target (used for defining plane that joint should be in).
FTransform JointTargetTransform(JointTargetLocation);
FCompactPoseBoneIndex JointTargetSpaceBoneIndex(INDEX_NONE);
if (JointTargetLocationSpace == BCS_ParentBoneSpace || JointTargetLocationSpace == BCS_BoneSpace)
{
int32 Index = BoneContainer.GetPoseBoneIndexForBoneName(JointTargetSpaceBoneName);
JointTargetSpaceBoneIndex = BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(Index));
}
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, JointTargetTransform, JointTargetSpaceBoneIndex, JointTargetLocationSpace);
FVector JointTargetPos = JointTargetTransform.GetTranslation();
FVector JointTargetDelta = JointTargetPos - RootPos;
float JointTargetLength = JointTargetDelta.Size();
// Same check as above, to cover case when JointTarget position is the same as RootPos.
FVector JointPlaneNormal, JointBendDir;
if (JointTargetLength < (float)KINDA_SMALL_NUMBER)
{
JointBendDir = FVector(0,1,0);
JointPlaneNormal = FVector(0,0,1);
}
else
{
//.........这里部分代码省略.........
示例15: UpdateFromLookAtTarget
void FAnimNode_AimOffsetLookAt::UpdateFromLookAtTarget(FPoseContext& LocalPoseContext)
{
const FBoneContainer& RequiredBones = LocalPoseContext.Pose.GetBoneContainer();
if (RequiredBones.GetSkeletalMeshAsset())
{
const USkeletalMeshSocket* Socket = RequiredBones.GetSkeletalMeshAsset()->FindSocket(SourceSocketName);
if (Socket)
{
const FTransform SocketLocalTransform = Socket->GetSocketLocalTransform();
FBoneReference SocketBoneReference;
SocketBoneReference.BoneName = Socket->BoneName;
SocketBoneReference.Initialize(RequiredBones);
if (SocketBoneReference.IsValid(RequiredBones))
{
const FCompactPoseBoneIndex SocketBoneIndex = SocketBoneReference.GetCompactPoseIndex(RequiredBones);
FCSPose<FCompactPose> GlobalPose;
GlobalPose.InitPose(LocalPoseContext.Pose);
USkeletalMeshComponent* Component = LocalPoseContext.AnimInstanceProxy->GetSkelMeshComponent();
AActor* Actor = Component ? Component->GetOwner() : nullptr;
if (Component && Actor && BlendSpace)
{
const FTransform ActorTransform = Actor->GetTransform();
const FTransform BoneTransform = GlobalPose.GetComponentSpaceTransform(SocketBoneIndex);
const FTransform SocketWorldTransform = SocketLocalTransform * BoneTransform * Component->ComponentToWorld;
// Convert Target to Actor Space
const FTransform TargetWorldTransform(LookAtLocation);
const FVector DirectionToTarget = ActorTransform.InverseTransformVectorNoScale(TargetWorldTransform.GetLocation() - SocketWorldTransform.GetLocation()).GetSafeNormal();
const FVector CurrentDirection = ActorTransform.InverseTransformVectorNoScale(SocketWorldTransform.GetUnitAxis(EAxis::X));
const FVector AxisX = FVector::ForwardVector;
const FVector AxisY = FVector::RightVector;
const FVector AxisZ = FVector::UpVector;
const FVector2D CurrentCoords = FMath::GetAzimuthAndElevation(CurrentDirection, AxisX, AxisY, AxisZ);
const FVector2D TargetCoords = FMath::GetAzimuthAndElevation(DirectionToTarget, AxisX, AxisY, AxisZ);
const FVector BlendInput(
FRotator::NormalizeAxis(FMath::RadiansToDegrees(TargetCoords.X - CurrentCoords.X)),
FRotator::NormalizeAxis(FMath::RadiansToDegrees(TargetCoords.Y - CurrentCoords.Y)),
0.f);
// Set X and Y, so ticking next frame is based on correct weights.
X = BlendInput.X;
Y = BlendInput.Y;
// Generate BlendSampleDataCache from inputs.
BlendSpace->GetSamplesFromBlendInput(BlendInput, BlendSampleDataCache);
if (CVarAimOffsetLookAtDebug.GetValueOnAnyThread() == 1)
{
DrawDebugLine(Component->GetWorld(), SocketWorldTransform.GetLocation(), TargetWorldTransform.GetLocation(), FColor::Green);
DrawDebugLine(Component->GetWorld(), SocketWorldTransform.GetLocation(), SocketWorldTransform.GetLocation() + SocketWorldTransform.GetUnitAxis(EAxis::X) * (TargetWorldTransform.GetLocation() - SocketWorldTransform.GetLocation()).Size(), FColor::Red);
DrawDebugCoordinateSystem(Component->GetWorld(), ActorTransform.GetLocation(), ActorTransform.GetRotation().Rotator(), 100.f);
FString DebugString = FString::Printf(TEXT("Socket (X:%f, Y:%f), Target (X:%f, Y:%f), Result (X:%f, Y:%f)")
, FMath::RadiansToDegrees(CurrentCoords.X)
, FMath::RadiansToDegrees(CurrentCoords.Y)
, FMath::RadiansToDegrees(TargetCoords.X)
, FMath::RadiansToDegrees(TargetCoords.Y)
, BlendInput.X
, BlendInput.Y);
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 0.f, FColor::Red, DebugString, false);
}
}
}
}
}
}