Recommand · June 4, 2021 0

Calculate offset angle between joints with different coordinate systems using Three.js

I’ve been developing a retargeting application for skeleton animations, everything’s working great, however I have come across a problem I’m struggling to wrap my head around.

The issue:

Users can import their own skeleton rigs which may have different coordinate systems than my reference rig (the rig that contains animation data). I have successfully built a system that retargets the reference animation onto their rig. However, I need to calculate the rotation offsets from their bones to the reference bones on Bind Pose – this allows the animation to be one to one accurate.

View Reference Image (#1) is User Joint and (#2) is Reference Joint

As you can see from the image I have placed AxesHelper in the scene to show the difference in Axis between the two joints.

What would be the best way to either rotate the User AxesHelper (#1) to match the rotation of the Ref AxesHelper (#2) while maintaining the User AxesHelper (#1) axis coordinates. This will allow me to compare and calculate the offset angle in rotation between the bind poses while maintaining the same axis coordinates.

Techniques I have tried:

Attaching a Reference AxesHelper to the User Rig to calculate the initial offset between the Reference Rig.

var retargetHelper = new THREE.AxesHelper(1);
scene.add(retargetHelper) = "retargetHelper_" + rigHelper.bones[userRigBone].name;


//zero out retarget helper

//set target helper to source helper to copy rotations
initialRotationRetargetArray[userRigBone] = {
  x: retargetHelper.rotation.x,
  y: retargetHelper.rotation.y,
  z: retargetHelper.rotation.z,
  quaternion: retargetHelper.quaternion,
  name: rigHelper.bones[userRigBone].name + "_initRotation"

What this does is technically accurate, I attach a dummy AxesHelper to the user joint, zero its position and rotation (this now matches the joint) and then attach it to the reference joint. I store the rotation in X Y Z in a custom object which holds each initial rotation – I can then convert the rotation to degrees by rad2deg() and this will provide the offset in degrees of each joint between the bind poses.

However, this does not account for which way it should offset the joints positively or negatively. This is where I don’t think this is the best way to do it.

Thanks for reading, hope it wasn’t too long and makes sense.