I'm exporting a model whose head is separate from its body (but, naturally, in the same file). The following code is apparently not adding the head to the AnimatedGroup, because my model is imported headless. What gives?
/** calculates and returns whole bounding box of skinned group */
protected float[] calcBoundingBox() {
float[] box = null;
for (Animated3D skin : animatedGroup) {
float[] skinBB = skin.getMesh().getBoundingBox();
if (box == null) {
box = skinBB;
} else {
// x
box[0] = Math.min(box[0], skinBB[0]);
box[1] = Math.max(box[1], skinBB[1]);
// y
box[2] = Math.min(box[2], skinBB[2]);
box[3] = Math.max(box[3], skinBB[3]);
// z
box[4] = Math.min(box[4], skinBB[4]);
box[5] = Math.max(box[5], skinBB[5]);
}
}
return box;
}
protected AnimatedGroup createAnimatedGroup() throws Exception {
// we only specify the mesh file, skeleton file automatically loaded, and should be in same directory.
URL ninjaUrl = new File(objectFileName).toURI().toURL();
com.jmex.model.ogrexml.OgreLoader loader = new com.jmex.model.ogrexml.OgreLoader();
OgreEntityNode node = loader.loadModel(ninjaUrl);
// data in ogre file is upside down, so rotate around x axis
AnimatedGroup animatedGroup = BonesImporter.importOgre(node, 2f, new Quaternion().rotateX((float)Math.PI));
Texture texture = new Texture(objectFileName.substring(0, objectFileName.lastIndexOf("."))+".jpg");
TextureManager.getInstance().addTexture("ninja", texture);
for (Animated3D o : animatedGroup) {
o.setTexture("ninja");
o.build();
o.discardMeshData();
}
return animatedGroup;
}
protected SkeletonDebugger createSkeletonDebugger() throws Exception {
// in this file, root joint always remain in origin which doesn't look so good.
// so we tell debugger to ignore root joint (0)
int[] ignore = new int[animatedGroup.get(0).getSkeleton().getNumberOfJoints() - 20];
for (int i = 0; i < ignore.length; i++) {
ignore[i] = i+20;
}
return new SkeletonDebugger(animatedGroup.get(0).getSkeletonPose(), 10f, 0.2f, 0);
}
protected void initialize() throws Exception {
this.animatedGroup = createAnimatedGroup();
this.skinClipSequence = animatedGroup.getSkinClipSequence();
this.poseClipSequence = animatedGroup.getPoseClipSequence();
this.hasSkinAnimation = (skinClipSequence != null) && (skinClipSequence.getSize() != 0);
this.hasPoseAnimation = (poseClipSequence != null) && (poseClipSequence.getSize() != 0);
this.skinAnim = hasSkinAnimation;
this.animationSequence = hasSkinAnimation ? -1 : 0;
animatedGroup.addToWorld(theWorld);
// all SkinnedObject3D share the same pose
this.currentPose = animatedGroup.get(0).getSkeletonPose();
this.skeletonDebugger = createSkeletonDebugger();
if (skeletonDebugger != null) {
skeletonDebugger.addToWorld(theWorld);
skeletonDebugger.setVisibility(showSkeleton);
}
float[] bb = calcBoundingBox();
float height = bb[3] - bb[2];
Config.farPlane = Math.max(height * 100, Config.farPlane);
for (Animated3D o : animatedGroup) {
o.setVisibility(showMesh);
}
update(0); // update once to reflect changes visible in first scene
}