MinieLibrary/src/main/java/com/jme3/bullet/animation/DacLinks.java
/**
     * 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)
     */
Create spatial-dependent data. Invoked each time the Control is added to
a Spatial. Also invoked by  #rebuild().

@param spatial the controlled spatial (not null)
Create spatial - dependent data . Invoked each time the Control is added to a Spatial . Also invoked by #rebuild () . @param spatial the controlled spatial ( not null )
@Override
    protected void createSpatialData(Spatial spatial) {
        RagUtils.validate(spatial);
        int numDacs
                = MySpatial.countControls(spatial, DynamicAnimControl.class);
        if (numDacs > 1) {
            logger3.log(Level.WARNING, "Added a DynamicAnimControl to a model "
                    + "that already contains {0}.",
                    numDacs - 1);
        }
        SkinningControl skinningControl
                = spatial.getControl(SkinningControl.class);
        String[] tempManagerMap;
        Transform[] savedTransforms;
        SkeletonControl skeletonControl = null;
        if (skinningControl == null) {
            skeletonControl = spatial.getControl(SkeletonControl.class);
            if (skeletonControl == null) {
                throw new IllegalArgumentException(
                        "The controlled spatial must have a SkinningControl or "
                        + "a SkeletonControl. Make sure the Control is there "
                        + "and not on some other Spatial.");
            }
            sortControls(skeletonControl);
            skeletonControl.setHardwareSkinningPreferred(false);
            /*
             * Analyze the model's Skeleton.
             */
            skeleton = skeletonControl.getSkeleton();
            validateSkeleton();
            tempManagerMap = managerMap(skeleton);
            int numBones = skeleton.getBoneCount();
            /*
             * Temporarily set all bones' local translations
             * and rotations to bind.
             */
            MySkeleton.setUserControl(skeleton, true);
            savedTransforms = new Transform[numBones];
            Vector3f userScale = new Vector3f();
            for (int boneIndex = 0; boneIndex < numBones; ++boneIndex) {
                Bone bone = skeleton.getBone(boneIndex);
                savedTransforms[boneIndex]
                        = MySkeleton.copyLocalTransform(bone, null);
                userScale.set(bone.getLocalScale());
                userScale.divideLocal(bone.getBindScale()); 
                bone.setUserTransforms(translateIdentity, rotateIdentity,
                        userScale);
            }
            MySkeleton.setUserControl(skeleton, false);
            skeleton.updateWorldVectors();
            bindTransforms = new Transform[numBones];
            for (int jointIndex = 0; jointIndex < numBones; ++jointIndex) {
                Bone bone = skeleton.getBone(jointIndex);
                bindTransforms[jointIndex]
                        = MySkeleton.copyBindTransform(bone, null);
            }
        } else { 
            sortControls(skinningControl);
            skinningControl.setHardwareSkinningPreferred(false);
            /*
             * Analyze the model's Armature.
             */
            armature = skinningControl.getArmature();
            validateArmature();
            tempManagerMap = managerMap(armature);
            int numArmatureJoints = armature.getJointCount();
            /*
             * Temporarily set all armature joints' local translations
             * and rotations to bind.
             */
            savedTransforms = new Transform[numArmatureJoints];
            for (int jointI = 0; jointI < numArmatureJoints; ++jointI) {
                Joint armatureJoint = armature.getJoint(jointI);
                savedTransforms[jointI]
                        = armatureJoint.getLocalTransform().clone();
                armatureJoint.applyBindPose(); 
            }
            armature.update();
            /*
             * Save the bind transform of each armature joint.
             */
            bindTransforms = new Transform[numArmatureJoints];
            for (int jointI = 0; jointI < numArmatureJoints; ++jointI) {
                Joint armatureJoint = armature.getJoint(jointI);
                bindTransforms[jointI]
                        = armatureJoint.getLocalTransform().clone();
            }
        }
        /*
         * Find the target meshes and choose the transform spatial.
         * Don't invoke getTargets() here, since the SkinningControl or
         * SkeletonControl might not be initialized yet.
         */
        List<Mesh> targetList = RagUtils.listDacMeshes(spatial, null);
        Mesh[] targets = new Mesh[targetList.size()];
        targetList.toArray(targets);
        transformer = MySpatial.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 TorsoLink.
         */
        VectorSet vertexLocations = coordsMap.get(torsoName);
        createTorsoLink(vertexLocations, targets);
        /*
         * Create bone links without physics joints.
         */
        String[] linkedBoneNames = listLinkedBoneNames();
        for (String boneName : linkedBoneNames) {
            vertexLocations = coordsMap.get(boneName);
            createBoneLink(boneName, vertexLocations);
        }
        int numLinkedBones = countLinkedBones();
        assert boneLinks.size() == numLinkedBones;
        /*
         * Add physics 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();
        /*
         * Create attachment links with physics joints.
         */
        String[] attachBoneNames = listAttachmentBoneNames();
        for (String boneName : attachBoneNames) {
            if (skinningControl == null) {
                createAttachmentLink(boneName, skeletonControl, tempManagerMap);
            } else {
                createAttachmentLink(boneName, skinningControl, tempManagerMap);
            }
        }
        if (skinningControl == null) {
            /*
             * Restore the skeleton's pose.
             */
            int numBones = skeleton.getBoneCount();
            for (int boneIndex = 0; boneIndex < numBones; ++boneIndex) {
                Bone bone = skeleton.getBone(boneIndex);
                MySkeleton.setLocalTransform(bone, savedTransforms[boneIndex]);
            }
            skeleton.updateWorldVectors();
        } else {
            /*
             * Restore the armature's pose.
             */
            int numArmatureJoints = armature.getJointCount();
            for (int jointI = 0; jointI < numArmatureJoints; ++jointI) {
                Joint armatureJoint = armature.getJoint(jointI);
                armatureJoint.setLocalTransform(savedTransforms[jointI]);
            }
            armature.update();
        }
        int maxHops = ignoredHops();
        ignoreCollisions(maxHops);
        if (added) {
            addPhysics();
        }
        logger3.log(Level.FINE, "Created ragdoll.");
    }
@ Override protected void createSpatialData ( Spatial spatial ) { RagUtils . validate ( spatial ) ; int numDacs = MySpatial . countControls ( spatial , DynamicAnimControl . class ) ; if ( numDacs > 1 ) { logger3 . log ( Level . WARNING , "Added a DynamicAnimControl to a model " + "that already contains {0}." , numDacs - 1 ) ; } SkinningControl skinningControl = spatial . getControl ( SkinningControl . class ) ; String [ ] tempManagerMap ; Transform [ ] savedTransforms ; SkeletonControl skeletonControl = null ; if ( skinningControl == null ) { skeletonControl = spatial . getControl ( SkeletonControl . class ) ; if ( skeletonControl == null ) { throw new IllegalArgumentException ( "The controlled spatial must have a SkinningControl or " + "a SkeletonControl. Make sure the Control is there " + "and not on some other Spatial." ) ; } sortControls ( skeletonControl ) ; skeletonControl . setHardwareSkinningPreferred ( false ) ; /*
             * Analyze the model's Skeleton.
             */ skeleton = skeletonControl . getSkeleton ( ) ; validateSkeleton ( ) ; tempManagerMap = managerMap ( skeleton ) ; int numBones = skeleton . getBoneCount ( ) ; /*
             * Temporarily set all bones' local translations
             * and rotations to bind.
             */ MySkeleton . setUserControl ( skeleton , true ) ; savedTransforms = new Transform [ numBones ] ; Vector3f userScale = new Vector3f ( ) ; for ( int boneIndex = 0 ; boneIndex < numBones ; ++ boneIndex ) { Bone bone = skeleton . getBone ( boneIndex ) ; savedTransforms [ boneIndex ] = MySkeleton . copyLocalTransform ( bone , null ) ; userScale . set ( bone . getLocalScale ( ) ) ; userScale . divideLocal ( bone . getBindScale ( ) ) ; bone . setUserTransforms ( translateIdentity , rotateIdentity , userScale ) ; } MySkeleton . setUserControl ( skeleton , false ) ; skeleton . updateWorldVectors ( ) ; bindTransforms = new Transform [ numBones ] ; for ( int jointIndex = 0 ; jointIndex < numBones ; ++ jointIndex ) { Bone bone = skeleton . getBone ( jointIndex ) ; bindTransforms [ jointIndex ] = MySkeleton . copyBindTransform ( bone , null ) ; } } else { sortControls ( skinningControl ) ; skinningControl . setHardwareSkinningPreferred ( false ) ; /*
             * Analyze the model's Armature.
             */ armature = skinningControl . getArmature ( ) ; validateArmature ( ) ; tempManagerMap = managerMap ( armature ) ; int numArmatureJoints = armature . getJointCount ( ) ; /*
             * Temporarily set all armature joints' local translations
             * and rotations to bind.
             */ savedTransforms = new Transform [ numArmatureJoints ] ; for ( int jointI = 0 ; jointI < numArmatureJoints ; ++ jointI ) { Joint armatureJoint = armature . getJoint ( jointI ) ; savedTransforms [ jointI ] = armatureJoint . getLocalTransform ( ) . clone ( ) ; armatureJoint . applyBindPose ( ) ; } armature . update ( ) ; /*
             * Save the bind transform of each armature joint.
             */ bindTransforms = new Transform [ numArmatureJoints ] ; for ( int jointI = 0 ; jointI < numArmatureJoints ; ++ jointI ) { Joint armatureJoint = armature . getJoint ( jointI ) ; bindTransforms [ jointI ] = armatureJoint . getLocalTransform ( ) . clone ( ) ; } } /*
         * Find the target meshes and choose the transform spatial.
         * Don't invoke getTargets() here, since the SkinningControl or
         * SkeletonControl might not be initialized yet.
         */ List < Mesh > targetList = RagUtils . listDacMeshes ( spatial , null ) ; Mesh [ ] targets = new Mesh [ targetList . size ( ) ] ; targetList . toArray ( targets ) ; transformer = MySpatial . 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 TorsoLink.
         */ VectorSet vertexLocations = coordsMap . get ( torsoName ) ; createTorsoLink ( vertexLocations , targets ) ; /*
         * Create bone links without physics joints.
         */ String [ ] linkedBoneNames = listLinkedBoneNames ( ) ; for ( String boneName : linkedBoneNames ) { vertexLocations = coordsMap . get ( boneName ) ; createBoneLink ( boneName , vertexLocations ) ; } int numLinkedBones = countLinkedBones ( ) ; assert boneLinks . size ( ) == numLinkedBones ; /*
         * Add physics 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 ( ) ; /*
         * Create attachment links with physics joints.
         */ String [ ] attachBoneNames = listAttachmentBoneNames ( ) ; for ( String boneName : attachBoneNames ) { if ( skinningControl == null ) { createAttachmentLink ( boneName , skeletonControl , tempManagerMap ) ; } else { createAttachmentLink ( boneName , skinningControl , tempManagerMap ) ; } } if ( skinningControl == null ) { /*
             * Restore the skeleton's pose.
             */ int numBones = skeleton . getBoneCount ( ) ; for ( int boneIndex = 0 ; boneIndex < numBones ; ++ boneIndex ) { Bone bone = skeleton . getBone ( boneIndex ) ; MySkeleton . setLocalTransform ( bone , savedTransforms [ boneIndex ] ) ; } skeleton . updateWorldVectors ( ) ; } else { /*
             * Restore the armature's pose.
             */ int numArmatureJoints = armature . getJointCount ( ) ; for ( int jointI = 0 ; jointI < numArmatureJoints ; ++ jointI ) { Joint armatureJoint = armature . getJoint ( jointI ) ; armatureJoint . setLocalTransform ( savedTransforms [ jointI ] ) ; } armature . update ( ) ; } int maxHops = ignoredHops ( ) ; ignoreCollisions ( maxHops ) ; if ( added ) { addPhysics ( ) ; } logger3 . log ( Level . FINE , "Created ragdoll." ) ; }
Create spatial-dependent data.
Create spatial - dependent data .
// multiply? // spatial has a SkinningControl // TODO adjust the scale?