Browse Source

Blender 4.2.1

-fixed typo with Blender Nodes
-allow more IK Bones to ignore
-added rest pose. No really working, but cannot spend any more time
right now. User waiting for nodes fix.
jeff 9 years ago
parent
commit
71c17cff30
3 changed files with 56 additions and 18 deletions
  1. 34 13
      Exporters/Blender/io_export_babylon.py
  2. 11 1
      src/Bones/babylon.bone.ts
  3. 11 4
      src/Bones/babylon.skeleton.ts

+ 34 - 13
Exporters/Blender/io_export_babylon.py

@@ -1,7 +1,7 @@
 bl_info = {
     'name': 'Babylon.js',
     'author': 'David Catuhe, Jeff Palmer',
-    'version': (4, 2, 0),
+    'version': (4, 2, 1),
     'blender': (2, 75, 0),
     'location': 'File > Export > Babylon.js (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',
@@ -169,7 +169,7 @@ class ExporterSettingsPanel(bpy.types.Panel):
         )
     bpy.types.Scene.ignoreIKBones = bpy.props.BoolProperty(
         name="Ignore IK Bones",
-        description="Do not export bones with '.ik' in the name",
+        description="Do not export bones with either '.ik' or 'ik.'(not case sensitive) in the name",
         default = False,
         )
 
@@ -531,7 +531,6 @@ class World:
             write_float(file_handler, 'fogStart', self.fogStart)
             write_float(file_handler, 'fogEnd', self.fogEnd)
             write_float(file_handler, 'fogDensity', self.fogDensity)
-
 #===============================================================================
 class Sound:
     def __init__(self, name, autoplay, loop, connectedMesh = None):
@@ -1239,7 +1238,7 @@ class MeshInstance:
 class Node(FCurveAnimatable):
     def __init__(self, node):
         Main.log('processing begun of node:  ' + node.name)
-        self.define_animations(object, True, True, True)  #Should animations be done when forcedParent
+        self.define_animations(node, True, True, True)  #Should animations be done when forcedParent
         self.name = node.name
 
         if node.parent and node.parent.type != 'ARMATURE':
@@ -1304,11 +1303,11 @@ class Bone:
         self.name = bone.name
         self.length = bone.length
         self.index = index
-        self.blenderBoneObj = bone # record so can be used by get_matrix, called by append_animation_pose
+        self.posedBone = bone # record so can be used by get_matrix, called by append_animation_pose
         self.parentBone = bone.parent
 
         self.matrix_world = skeleton.matrix_world
-        self.matrix = self.get_matrix()
+        self.matrix = self.get_bone_matrix()
 
         parentId = -1
         if (bone.parent):
@@ -1325,32 +1324,40 @@ class Bone:
             self.previousBoneMatrix = None
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     def append_animation_pose(self, frame, force = False):
-        currentBoneMatrix = self.get_matrix()
+        currentBoneMatrix = self.get_bone_matrix()
 
         if (force or not same_matrix4(currentBoneMatrix, self.previousBoneMatrix)):
             self.animation.frames.append(frame)
             self.animation.values.append(currentBoneMatrix)
             self.previousBoneMatrix = currentBoneMatrix
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-    def get_matrix(self):
+    def set_rest_pose(self, editBone, matrix_world):
+        self.rest = Bone.get_matrix(editBone, self.matrix_world)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    def get_bone_matrix(self):
+        return Bone.get_matrix(self.posedBone, self.matrix_world)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    @staticmethod
+    def get_matrix(bone, matrix_world):
         SystemMatrix = mathutils.Matrix.Scale(-1, 4, mathutils.Vector((0, 0, 1))) * mathutils.Matrix.Rotation(math.radians(-90), 4, 'X')
 
-        if (self.parentBone):
-            return (SystemMatrix * self.matrix_world * self.parentBone.matrix).inverted() * (SystemMatrix * self.matrix_world * self.blenderBoneObj.matrix)
+        if (bone.parent):
+            return (SystemMatrix * matrix_world * bone.parent.matrix).inverted() * (SystemMatrix * matrix_world * bone.matrix)
         else:
-            return  SystemMatrix * self.matrix_world * self.blenderBoneObj.matrix
+            return SystemMatrix * matrix_world * bone.matrix
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     def to_scene_file(self, file_handler):
         file_handler.write('\n{')
         write_string(file_handler, 'name', self.name, True)
         write_int(file_handler, 'index', self.index)
         write_matrix4(file_handler, 'matrix', self.matrix)
+        write_matrix4(file_handler, 'rest', self.rest)
         write_int(file_handler, 'parentBoneIndex', self.parentBoneIndex)
         write_float(file_handler, 'length', self.length)
 
         #animation
         if hasattr(self, 'animation'):
-            file_handler.write(',"animation":')
+            file_handler.write('\n,"animation":')
             self.animation.to_scene_file(file_handler)
 
         file_handler.write('}')
@@ -1363,7 +1370,7 @@ class Skeleton:
         self.bones = []
 
         for bone in skeleton.pose.bones:
-            if scene.ignoreIKBones and '.ik' in bone.name:
+            if scene.ignoreIKBones and ('.ik' in bone.name.lower() or 'ik.' in bone.name.lower() ):
                 Main.log('Ignoring IK bone:  ' + bone.name, 2)
                 continue
 
@@ -1388,6 +1395,20 @@ class Skeleton:
                         bone.append_animation_pose(frame + frameOffset, frame == animationRange.highest_frame)
 
                 frameOffset = animationRange.frame_end + 1
+                
+        # mode_set's only work when there is an active object, switch bones to edit mode to rest position
+        scene.objects.active = skeleton
+        bpy.ops.object.mode_set(mode='EDIT')
+        matrix_world = skeleton.matrix_world
+
+        # you need to access edit_bones from skeleton.data not skeleton.pose when in edit mode
+        for editBone in skeleton.data.edit_bones:
+            for myBoneObj in self.bones:
+                if editBone.name == myBoneObj.name:
+                    myBoneObj.set_rest_pose(editBone, matrix_world)
+                    break
+           
+        bpy.ops.object.mode_set(mode='OBJECT')
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     # Since IK bones could be being skipped, looking up index of bone in second pass of mesh required
     def get_index_of_bone(self, boneName):

+ 11 - 1
src/Bones/babylon.bone.ts

@@ -6,17 +6,19 @@
 
         private _skeleton: Skeleton;
         private _matrix: Matrix;
+        private _restPose: Matrix;
         private _baseMatrix: Matrix;
         private _worldTransform = new Matrix();
         private _absoluteTransform = new Matrix();
         private _invertedAbsoluteTransform = new Matrix();
         private _parent: Bone;
 
-        constructor(public name: string, skeleton: Skeleton, parentBone: Bone, matrix: Matrix) {
+        constructor(public name: string, skeleton: Skeleton, parentBone: Bone, matrix: Matrix, restPose? : Matrix) {
             super(name, skeleton.getScene());
             this._skeleton = skeleton;
             this._matrix = matrix;
             this._baseMatrix = matrix;
+            this._restPose = restPose ? restPose : matrix.clone();
 
             skeleton.bones.push(this);
 
@@ -43,6 +45,14 @@
             return this._baseMatrix;
         }
 
+        public getRestPose(): Matrix {
+            return this._restPose;
+        }
+        
+        public returnToRest(): void {
+            this.updateMatrix(this._restPose.clone());
+        }
+
         public getWorldMatrix(): Matrix {
             return this._worldTransform;
         }

+ 11 - 4
src/Bones/babylon.skeleton.ts

@@ -90,6 +90,12 @@
             return ret;
         }
 
+        public returnToRest(): void {
+            for (var index = 0; index < this.bones.length; index++) {
+                this.bones[index].returnToRest();
+            }
+        }
+
         private _getHighestAnimationFrame(): number {
             var ret = 0;
             for (var i = 0, nBones = this.bones.length; i < nBones; i++) {
@@ -170,7 +176,7 @@
                     parentBone = result.bones[parentIndex];
                 }
 
-                var bone = new Bone(source.name, result, parentBone, source.getBaseMatrix().clone());
+                var bone = new Bone(source.name, result, parentBone, source.getBaseMatrix().clone(), source.getRestPose().clone());
                 Tools.DeepCopy(source.animations, bone.animations);
             }
 
@@ -199,7 +205,8 @@
                 var serializedBone: any = {
                     parentBoneIndex: bone.getParent() ? this.bones.indexOf(bone.getParent()) : -1,
                     name: bone.name,
-                    matrix: bone.getLocalMatrix().toArray()
+                    matrix: bone.getLocalMatrix().toArray(),
+                    rest: bone.getRestPose().toArray()
                 };
 
                 serializationObject.bones.push(serializedBone);
@@ -234,8 +241,8 @@
                 if (parsedBone.parentBoneIndex > -1) {
                     parentBone = skeleton.bones[parsedBone.parentBoneIndex];
                 }
-
-                var bone = new Bone(parsedBone.name, skeleton, parentBone, Matrix.FromArray(parsedBone.matrix));
+                var rest : Matrix = parsedBone.rest ? Matrix.FromArray(parsedBone.rest) : null;
+                var bone = new Bone(parsedBone.name, skeleton, parentBone, Matrix.FromArray(parsedBone.matrix), rest);
 
                 if (parsedBone.length) {
                     bone.length = parsedBone.length;