[Bf-extensions-cvs] [c8d0eb3] fbx_io_development: FBX io: some work over transform system.

Bastien Montagne noreply at git.blender.org
Thu Jul 10 21:41:44 CEST 2014


Commit: c8d0eb3c83e0bc857bdfff390e717d85ff890aea
Author: Bastien Montagne
Date:   Tue Jul 8 17:22:58 2014 +0200
https://developer.blender.org/rBAc8d0eb3c83e0bc857bdfff390e717d85ff890aea

FBX io: some work over transform system.

Applied a tiny part of D607 (baking tranform into child objects as well).
Left most of it outside for now, though, for several reasons.

Also, simplified and refactored a bit transform code, export and import.
First goal was to fix 'bone rotation' issue (FBX and Blender do not have
bones oriented along the same axis), but I failed here (managed to get
rest pose (which is also bind pose) working in both export and import,
but pose/animation break completely, giving isane results). For now,
bone correction matrix is identity (which means we are in same state as before,
no correction applied to bones).

Note fbx exported from Blender imports OK in Blender, which means error is coherent.
I just can't understand how it's expected in FBX... :/

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

M	io_scene_fbx/fbx_utils.py
M	io_scene_fbx/import_fbx.py

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

diff --git a/io_scene_fbx/fbx_utils.py b/io_scene_fbx/fbx_utils.py
index 9b3f638..3af51a4 100644
--- a/io_scene_fbx/fbx_utils.py
+++ b/io_scene_fbx/fbx_utils.py
@@ -72,7 +72,8 @@ FBX_KTIME = 46186158000  # This is the number of "ktimes" in one second (yep, pr
 
 MAT_CONVERT_LAMP = Matrix.Rotation(math.pi / 2.0, 4, 'X')  # Blender is -Z, FBX is -Y.
 MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y')  # Blender is -Z, FBX is +X.
-#MAT_CONVERT_BONE = Matrix.Rotation(math.pi / -2.0, 4, 'X')  # Blender is +Y, FBX is +Z.
+# XXX I can't get this working :(
+#MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z')  # Blender is +Y, FBX is -X.
 MAT_CONVERT_BONE = Matrix()
 
 
@@ -914,11 +915,10 @@ class ObjectWrapper(metaclass=MetaObjectWrapper):
         return False
 
     def use_bake_space_transform(self, scene_data):
-        # NOTE: Only applies to object types supporting this!!! Currently, only meshes...
-        #       Also, do not apply it to children objects.
+        # NOTE: Only applies to object types supporting this!!! Currently, only meshes and the like...
         # TODO: Check whether this can work for bones too...
-        return (scene_data.settings.bake_space_transform and self._tag == 'OB' and
-                self.bdata.type in BLENDER_OBJECT_TYPES_MESHLIKE and not self.has_valid_parent(scene_data.objects))
+        return (scene_data.settings.bake_space_transform and self._tag in {'OB', 'DP'} and
+                self.bdata.type in BLENDER_OBJECT_TYPES_MESHLIKE)
 
     def fbx_object_matrix(self, scene_data, rest=False, local_space=False, global_space=False):
         """
@@ -936,34 +936,32 @@ class ObjectWrapper(metaclass=MetaObjectWrapper):
         is_global = (not local_space and
                      (global_space or not (self._tag in {'DP', 'BO'} or self.has_valid_parent(scene_data.objects))))
 
+        # Since we have to apply corrections to some types of object, we always need local Blender space here...
+        matrix = self.matrix_rest_local if rest else self.matrix_local
+        parent = self.parent
+
+        # Bones, lamps and cameras need to be rotated (in local space!).
         if self._tag == 'BO':
-            if rest:
-                matrix = self.matrix_rest_global if is_global else self.matrix_rest_local
-            else:  # Current pose.
-                matrix = self.matrix_global if is_global else self.matrix_local
-        else:
-            # Since we have to apply corrections to some types of object, we always need local Blender space here...
-            matrix = self.matrix_local
-            parent = self.parent
-
-            # Lamps and cameras need to be rotated (in local space!).
-            if self.bdata.type == 'LAMP':
-                matrix = matrix * MAT_CONVERT_LAMP
-            elif self.bdata.type == 'CAMERA':
-                matrix = matrix * MAT_CONVERT_CAMERA
-
-            # Our matrix is in local space, time to bring it in its final desired space.
-            if parent:
-                if is_global:
-                    # Move matrix to global Blender space.
-                    matrix = parent.matrix_global * matrix
-                elif parent.use_bake_space_transform(scene_data):
-                    # Blender's and FBX's local space of parent may differ if we use bake_space_transform...
-                    # Apply parent's *Blender* local space...
-                    matrix = parent.matrix_local * matrix
-                    # ...and move it back into parent's *FBX* local space.
-                    par_mat = parent.fbx_object_matrix(scene_data, local_space=True)
-                    matrix = par_mat.inverted() * matrix
+            # XXX This should work smoothly, but actually is only OK for 'rest' pose, actual pose/animations
+            #     give insane results... :(
+            matrix = matrix * MAT_CONVERT_BONE
+        elif self.bdata.type == 'LAMP':
+            matrix = matrix * MAT_CONVERT_LAMP
+        elif self.bdata.type == 'CAMERA':
+            matrix = matrix * MAT_CONVERT_CAMERA
+
+        # Our matrix is in local space, time to bring it in its final desired space.
+        if parent:
+            if is_global:
+                # Move matrix to global Blender space.
+                matrix = (parent.matrix_rest_global if rest else parent.matrix_global) * matrix
+            elif parent.use_bake_space_transform(scene_data):
+                # Blender's and FBX's local space of parent may differ if we use bake_space_transform...
+                # Apply parent's *Blender* local space...
+                matrix = (parent.matrix_rest_local if rest else parent.matrix_local) * matrix
+                # ...and move it back into parent's *FBX* local space.
+                par_mat = parent.fbx_object_matrix(scene_data, rest=rest, local_space=True)
+                matrix = par_mat.inverted() * matrix
 
         if self.use_bake_space_transform(scene_data):
             # If we bake the transforms we need to post-multiply inverse global transform.
diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index a29506a..2e7708d 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -52,6 +52,10 @@ fbx_elem_nil = None
 # Units convertors...
 convert_deg_to_rad_iter = units_convertor_iter("degree", "radian")
 
+MAT_CONVERT_BONE = fbx_utils.MAT_CONVERT_BONE.inverted()
+MAT_CONVERT_LAMP = fbx_utils.MAT_CONVERT_LAMP.inverted()
+MAT_CONVERT_CAMERA = fbx_utils.MAT_CONVERT_CAMERA.inverted()
+
 
 def elem_find_first(elem, id_search, default=None):
     for fbx_item in elem.elems:
@@ -386,9 +390,9 @@ def blen_read_object(fbx_tmpl, fbx_obj, object_data):
 
     # rotation corrections
     if obj.type == 'CAMERA':
-        rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'Y')
+        rot_alt_mat = MAT_CONVERT_CAMERA
     elif obj.type == 'LAMP':
-        rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'X')
+        rot_alt_mat = MAT_CONVERT_LAMP
     else:
         rot_alt_mat = Matrix()
 
@@ -432,6 +436,16 @@ def blen_read_armatures_add_bone(bl_obj, bl_arm, bones, b_uuid, matrices, fbx_tm
         bmat_glob = array_to_matrix4(elm.props[0]) if elm is not None else Matrix()
         elm = elem_find_first(fbx_cdata, b'TransformAssociateModel', default=None)
         amat_glob = array_to_matrix4(elm.props[0]) if elm is not None else Matrix()
+
+        mmat_glob = bmat_glob * mmat_bone
+
+        # We seek for matrix of bone in armature space...
+        bmat_arm = amat_glob.inverted() * bmat_glob
+
+        # Bone correction, works here...
+        bmat_loc = (p_ebo.matrix.inverted() * bmat_arm) if p_ebo else bmat_arm
+        bmat_loc = bmat_loc * MAT_CONVERT_BONE
+        bmat_arm = (p_ebo.matrix * bmat_loc) if p_ebo else bmat_loc
     else:
         # Armature bound to no mesh...
         fbx_cdata, meshes, objects = (None, (), ())
@@ -442,18 +456,14 @@ def blen_read_armatures_add_bone(bl_obj, bl_arm, bones, b_uuid, matrices, fbx_tm
                      elem_find_first(fbx_tmpl_model, b'Properties70', fbx_elem_nil))
         assert(fbx_props[0] is not None)
 
-        transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, Matrix())
-        bmat_glob = blen_read_object_transform_do(transform_data)
-        if p_ebo:
-            # Bring back matrix in armature space.
-            bmat_glob = p_ebo.matrix * bmat_glob
-        # And back into global space...
-        bmat_glob = amat_glob * bmat_glob
+        # Bone correction, works here...
+        transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, MAT_CONVERT_BONE)
+        bmat_loc = blen_read_object_transform_do(transform_data)
+        # Bring back matrix in armature space.
+        bmat_arm = (p_ebo.matrix * bmat_loc) if p_ebo else bmat_loc
 
     # ----
     # Now, create the (edit)bone.
-    # We seek for matrix of bone in armature space...
-    bmat_arm = amat_glob.inverted() * bmat_glob
     bone_name = elem_name_ensure_class(fbx_bdata, b'Model')
 
     ebo = bl_arm.edit_bones.new(name=bone_name)
@@ -485,7 +495,6 @@ def blen_read_armatures_add_bone(bl_obj, bl_arm, bones, b_uuid, matrices, fbx_tm
     # Note we assume all bones were bound with the same mesh/armature (global) matrix, we do not support otherwise
     # in Blender anyway!
     if mmat_bone is not None:
-        mmat_glob = bmat_glob * mmat_bone
         for obj in objects:
             if obj in matrices:
                 continue
@@ -561,7 +570,8 @@ def blen_read_armatures(fbx_tmpl, armatures, fbx_bones_to_fake_object, scene, gl
             pbo = b_item[1] = bl_adata.pose.bones[bl_bname]
             transform_data = object_tdata_cache.get(pbo)
             if transform_data is None:
-                transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, Matrix())
+                # Bone correction, gives a mess as result. :(
+                transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, MAT_CONVERT_BONE)
                 object_tdata_cache[pbo] = transform_data
             mat = blen_read_object_transform_do(transform_data)
             if pbo.parent:



More information about the Bf-extensions-cvs mailing list