[Bf-extensions-cvs] [f5f7b1d] master: Fix T45171: FBX importer can't handle mesh bound to multiple armatures.
Bastien Montagne
noreply at git.blender.org
Sun Jun 28 17:41:27 CEST 2015
Commit: f5f7b1df1a6b304bf1daf8147afbe2074b8eef7c
Author: Bastien Montagne
Date: Sun Jun 28 17:35:01 2015 +0200
Branches: master
https://developer.blender.org/rBAf5f7b1df1a6b304bf1daf8147afbe2074b8eef7c
Fix T45171: FBX importer can't handle mesh bound to multiple armatures.
There were two issues here:
I) Since an object can only have *one* parent, it it gets created only during its parent's creation,
we could end in situation where we would be creating an armature that would need its 'fake' children
mesh objects, before we have actually created this mesh object (which would only happen during creation
of the only armature that would be its *real* parent).
This was solved by decoupling object creation/instancing and creation of objets' relationships.
II) We were only storing one set of binding data (matrices) per mesh, which obviously failed when
binding several armatures to a single mesh.
Simply fixed by storing one set of binding data per mesh per armature.
FBX can store on set of binding matrices per mesh per bone, but this is not supported by Blender!
===================================================================
M io_scene_fbx/__init__.py
M io_scene_fbx/import_fbx.py
===================================================================
diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index 48ace03..a5f4258 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -21,7 +21,7 @@
bl_info = {
"name": "FBX format",
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier",
- "version": (3, 3, 6),
+ "version": (3, 4, 0),
"blender": (2, 74, 0),
"location": "File > Import-Export",
"description": "FBX IO meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions",
diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index 4b8f3eb..851339d 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -1453,7 +1453,7 @@ class FbxImportHelperNode:
It tries to keep the correction data in one place so it can be applied consistently to the imported data.
"""
- __slots__ = ('_parent', 'anim_compensation_matrix', 'armature_setup', 'bind_matrix',
+ __slots__ = ('_parent', 'anim_compensation_matrix', 'armature_setup', 'armature', 'bind_matrix',
'bl_bone', 'bl_data', 'bl_obj', 'bone_child_matrix', 'children', 'clusters',
'fbx_elem', 'fbx_name', 'fbx_transform_data', 'fbx_type', 'has_bone_children', 'ignore', 'is_armature',
'is_bone', 'is_root', 'matrix', 'matrix_as_parent', 'matrix_geom', 'meshes', 'post_matrix', 'pre_matrix')
@@ -1469,6 +1469,7 @@ class FbxImportHelperNode:
self.is_root = False
self.is_bone = is_bone
self.is_armature = False
+ self.armature = None # For bones only, relevant armature node.
self.has_bone_children = False # True if the hierarchy below this node contains bones, important to support mixed hierarchies.
self.ignore = False # True for leaf-bones added to the end of some bone chains to set the lengths.
self.pre_matrix = None # correction matrix that needs to be applied before the FBX transform
@@ -1483,7 +1484,7 @@ class FbxImportHelperNode:
self.meshes = None # List of meshes influenced by this bone.
self.clusters = [] # Deformer Cluster nodes
- self.armature_setup = None # mesh and armature matrix when the mesh was bound
+ self.armature_setup = {} # mesh and armature matrix when the mesh was bound
self._parent = None
self.children = []
@@ -1636,6 +1637,12 @@ class FbxImportHelperNode:
for child in self.children:
child.find_correction_matrix(settings, correction_matrix_inv)
+ def find_armature_bones(self, armature):
+ for child in self.children:
+ if child.is_bone:
+ child.armature = armature
+ child.find_armature_bones(armature)
+
def find_armatures(self):
needs_armature = False
for child in self.children:
@@ -1646,18 +1653,21 @@ class FbxImportHelperNode:
if self.fbx_type in {b'Null', b'Root'}:
# if empty then convert into armature
self.is_armature = True
+ armature = self
else:
# otherwise insert a new node
armature = FbxImportHelperNode(None, None, None, False)
armature.fbx_name = "Armature"
armature.is_armature = True
- for child in self.children[:]:
+ for child in self.children:
if child.is_bone:
child.parent = armature
armature.parent = self
+ armature.find_armature_bones(armature)
+
for child in self.children:
if child.is_armature or child.is_bone:
continue
@@ -1812,7 +1822,13 @@ class FbxImportHelperNode:
return bone
- def build_node(self, fbx_tmpl, settings):
+ def build_node_obj(self, fbx_tmpl, settings):
+ if self.bl_obj:
+ return self.bl_obj
+
+ if self.is_bone or not self.fbx_elem:
+ return None
+
# create when linking since we need object data
elem_name_utf8 = self.fbx_name
@@ -1841,7 +1857,29 @@ class FbxImportHelperNode:
for child in self.children:
if child.ignore:
continue
- child_obj = child.build_skeleton_children(fbx_tmpl, settings, scene)
+ child.build_skeleton_children(fbx_tmpl, settings, scene)
+ return None
+ else:
+ # child is not a bone
+ obj = self.build_node_obj(fbx_tmpl, settings)
+
+ for child in self.children:
+ if child.ignore:
+ continue
+ child.build_skeleton_children(fbx_tmpl, settings, scene)
+
+ # instance in scene
+ obj_base = scene.objects.link(obj)
+ obj_base.select = True
+
+ return obj
+
+ def link_skeleton_children(self, fbx_tmpl, settings, scene):
+ if self.is_bone:
+ for child in self.children:
+ if child.ignore:
+ continue
+ child_obj = child.bl_obj
if child_obj:
child_obj.parent = self.bl_obj # get the armature the bone belongs to
child_obj.parent_bone = self.bl_bone
@@ -1858,20 +1896,15 @@ class FbxImportHelperNode:
child_obj.matrix_basis = child.get_matrix()
return None
else:
- # child is not a bone
- obj = self.build_node(fbx_tmpl, settings)
+ obj = self.bl_obj
for child in self.children:
if child.ignore:
continue
- child_obj = child.build_skeleton_children(fbx_tmpl, settings, scene)
+ child_obj = child.link_skeleton_children(fbx_tmpl, settings, scene)
if child_obj:
child_obj.parent = obj
- # instance in scene
- obj_base = scene.objects.link(obj)
- obj_base.select = True
-
return obj
def set_pose_matrix(self, arm):
@@ -1997,13 +2030,42 @@ class FbxImportHelperNode:
if child.ignore:
continue
child_obj = child.build_skeleton_children(fbx_tmpl, settings, scene)
+
+ return arm
+ elif self.fbx_elem:
+ obj = self.build_node_obj(fbx_tmpl, settings)
+
+ # walk through children
+ for child in self.children:
+ child.build_hierarchy(fbx_tmpl, settings, scene)
+
+ # instance in scene
+ obj_base = scene.objects.link(obj)
+ obj_base.select = True
+
+ return obj
+ else:
+ for child in self.children:
+ child.build_hierarchy(fbx_tmpl, settings, scene)
+
+ return None
+
+ def link_hierarchy(self, fbx_tmpl, settings, scene):
+ if self.is_armature:
+ arm = self.bl_obj
+
+ # Link bone children:
+ for child in self.children:
+ if child.ignore:
+ continue
+ child_obj = child.link_skeleton_children(fbx_tmpl, settings, scene)
if child_obj:
child_obj.parent = arm
# Add armature modifiers to the meshes
if self.meshes:
for mesh in self.meshes:
- (mmat, amat) = mesh.armature_setup
+ (mmat, amat) = mesh.armature_setup[self]
me_obj = mesh.bl_obj
# bring global armature & mesh matrices into *Blender* global space.
@@ -2024,7 +2086,7 @@ class FbxImportHelperNode:
# we can compute inverse parenting matrix of the mesh.
me_obj.matrix_parent_inverse = amat.inverted_safe() * mmat * me_obj.matrix_basis.inverted_safe()
- mod = mesh.bl_obj.modifiers.new(elem_name_utf8, 'ARMATURE')
+ mod = mesh.bl_obj.modifiers.new(arm.name, 'ARMATURE')
mod.object = arm
# Add bone weights to the deformers
@@ -2035,22 +2097,20 @@ class FbxImportHelperNode:
child.set_bone_weights()
return arm
- elif self.fbx_elem:
- obj = self.build_node(fbx_tmpl, settings)
+ elif self.bl_obj:
+ obj = self.bl_obj
# walk through children
for child in self.children:
- child_obj = child.build_hierarchy(fbx_tmpl, settings, scene)
+ child_obj = child.link_hierarchy(fbx_tmpl, settings, scene)
child_obj.parent = obj
- # instance in scene
- obj_base = scene.objects.link(obj)
- obj_base.select = True
-
return obj
else:
for child in self.children:
- child.build_hierarchy(fbx_tmpl, settings, scene)
+ child.link_hierarchy(fbx_tmpl, settings, scene)
+
+ return None
def is_ascii(filepath, size):
@@ -2527,7 +2587,7 @@ def load(operator, context, filepath="",
# when actually binding them via the modifier.
# Note we assume all bones were bound with the same mesh/armature (global) matrix,
# we do not support otherwise in Blender anyway!
- mesh_node.armature_setup = (mesh_matrix, armature_matrix)
+ mesh_node.armature_setup[helper_node.armature] = (mesh_matrix, armature_matrix)
meshes.add(mesh_node)
helper_node.clusters.append((fbx_cluster, meshes))
@@ -2544,6 +2604,9 @@ def load(operator, context, filepath="",
# build the Object/Armature/Bone hierarchy
root_helper.build_hierarchy(fbx_tmpl, settings, scene)
+ # Link the Object/Armature/Bone hierarchy
+ root_helper.link_hierarchy(fbx_tmpl, settings, scene)
+
# root_helper.print_info(0)
_(); del _
More information about the Bf-extensions-cvs
mailing list