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.
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.
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.app.SimpleApplication;
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;
@Override
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();
stateManager.attach(lightingState);
//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);
System.out.println("Controls:");
for (int i = 0; i < child.getNumControls(); i++) {
Control control = child.getControl(i);
System.out.println(control.getClass().getName());
if (control instanceof AnimComposer) {
composer = (AnimComposer) control;
System.out.println("Animations:");
for (AnimClip clip : composer.getAnimClips()) {
System.out.println(clip.getName());
}
} else if (control instanceof SkinningControl) {
skinning = (SkinningControl) control;
}
}
}
if (skinning != null) {
Node root = (Node) skinning.getSpatial();
root.attachChild(cloths);
}
//Add to world
world.attachChild(walker);
rootNode.attachChild(world);
cam.setLocation(new Vector3f(0, 10f, 50f));
cam.setFrustumFar(5000f);
flyCam.setMoveSpeed(20f);
ActionListener tab = new ActionListener() {
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (!isPressed) {
cursor = !cursor;
flyCam.setEnabled(cursor);
}
}
};
inputManager.addMapping("tab", new KeyTrigger(KeyInput.KEY_TAB));
inputManager.addListener(tab, "tab");
}
public static void main(String[] args) {
AnimClothingTest main = new AnimClothingTest();
main.start();
}
}