Join skeletons in new animation system?

OK, forgive my ignorance, I am trying to get an idea of how to do something that I understand very little about.

Say I have a player model rigged with a skeleton, and I have a model of a pair of pants rigged with the same skeleton. How can I join the two skeletons together so that when the player is animated the pair of pants’ bones are animated with the player?

Is there a way to join/bind the rigs together in jme? I would like to be able to swap out several different clothing models and just have the bones bind to the player models’ bones.


1 Like

A SkinningControl transforms all geometries in the subtree it controls. So attach the player model and the pants model to a Node, then add the SkinningControl and AnimComposer to that Node.


Thank you for the fast reply. I did not think it would be anywhere near the simple. I will test that and report back. Thank you.

1 Like

So I am going to assume I perhaps did something wrong.

Is this a bone rotation issue? It is the same rig, but the animated character was exported from a T-pose and the clothing was from a A-pose, would this be an issue?

package io.tlf.jme.test;

import com.jme3.anim.*;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;

public class AnimClothingTest extends SimpleApplication {

    private boolean cursor = false;

    public void simpleInitApp() {
        //Import cloths
        Spatial cloths = assetManager.loadModel("Models/daz Joan 2.glb");

        Node world = new Node("world");
        //Load lighting
        JmeLightingState lightingState = new JmeLightingState();

        //Player with walking animation
        Spatial walker = assetManager.loadModel("Models/daz Joan.glb");
        AnimComposer composer;
        SkinningControl skinning = null;

        for (Spatial child : ((Node) walker).getChildren()) {
            System.out.println("Spatial Name: " + child);
            for (int i = 0; i < child.getNumControls(); i++) {
                Control control = child.getControl(i);
                if (control instanceof AnimComposer) {
                    composer = (AnimComposer) control;
                    for (AnimClip clip : composer.getAnimClips()) {
                } else if (control instanceof SkinningControl) {
                   skinning = (SkinningControl) control;

        if (skinning != null) {
            Node root = (Node) skinning.getSpatial();

        //Add to world

        cam.setLocation(new Vector3f(0, 10f, 50f));

        ActionListener tab = new ActionListener() {
            public void onAction(String name, boolean isPressed, float tpf) {
                if (!isPressed) {
                    cursor = !cursor;
        inputManager.addMapping("tab", new KeyTrigger(KeyInput.KEY_TAB));
        inputManager.addListener(tab, "tab");


    public static void main(String[] args) {
        AnimClothingTest main = new AnimClothingTest();

Could be.