[Bf-extensions-cvs] [06bb353c] master: glTF importer: big perf improvement

Julien Duroure noreply at git.blender.org
Thu Sep 26 18:15:59 CEST 2019


Commit: 06bb353c848921a3f68f928aea154d471555e2dc
Author: Julien Duroure
Date:   Thu Sep 26 16:35:44 2019 +0200
Branches: master
https://developer.blender.org/rBA06bb353c848921a3f68f928aea154d471555e2dc

glTF importer: big perf improvement

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

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/imp/gltf2_blender_animation_weight.py
M	io_scene_gltf2/blender/imp/gltf2_blender_gltf.py
M	io_scene_gltf2/blender/imp/gltf2_blender_mesh.py
M	io_scene_gltf2/blender/imp/gltf2_blender_primitive.py
M	io_scene_gltf2/blender/imp/gltf2_blender_scene.py
M	io_scene_gltf2/blender/imp/gltf2_blender_skin.py

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

diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 448266f1..5282cde6 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, 73),
+    "version": (0, 9, 74),
     'blender': (2, 81, 6),
     'location': 'File > Import-Export',
     'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_animation_weight.py b/io_scene_gltf2/blender/imp/gltf2_blender_animation_weight.py
index baa0d95e..3c861451 100644
--- a/io_scene_gltf2/blender/imp/gltf2_blender_animation_weight.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_animation_weight.py
@@ -70,11 +70,8 @@ class BlenderWeightAnim():
         values = BinaryData.get_data_from_accessor(gltf, animation.samplers[channel.sampler].output)
 
         # retrieve number of targets
-        nb_targets = 0
-        for prim in gltf.data.meshes[gltf.data.nodes[node_idx].mesh].primitives:
-            if prim.targets:
-                if len(prim.targets) > nb_targets:
-                    nb_targets = len(prim.targets)
+        pymesh = gltf.data.meshes[gltf.data.nodes[node_idx].mesh]
+        nb_targets = len(pymesh.shapekey_names)
 
         if animation.samplers[channel.sampler].interpolation == "CUBICSPLINE":
             offset = nb_targets
@@ -92,8 +89,8 @@ class BlenderWeightAnim():
         group = action.groups[group_name]
 
         for sk in range(nb_targets):
-            if gltf.shapekeys[sk] is not None: # Do not animate shapekeys not created
-                kb_name = obj.data.shape_keys.key_blocks[gltf.shapekeys[sk]].name
+            if pymesh.shapekey_names[sk] is not None: # Do not animate shapekeys not created
+                kb_name = pymesh.shapekey_names[sk]
                 data_path = "key_blocks[" + json.dumps(kb_name) + "].value"
                 fcurve = action.fcurves.new(data_path=data_path)
                 fcurve.group = group
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py b/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py
index 0f603bf3..c0507c03 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py
@@ -109,10 +109,6 @@ class BlenderGlTF():
         # Init is to False, and will be set to True during creation
         gltf.animation_object = False
 
-        # Store shapekeys equivalent between target & shapekey index
-        # For example when no POSITION on target
-        gltf.shapekeys = {}
-
         # Blender material
         if gltf.data.materials:
             for material in gltf.data.materials:
@@ -281,6 +277,33 @@ class BlenderGlTF():
                 mesh.blender_name = None
                 mesh.is_weight_animated = False
 
+        # Calculate names for each mesh's shapekeys
+        for mesh in gltf.data.meshes:
+            mesh.shapekey_names = []
+            used_names = set()
+
+            for sk, target in enumerate(mesh.primitives[0].targets or []):
+                if 'POSITION' not in target:
+                    mesh.shapekey_names.append(None)
+                    continue
+
+                # Check if glTF file has some extras with targetNames. Otherwise
+                # use the name of the POSITION accessor on the first primitive.
+                shapekey_name = None
+                if mesh.extras is not None:
+                    if 'targetNames' in mesh.extras and sk < len(mesh.extras['targetNames']):
+                        shapekey_name = mesh.extras['targetNames'][sk]
+                if shapekey_name is None:
+                    if gltf.data.accessors[target['POSITION']].name is not None:
+                        shapekey_name = gltf.data.accessors[target['POSITION']].name
+                if shapekey_name is None:
+                    shapekey_name = "target_" + str(sk)
+
+                shapekey_name = BlenderGlTF.find_unused_name(used_names, shapekey_name)
+                used_names.add(shapekey_name)
+
+                mesh.shapekey_names.append(shapekey_name)
+
     @staticmethod
     def find_unused_name(haystack, desired_name):
         """Finds a name not in haystack and <= 63 UTF-8 bytes.
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py
index 69aebd13..ba22d0cc 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py
@@ -14,10 +14,11 @@
 
 import bpy
 import bmesh
+from mathutils import Vector
 
+from .gltf2_blender_material import BlenderMaterial
 from .gltf2_blender_primitive import BlenderPrimitive
 from ...io.imp.gltf2_io_binary import BinaryData
-from ...io.com.gltf2_io_color_management import color_linear_to_srgb
 from ..com.gltf2_blender_conversion import loc_gltf_to_blender
 
 
@@ -31,21 +32,48 @@ class BlenderMesh():
         """Mesh creation."""
         pymesh = gltf.data.meshes[mesh_idx]
 
-        # Geometry
-        if pymesh.name:
-            mesh_name = pymesh.name
-        else:
-            mesh_name = "Mesh_" + str(mesh_idx)
+        # Create one bmesh, add all primitives to it, and then convert it to a
+        # mesh.
+        bme = bmesh.new()
 
-        mesh = bpy.data.meshes.new(mesh_name)
-        verts = []
-        edges = []
-        faces = []
-        for prim in pymesh.primitives:
-            verts, edges, faces = BlenderPrimitive.create(gltf, prim, verts, edges, faces)
+        # List of all the materials this mesh will use. The material each
+        # primitive uses is set by giving an index into this list.
+        materials = []
 
-        mesh.from_pydata(verts, edges, faces)
-        mesh.validate()
+        # Process all primitives
+        for prim in pymesh.primitives:
+            prim.blender_texcoord = {}
+
+            if prim.material is None:
+                material_idx = None
+            else:
+                pymaterial = gltf.data.materials[prim.material]
+
+                vertex_color = None
+                if 'COLOR_0' in prim.attributes:
+                    vertex_color = 'COLOR_0'
+
+                # Create Blender material if needed
+                if vertex_color not in pymaterial.blender_material:
+                    BlenderMaterial.create(gltf, prim.material, vertex_color)
+                material_name = pymaterial.blender_material[vertex_color]
+                material = bpy.data.materials[material_name]
+
+                try:
+                    material_idx = materials.index(material)
+                except ValueError:
+                    materials.append(material)
+                    material_idx = len(materials) - 1
+
+            BlenderPrimitive.add_primitive_to_bmesh(gltf, bme, pymesh, prim, material_idx)
+
+        name = pymesh.name or 'Mesh_' + str(mesh_idx)
+        mesh = bpy.data.meshes.new(name)
+        BlenderMesh.bmesh_to_mesh(gltf, pymesh, bme, mesh)
+        bme.free()
+        for material in materials:
+            mesh.materials.append(material)
+        mesh.update()
 
         pymesh.blender_name = mesh.name
 
@@ -53,31 +81,7 @@ class BlenderMesh():
 
     @staticmethod
     def set_mesh(gltf, pymesh, mesh, obj):
-        """Set all data after mesh creation."""
-        # Normals
-        offset = 0
-        custom_normals = [[0.0, 0.0, 0.0]] * len(mesh.vertices)
-
-        if gltf.import_settings['import_shading'] == "NORMALS":
-            mesh.create_normals_split()
-
-        for prim in pymesh.primitives:
-            offset = BlenderPrimitive.set_normals(gltf, prim, mesh, offset, custom_normals)
-
-        mesh.update()
-
-        # manage UV
-        offset = 0
-        for prim in pymesh.primitives:
-            offset = BlenderPrimitive.set_UV(gltf, prim, obj, mesh, offset)
-
-        mesh.update()
-
-        # Normals, now that every update is done
-        if gltf.import_settings['import_shading'] == "NORMALS":
-            mesh.normals_split_custom_set_from_vertices(custom_normals)
-            mesh.use_auto_smooth = True
-
+        """Sets mesh data after creation."""
         # Object and UV are now created, we can set UVMap into material
         for prim in pymesh.primitives:
             vertex_color = None
@@ -85,139 +89,88 @@ class BlenderMesh():
                 vertex_color = 'COLOR_0'
             BlenderPrimitive.set_UV_in_mat(gltf, prim, obj, vertex_color)
 
-        # Assign materials to mesh
-        offset = 0
-        cpt_index_mat = 0
-        bm = bmesh.new()
-        bm.from_mesh(obj.data)
-        bm.faces.ensure_lookup_table()
-        for prim in pymesh.primitives:
-            offset, cpt_index_mat = BlenderPrimitive.assign_material(gltf, prim, obj, bm, offset, cpt_index_mat)
-
-        bm.to_mesh(obj.data)
-        bm.free()
-
-        # Create shapekeys if needed
-        max_shape_to_create = 0
-        for prim in pymesh.primitives:
-            if prim.targets:
-                if len(prim.targets) > max_shape_to_create:
-                    max_shape_to_create = len(prim.targets)
-
-        # Create basis shape key
-        if max_shape_to_create > 0:
-            obj.shape_key_add(name="Basis")
-
-        current_shapekey_index = 0
-        for sk in range(max_shape_to_create):
-
-            # Check if this target has POSITION
-            if 'POSITION' not in prim.targets[sk].keys():
-                gltf.shapekeys[sk] = None
-                continue
-
-            # Check if glTF file has some extras with targetNames
-            shapekey_name = None
-            if pymesh.extras is not None:
-                if 'targetNames' in pymesh.extras.keys() and sk < len(pymesh.extras['targetNames']):
-                    shapekey_name = pymesh.extras['targetNames'][sk]
-
-            if shapekey_name is None:
-                shapekey_name = "target_" + str(sk)
-
-            obj.shape_key_add(name=shapekey_name)
-            current_shapekey_index += 1
-
-            offset_idx = 0
-            for prim in pymesh.primitives:
-                if prim.targets is None:
-           

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list