[Bf-extensions-cvs] [a47e870] master: FBX: user request: check for vertices used by/assigned to more than four bones.

Bastien Montagne noreply at git.blender.org
Mon Apr 14 16:49:09 CEST 2014


Commit: a47e8703491da326e31996024576bc27ce581836
Author: Bastien Montagne
Date:   Mon Apr 14 16:46:32 2014 +0200
https://developer.blender.org/rBAa47e8703491da326e31996024576bc27ce581836

FBX: user request: check for vertices used by/assigned to more than four bones.

If new option "Simplify Skinning" is set (by default), only four most significant weights are kept.
Else, only a warning is issued.

Also added more OrederedDict's!

===================================================================

M	io_scene_fbx/__init__.py
M	io_scene_fbx/export_fbx_bin.py

===================================================================

diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index 0631c03..8d29b3a 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -220,6 +220,12 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
         description="Apply modifiers to mesh objects (except Armature ones!)",
         default=True,
     )
+    # 7.4 only
+    use_simplify_skinning = BoolProperty(
+        name="Simplify Skinning",
+        description="Many game engines do not support more than four bones per vertex, select four most important ones",
+        default=True,
+    )
     mesh_smooth_type = EnumProperty(
         name="Smoothing",
         items=(('OFF', "Off", "Don't write smoothing"),
@@ -348,6 +354,10 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
         layout.separator()
         layout.prop(self, "object_types")
         layout.prop(self, "use_mesh_modifiers")
+        if is_74bin:
+            sub = layout.column()
+            sub.enabled = ({'ARMATURE', 'MESH'} <= self.object_types)
+            sub.prop(self, "use_simplify_skinning")
         layout.prop(self, "mesh_smooth_type")
         layout.prop(self, "use_mesh_edges")
         layout.prop(self, "use_tspace")
diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index c8d71c9..c54714c 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -1843,17 +1843,37 @@ def fbx_data_armature_elements(root, armature, scene_data):
             elem_data_single_int32(fbx_skin, b"Version", FBX_DEFORMER_SKIN_VERSION)
             elem_data_single_float64(fbx_skin, b"Link_DeformAcuracy", 50.0)  # Only vague idea what it is...
 
+            # Pre-process vertex weights (also to check vertices assigned ot more than four bones).
+            is_complex_skinning = False
+            simplify_skinning = scene_data.settings.use_simplify_skinning
+            bo_vg_idx = {bo.name: obj.vertex_groups[bo.name].index for bo in clusters.keys()}
+            valid_idxs = set(bo_vg_idx.values())
+            vgroups = {vg.index: OrderedDict() for vg in obj.vertex_groups}
+            verts_vgroups = (sorted(((vg.group, vg.weight) for vg in v.groups if vg.weight and vg.group in valid_idxs),
+                                    key=lambda e: e[1], reverse=True)
+                             for v in me.vertices)
+            for idx, vgs in enumerate(verts_vgroups):
+                if len(vgs) > 4:
+                    is_complex_skinning = True
+                    if simplify_skinning:
+                        vgs[:] = vgs[:4]
+                for vg_idx, w in vgs:
+                    vgroups[vg_idx][idx] = w
+
+            if is_complex_skinning:
+                report = scene_data.settings.report
+                if simplify_skinning:
+                    report({'WARNING'}, "Some vertices were assigned to more than four bones, "
+                                        "only the four most significant weights were kept")
+                else:
+                    report({'WARNING'}, "Some vertices are assigned to more than four bones, "
+                                        "this is usually not supported by game engines")
+
             for bo, clstr_key in clusters.items():
                 # Find which vertices are affected by this bone/vgroup pair, and matching weights.
-                indices = []
-                weights = []
-                vg_idx = obj.vertex_groups[bo.name].index
-                for idx, v in enumerate(me.vertices):
-                    vert_vg = [vg for vg in v.groups if vg.group == vg_idx]
-                    if not vert_vg:
-                        continue
-                    indices.append(idx)
-                    weights.append(vert_vg[0].weight)
+                vg_idx = bo_vg_idx[bo.name]
+                indices = vgroups[vg_idx].keys()
+                weights = vgroups[vg_idx].values()
 
                 # Create the cluster.
                 fbx_clstr = elem_data_single_int64(root, b"Deformer", get_fbxuid_from_key(clstr_key))
@@ -2131,8 +2151,9 @@ def fbx_skeleton_from_armature(scene, settings, armature, objects, data_meshes,
 
         # Create skin & clusters relations (note skins are connected to geometry, *not* model!).
         _key, me, _free = data_meshes[obj]
-        clusters = {bo: get_blender_bone_cluster_key(armature, me, bo) for bo in used_bones}
-        data_deformers.setdefault(armature, {})[me] = (get_blender_armature_skin_key(armature, me), obj, clusters)
+        clusters = OrderedDict((bo, get_blender_bone_cluster_key(armature, me, bo)) for bo in used_bones)
+        data_deformers.setdefault(armature, OrderedDict())[me] = (get_blender_armature_skin_key(armature, me),
+                                                                  obj, clusters)
 
         # We don't want a regular parent relationship for those in FBX...
         arm_parents.add((armature, obj))
@@ -2878,9 +2899,9 @@ FBXSettingsMedia = namedtuple("FBXSettingsMedia", (
     "embed_textures", "copy_set",
 ))
 FBXSettings = namedtuple("FBXSettings", (
-    "to_axes", "global_matrix", "global_scale",
+    "report", "to_axes", "global_matrix", "global_scale",
     "bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed",
-    "context_objects", "object_types", "use_mesh_modifiers",
+    "context_objects", "object_types", "use_mesh_modifiers", "use_simplify_skinning",
     "mesh_smooth_type", "use_mesh_edges", "use_tspace", "use_armature_deform_only",
     "bake_anim", "bake_anim_use_nla_strips", "bake_anim_step", "bake_anim_simplify_factor",
     "use_metadata", "media_settings", "use_custom_properties",
@@ -2895,6 +2916,7 @@ def save_single(operator, scene, filepath="",
                 context_objects=None,
                 object_types=None,
                 use_mesh_modifiers=True,
+                use_simplify_skinning=True,
                 mesh_smooth_type='FACE',
                 bake_anim=True,
                 bake_anim_use_nla_strips=True,
@@ -2936,9 +2958,9 @@ def save_single(operator, scene, filepath="",
     )
 
     settings = FBXSettings(
-        (axis_up, axis_forward), global_matrix, global_scale,
+        operator.report, (axis_up, axis_forward), global_matrix, global_scale,
         bake_space_transform, global_matrix_inv, global_matrix_inv_transposed,
-        context_objects, object_types, use_mesh_modifiers,
+        context_objects, object_types, use_mesh_modifiers, use_simplify_skinning,
         mesh_smooth_type, use_mesh_edges, use_tspace, False,
         bake_anim, bake_anim_use_nla_strips, bake_anim_step, bake_anim_simplify_factor,
         False, media_settings, use_custom_properties,



More information about the Bf-extensions-cvs mailing list