[Bf-extensions-cvs] [2e372f0] fbx_io_development: FBX import: Refactor anim system a bit.

Bastien Montagne noreply at git.blender.org
Mon Jul 21 21:16:33 CEST 2014


Commit: 2e372f06d6f59e98801eddfa7574c37f710f7b44
Author: Bastien Montagne
Date:   Mon Jul 21 21:11:46 2014 +0200
Branches: fbx_io_development
https://developer.blender.org/rBA2e372f06d6f59e98801eddfa7574c37f710f7b44

FBX import: Refactor anim system a bit.

Hopefully it's more consistent now, should be easier too if we want to read more
animated things later (like materials things...).

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

M	io_scene_fbx/import_fbx.py

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

diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index ff75011..18f31a0 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -583,7 +583,7 @@ def blen_read_armatures(fbx_tmpl, armatures, fbx_bones_to_fake_object, scene, gl
 
 # ---------
 # Animation
-def blen_read_animations_curves_iter(curves, blen_start_offset, fbx_start_offset, fps):
+def blen_read_animations_curves_iter(fbx_curves, blen_start_offset, fbx_start_offset, fps):
     """
     Get raw FBX AnimCurve list, and yield values for all curves at each singular curves' keyframes,
     together with (blender) timing, in frames.
@@ -594,29 +594,30 @@ def blen_read_animations_curves_iter(curves, blen_start_offset, fbx_start_offset
     from .fbx_utils import FBX_KTIME
     timefac = fps / FBX_KTIME
 
-    fbx_curves = tuple([0,
-                        elem_prop_first(elem_find_first(c[2], b'KeyTime')),
-                        elem_prop_first(elem_find_first(c[2], b'KeyValueFloat'))]
-                       for c in curves)
+    curves = tuple([0,
+                    elem_prop_first(elem_find_first(c[2], b'KeyTime')),
+                    elem_prop_first(elem_find_first(c[2], b'KeyValueFloat')),
+                    c]
+                    for c in fbx_curves)
 
     while True:
-        tmin = min(fbx_curves, key=lambda e: e[1][e[0]])
+        tmin = min(curves, key=lambda e: e[1][e[0]])
         curr_fbxktime = tmin[1][tmin[0]]
         curr_values = []
         do_break = True
-        for item in fbx_curves:
-            idx, times, values = item
+        for item in curves:
+            idx, times, values, fbx_curve = item
             if idx != -1:
                 do_break = False
             if times[idx] > curr_fbxktime:
                 if idx == 0:
-                    curr_values.append(values[idx])
+                    curr_values.append((values[idx], fbx_curve))
                 else:
                     # Interpolate between this key and the previous one.
                     ifac = (curr_fbxktime - times[idx - 1]) / (times[idx] - times[idx - 1])
-                    curr_values.append((values[idx] - values[idx - 1]) * ifac + values[idx - 1])
+                    curr_values.append(((values[idx] - values[idx - 1]) * ifac + values[idx - 1], fbx_curve))
             else:
-                curr_values.append(values[idx])
+                curr_values.append((values[idx], fbx_curve))
                 if idx >= 0:
                     idx += 1
                     if idx >= len(times):
@@ -629,109 +630,107 @@ def blen_read_animations_curves_iter(curves, blen_start_offset, fbx_start_offset
             break
 
 
-def blen_read_animations_action_object(action, ob, obpath, grpname, cnodes, global_matrix, force_global, fps):
+def blen_read_animations_action_item(action, item, cnodes, global_matrix, force_global, fps):
     """
     'Bake' loc/rot/scale into the action, taking into account global_matrix if no parent is present.
     """
-    from bpy.types import Object
+    from bpy.types import Object, PoseBone, ShapeKey
     from mathutils import Euler, Matrix
     from itertools import chain
 
-    if ob not in object_tdata_cache:
-        print("ERROR! object '%s' has no transform data, while being animated!" % ob.name)
-
+    blen_curves = []
     fbx_curves = []
-    # Since we might get other channels animated in the end, due to all FBX transform magic,
-    # we need to add curves for whole loc/rot/scale in any case.
-    rot_mode = ob.rotation_mode
-    if rot_mode == 'QUATERNION':
-        obprops = ((obpath + "location", 3, grpname or "Location"),
-                   (obpath + "rotation_quaternion", 4, grpname or "Quaternion Rotation"),
-                   (obpath + "scale", 3, grpname or "Scale"))
-    elif rot_mode == 'AXIS_ANGLE':
-        obprops = ((obpath + "location", 3, grpname or "Location"),
-                   (obpath + "rotation_axis_angle", 4, grpname or "Axis Angle Rotation"),
-                   (obpath + "scale", 3, grpname or "Scale"))
-    else:  # Euler
-        obprops = ((obpath + "location", 3, grpname or "Location"),
-                   (obpath + "rotation_euler", 3, grpname or "Euler Rotation"),
-                   (obpath + "scale", 3, grpname or "Scale"))
-    blen_curves = [action.fcurves.new(obprop, channel, grpname)
-                   for obprop, nbr_channels, grpname in obprops for channel in range(nbr_channels)]
-    for acn_uuid, (curves, fbxprop) in cnodes.items():
-        for ac_uuid, ((fbx_acdata, _blen_data), channel) in curves.items():
-            fbx_curves.append((fbxprop, channel, fbx_acdata))
-
-    transform_data = object_tdata_cache[ob]
-
-    rot_prev = ob.rotation_euler.copy()
-    # We assume for now blen init point is frame 1.0, while FBX ktime init point is 0.
-    for frame, values in blen_read_animations_curves_iter(fbx_curves, 1.0, 0, fps):
-        for v, (fbxprop, channel, _fbx_acdata) in zip(values, fbx_curves):
-            if fbxprop == b'Lcl Translation':
-                transform_data.loc[channel] = v
-            elif fbxprop == b'Lcl Rotation':
-                transform_data.rot[channel] = v
-            elif fbxprop == b'Lcl Scaling':
-                transform_data.sca[channel] = v
-        mat = blen_read_object_transform_do(transform_data)
-        # Don't forget global matrix - but never for bones!
-        if isinstance(ob, Object):
-            if (not ob.parent or force_global) and global_matrix is not None:
-                mat = global_matrix * mat
-        else:  # PoseBone, Urg!
-            # First, get local (i.e. parentspace) rest pose matrix
-            restmat = ob.bone.matrix_local
-            if ob.parent:
-                restmat = ob.parent.bone.matrix_local.inverted() * restmat
-            # And now, remove that rest pose matrix from current mat (also in parent space).
-            mat = restmat.inverted() * mat
-
-        # Now we have a virtual matrix of transform from AnimCurves, we can insert keyframes!
-        loc, rot, sca = mat.decompose()
+    props = []
+
+    if isinstance(item, ShapeKey):
+        props = [(item.path_from_id("value"), 1, "Key")]
+    else:  # Object or PoseBone:
+        if item not in object_tdata_cache:
+            print("ERROR! object '%s' has no transform data, while being animated!" % ob.name)
+            return
+
+        # We want to create actions for objects, but for bones we 'reuse' armatures' actions!
+        grpname = None
+        if item.id_data != item:
+            grpname = item.name
+
+        # Since we might get other channels animated in the end, due to all FBX transform magic,
+        # we need to add curves for whole loc/rot/scale in any case.
+        props = [(item.path_from_id("location"), 3, grpname or "Location"),
+                 None,
+                 (item.path_from_id("scale"), 3, grpname or "Scale")]
+        rot_mode = item.rotation_mode
         if rot_mode == 'QUATERNION':
-            pass  # nothing to do!
+            props[1] = (item.path_from_id("rotation_quaternion"), 4, grpname or "Quaternion Rotation")
         elif rot_mode == 'AXIS_ANGLE':
-            vec, ang = rot.to_axis_angle()
-            rot = ang, vec.x, vec.y, vec.z
+            props[1] = (item.path_from_id("rotation_axis_angle"), 4, grpname or "Axis Angle Rotation")
         else:  # Euler
-            rot = rot.to_euler(rot_mode, rot_prev)
-            rot_prev = rot
-        for fc, value in zip(blen_curves, chain(loc, rot, sca)):
-            fc.keyframe_points.insert(frame, value, {'NEEDED', 'FAST'}).interpolation = 'LINEAR'
-
-    # Since we inserted our keyframes in 'FAST' mode, we have to update the fcurves now.
-    for fc in blen_curves:
-        fc.update()
+            props[1] = (item.path_from_id("rotation_euler"), 3, grpname or "Euler Rotation")
 
+    blen_curves = [action.fcurves.new(prop, channel, grpname)
+                   for prop, nbr_channels, grpname in props for channel in range(nbr_channels)]
 
-def blen_read_animations_action_shapes(action, kb, curves, fps):
-    """
-    'Bake' shapekeys' value into the action.
-    """
-    fbx_curves = []
-    kbpath = kb.path_from_id("value")
-
-    blen_curves = [action.fcurves.new(kbpath, 0, "Key")]
-    for ac_uuid, ((fbx_acdata, _blen_data), channel) in curves.items():
-        fbx_curves.append((b'DeformPercent', channel, fbx_acdata))
-
-    # We assume for now blen init point is frame 1.0, while FBX ktime init point is 0.
-    for frame, values in blen_read_animations_curves_iter(fbx_curves, 1.0, 0, fps):
-        value = 0.0
-        for v, (fbxprop, channel, _fbx_acdata) in zip(values, fbx_curves):
-            assert(fbxprop == b'DeformPercent')
-            value = v / 100.0
+    for curves, fbxprop in cnodes.values():
+        for (fbx_acdata, _blen_data), channel in curves.values():
+            fbx_curves.append((fbxprop, channel, fbx_acdata))
 
-        for fc, v in zip(blen_curves, (value,)):
-            fc.keyframe_points.insert(frame, v, {'NEEDED', 'FAST'}).interpolation = 'LINEAR'
+    if isinstance(item, ShapeKey):
+        # We assume for now blen init point is frame 1.0, while FBX ktime init point is 0.
+        for frame, values in blen_read_animations_curves_iter(fbx_curves, 1.0, 0, fps):
+            value = 0.0
+            for v, (fbxprop, channel, _fbx_acdata) in values:
+                assert(fbxprop == b'DeformPercent')
+                assert(channel == 0)
+                value = v / 100.0
+
+            for fc, v in zip(blen_curves, (value,)):
+                fc.keyframe_points.insert(frame, v, {'NEEDED', 'FAST'}).interpolation = 'LINEAR'
+
+    else:  # Object or PoseBone:
+        transform_data = object_tdata_cache[item]
+        rot_prev = item.rotation_euler.copy()
+
+        # We assume for now blen init point is frame 1.0, while FBX ktime init point is 0.
+        for frame, values in blen_read_animations_curves_iter(fbx_curves, 1.0, 0, fps):
+            for v, (fbxprop, channel, _fbx_acdata) in values:
+                if fbxprop == b'Lcl Translation':
+                    transform_data.loc[channel] = v
+                elif fbxprop == b'Lcl Rotation':
+                    transform_data.rot

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list