فهرست منبع

Feature: applying static pose transformations for bones.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10872 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 12 سال پیش
والد
کامیت
44a7b1f098

+ 3 - 3
engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java

@@ -29,7 +29,7 @@ public class BoneContext {
      * The bones' matrices have, unlike objects', the coordinate system identical to JME's (Y axis is UP, X to the right and Z toward us).
      * So in order to have them loaded properly we need to transform their armature matrix (which blender sees as rotated) to make sure we get identical results.
      */
-    private static final Matrix4f BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix4f(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
+    public static final Matrix4f  BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix4f(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
 
     private BlenderContext        blenderContext;
     /** The OMA of the bone's armature object. */
@@ -102,7 +102,7 @@ public class BoneContext {
         // then make sure it is rotated in a proper way to fit the jme bone transformation conventions
         globalBoneMatrix.multLocal(BONE_ARMATURE_TRANSFORMATION_MATRIX);
 
-        Spatial armature = (Spatial) blenderContext.getLoadedFeature(armatureObjectOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        Spatial armature = (Spatial) objectHelper.toObject(blenderContext.getFileBlock(armatureObjectOMA).getStructure(blenderContext), blenderContext);
         ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
         Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform());
 
@@ -177,7 +177,7 @@ public class BoneContext {
      * @return the length of the bone
      */
     public float getLength() {
-        return length;
+        return length * bone.getModelSpaceScale().y;
     }
 
     /**

+ 1 - 11
engine/src/blender/com/jme3/scene/plugins/blender/constraints/SimulationNode.java

@@ -250,7 +250,6 @@ public class SimulationNode {
      */
     private void simulateSkeleton() {
         if (constraints != null && constraints.size() > 0) {
-            boolean applyStaticConstraints = true;
             Set<Long> alteredOmas = new HashSet<Long>();
 
             if (animations != null) {
@@ -335,22 +334,12 @@ public class SimulationNode {
                                 animation.addTrack(newTrack);
                             }
                         }
-                        applyStaticConstraints = false;
                     }
                 }
                 vars.release();
                 animControl.clearChannels();
                 this.reset();
             }
-
-            // if there are no animations then just constraint the static
-            // object's transformation
-            if (applyStaticConstraints) {
-                for (Constraint constraint : constraints) {
-                    constraint.apply(0);
-                }
-                skeleton.updateWorldVectors();
-            }
         }
     }
 
@@ -373,6 +362,7 @@ public class SimulationNode {
                 if (constraint.getAlteredOmas() != null) {
                     alteredOmas.addAll(constraint.getAlteredOmas());
                 }
+                alteredOmas.add(boneContext.getBoneOma());
             }
         }
         for (Bone child : bone.getChildren()) {

+ 64 - 16
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java

@@ -17,6 +17,8 @@ import com.jme3.animation.Bone;
 import com.jme3.animation.BoneTrack;
 import com.jme3.animation.Skeleton;
 import com.jme3.animation.SkeletonControl;
+import com.jme3.math.Matrix4f;
+import com.jme3.math.Transform;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
@@ -29,12 +31,16 @@ import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType;
 import com.jme3.scene.plugins.blender.animations.AnimationData;
 import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
 import com.jme3.scene.plugins.blender.animations.BoneContext;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
 import com.jme3.scene.plugins.blender.file.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.FileBlockHeader;
 import com.jme3.scene.plugins.blender.file.Pointer;
 import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.meshes.MeshContext;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
 import com.jme3.util.BufferUtils;
+import com.jme3.util.TempVars;
 
 /**
  * This modifier allows to add bone animation to the object.
@@ -45,6 +51,7 @@ import com.jme3.util.BufferUtils;
     private static final Logger LOGGER                     = Logger.getLogger(ArmatureModifier.class.getName());
     private static final int    MAXIMUM_WEIGHTS_PER_VERTEX = 4;                                                 // JME
 
+    private Structure           armatureObject;
     private Skeleton            skeleton;
     private Structure           objectStructure;
     private Structure           meshStructure;
@@ -75,7 +82,7 @@ import com.jme3.util.BufferUtils;
             if (pArmatureObject.isNotNull()) {
                 ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class);
 
-                Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0);
+                armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0);
 
                 // load skeleton
                 Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
@@ -147,7 +154,7 @@ import com.jme3.util.BufferUtils;
 
                 // store the animation data for each bone
                 for (Bone bone : bones) {
-                    if(bone.getName().length() > 0) {
+                    if (bone.getName().length() > 0) {
                         BoneContext boneContext = blenderContext.getBoneContext(bone);
                         Long boneOma = boneContext.getBoneOma();
                         if (boneOma != null) {
@@ -167,7 +174,7 @@ import com.jme3.util.BufferUtils;
         if (invalid) {
             LOGGER.log(Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName());
         }// if invalid, animData will be null
-        if(animationData != null && skeleton != null) {
+        if (animationData != null && skeleton != null) {
             // setting weights for bones
             List<Geometry> geomList = (List<Geometry>) blenderContext.getLoadedFeature(meshOMA, LoadedFeatureDataType.LOADED_FEATURE);
             MeshContext meshContext = blenderContext.getMeshContext(meshOMA);
@@ -175,25 +182,24 @@ import com.jme3.util.BufferUtils;
             for (Geometry geom : geomList) {
                 int materialIndex = meshContext.getMaterialIndex(geom);
                 Mesh mesh = geom.getMesh();
-    
+
                 try {
                     VertexBuffer[] buffers = this.readVerticesWeightsData(objectStructure, meshStructure, skeleton, materialIndex, bonesGroups, blenderContext);
                     if (buffers != null) {
                         mesh.setMaxNumWeights(bonesGroups[0]);
                         mesh.setBuffer(buffers[0]);
                         mesh.setBuffer(buffers[1]);
-    
+
                         LOGGER.fine("Generating bind pose and normal buffers.");
                         mesh.generateBindPose(true);
-                        
+
                         // change the usage type of vertex and normal buffers from
                         // Static to Stream
                         mesh.getBuffer(Type.Position).setUsage(Usage.Stream);
                         mesh.getBuffer(Type.Normal).setUsage(Usage.Stream);
-                        
-                        
-                        //creating empty buffers for HW skinning 
-                        //the buffers will be setup if ever used.
+
+                        // creating empty buffers for HW skinning
+                        // the buffers will be setup if ever used.
                         VertexBuffer verticesWeightsHW = new VertexBuffer(Type.HWBoneWeight);
                         VertexBuffer verticesWeightsIndicesHW = new VertexBuffer(Type.HWBoneIndex);
                         mesh.setBuffer(verticesWeightsHW);
@@ -204,8 +210,8 @@ import com.jme3.util.BufferUtils;
                     invalid = true;
                 }
             }
-    
-            if(!invalid) {
+
+            if (!invalid) {
                 // applying animations
                 AnimControl control = new AnimControl(animationData.skeleton);
                 List<Animation> animList = animationData.anims;
@@ -219,8 +225,51 @@ import com.jme3.util.BufferUtils;
                 }
                 node.addControl(control);
                 node.addControl(new SkeletonControl(animationData.skeleton));
-        
                 blenderContext.setNodeForSkeleton(skeleton, node);
+
+                TempVars tempVars = TempVars.get();
+                try {
+                    Pointer pPose = (Pointer) armatureObject.getFieldValue("pose");
+                    if (pPose.isNotNull()) {
+                        LOGGER.fine("Loading the pose of the armature.");
+                        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
+                        ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
+
+                        Structure pose = pPose.fetchData(blenderContext.getInputStream()).get(0);
+                        Structure chanbase = (Structure) pose.getFieldValue("chanbase");
+                        List<Structure> chans = chanbase.evaluateListBase(blenderContext);
+                        Transform transform = new Transform();
+                        for (Structure poseChannel : chans) {
+                            Pointer pBone = (Pointer) poseChannel.getFieldValue("bone");
+                            if (pBone.isNull()) {
+                                throw new BlenderFileException("Cannot find bone for pose channel named: " + poseChannel.getName());
+                            }
+                            BoneContext boneContext = blenderContext.getBoneContext(pBone.getOldMemoryAddress());
+
+                            LOGGER.log(Level.FINEST, "Getting the global pose transformation for bone: {0}", boneContext);
+                            Matrix4f poseMat = objectHelper.getMatrix(poseChannel, "pose_mat", blenderContext.getBlenderKey().isFixUpAxis());
+                            poseMat.multLocal(BoneContext.BONE_ARMATURE_TRANSFORMATION_MATRIX);
+
+                            Matrix4f armatureWorldMat = objectHelper.getMatrix(armatureObject, "obmat", blenderContext.getBlenderKey().isFixUpAxis());
+                            Matrix4f boneWorldMat = armatureWorldMat.multLocal(poseMat);
+
+                            boneWorldMat.toTranslationVector(tempVars.vect1);
+                            boneWorldMat.toRotationQuat(tempVars.quat1);
+                            boneWorldMat.toScaleVector(tempVars.vect2);
+                            transform.setTranslation(tempVars.vect1);
+                            transform.setRotation(tempVars.quat1);
+                            transform.setScale(tempVars.vect2);
+
+                            constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, transform);
+                        }
+                    }
+                } catch (BlenderFileException e) {
+                    LOGGER.log(Level.WARNING, "Problems occured during pose loading: {0}.", e.getLocalizedMessage());
+                } finally {
+                    tempVars.release();
+                }
+
+                node.updateModelBound();
             }
         }
     }
@@ -277,8 +326,7 @@ import com.jme3.util.BufferUtils;
      *             this exception is thrown when the blend file structure is
      *             somehow invalid or corrupted
      */
-    private VertexBuffer[] getBoneWeightAndIndexBuffer(Structure meshStructure, int vertexListSize, int[] bonesGroups, Map<Integer, List<Integer>> vertexReferenceMap, Map<Integer, Integer> groupToBoneIndexMap, BlenderContext blenderContext)
-            throws BlenderFileException {
+    private VertexBuffer[] getBoneWeightAndIndexBuffer(Structure meshStructure, int vertexListSize, int[] bonesGroups, Map<Integer, List<Integer>> vertexReferenceMap, Map<Integer, Integer> groupToBoneIndexMap, BlenderContext blenderContext) throws BlenderFileException {
         bonesGroups[0] = 0;
         Pointer pDvert = (Pointer) meshStructure.getFieldValue("dvert");// dvert
                                                                         // =
@@ -295,7 +343,7 @@ import com.jme3.util.BufferUtils;
             TreeMap<Float, Integer> weightToIndexMap = new TreeMap<Float, Integer>();
 
             for (Structure dvert : dverts) {
-                //we fetch the referenced vertices here
+                // we fetch the referenced vertices here
                 List<Integer> vertexIndices = vertexReferenceMap.get(Integer.valueOf(vertexIndex));
                 if (vertexIndices != null) {
                     // total amount of wights assigned to the vertex (max. 4 in JME)