Finding bone-local transforms

I answered this myself already - I’m posting it in case somebody might arrive here from a web search on a similar problem. I was manipulating bones through the interface in UPoseableMeshComponent. Many of the functions give you a EBoneSpaces::Type container, but the only choice for it are world space, and component space. There’s no bone space, which to me is the most common thing to want!

I did not find any solution in the documentation, and didn’t turn up much on this site either. After scouring the UE4 source code, I came up with this, to arrive at a component-relative bone transform, which you can use as the basis for further bone-relative manipulations. It only handles rotation, but you could extend it to translation easily. There could be a better way to do this, but if so, I never found it.

So here you go, future google-arriving person:

   FQuat boneToComponent(FQuat::Identity);

   if (Mesh != nullptr && Mesh->SkeletalMesh != nullptr) {
      uint32 boneidx = Mesh->GetBoneIndex(BoneName);
      const FReferenceSkeleton& refskel(Mesh->SkeletalMesh->RefSkeleton);

      while (boneidx != INDEX_NONE) {
         boneToComponent = refskel.GetRefBonePose()[boneidx].GetRotation() * boneToComponent;
         boneidx = refskel.GetParentIndex(boneidx);
      }
   }

You can then quat-mul on your own transforms and set the bone’s new position, which you have to do by getting a rotator out of the quaternion, since there’s no SetBoneQuaternionByName:

  const FQuat localRot = boneToComponent * my_quaternion;
  Mesh->SetBoneRotationByName(BoneName, localRot.Rotator(), EBoneSpaces::ComponentSpace);

For future google-arriving persons: in version 4.21, FAnimationRuntime::GetComponentSpaceTransformRefPose does something similar.