diff options
author | Philipp <Hotox> | 2020-05-22 16:30:56 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-05-22 16:30:56 +0300 |
commit | 8e70aeae091c5b3578ded4b6977150e6d19b3c48 (patch) | |
tree | 1a9d179c48b74ea6ec7c07102c28351cad42ef70 /io_scene_fbx | |
parent | ee468ba535022efc699309aaa29659e52cb4aa35 (diff) |
Fix T76566: Fix slow FBX import of long animations.
Note that this patches changes how we insert keyframes, since we cannot
use the `'NEEDED'` option of the slower previous code, we may generate
more keys than needed.
This change gives about 60 times speedup when importing heavy animations
though, so think that trade-of is totally acceptable.
Patch by @Hotox, with some fixes and cleanup by @mont29.
Differential: https://developer.blender.org/D7762
Diffstat (limited to 'io_scene_fbx')
-rw-r--r-- | io_scene_fbx/__init__.py | 2 | ||||
-rw-r--r-- | io_scene_fbx/import_fbx.py | 33 |
2 files changed, 29 insertions, 6 deletions
diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index b935768d..08e95cf9 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": (4, 20, 3), + "version": (4, 21, 0), "blender": (2, 81, 6), "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 1c3447ef..e580a147 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -576,6 +576,14 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): blen_curves = [] props = [] + keyframes = {} + + # Add each keyframe to the keyframe dict + def store_keyframe(fc, frame, value): + fc_key = (fc.data_path, fc.array_index) + if not keyframes.get(fc_key): + keyframes[fc_key] = [] + keyframes[fc_key].append((frame, value)) if isinstance(item, Material): grpname = item.name @@ -618,7 +626,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value[channel] = v for fc, v in zip(blen_curves, value): - fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' + store_keyframe(fc, frame, v) elif isinstance(item, ShapeKey): for frame, values in blen_read_animations_curves_iter(fbx_curves, anim_offset, 0, fps): @@ -629,7 +637,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value = v / 100.0 for fc, v in zip(blen_curves, (value,)): - fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' + store_keyframe(fc, frame, v) elif isinstance(item, Camera): for frame, values in blen_read_animations_curves_iter(fbx_curves, anim_offset, 0, fps): @@ -640,7 +648,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value = v for fc, v in zip(blen_curves, (value,)): - fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' + store_keyframe(fc, frame, v) else: # Object or PoseBone: if item.is_bone: @@ -652,7 +660,6 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): rot_eul_prev = bl_obj.rotation_euler.copy() rot_quat_prev = bl_obj.rotation_quaternion.copy() - # Pre-compute inverted local rest matrix of the bone, if relevant. restmat_inv = item.get_bind_matrix().inverted_safe() if item.is_bone else None @@ -694,8 +701,24 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): else: # Euler rot = rot.to_euler(rot_mode, rot_eul_prev) rot_eul_prev = rot + + # Add each keyframe and its value to the keyframe dict for fc, value in zip(blen_curves, chain(loc, rot, sca)): - fc.keyframe_points.insert(frame, value, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' + store_keyframe(fc, frame, value) + + # Add all keyframe points to the fcurves at once and modify them after + for fc_key, key_values in keyframes.items(): + data_path, index = fc_key + + # Add all keyframe points at once + fcurve = action.fcurves.find(data_path=data_path, index=index) + num_keys = len(key_values) + fcurve.keyframe_points.add(num_keys) + + # Apply values to each keyframe point + for kf_point, v in zip(fcurve.keyframe_points, key_values): + kf_point.co = v + kf_point.interpolation = 'LINEAR' # Since we inserted our keyframes in 'FAST' mode, we have to update the fcurves now. for fc in blen_curves: |