Browse Source

Merge pull request #5546 from jpweeks/feature/blender-filter-deforming-bones

[blender exporter] Only export bones that deform mesh geometry
Mr.doob 10 years ago
parent
commit
9b083c5b05

+ 1 - 0
utils/exporters/blender/addons/io_three/constants.py

@@ -43,6 +43,7 @@ VERTICES = 'vertices'
 FACES = 'faces'
 FACES = 'faces'
 NORMALS = 'normals'
 NORMALS = 'normals'
 BONES = 'bones'
 BONES = 'bones'
+BONE_MAP = 'boneMap'
 UVS = 'uvs'
 UVS = 'uvs'
 COLORS = 'colors'
 COLORS = 'colors'
 MIX_COLORS = 'mixColors'
 MIX_COLORS = 'mixColors'

+ 33 - 14
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -35,10 +35,14 @@ def bones(mesh):
     if not armature: return
     if not armature: return
 
 
     bones = []
     bones = []
+    bone_map = {}
+    bone_count = 0
+    bone_index_rel = 0
+
     for bone in armature.data.bones:
     for bone in armature.data.bones:
         logger.info('Parsing bone %s', bone.name)
         logger.info('Parsing bone %s', bone.name)
 
 
-        if bone.parent is None:
+        if bone.parent is None or bone.parent.use_deform is False:
             bone_pos = bone.head_local
             bone_pos = bone.head_local
             bone_index = -1
             bone_index = -1
         else:
         else:
@@ -55,14 +59,25 @@ def bones(mesh):
         y_axis = bone_world_pos.z
         y_axis = bone_world_pos.z
         z_axis = -bone_world_pos.y
         z_axis = -bone_world_pos.y
 
 
-        bones.append({
-            constants.PARENT: bone_index,
-            constants.NAME: bone.name,
-            constants.POS: (x_axis, y_axis, z_axis),
-            constants.ROTQ: (0,0,0,1)
-        })
+        if bone.use_deform:
+            logger.debug('Adding bone %s at: %s, %s', bone.name, bone_index, bone_index_rel)
+            bone_map[bone_count] = bone_index_rel
+            bone_index_rel += 1
+            bones.append({
+                constants.PARENT: bone_index,
+                constants.NAME: bone.name,
+                constants.POS: (x_axis, y_axis, z_axis),
+                constants.ROTQ: (0,0,0,1)
+            })
+        else:
+            logger.debug('Ignoring bone %s at: %s, %s', bone.name, bone_index, bone_index_rel)
 
 
-    return bones
+        bone_count += 1
+
+    return {
+        constants.BONES: bones,
+        constants.BONE_MAP: bone_map
+    }
 
 
 
 
 @_mesh
 @_mesh
@@ -362,15 +377,15 @@ def normals(mesh, options):
 
 
 
 
 @_mesh
 @_mesh
-def skin_weights(mesh):
+def skin_weights(mesh, bone_map):
     logger.debug('mesh.skin_weights(%s)', mesh)
     logger.debug('mesh.skin_weights(%s)', mesh)
-    return _skinning_data(mesh, 1)
+    return _skinning_data(mesh, bone_map, 1)
 
 
 
 
 @_mesh
 @_mesh
-def skin_indices(mesh):
+def skin_indices(mesh, bone_map):
     logger.debug('mesh.skin_indices(%s)', mesh)
     logger.debug('mesh.skin_indices(%s)', mesh)
-    return _skinning_data(mesh, 0)
+    return _skinning_data(mesh, bone_map, 0)
 
 
 
 
 @_mesh
 @_mesh
@@ -615,7 +630,7 @@ def _armature(mesh):
     return armature
     return armature
 
 
 
 
-def _skinning_data(mesh, array_index):
+def _skinning_data(mesh, bone_map, array_index):
     armature = _armature(mesh)
     armature = _armature(mesh)
     if not armature: return
     if not armature: return
 
 
@@ -639,7 +654,7 @@ def _skinning_data(mesh, array_index):
                 if bone.name != obj.vertex_groups[bone_array[index][0]].name:
                 if bone.name != obj.vertex_groups[bone_array[index][0]].name:
                     continue
                     continue
                 if array_index is 0:
                 if array_index is 0:
-                    entry = bone_index
+                    entry = bone_map.get(bone_index, -1)
                 else:
                 else:
                     entry = bone_array[index][1]
                     entry = bone_array[index][1]
 
 
@@ -668,6 +683,10 @@ def _skeletal_animations(armature, options):
 
 
     #@TODO need key constants
     #@TODO need key constants
     for bone in armature.data.bones:
     for bone in armature.data.bones:
+        if bone.use_deform is False:
+            logger.info('Skipping animation data for bone %s', bone.name)
+            continue
+
         logger.info('Parsing animation data for bone %s', bone.name)
         logger.info('Parsing animation data for bone %s', bone.name)
 
 
         keys = []
         keys = []

+ 7 - 4
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -229,7 +229,7 @@ class Geometry(base_classes.BaseNode):
     def __geometry_metadata(self, metadata): 
     def __geometry_metadata(self, metadata): 
         skip = (constants.TYPE, constants.FACES, constants.UUID,
         skip = (constants.TYPE, constants.FACES, constants.UUID,
             constants.ANIMATION, constants.SKIN_INDICES,
             constants.ANIMATION, constants.SKIN_INDICES,
-            constants.SKIN_WEIGHTS, constants.NAME)
+            constants.BONE_MAP, constants.SKIN_WEIGHTS, constants.NAME)
         vectors = (constants.VERTICES, constants.NORMALS)
         vectors = (constants.VERTICES, constants.NORMALS)
 
 
         for key in self.keys():
         for key in self.keys():
@@ -339,12 +339,15 @@ class Geometry(base_classes.BaseNode):
 
 
         if self.options.get(constants.BONES):
         if self.options.get(constants.BONES):
             logger.info('Parsing %s', constants.BONES)
             logger.info('Parsing %s', constants.BONES)
-            self[constants.BONES] = api.mesh.bones(self.node) 
+            bone_data = api.mesh.bones(self.node)
+            self[constants.BONES] = bone_data[constants.BONES]
+            self[constants.BONE_MAP] = bone_data[constants.BONE_MAP]
 
 
         if self.options.get(constants.SKINNING):
         if self.options.get(constants.SKINNING):
             logger.info('Parsing %s', constants.SKINNING)
             logger.info('Parsing %s', constants.SKINNING)
-            self[constants.SKIN_INDICES] = api.mesh.skin_indices(self.node)
-            self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights(self.node)
+            bone_map = self.get(constants.BONE_MAP) or {}
+            self[constants.SKIN_INDICES] = api.mesh.skin_indices(self.node, bone_map)
+            self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights(self.node, bone_map)
 
 
         if self.options.get(constants.MORPH_TARGETS):
         if self.options.get(constants.MORPH_TARGETS):
             logger.info('Parsing %s', constants.MORPH_TARGETS)
             logger.info('Parsing %s', constants.MORPH_TARGETS)