x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Calculating local space position from reference pose on animated mesh

I'm not very good at geometry functions so I'm hoping to get some help here. Thanks in advance.

I'm trying to calculate the local(preskinned) position of a hit on a skeletal mesh. Now if the mesh is locked in its default, reference pose, all I have to do is subtract the ComponentTransform of the skeletal mesh from the ImpactPoint, and I can feed the result directly to my material and it will work well. However, I'm not sure how to get to the same result if the mesh is being animated.

I know I can access the reference skeleton, however, the locations of ref bones are all relative to their parent bone, as opposed to being relative to the skeletal mesh's root transform. GetBoneTransform() returns the bone's location relative to the root, which is something I could work with, however, I'm not sure what to do with the reference bones. Different approaches that I've tried yielded incorrect results, including the one described via this link.

According to the aforementioned article, this should have worked:

 FTransform SocketTransformWorld = SkeletalMesh->GetSocketTransform(ImpactResult.BoneName, ERelativeTransformSpace::RTS_World);
 FReferenceSkeleton RefSkeleton = SkeletalMesh->SkeletalMesh->RefSkeleton;
 FTransform RefPoseTransform = RefSkeleton.GetRefBonePose()[RefSkeleton.FindBoneIndex(ImpactResult.BoneName)];
 FVector InverseTransformPosition = SocketTransformWorld.InverseTransformPosition(ImpactResult.ImpactPoint);
 FVector RefPoseInverseTransformPosition = RefPoseTransform.TransformPosition(InverseTransformPosition);

Except it doesn't. The final transformed position is not relative to the root bone. So either I'm doing something wrong, or the author forgot to mention something crucial.

Either way, any help would be appreciated, and thanks again.

Product Version: UE 4.18
Tags:
more ▼

asked Mar 24 '18 at 08:07 PM in Using UE4

avatar image

Visor90
33 1 3 6

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Hi Visor, I have read the same tutorial by Tom Looman.

In my project GetRefBonePose() return position relative to the parent bone, so I made a recursive function to have results relative to world origin.

 // .h
 // static FTransform GetWorldSpaceTransform(FReferenceSkeleton RefSkel, int32 BoneIdx);
 // .cpp
 FTransform USurvivalFunctionLibrary::GetWorldSpaceTransform(FReferenceSkeleton RefSkel, int32 BoneIdx)
 {
     FTransform BoneTransform;
 
     if (BoneIdx > 0)
     {
         BoneTransform = RefSkel.GetRefBonePose()[BoneIdx];
 
         FMeshBoneInfo BoneInfo = RefSkel.GetRefBoneInfo()[BoneIdx];
         if (BoneInfo.ParentIndex != 0)
         {
             BoneTransform *= GetWorldSpaceTransform(RefSkel, BoneInfo.ParentIndex);
         }
     }
 
     return BoneTransform;
 }
 
 // .h
 // UFUNCTION(BlueprintCallable, Category = "BPLibrary")
 // static FTransform GetRefPoseBoneTransform(USkeletalMeshComponent* SkelMesh, FName BoneName);
 // .cpp
 FTransform USurvivalFunctionLibrary::GetRefPoseBoneTransform(USkeletalMeshComponent* SkelMesh, FName BoneName)
 {
     FTransform BoneTransform;
 
     if (SkelMesh && !BoneName.IsNone())
     {
         SkelMesh->ClearRefPoseOverride();
         FReferenceSkeleton RefSkel;
         RefSkel = SkelMesh->SkeletalMesh->RefSkeleton;
 
         BoneTransform = GetWorldSpaceTransform(RefSkel, RefSkel.FindBoneIndex(BoneName));
     }
 
     return BoneTransform;
 }
 
 // .h
 // UFUNCTION(BlueprintCallable, Category = "BPLibrary")
 // static FTransform GetBoneTransform(USkeletalMeshComponent* SkelMesh, FName BoneName);
 // .cpp
 FTransform USurvivalFunctionLibrary::GetBoneTransform(USkeletalMeshComponent* SkelMesh, FName BoneName)
 {
     FTransform BoneTransform;
 
     if (SkelMesh && !BoneName.IsNone())
     {
         FReferenceSkeleton RefSkel;
         RefSkel = SkelMesh->SkeletalMesh->RefSkeleton;
         BoneTransform = SkelMesh->GetBoneTransform(RefSkel.FindBoneIndex(BoneName));
     }
 
     return BoneTransform;
 }

more ▼

answered Jun 18 '18 at 09:14 AM

avatar image

NomadMonkey
106 1 5 5

avatar image Visor90 Jun 19 '18 at 03:38 PM

Thanks for taking the time to answer. Though it's been 3 months since I posted the question and I've managed to figure out a solution on my own since then. It's pretty much the same as yours except it's caching all the positions instead of calculating them on the fly, to increase efficiency. Have an upvote nonetheless!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question