stephengold / Wes

An animation editing and retargeting library for jMonkeyEngine (code has New BSD license)
Other
17 stars 2 forks source link

Animation retarget: add support for root-bone translations #1

Open Ali-RS opened 4 years ago

Ali-RS commented 4 years ago

Tried to retarget an AnimClip from one model to another, seems it only retargets bone rotations (makes an in-place animation) and does not have support for root motion export. While in-place animation might be what one needs most of the time, but yet sometimes we might need to have the root motion also. It will be nice to add support for this as well.

stephengold commented 4 years ago

The main difficulty I see is that different models place the root bone differently. For instance, Jaime's root bone is between his feet, while Sinbad's is in his belly. Also, translation introduces the issue of models built at different scales (meter units versus centimeter units, for instance.) For these reasons and others, I think root translation should be handled separately from rotations.

The Maud editor includes support for translating models so that their feet touch the ground without sliding. I believe the relevant code could be added to Wes. Would that serve your need?

Ali-RS commented 4 years ago

I calculate target track translation by finding delta translation from the source track ( delta translation = source track translation - source joint bind translation) and add it to target joint bind translation. This works fine for me but not sure if it will fit into all cases.

Here is simplified version of my anim retarget script:

AnimClip retargetClip(AnimClip sourceClip, Spatial target) {
    Spatial animRoot = getAnimRoot(target);
    if (animRoot == null) {
        return null;
    }

    SkinningControl sc = animRoot.getControl(SkinningControl.class);
    sc.getArmature().applyBindPose();
    sc.getArmature().saveInitialPose();

    SafeArrayList<AnimTrack> tracks = new SafeArrayList<>(AnimTrack.class);
    for (AnimTrack animTrack : sourceClip.getTracks()) {
        if (animTrack instanceof TransformTrack) {
            TransformTrack sourceTrack = (TransformTrack) animTrack;
            Joint sourceJoint = sourceTrack.getTarget();
            // I am using a standard humanoid rig for all my characters so joint 
            // names are the same on all rigs
            Joint targetJoint = sc.getArmature().getJoint(sourceJoint.getName()); 
            if (targetJoint == null) {
                println "Joint with name " + sourceJoint.getName() + " not fount on target";
                continue;
            }

            // Rotations and Scales are cloned without change
            TransformTrack targetTrack = sourceTrack.jmeClone();
            targetTrack.setTarget(targetJoint);

            // Modify translations to fit in target rig
            if (sourceTrack.getTranslations() != null) {
                Vector3f[] translations = new Vector3f[sourceTrack.getTimes().length];

                for (int i = 0; i < sourceTrack.getTranslations().length; i++) {
                    // delta translation = track translation - bind translation
                    Vector3f deltaTranslation = sourceTrack.getTranslations()[i].subtract(sourceJoint.getLocalTranslation());

                    Vector3f targetTranslation = new Vector3f(targetJoint.getInitialTransform().getTranslation());
                    targetTranslation.addLocal(deltaTranslation);
                    translations[i] = targetTranslation;
                }
                targetTrack.setKeyframesTranslation(translations);
            }
            tracks.add(targetTrack);
        }
    }

    AnimClip targetClip = new AnimClip(sourceClip.getName());
    targetClip.setTracks(tracks.getArray());
    return targetClip;
}
stephengold commented 4 years ago

Is there anything that should be added to the Wes library to support your solution?

Ali-RS commented 4 years ago

Nothing needed ATM, I need to thoroughly test my solution for different scenarios. I will let you know the outcome.

stephengold commented 4 years ago

@Ali-RS Any news?

Ali-RS commented 4 years ago

Really sorry, no progress on this yet. I do not think I can come back to this anytime soon. Please feel free to close this if you want.