本文整理汇总了C++中FA2CSPose::GetComponentSpaceTransform方法的典型用法代码示例。如果您正苦于以下问题:C++ FA2CSPose::GetComponentSpaceTransform方法的具体用法?C++ FA2CSPose::GetComponentSpaceTransform怎么用?C++ FA2CSPose::GetComponentSpaceTransform使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类FA2CSPose
的用法示例。
在下文中一共展示了FA2CSPose::GetComponentSpaceTransform方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: EvaluateBoneTransforms
void FAnimNode_HandIKRetargeting::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
checkSlow(OutBoneTransforms.Num() == 0);
// Get component space transforms for all of our IK and FK bones.
FTransform const RightHandFKTM = MeshBases.GetComponentSpaceTransform(RightHandFK.BoneIndex);
FTransform const LeftHandFKTM = MeshBases.GetComponentSpaceTransform(LeftHandFK.BoneIndex);
FTransform const RightHandIKTM = MeshBases.GetComponentSpaceTransform(RightHandIK.BoneIndex);
FTransform const LeftHandIKTM = MeshBases.GetComponentSpaceTransform(LeftHandIK.BoneIndex);
// 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 (int32 BoneIndex = 0; BoneIndex < IKBonesToMove.Num(); BoneIndex++)
{
FBoneReference const & BoneReference = IKBonesToMove[BoneIndex];
if (BoneReference.IsValid(RequiredBones))
{
FTransform BoneTransform = MeshBases.GetComponentSpaceTransform(BoneReference.BoneIndex);
BoneTransform.AddToTranslation(IK_To_FK_Translation);
OutBoneTransforms.Add(FBoneTransform(BoneReference.BoneIndex, BoneTransform));
}
}
}
}
示例2: EvaluateBoneTransforms
void FAnimNode_CopyBone::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer & RequiredBones, FA2CSPose& 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.
FTransform SourceBoneTM = MeshBases.GetComponentSpaceTransform(SourceBone.BoneIndex);
FTransform CurrentBoneTM = MeshBases.GetComponentSpaceTransform(TargetBone.BoneIndex);
// Copy individual components
if (bCopyTranslation)
{
CurrentBoneTM.SetTranslation( SourceBoneTM.GetTranslation() );
}
if (bCopyRotation)
{
CurrentBoneTM.SetRotation( SourceBoneTM.GetRotation() );
}
if (bCopyScale)
{
CurrentBoneTM.SetScale3D( SourceBoneTM.GetScale3D() );
}
// Output new transform for current bone.
OutBoneTransforms.Add( FBoneTransform(TargetBone.BoneIndex, CurrentBoneTM) );
}
示例3: GetBoneTransformByName
FTransform UPoseableMeshComponent::GetBoneTransformByName(FName BoneName, EBoneSpaces::Type BoneSpace)
{
if( !SkeletalMesh || !RequiredBones.IsValid() )
{
return FTransform();
}
int32 BoneIndex = GetBoneIndex(BoneName);
if( BoneIndex == INDEX_NONE)
{
FString Message = FString::Printf(TEXT("Invalid Bone Name '%s'"), *BoneName.ToString());
FFrame::KismetExecutionMessage(*Message, ELogVerbosity::Warning);
return FTransform();
}
/*if(BoneSpace == EBoneSpaces::LocalSpace)
{
return LocalAtoms[i];
}*/
FA2CSPose CSPose;
CSPose.AllocateLocalPoses(RequiredBones, LocalAtoms);
if(BoneSpace == EBoneSpaces::ComponentSpace)
{
return CSPose.GetComponentSpaceTransform(BoneIndex);
}
else
{
return CSPose.GetComponentSpaceTransform(BoneIndex) * ComponentToWorld;
}
}
示例4: ConvertCSRotationToBoneSpace
FQuat UAnimGraphNode_SkeletalControlBase::ConvertCSRotationToBoneSpace(const USkeletalMeshComponent* SkelComp, FRotator& InCSRotator, FA2CSPose& MeshBases, const FName& BoneName, const EBoneControlSpace Space)
{
FQuat OutQuat = FQuat::Identity;
if (MeshBases.IsValid())
{
int32 MeshBoneIndex = SkelComp->GetBoneIndex(BoneName);
FVector RotAxis;
float RotAngle;
InCSRotator.Quaternion().ToAxisAndAngle(RotAxis, RotAngle);
switch (Space)
{
// World Space, no change in preview window
case BCS_WorldSpace:
case BCS_ComponentSpace:
// Component Space, no change.
OutQuat = InCSRotator.Quaternion();
break;
case BCS_ParentBoneSpace:
{
const int32 ParentIndex = MeshBases.GetParentBoneIndex(MeshBoneIndex);
if (ParentIndex != INDEX_NONE)
{
FTransform ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
ParentTM = ParentTM.Inverse();
//Calculate the new delta rotation
FVector4 BoneSpaceAxis = ParentTM.TransformVector(RotAxis);
FQuat DeltaQuat(BoneSpaceAxis, RotAngle);
DeltaQuat.Normalize();
OutQuat = DeltaQuat;
}
}
break;
case BCS_BoneSpace:
{
FTransform BoneTM = MeshBases.GetComponentSpaceTransform(MeshBoneIndex);
BoneTM = BoneTM.Inverse();
FVector4 BoneSpaceAxis = BoneTM.TransformVector(RotAxis);
//Calculate the new delta rotation
FQuat DeltaQuat(BoneSpaceAxis, RotAngle);
DeltaQuat.Normalize();
OutQuat = DeltaQuat;
}
break;
}
}
return OutQuat;
}
示例5: SetBoneTransformByName
void UPoseableMeshComponent::SetBoneTransformByName(FName BoneName, const FTransform& InTransform, EBoneSpaces::Type BoneSpace)
{
if( !SkeletalMesh || !RequiredBones.IsValid() )
{
return;
}
int32 BoneIndex = GetBoneIndex(BoneName);
if(BoneIndex >=0 && BoneIndex < LocalAtoms.Num())
{
LocalAtoms[BoneIndex] = InTransform;
// If we haven't requested local space we need to transform the position passed in
//if(BoneSpace != EBoneSpaces::LocalSpace)
{
if(BoneSpace == EBoneSpaces::WorldSpace)
{
LocalAtoms[BoneIndex].SetToRelativeTransform(GetComponentToWorld());
}
int32 ParentIndex = RequiredBones.GetParentBoneIndex(BoneIndex);
if(ParentIndex >=0)
{
FA2CSPose CSPose;
CSPose.AllocateLocalPoses(RequiredBones, LocalAtoms);
LocalAtoms[BoneIndex].SetToRelativeTransform(CSPose.GetComponentSpaceTransform(ParentIndex));
}
// Need to send new state to render thread
MarkRenderDynamicDataDirty();
}
}
}
示例6: EvaluateBoneTransforms
void FAnimNode_RotationMultiplier::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer & RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
if ( Multiplier != 0.f )
{
// Reference bone
const TArray<FTransform> & LocalRefPose = RequiredBones.GetRefPoseArray();
const FQuat RefQuat = LocalRefPose[TargetBone.BoneIndex].GetRotation();
FQuat NewQuat;
MultiplyQuatBasedOnSourceIndex(LocalRefPose, MeshBases, RotationAxisToRefer, SourceBone.BoneIndex, Multiplier, RefQuat, NewQuat);
FTransform NewLocalTransform = MeshBases.GetLocalSpaceTransform(TargetBone.BoneIndex);
NewLocalTransform.SetRotation(NewQuat);
const int32 ParentIndex = RequiredBones.GetParentBoneIndex(TargetBone.BoneIndex);
if( ParentIndex != INDEX_NONE )
{
const FTransform ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
FTransform NewTransform = NewLocalTransform * ParentTM;
OutBoneTransforms.Add( FBoneTransform(TargetBone.BoneIndex, NewTransform) );
}
else
{
OutBoneTransforms.Add( FBoneTransform(TargetBone.BoneIndex, NewLocalTransform) );
}
}
}
示例7: EvaluateBoneTransforms
void FAnimNode_WheelHandler::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
for(const auto & WheelSim : WheelSimulators)
{
if(WheelSim.BoneReference.IsValid(RequiredBones))
{
// 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(WheelSim.BoneReference.BoneIndex);
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, WheelSim.BoneReference.BoneIndex, BCS_ComponentSpace);
// Apply rotation offset
const FQuat BoneQuat(WheelSim.RotOffset);
NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
// Apply loc offset
NewBoneTM.AddToTranslation(WheelSim.LocOffset);
// Convert back to Component Space.
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, WheelSim.BoneReference.BoneIndex, BCS_ComponentSpace);
// add back to it
OutBoneTransforms.Add( FBoneTransform(WheelSim.BoneReference.BoneIndex, NewBoneTM) );
}
}
}
示例8: ConvertWidgetLocation
FVector UAnimGraphNode_SkeletalControlBase::ConvertWidgetLocation(const USkeletalMeshComponent* SkelComp, FA2CSPose& MeshBases, const FName& BoneName, const FVector& Location, const EBoneControlSpace Space)
{
FVector WidgetLoc = FVector::ZeroVector;
if (MeshBases.IsValid())
{
USkeleton * Skeleton = SkelComp->SkeletalMesh->Skeleton;
int32 MeshBoneIndex = SkelComp->GetBoneIndex(BoneName);
switch (Space)
{
// ComponentToWorld must be Identity in preview window so same as ComponentSpace
case BCS_WorldSpace:
case BCS_ComponentSpace:
{
// Component Space, no change.
WidgetLoc = Location;
}
break;
case BCS_ParentBoneSpace:
if (MeshBoneIndex != INDEX_NONE)
{
const int32 MeshParentIndex = MeshBases.GetParentBoneIndex(MeshBoneIndex);
if (MeshParentIndex != INDEX_NONE)
{
const FTransform ParentTM = MeshBases.GetComponentSpaceTransform(MeshParentIndex);
WidgetLoc = ParentTM.TransformPosition(Location);
}
}
break;
case BCS_BoneSpace:
if (MeshBoneIndex != INDEX_NONE)
{
FTransform BoneTM = MeshBases.GetComponentSpaceTransform(MeshBoneIndex);
WidgetLoc = BoneTM.TransformPosition(Location);
}
}
}
return WidgetLoc;
}
示例9: EvaluateBoneTransforms
void FAnimNode_LookAt::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
FTransform ComponentBoneTransform = MeshBases.GetComponentSpaceTransform(BoneToModify.BoneIndex);
// get target location
FVector TargetLocationInComponentSpace;
if (LookAtBone.IsValid(RequiredBones))
{
FTransform LookAtTransform = MeshBases.GetComponentSpaceTransform(LookAtBone.BoneIndex);
TargetLocationInComponentSpace = LookAtTransform.GetLocation();
}
else
{
TargetLocationInComponentSpace = SkelComp->ComponentToWorld.InverseTransformPosition(LookAtLocation);
}
CurrentLookAtLocation = TargetLocationInComponentSpace;
// 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;
}
// get delta rotation
FQuat DeltaRot = FQuat::FindBetween(LookAtVector, ToTarget);
// transform current rotation to delta rotation
FQuat CurrentRot = ComponentBoneTransform.GetRotation();
FQuat NewRotation = DeltaRot * CurrentRot;
ComponentBoneTransform.SetRotation(NewRotation);
OutBoneTransforms.Add( FBoneTransform(BoneToModify.BoneIndex, ComponentBoneTransform) );
}
示例10: ConvertCSVectorToBoneSpace
FVector UAnimGraphNode_SkeletalControlBase::ConvertCSVectorToBoneSpace(const USkeletalMeshComponent* SkelComp, FVector& InCSVector, FA2CSPose& MeshBases, const FName& BoneName, const EBoneControlSpace Space)
{
FVector OutVector = InCSVector;
if (MeshBases.IsValid())
{
int32 MeshBoneIndex = SkelComp->GetBoneIndex(BoneName);
switch (Space)
{
// World Space, no change in preview window
case BCS_WorldSpace:
case BCS_ComponentSpace:
// Component Space, no change.
break;
case BCS_ParentBoneSpace:
{
const int32 ParentIndex = MeshBases.GetParentBoneIndex(MeshBoneIndex);
if (ParentIndex != INDEX_NONE)
{
FTransform ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
OutVector = ParentTM.InverseTransformVector(InCSVector);
}
}
break;
case BCS_BoneSpace:
{
FTransform BoneTM = MeshBases.GetComponentSpaceTransform(MeshBoneIndex);
OutVector = BoneTM.InverseTransformVector(InCSVector);
}
break;
}
}
return OutVector;
}
示例11: EvaluateBoneTransforms
void FAnimNode_Trail::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& 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.
int32 WalkBoneIndex = TrailBone.BoneIndex;
TArray<int32> 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 = RequiredBones.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++)
{
int32 ChildIndex = ChainBoneIndices[i];
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()->GetActorRotation(), 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.
int32 RootIndex = ChainBoneIndices[0];
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.
int32 ParentIndex = ChainBoneIndices[i-1];
FVector ParentPos = TrailBoneLocations[i-1];
FVector ParentAnimPos = MeshBases.GetComponentSpaceTransform(ParentIndex).GetTranslation();
// Child bone position in component space.
int32 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: GetSpaceTransform
FTransform FAnimationRuntime::GetSpaceTransform(FA2CSPose& Pose, int32 Index)
{
return Pose.GetComponentSpaceTransform(Index);
}
示例13: 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
// Non retargeted pose.
NonRetargetedSpaceBases.Empty();
if( bDisplayNonRetargetedPose && AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid() )
{
TArray<FTransform> BackupSpaceBases = SpaceBases;
AnimScriptInstance->RequiredBones.SetDisableRetargeting(true);
Super::RefreshBoneTransforms(NULL);
AnimScriptInstance->RequiredBones.SetDisableRetargeting(false);
NonRetargetedSpaceBases = SpaceBases;
SpaceBases = BackupSpaceBases;
}
if( bDisplayRawAnimation )
{
// save the transform in CompressedSpaceBases
CompressedSpaceBases = SpaceBases;
// use raw data now
if( AnimScriptInstance && AnimScriptInstance->RequiredBones.IsValid() )
{
AnimScriptInstance->RequiredBones.SetUseRAWData(true);
Super::RefreshBoneTransforms(NULL);
AnimScriptInstance->RequiredBones.SetUseRAWData(false);
}
// Otherwise we'll just get ref pose.
else
{
Super::RefreshBoneTransforms(NULL);
}
}
else
{
CompressedSpaceBases.Empty();
}
const bool bIsPreviewInstance = (PreviewInstance && PreviewInstance == AnimScriptInstance);
// 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())
{
AdditiveBasePoses.AddUninitialized(PreviewInstance->RequiredBones.GetNumBones());
Sequence->GetAdditiveBasePose(AdditiveBasePoses, PreviewInstance->RequiredBones, FAnimExtractContext(PreviewInstance->CurrentTime));
FA2CSPose CSPose;
CSPose.AllocateLocalPoses(AnimScriptInstance->RequiredBones, AdditiveBasePoses);
for(int32 i=0; i<AdditiveBasePoses.Num(); ++i)
{
AdditiveBasePoses[i] = CSPose.GetComponentSpaceTransform(i);
}
}
}
}
}
示例14: EvaluateBoneTransforms
void FAnimNode_SpringBone::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
check(OutBoneTransforms.Num() == 0);
// Location of our bone in world space
FTransform SpaceBase = MeshBases.GetComponentSpaceTransform(SpringBone.BoneIndex);
FTransform BoneTransformInWorldSpace = (SkelComp != NULL) ? SpaceBase * SkelComp->GetComponentToWorld() : SpaceBase;
FVector const TargetPos = BoneTransformInWorldSpace.GetLocation();
AActor* SkelOwner = (SkelComp != NULL) ? SkelComp->GetOwner() : NULL;
if ((SkelComp != NULL) && (SkelComp->AttachParent != NULL) && (SkelOwner == NULL))
{
SkelOwner = SkelComp->AttachParent->GetOwner();
}
// Init values first time
if (RemainingTime == 0.0f)
{
BoneLocation = TargetPos;
BoneVelocity = FVector::ZeroVector;
}
while (RemainingTime > FixedTimeStep)
{
// Update location of our base by how much our base moved this frame.
FVector const BaseTranslation = SkelOwner ? (SkelOwner->GetVelocity() * FixedTimeStep) : FVector::ZeroVector;
BoneLocation += BaseTranslation;
// Reinit values if outside reset threshold
if (((TargetPos - BoneLocation).SizeSquared() > (ErrorResetThresh*ErrorResetThresh)))
{
BoneLocation = TargetPos;
BoneVelocity = FVector::ZeroVector;
}
// Calculate error vector.
FVector const Error = (TargetPos - BoneLocation);
FVector const DampingForce = SpringDamping * BoneVelocity;
FVector const SpringForce = SpringStiffness * Error;
// Calculate force based on error and vel
FVector const Acceleration = SpringForce - DampingForce;
// Integrate velocity
// Make sure damping with variable frame rate actually dampens velocity. Otherwise Spring will go nuts.
float const CutOffDampingValue = 1.f/FixedTimeStep;
if (SpringDamping > CutOffDampingValue)
{
float const SafetyScale = CutOffDampingValue / SpringDamping;
BoneVelocity += SafetyScale * (Acceleration * FixedTimeStep);
}
else
{
BoneVelocity += (Acceleration * FixedTimeStep);
}
// Clamp velocity to something sane (|dX/dt| <= ErrorResetThresh)
float const BoneVelocityMagnitude = BoneVelocity.Size();
if (BoneVelocityMagnitude * FixedTimeStep > ErrorResetThresh)
{
BoneVelocity *= (ErrorResetThresh / (BoneVelocityMagnitude * FixedTimeStep));
}
// Integrate position
FVector const OldBoneLocation = BoneLocation;
FVector const DeltaMove = (BoneVelocity * FixedTimeStep);
BoneLocation += DeltaMove;
// Force z to be correct if desired
if (bNoZSpring)
{
BoneLocation.Z = TargetPos.Z;
}
// If desired, limit error
if (bLimitDisplacement)
{
FVector CurrentDisp = BoneLocation - TargetPos;
// Too far away - project back onto sphere around target.
if (CurrentDisp.Size() > MaxDisplacement)
{
FVector DispDir = CurrentDisp.GetSafeNormal();
BoneLocation = TargetPos + (MaxDisplacement * DispDir);
}
}
// Update velocity to reflect post processing done to bone location.
BoneVelocity = (BoneLocation - OldBoneLocation) / FixedTimeStep;
check( !BoneLocation.ContainsNaN() );
check( !BoneVelocity.ContainsNaN() );
RemainingTime -= FixedTimeStep;
}
// Now convert back into component space and output - rotation is unchanged.
FTransform OutBoneTM = SpaceBase;
OutBoneTM.SetLocation( SkelComp->GetComponentToWorld().InverseTransformPosition(BoneLocation) );
//.........这里部分代码省略.........
示例15: EvaluateBoneTransforms
void FAnimNode_Fabrik::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, const FBoneContainer& RequiredBones, FA2CSPose& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
// IsValidToEvaluate validated our inputs, we don't need to check pre-requisites again.
int32 const RootIndex = RootBone.BoneIndex;
// Update EffectorLocation if it is based off a bone position
FTransform CSEffectorTransform = FTransform(EffectorTransform);
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, CSEffectorTransform, EffectorTransformBone.BoneIndex, EffectorTransformSpace);
FVector const CSEffectorLocation = CSEffectorTransform.GetLocation();
// @fixme - we need better to draw widgets and debug information in editor.
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (bEnableDebugDraw)
{
// Show end effector position.
DrawDebugBox(SkelComp->GetWorld(), CSEffectorLocation, FVector(Precision), FColor::Green, true, 0.1f);
DrawDebugCoordinateSystem(SkelComp->GetWorld(), CSEffectorLocation, CSEffectorTransform.GetRotation().Rotator(), 5.f, true, 0.1f);
}
#endif
// Gather all bone indices between root and tip.
TArray<int32> BoneIndices;
{
int32 BoneIndex = TipBone.BoneIndex;
do
{
BoneIndices.Insert(BoneIndex, 0);
BoneIndex = RequiredBones.GetParentBoneIndex(BoneIndex);
} while (BoneIndex != RootIndex);
BoneIndices.Insert(BoneIndex, 0);
}
// Maximum length of skeleton segment at full extension
float MaximumReach = 0;
// Gather transforms
int32 const NumTransforms = BoneIndices.Num();
OutBoneTransforms.AddUninitialized(NumTransforms);
// Gather chain links. These are non zero length bones.
TArray<FABRIKChainLink> Chain;
Chain.Reserve(NumTransforms);
// Start with Root Bone
{
int32 const & RootBoneIndex = BoneIndices[0];
FTransform const BoneCSTransform = MeshBases.GetComponentSpaceTransform(RootBoneIndex);
OutBoneTransforms[0] = FBoneTransform(RootBoneIndex, BoneCSTransform);
Chain.Add(FABRIKChainLink(BoneCSTransform.GetLocation(), 0.f, RootBoneIndex, 0));
}
// Go through remaining transforms
for (int32 TransformIndex = 1; TransformIndex < NumTransforms; TransformIndex++)
{
int32 const & BoneIndex = BoneIndices[TransformIndex];
FTransform const BoneCSTransform = MeshBases.GetComponentSpaceTransform(BoneIndex);
FVector const BoneCSPosition = BoneCSTransform.GetLocation();
OutBoneTransforms[TransformIndex] = FBoneTransform(BoneIndex, BoneCSTransform);
// Calculate the combined length of this segment of skeleton
float const BoneLength = FVector::Dist(BoneCSPosition, OutBoneTransforms[TransformIndex-1].Transform.GetLocation());
if (!FMath::IsNearlyZero(BoneLength))
{
Chain.Add(FABRIKChainLink(BoneCSPosition, BoneLength, BoneIndex, TransformIndex));
MaximumReach += BoneLength;
}
else
{
// Mark this transform as a zero length child of the last link.
// It will inherit position and delta rotation from parent link.
FABRIKChainLink & ParentLink = Chain[Chain.Num()-1];
ParentLink.ChildZeroLengthTransformIndices.Add(TransformIndex);
}
}
bool bBoneLocationUpdated = false;
float const RootToTargetDist = FVector::Dist(Chain[0].Position, CSEffectorLocation);
int32 const NumChainLinks = Chain.Num();
// FABRIK algorithm - bone translation calculation
// If the effector is further away than the distance from root to tip, simply move all bones in a line from root to effector location
if (RootToTargetDist > MaximumReach)
{
for (int32 LinkIndex = 1; LinkIndex < NumChainLinks; LinkIndex++)
{
FABRIKChainLink const & ParentLink = Chain[LinkIndex - 1];
FABRIKChainLink & CurrentLink = Chain[LinkIndex];
CurrentLink.Position = ParentLink.Position + (CSEffectorLocation - ParentLink.Position).GetUnsafeNormal() * CurrentLink.Length;
}
bBoneLocationUpdated = true;
}
else // Effector is within reach, calculate bone translations to position tip at effector location
{
int32 const TipBoneLinkIndex = NumChainLinks - 1;
// Check distance between tip location and effector location
float Slop = FVector::Dist(Chain[TipBoneLinkIndex].Position, CSEffectorLocation);
//.........这里部分代码省略.........