@Override
    protected void createSpatialData(Spatial spatial) {
        RagUtils.validate(spatial);

        SkinningControl skeletonControl
                = spatial.getControl(SkinningControl.class);
        if (skeletonControl == null) {
            throw new IllegalArgumentException(
                    "The controlled spatial must have a SkinningControl. "
                    + "Make sure the control is there and not on a subnode.");
        }
        sortControls(skeletonControl);
        skeletonControl.setHardwareSkinningPreferred(false);
        /*
         * Analyze the model's skeleton.
         */
        skeleton = skeletonControl.getArmature();
        validateSkeleton();
        String[] tempManagerMap = managerMap(skeleton);
        int numBones = skeleton.getJointCount();
        /*
         * Temporarily set all bones' local translations and rotations to bind.
         */
        Transform[] savedTransforms = new Transform[numBones];
        for (int boneIndex = 0; boneIndex < numBones; ++boneIndex) {
            Joint bone = skeleton.getJoint(boneIndex);
            savedTransforms[boneIndex] = bone.getLocalTransform().clone();
            bone.applyBindPose(); // TODO adjust the scale?
        }
        skeleton.update();
        /*
         * Find the target meshes and choose the transform spatial.
         */
        List<Mesh> targetList = RagUtils.listAnimatedMeshes(spatial, null);
        Mesh[] targets = new Mesh[targetList.size()];
        targetList.toArray(targets);
        transformer = RagUtils.findAnimatedGeometry(spatial);
        if (transformer == null) {
            transformer = spatial;
        }
        /*
         * Enumerate mesh-vertex coordinates and assign them to managers.
         */
        Map<String, VectorSet> coordsMap
                = RagUtils.coordsMap(targets, tempManagerMap);
        /*
         * Create the torso link.
         */
        VectorSet vertexLocations = coordsMap.get(torsoName);
        createTorsoLink(vertexLocations, targets);
        /*
         * Create bone links without joints.
         */
        String[] linkedBoneNames = listLinkedBoneNames();
        for (String boneName : linkedBoneNames) {
            vertexLocations = coordsMap.get(boneName);
            createBoneLink(boneName, vertexLocations);
        }
        int numLinkedBones = countLinkedBones();
        assert boneLinks.size() == numLinkedBones;
        /*
         * Add joints to connect each BoneLink rigid body with its parent in the
         * link hierarchy.  Also initialize the boneLinkList.
         */
        boneLinkList = new ArrayList<>(numLinkedBones);
        addJoints(torsoLink);
        assert boneLinkList.size() == numLinkedBones : boneLinkList.size();
        /*
         * Restore the skeleton's pose.
         */
        for (int boneIndex = 0; boneIndex < numBones; ++boneIndex) {
            Joint bone = skeleton.getJoint(boneIndex);
            bone.setLocalTransform(savedTransforms[boneIndex]);
        }
        skeleton.update();

        if (added) {
            addPhysics(space);
        }

        logger3.log(Level.FINE, "Created ragdoll for skeleton.");
    }
Create spatial-dependent data. Invoked each time the control is added to
a spatial. Also invoked by {@link #rebuild()}.

@param spatial the controlled spatial (not null)
jme3-jbullet/src/main/java/com/jme3/bullet/animation/DacLinks.java