瀏覽代碼

Blender Exporter 4.1.0

added:
- support for Bone.length

fixed:
- Error caused when # of influencers exceed 8
- Flawed checking for bone animation optimization
jeff 9 年之前
父節點
當前提交
92cc1d7048
共有 3 個文件被更改,包括 38 次插入15 次删除
  1. 28 14
      Exporters/Blender/io_export_babylon.py
  2. 1 0
      src/Bones/babylon.bone.ts
  3. 9 1
      src/Bones/babylon.skeleton.ts

+ 28 - 14
Exporters/Blender/io_export_babylon.py

@@ -1,7 +1,7 @@
 bl_info = {
     'name': 'Babylon.js',
     'author': 'David Catuhe, Jeff Palmer',
-    'version': (4, 0, 1),
+    'version': (4, 1, 0),
     'blender': (2, 75, 0),
     'location': 'File > Export > Babylon.js (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',
@@ -39,7 +39,8 @@ if __name__ == '__main__':
 MAX_VERTEX_ELEMENTS = 65535
 MAX_VERTEX_ELEMENTS_32Bit = 16777216
 VERTEX_OUTPUT_PER_LINE = 100
-MAX_FLOAT_PRECISION = '%.4f'
+MAX_FLOAT_PRECISION_INT = 4
+MAX_FLOAT_PRECISION = '%.' + str(MAX_FLOAT_PRECISION_INT) + 'f'
 COMPRESS_MATRIX_INDICES = True # this is True for .babylon exporter & False for TOB
 
 # used in World constructor, defined in BABYLON.Scene
@@ -756,7 +757,8 @@ class Mesh(FCurveAnimatable):
         if hasSkeleton:
             weightsPerVertex = []
             indicesPerVertex = []
-            influenceCounts = [0, 0, 0, 0, 0, 0, 0, 0, 0] # 9, so accessed orign 1
+            influenceCounts = [0, 0, 0, 0, 0, 0, 0, 0, 0] # 9, so accessed orign 1; 0 used for all those greater than 8
+            totalInfluencers = 0
             highestInfluenceObserved = 0
 
         # used tracking of vertices as they are received
@@ -908,7 +910,11 @@ class Mesh(FCurveAnimatable):
                             vertices_sk_weights[vertex_index].append(matricesWeights)
                             vertices_sk_indices[vertex_index].append(matricesIndices)
                             nInfluencers = len(matricesWeights)
-                            influenceCounts[nInfluencers] += 1
+                            totalInfluencers += nInfluencers
+                            if nInfluencers <= 8:
+                                influenceCounts[nInfluencers] += 1
+                            else:
+                                influenceCounts[0] += 1
                             highestInfluenceObserved = nInfluencers if nInfluencers > highestInfluenceObserved else highestInfluenceObserved
                             weightsPerVertex.append(matricesWeights)
                             indicesPerVertex.append(matricesIndices)
@@ -943,17 +949,9 @@ class Mesh(FCurveAnimatable):
                 if (self.numBoneInfluencers > 4):
                     self.skeletonIndicesExtra = Mesh.packSkeletonIndices(self.skeletonIndicesExtra)
                 
-            totalInfluencers  = influenceCounts[1]
-            totalInfluencers += influenceCounts[2] * 2
-            totalInfluencers += influenceCounts[3] * 3
-            totalInfluencers += influenceCounts[4] * 4
-            totalInfluencers += influenceCounts[5] * 5
-            totalInfluencers += influenceCounts[6] * 6
-            totalInfluencers += influenceCounts[7] * 7
-            totalInfluencers += influenceCounts[8] * 8
             Main.log('Total Influencers:  ' + format_f(totalInfluencers), 3)
             Main.log('Avg # of influencers per vertex:  ' + format_f(totalInfluencers / len(self.positions)), 3)
-            Main.log('Highest # of influencers observed:  ' + str(highestInfluenceObserved) + ', num vertices with this:  ' + format_int(influenceCounts[highestInfluenceObserved]), 3)
+            Main.log('Highest # of influencers observed:  ' + str(highestInfluenceObserved) + ', num vertices with this:  ' + format_int(influenceCounts[highestInfluenceObserved if highestInfluenceObserved < 9 else 0]), 3)
             Main.log('exported as ' + str(self.numBoneInfluencers) + ' influencers', 3)
             nWeights = len(self.skeletonWeights) + len(self.skeletonWeightsExtra) if hasattr(self, 'skeletonWeightsExtra') else 0
             Main.log('num skeletonWeights and skeletonIndices:  ' + str(nWeights), 3)
@@ -1241,6 +1239,7 @@ class Bone:
     def __init__(self, bone, skeleton, scene, index):
         Main.log('processing begun of bone:  ' + bone.name + ', index:  '+ str(index), 2)
         self.name = bone.name
+        self.length = bone.length
         self.index = index
 
         matrix_world = skeleton.matrix_world
@@ -1267,7 +1266,7 @@ class Bone:
                 bpy.context.scene.frame_set(frame)
                 currentBoneMatrix = Bone.get_matrix(bone, matrix_world)
 
-                if (frame != end_frame and currentBoneMatrix == previousBoneMatrix):
+                if (frame != end_frame and same_matrix4(currentBoneMatrix, previousBoneMatrix)):
                     continue
 
                 self.animation.frames.append(frame)
@@ -1291,6 +1290,7 @@ class Bone:
         write_int(file_handler, 'index', self.index)
         write_matrix4(file_handler, 'matrix', self.matrix)
         write_int(file_handler, 'parentBoneIndex', self.parentBoneIndex)
+        write_float(file_handler, 'length', self.length)
 
         #animation
         if hasattr(self, 'animation'):
@@ -2306,10 +2306,24 @@ def scale_vector(vector, mult, xOffset = 0):
     ret.y *= mult
     return ret
 
+def same_matrix4(matA, matB):
+    if(matA is None or matB is None): return False
+    if (len(matA) != len(matB)): return False
+    for i in range(len(matA)):
+        if (round(matA[i][0], MAX_FLOAT_PRECISION_INT) != round(matB[i][0], MAX_FLOAT_PRECISION_INT) or 
+            round(matA[i][1], MAX_FLOAT_PRECISION_INT) != round(matB[i][1], MAX_FLOAT_PRECISION_INT) or 
+            round(matA[i][2], MAX_FLOAT_PRECISION_INT) != round(matB[i][2], MAX_FLOAT_PRECISION_INT) or 
+            round(matA[i][3], MAX_FLOAT_PRECISION_INT) != round(matB[i][3], MAX_FLOAT_PRECISION_INT)): 
+            return False
+        
+    return True
+
 def same_vertex(vertA, vertB):
+    if(vertA is None or vertB is None): return False
     return vertA.x == vertB.x and vertA.y == vertB.y and vertA.z == vertB.z
 
 def same_array(arrayA, arrayB):
+    if(arrayA is None or arrayB is None): return False
     if len(arrayA) != len(arrayB): return False
     for i in range(len(arrayA)):
         if arrayA[i] != arrayB[i] : return False

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

@@ -2,6 +2,7 @@
     export class Bone extends Node {
         public children = new Array<Bone>();
         public animations = new Array<Animation>();
+        public length : number;
 
         private _skeleton: Skeleton;
         private _matrix: Matrix;

+ 9 - 1
src/Bones/babylon.skeleton.ts

@@ -155,6 +155,10 @@
                 };
 
                 serializationObject.bones.push(serializedBone);
+                
+                if (bone.length){
+                    serializedBone.length = bone.length;
+                }
 
                 if (bone.animations && bone.animations.length > 0) {
                     serializedBone.animation = bone.animations[0].serialize();
@@ -175,7 +179,11 @@
                 }
     
                 var bone = new Bone(parsedBone.name, skeleton, parentBone, Matrix.FromArray(parsedBone.matrix));
-    
+                
+                if (parsedBone.length){
+                    bone.length = parsedBone.length;
+                }
+                
                 if (parsedBone.animation) {
                     bone.animations.push(Animation.Parse(parsedBone.animation));
                 }