Right after importing a .blend the target meshes in it skeleton control are some unknown meshes (maybe it has something to do with it internal cloning on import, which I don’t really know if it is being done or not). However, when the model is put on the scene, this meshes are updated and set to the correct ones.
This problem is only there for runtime loaded .blend (when generating a .j3o, this is just right) and it is easily patched (remove->add the control from the generated spatial).
The next code shows that problem for a given model:
public class TestPlayerSkeleton extends SimpleApplication {
public static void main(String[] args) {
TestPlayerSkeleton app = new TestPlayerSkeleton();
app.start();
}
Material mat;
Spatial player;
@Override
public void simpleInitApp() {
rootNode.addLight(new AmbientLight());
player = assetManager.loadModel("Models/player.blend");
checkSkeletonControls(player);
rootNode.attachChild(player);
}
public static boolean checkSkeletonControls(Spatial spatial) {
List<Geometry> list = new ArrayList<>();
GeometryBatchFactory.gatherGeoms(spatial, list);
Map<Mesh, Geometry> meshAssocMap = new HashMap<>();
for(Geometry geom : list) {
meshAssocMap.put(geom.getMesh(), geom);
// System.out.println("MESH for: " + geom + ":" + geom.getMesh());
}
final List<SkeletonControl> skControls = new ArrayList<>();
spatial.depthFirstTraversal(new SceneGraphVisitor() {
@Override
public void visit(Spatial spatial) {
SkeletonControl sk = spatial.getControl(SkeletonControl.class);
if(sk != null) {
// --- PATCH THAT FIX THE ISSUE ---
// spatial.removeControl(sk);
// spatial.addControl(sk);
// --------------------------------
skControls.add(sk);
}
}
});
boolean success = true;
if(skControls != null) {
for (SkeletonControl skeletonControl : skControls) {
Mesh[] targets = skeletonControl.getTargets();
if(targets != null) {
for(Mesh target : targets) {
if(!meshAssocMap.containsKey(target)) {
success = false;
List<Geometry> skeletonGeoms = new ArrayList<>();
GeometryBatchFactory.gatherGeoms(skeletonControl.getSpatial(), skeletonGeoms);
boolean containsGeoms = true;
if(skeletonGeoms != null) {
for (Geometry geometry : skeletonGeoms) {
if(!meshAssocMap.containsValue(geometry)) {
containsGeoms = false;
}
}
}
System.out.println("SkeletonControl for: " + skeletonControl.getSpatial() + ", has a mesh: " + target + ", that isn't in it container spatial: " + spatial + ". However, it skeletonControls subGeoms are fine?:" + containsGeoms);
}
}
}
}
}
return success;
}
}