[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