I am experimenting with nehon’s BVH re-targeting library. It works fine, I need to add an extra feature to it, and need help with math computation.
So let me demonstrate my requirement with this example:
I have tow characters and want to re-target animation from character1 to character2.
They have different rest pose (T-pose, Bind pose)
character1 rest pose :
character2 rest pose:
I have a walking animation on character1 :
I want to re-target it to character2, so it should look like this (result in blender retargetter), as you see it applied animation while keeping the offset on arms.
Now I want to do the same in jme using BVHUtils class.
the result looks like this :
Re-targeting from character in the left to the character in the right,
as you see the result on both characters looks the same, (there is an slight difference, and that happened when tacking screen shot I guess).
As I guess the bvh re-target class inverses bone rotations on target character to looks the same with source character. what I want, is to add an option to re-target by keeping the offset on target model, so the result should look like the image I posted above from blender.
Here is the code from bvh re-target where computation is done: (see the whole method here)
// computing target's parent's inverse model rotation Quaternion inverseTargetParentModelRot = vars.quat1; inverseTargetParentModelRot.set(parentBone.getModelSpaceRotation()).inverseLocal().normalizeLocal(); //ANIMATION ROTATION //Computing target's local rotation by multiplying source's model //rotation with target's parent's inverse model rotation and multiplying //with the target's inverse world bind rotation. // //The twist quaternion is here to fix the twist on Y axis some //bones may have after the rotation in model space has been computed //For now the problem is worked around by some constant twist //rotation that you set in the bone mapping. //This is probably a predictable behavior that could be detected //and automatically corrected, but as for now I don't have a clue where it comes from. //Don't use inverseTargetParentModelRot as is after this point as the //following line compromizes its value. multlocal is used instead of mult for obvious optimization reason. Quaternion targetLocalRot = inverseTargetParentModelRot.multLocal(sourceBone.getModelSpaceRotation()).normalizeLocal(); Quaternion targetInverseBindRotation = vars.quat2.set(targetBone.getBindRotation()).inverseLocal().normalizeLocal(); Quaternion twist = boneMapping.get(targetBone.getName()).getTwist(); //finally computing the animation rotation for the current frame. Note that the first "mult" instanciate a new Quaternion. t.rotations[frameId] = targetInverseBindRotation.mult(targetLocalRot).multLocal(twist).normalizeLocal();
I tried by removing the inversing rotation and played with different orders but because of my poor math and unfamiliarity with jme bone setup at low level I was not able to put correct rotations I guess, and was not able to get the result I want, so finally decided to ask it here.
Will appreciate if some one can point me to correct implementation.