[Bf-extensions-cvs] [8d9e3c94] master: glTF exporter: performance: huge speedup when exporting using sample animations

Julien Duroure noreply at git.blender.org
Wed Sep 11 22:18:07 CEST 2019


Commit: 8d9e3c94aff9e366d9a4804d98b2517bd04244f6
Author: Julien Duroure
Date:   Wed Sep 11 22:17:38 2019 +0200
Branches: master
https://developer.blender.org/rBA8d9e3c94aff9e366d9a4804d98b2517bd04244f6

glTF exporter: performance: huge speedup when exporting using sample animations

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

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_cache.py

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

diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 3460c27c..6630ea1b 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -15,7 +15,7 @@
 bl_info = {
     'name': 'glTF 2.0 format',
     'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
-    "version": (0, 9, 62),
+    "version": (0, 9, 63),
     'blender': (2, 81, 6),
     'location': 'File > Import-Export',
     'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
index 5d7763d0..20e7dbb6 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
@@ -16,7 +16,7 @@ import bpy
 import mathutils
 import typing
 
-from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached
+from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached, bonecache
 from io_scene_gltf2.blender.com import gltf2_blender_math
 from io_scene_gltf2.blender.exp import gltf2_blender_get
 from io_scene_gltf2.blender.exp import gltf2_blender_extract
@@ -111,6 +111,47 @@ class Keyframe:
         self.__out_tangent = self.__set_indexed(value)
 
 
+
+ at bonecache
+def get_bone_matrix(blender_object_if_armature: typing.Optional[bpy.types.Object],
+                     channels: typing.Tuple[bpy.types.FCurve],
+                     bake_bone: typing.Union[str, None],
+                     bake_channel: typing.Union[str, None],
+                     bake_range_start,
+                     bake_range_end,
+                     action_name: str,
+                     current_frame: int,
+                     step: int
+                     ):
+
+    data = {}
+
+    if bake_bone is None:
+        # Find the start and end of the whole action group
+        ranges = [channel.range() for channel in channels]
+
+        start_frame = min([channel.range()[0] for channel in channels])
+        end_frame = max([channel.range()[1] for channel in channels])
+    else:
+        start_frame = bake_range_start
+        end_frame = bake_range_end
+
+    frame = start_frame
+    while frame <= end_frame:
+        data[frame] = {}
+        # we need to bake in the constraints
+        bpy.context.scene.frame_set(frame)
+        for pbone in blender_object_if_armature.pose.bones:
+            if bake_bone is None:
+                matrix = pbone.matrix_basis
+            else:
+                matrix = pbone.matrix
+                matrix = blender_object_if_armature.convert_space(pose_bone=pbone, matrix=matrix, from_space='POSE', to_space='LOCAL')
+            data[frame][pbone.name] = matrix
+        frame += step
+
+    return data
+
 # cache for performance reasons
 @cached
 def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Object],
@@ -154,14 +195,20 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec
         while frame <= end_frame:
             key = Keyframe(channels, frame, bake_channel)
             if isinstance(pose_bone_if_armature, bpy.types.PoseBone):
-                # we need to bake in the constraints
-                bpy.context.scene.frame_set(frame)
-                if bake_bone is None:
-                    trans, rot, scale = pose_bone_if_armature.matrix_basis.decompose()
-                else:
-                    matrix = pose_bone_if_armature.matrix
-                    new_matrix = blender_object_if_armature.convert_space(pose_bone=pose_bone_if_armature, matrix=matrix, from_space='POSE', to_space='LOCAL')
-                    trans, rot, scale = new_matrix.decompose()
+
+                mat = get_bone_matrix(
+                    blender_object_if_armature,
+                    channels,
+                    bake_bone,
+                    bake_channel,
+                    bake_range_start,
+                    bake_range_end,
+                    action_name,
+                    frame,
+                    step
+                )
+                trans, rot, scale = mat.decompose()
+
                 if bake_channel is None:
                     target_property = channels[0].data_path.split('.')[-1]
                 else:
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cache.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cache.py
index 99286aea..e73e5522 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cache.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cache.py
@@ -65,6 +65,27 @@ def cached(func):
             return result
     return wrapper_cached
 
+def bonecache(func):
+
+    @functools.wraps(func)
+    def wrapper_bonecache(*args, **kwargs):
+        if args[2] is None:
+            pose_bone_if_armature = gltf2_blender_get.get_object_from_datapath(args[0],
+                                                                args[1][0].data_path)
+        else:
+            pose_bone_if_armature = args[0].pose.bones[args[2]]
+
+        if not hasattr(func, "__current_action_name"):
+            func.__current_action_name = None
+            func.__bonecache = {}
+        if args[6] != func.__current_action_name:
+            result = func(*args)
+            func.__bonecache = result
+            func.__current_action_name = args[6]
+            return result[args[7]][pose_bone_if_armature.name]
+        else:
+            return func.__bonecache[args[7]][pose_bone_if_armature.name]
+    return wrapper_bonecache
 
 # TODO: replace "cached" with "unique" in all cases where the caching is functional and not only for performance reasons
 call_or_fetch = cached



More information about the Bf-extensions-cvs mailing list