[Bf-extensions-cvs] [5b2953ad] blender-v3.3-release: glTF exporter: performance: cache parent/children data to avoid bad .children performance when used a lot Thanks rotoglup!

Julien Duroure noreply at git.blender.org
Sat Aug 6 11:52:54 CEST 2022


Commit: 5b2953ad0883223bf8f58cf2bd650891f759bb65
Author: Julien Duroure
Date:   Sat Aug 6 11:52:04 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rBA5b2953ad0883223bf8f58cf2bd650891f759bb65

glTF exporter: performance: cache parent/children data to avoid bad .children performance when used a lot
Thanks rotoglup!

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

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py

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

diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 98210e82..65cfb759 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -4,7 +4,7 @@
 bl_info = {
     'name': 'glTF 2.0 format',
     'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
-    "version": (3, 3, 17),
+    "version": (3, 3, 18),
     'blender': (3, 3, 0),
     'location': 'File > Import-Export',
     'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
index 36772667..c654b445 100644
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
@@ -95,10 +95,18 @@ class VExportTree:
         bpy.context.window.scene = blender_scene
         depsgraph = bpy.context.evaluated_depsgraph_get()
 
+        # Gather parent/children information once, as calling bobj.children is
+        #   very expensive operation : takes O(len(bpy.data.objects)) time.
+        blender_children = dict()
+        for bobj in bpy.data.objects:
+            bparent = bobj.parent
+            blender_children.setdefault(bobj, [])
+            blender_children.setdefault(bparent, []).append(bobj)
+
         for blender_object in [obj.original for obj in depsgraph.scene_eval.objects if obj.parent is None]:
-            self.recursive_node_traverse(blender_object, None, None, Matrix.Identity(4))
+            self.recursive_node_traverse(blender_object, None, None, Matrix.Identity(4), blender_children)
 
-    def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, parent_coll_matrix_world, armature_uuid=None, dupli_world_matrix=None):
+    def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, parent_coll_matrix_world, blender_children, armature_uuid=None, dupli_world_matrix=None):
         node = VExportNode()
         node.uuid = str(uuid.uuid4())
         node.parent_uuid = parent_uuid
@@ -199,42 +207,42 @@ class VExportTree:
 
         # standard children
         if blender_bone is None and blender_object.is_instancer is False:
-            for child_object in blender_object.children:
+            for child_object in blender_children[blender_object]:
                 if child_object.parent_bone:
                     # Object parented to bones
                     # Will be manage later
                     continue
                 else:
                     # Classic parenting
-                    self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world)
+                    self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, blender_children)
 
         # Collections
         if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
             for dupli_object in blender_object.instance_collection.all_objects:
                 if dupli_object.parent is not None:
                     continue
-                self.recursive_node_traverse(dupli_object, None, node.uuid, node.matrix_world)
+                self.recursive_node_traverse(dupli_object, None, node.uuid, node.matrix_world, blender_children)
 
         # Armature : children are bones with no parent
         if blender_object.type == "ARMATURE" and blender_bone is None:
             for b in [b for b in blender_object.pose.bones if b.parent is None]:
-                self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, node.uuid)
+                self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, blender_children, node.uuid)
 
         # Bones
         if blender_object.type == "ARMATURE" and blender_bone is not None:
             for b in blender_bone.children:
-                self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, armature_uuid)
+                self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, blender_children, armature_uuid)
 
         # Object parented to bone
         if blender_bone is not None:
-            for child_object in [c for c in blender_object.children if c.parent_bone is not None and c.parent_bone == blender_bone.name]:
-                self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world)
+            for child_object in [c for c in blender_children[blender_object] if c.parent_bone is not None and c.parent_bone == blender_bone.name]:
+                self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, blender_children)
 
         # Duplis
         if blender_object.is_instancer is True and blender_object.instance_type != 'COLLECTION':
             depsgraph = bpy.context.evaluated_depsgraph_get()
             for (dupl, mat) in [(dup.object.original, dup.matrix_world.copy()) for dup in depsgraph.object_instances if dup.parent and id(dup.parent.original) == id(blender_object)]:
-                self.recursive_node_traverse(dupl, None, node.uuid, parent_coll_matrix_world, dupli_world_matrix=mat)
+                self.recursive_node_traverse(dupl, None, node.uuid, parent_coll_matrix_world, blender_children, dupli_world_matrix=mat)
 
     def get_all_objects(self):
         return [n.uuid for n in self.nodes.values() if n.blender_type != VExportNode.BONE]



More information about the Bf-extensions-cvs mailing list