copy bone rotations between two skeletons

I want to copy bone rotations between two skeletons. But since the initial transforms of the bones are different, just using the “Get Socket Transform” node and the “Transform Bone” don’t work, I think I need some transformations here, but I am not sure how to do that, can anyone give me some ideas?

Hi fengkan,

Can you provide some more information?

Do you want to apply the same amount of rotation from A to B, or do you want, for instance, the left arm of B to point in the same direction of A in world/component space?
Are the bone axes the same between the two skeletons?

Hi, gryphen_76, thank you for your reply.

I want A and B can make the same pose during the animation. I wish this will be clearer. And I am afraid the axes are not same between the two skeletons.

The most important thing for any type of retargeting is to make sure the skeletons have the same bone axes.

It’s really complex and costly (performance-wise) to convert the rotations when the bone axes aren’t the same. It’s a lot of extra calculations done each frame. I would highly recommend just changing the bone orientations in your content creation tool so they are the same.

Generally speaking, what you want to do is get the local rotation from bone A, rotate it so it matches the bone orientation of skeleton B, then apply it.

To get local rotation, which is actually the offset from the reference pose, you’ll need to store the reference pose rotation (I do this in the Construction Script), then get the delta between that and it’s current rotation in parent-bone space.

To convert that local rotation to the other bone, you’ll need to know which axes are which. Does the X rotation (usually twist) of the source bone go to the Y or Z axis of the target bone? The engine doesn’t know, and while there may be a way to have it guess, it’s not going to be perfect. So you would have to specify, for each bone that you want to copy, how to rotate the rotation value to apply it correctly on the target bone.

Thank you for the detailed explanation, gryphen_76, that’s very helpful.

Please let me make sure I understand you clearly.

In the source animation:

  1. In the Construction Script, “Get Socket Rotation” of every bone and save them as initial rotation.
  2. In the Event Tick, “Get Socket Rotation” and get the delta rotation by comparing with initial rotation.

In the target animation:

  1. Get the delta rotation from the source, and break the rotation into yaw, pitch, and roll.
  2. Remake the rotation according to the axis mapping of the bones.
  3. Set the rotation with “Transform Bone".

Is this right? I wish I have got your point.

I will look into changing the bone orientations, but I think that will take some time, so I prefer solving this in the UE side first.

Another thing on my mind is that since the retargeting of anim sequence between the two skeletons seems to be fine, does it mean the engine just makes a guess about the bone axes mapping? I have attached some pics to show the difference.

I think I missed

  1. In the Construction Script, “Get Socket Rotation” of every bone and save them as initial rotation.

of the target animation. We need the initial rotation to apply the delta.

It looks like you understand my idea fine. :slight_smile:

Regarding the retargeting of animations, that’s what the rig handles. It essentially rotates each bone of the target the same way the source rotates. While it may not convert to local space to apply the converted rotation, it still uses the offset from the reference rotation to know how to do it.

I haven’t found any BP nodes that allow you to get reference rotation, although it’s really easy to do in code.

edit: Oh and you’re going to need to set the reference poses as close to the same as possible since all this is based on the reference pose.

Hi, gryphen_76, I intended to post after getting some result, but I haven’t got anything satisfying yet. But your explanation clarifies things a lot for me, thank you.

If I understand right, you need to traverse the bone hierarchy and copy the parent bone rotations from source skeleton to target skeleton.

If you are using different skeletons, each starting bone orientation may be different.
E.g. the standard epic skeleton has x pointing down one arm and up the other.

So you will have to take that into account and convert source rotation into target bone orientation.

Recommend doing this in code.

Hi, OptimisticMonkey, thank you.

One thing that I am still not clear is actually the way to convert rotation.
In the case below, if I get the deltaXYZ from src, and initTgtXYZ from the reference pose of target skeleton,
can I use tgtX = initTgtX + deltaX, tgtY = initTgtY - deltaY, tgtX = initTgtZ - deltaZ
because the Xs are pointing the same way, and YZ are opposite?

Hi fengkan,

To convert that rotation from source to target you would delta the src.deltaXYZrotator 180 on X (Roll). That assumes that the difference is exactly 180 degrees on X between the source and target bones though.

So I’ve been thinking about it more, and think it might be easier using component space (although doing it in code is the best way).

  1. Make sure the root bones of both source and target skeletons have the same orientation.
  2. Store the reference rotations of the source skeleton as component space rotations.
  3. Get the delta from reference rotation for the source bone.
  4. Apply that rotation to the target bone in component space.

And as a side note, using the Character BP to set bone positions will result in the target skeleton being 1 frame behind the source skeleton’s animation.

Hi, gryphen_76, I appreciate your answers as always. I am trying to converting using component space.

One thing I want to make sure is that to delta the src.deltaXYZrotator 180 on X, should I combine the src.deltaXYZrotator with another rotator with a Roll value of 180,
or can I just add 180 on the src.deltaX?

Another thing that confuses me is that changing the rotation value using the axis of the editor may have a different result in the detail panel.

In this case, Imgur: The magic of the Internet,
I rotate around z-axis from 0 - 20 degrees, and the z value in the detail panel changes from -10 to 10.

but in this case, Imgur: The magic of the Internet
as I rotate from 0-20 degrees, z value in the detail panel changes from 166 to 146. Shouldn’t the z value increase as well?
The orientations of the two bones are same.

I think it’s irrelevant to the original question, but I wish you just happen to know the answer. :slight_smile: Thank you!

Hi fengkan,

I think the issues with the z-rotation going from 166 to 146 (backwards according to the gizmo) are because Euler rotations in UE4 only go from 0-180, so you are working on the negative side which results in a gizmo mis-match (nothing to worry about). This happens because (if i remember correctly) UE4 uses quaternion rotations internally but converts to Euler for input.

As a side note, UE4 also uses XYZ as the rotation order, so it’s a good idea to make sure your rotation order matches in your skeleton.

To rotate a rotator, I use Delta Rotator as it will provide a clamped (0-180) rotation value. The image below rotates locally on the X axis by 180 degrees.

Hi, gryphen_76, thank you, the detail is very helpful and takes me some time to digest.

I found another approach to avoid copying bones BTW, I think I will come back to this when I know more about animation. :slight_smile: