@Override @SuppressWarnings("unchecked") public Node apply(Node node, BlenderContext blenderContext) { if (invalid) { LOGGER.log( Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName()); } // if invalid, animData will be null if (animData == null) { return node; } // setting weights for bones List<Geometry> geomList = (List<Geometry>) blenderContext.getLoadedFeature(this.meshOMA, LoadedFeatureDataType.LOADED_FEATURE); for (Geometry geom : geomList) { Mesh mesh = geom.getMesh(); if (this.verticesWeights != null) { mesh.setMaxNumWeights(this.boneGroups); mesh.setBuffer(this.verticesWeights); mesh.setBuffer(this.verticesWeightsIndices); } } ArrayList<Animation> animList = animData.anims; if (animList != null && animList.size() > 0) { List<Constraint> constraints = blenderContext.getConstraints(this.armatureObjectOMA); HashMap<String, Animation> anims = new HashMap<String, Animation>(); for (int i = 0; i < animList.size(); ++i) { Animation animation = (Animation) animList.get(i).clone(); // baking constraints into animations if (constraints != null && constraints.size() > 0) { for (Constraint constraint : constraints) { Long boneOMA = constraint.getBoneOMA(); Bone bone = (Bone) blenderContext.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE); int targetIndex = bone == null ? 0 : animData.skeleton.getBoneIndex( bone); // bone==null may mean the object animation constraint.affectAnimation(animation, targetIndex); } } anims.put(animation.getName(), animation); } // applying the control to the node SkeletonControl skeletonControl = new SkeletonControl(animData.skeleton); AnimControl control = new AnimControl(animData.skeleton); control.setAnimations(anims); node.addControl(control); node.addControl(skeletonControl); } return node; }