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(); } } }
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; } }
void FAnimNode_KinectV2Retarget::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms) { uint8 i = 0; if (!KinectBody.bIsTracked) { return; } const FBoneContainer BoneContainer = MeshBases.GetPose().GetBoneContainer(); FA2CSPose TempPose; TempPose.AllocateLocalPoses(BoneContainer, SkelComp->LocalAtoms); for (auto Bone : KinectBody.KinectBones) { if (BonesToRetarget[i].IsValid(BoneContainer)) { auto DeltaTranform = Bone.MirroredJointTransform.GetRelativeTransform(SkelComp->GetBoneTransform(0)); //AxisMeshes[Bone.JointTypeEnd]->SetRelativeLocation(PosableMesh->GetBoneLocationByName(RetargetBoneNames[Bone.JointTypeEnd], EBoneSpaces::ComponentSpace)); auto BoneBaseTransform = DeltaTranform*SkelComp->GetBoneTransform(0); FRotator PreAdjusmentRotator = BoneBaseTransform.Rotator(); FRotator PostBoneDirAdjustmentRotator = (BoneAdjustments[Bone.JointTypeEnd].BoneDirAdjustment.Quaternion()*PreAdjusmentRotator.Quaternion()).Rotator(); 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; } }
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); } } } } }