[Bf-extensions-cvs] [566a68e2] master: glTF exporter: perf: use numpy to speedup primitive extract

Julien Duroure noreply at git.blender.org
Sat Sep 5 15:20:03 CEST 2020


Commit: 566a68e2083a2a5d7ad66157dc9b79e410bd038c
Author: Julien Duroure
Date:   Sat Sep 5 15:19:55 2020 +0200
Branches: master
https://developer.blender.org/rBA566a68e2083a2a5d7ad66157dc9b79e410bd038c

glTF exporter: perf: use numpy to speedup primitive extract

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

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/exp/gltf2_blender_extract.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py

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

diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index d3a247de..daa6c7e4 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, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
-    "version": (1, 4, 8),
+    "version": (1, 4, 9),
     'blender': (2, 90, 0),
     'location': 'File > Import-Export',
     'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py
index eef05044..ca38aa72 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py
@@ -12,128 +12,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#
-# Imports
-#
-
+import numpy as np
 from mathutils import Vector, Quaternion, Matrix
 
 from . import gltf2_blender_export_keys
 from ...io.com.gltf2_io_debug import print_console
-from ...io.com.gltf2_io_color_management import color_srgb_to_scene_linear
 from io_scene_gltf2.blender.exp import gltf2_blender_gather_skins
 
 
-#
-# Classes
-#
-
-class Prim:
-    def __init__(self):
-        self.verts = {}
-        self.indices = []
-
-class ShapeKey:
-    def __init__(self, shape_key, split_normals):
-        self.shape_key = shape_key
-        self.split_normals = split_normals
-
-
-#
-# Functions
-#
-
-def convert_swizzle_normal(loc, armature, blender_object, export_settings):
-    """Convert a normal data from Blender coordinate system to glTF coordinate system."""
-    if (not armature) or (not blender_object):
-        # Classic case. Mesh is not skined, no need to apply armature transfoms on vertices / normals / tangents
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((loc[0], loc[2], -loc[1]))
-        else:
-            return Vector((loc[0], loc[1], loc[2]))
-    else:
-        # Mesh is skined, we have to apply armature transforms on data
-        apply_matrix = (armature.matrix_world.inverted() @ blender_object.matrix_world).to_3x3().inverted()
-        apply_matrix.transpose()
-        new_loc = ((armature.matrix_world.to_3x3() @ apply_matrix).to_4x4() @ Matrix.Translation(Vector((loc[0], loc[1], loc[2])))).to_translation()
-        new_loc.normalize()
-
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((new_loc[0], new_loc[2], -new_loc[1]))
-        else:
-            return Vector((new_loc[0], new_loc[1], new_loc[2]))
-
-def convert_swizzle_location(loc, armature, blender_object, export_settings):
-    """Convert a location from Blender coordinate system to glTF coordinate system."""
-    if (not armature) or (not blender_object):
-        # Classic case. Mesh is not skined, no need to apply armature transfoms on vertices / normals / tangents
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((loc[0], loc[2], -loc[1]))
-        else:
-            return Vector((loc[0], loc[1], loc[2]))
-    else:
-        # Mesh is skined, we have to apply armature transforms on data
-        apply_matrix = armature.matrix_world.inverted() @ blender_object.matrix_world
-        new_loc = (armature.matrix_world @ apply_matrix @ Matrix.Translation(Vector((loc[0], loc[1], loc[2])))).to_translation()
-
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((new_loc[0], new_loc[2], -new_loc[1]))
-        else:
-            return Vector((new_loc[0], new_loc[1], new_loc[2]))
-
-
-def convert_swizzle_tangent(tan, armature, blender_object, export_settings):
-    """Convert a tangent from Blender coordinate system to glTF coordinate system."""
-    if tan[0] == 0.0 and tan[1] == 0.0 and tan[2] == 0.0:
-        print_console('WARNING', 'Tangent has zero length.')
-
-    if (not armature) or (not blender_object):
-        # Classic case. Mesh is not skined, no need to apply armature transfoms on vertices / normals / tangents
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((tan[0], tan[2], -tan[1]))
-        else:
-            return Vector((tan[0], tan[1], tan[2]))
-    else:
-        # Mesh is skined, we have to apply armature transforms on data
-        apply_matrix = armature.matrix_world.inverted() @ blender_object.matrix_world
-        new_tan = apply_matrix.to_quaternion() @ Vector((tan[0], tan[1], tan[2]))
-        if export_settings[gltf2_blender_export_keys.YUP]:
-            return Vector((new_tan[0], new_tan[2], -new_tan[1]))
-        else:
-            return Vector((new_tan[0], new_tan[1], new_tan[2]))
-
-def convert_swizzle_rotation(rot, export_settings):
-    """
-    Convert a quaternion rotation from Blender coordinate system to glTF coordinate system.
-
-    'w' is still at first position.
-    """
-    if export_settings[gltf2_blender_export_keys.YUP]:
-        return Quaternion((rot[0], rot[1], rot[3], -rot[2]))
-    else:
-        return Quaternion((rot[0], rot[1], rot[2], rot[3]))
-
-
-def convert_swizzle_scale(scale, export_settings):
-    """Convert a scale from Blender coordinate system to glTF coordinate system."""
-    if export_settings[gltf2_blender_export_keys.YUP]:
-        return Vector((scale[0], scale[2], scale[1]))
-    else:
-        return Vector((scale[0], scale[1], scale[2]))
-
-
 def extract_primitives(glTF, blender_mesh, library, blender_object, blender_vertex_groups, modifiers, export_settings):
-    """
-    Extract primitives from a mesh. Polygons are triangulated and sorted by material.
-    Vertices in multiple faces get split up as necessary.
-    """
+    """Extract primitives from a mesh."""
     print_console('INFO', 'Extracting primitive: ' + blender_mesh.name)
 
-    #
-    # First, decide what attributes to gather (eg. how many COLOR_n, etc.)
-    # Also calculate normals/tangents now if necessary.
-    #
-
     use_normals = export_settings[gltf2_blender_export_keys.NORMALS]
     if use_normals:
         blender_mesh.calc_normals_split()
@@ -156,8 +46,8 @@ def extract_primitives(glTF, blender_mesh, library, blender_object, blender_vert
     if export_settings[gltf2_blender_export_keys.COLORS]:
         color_max = len(blender_mesh.vertex_colors)
 
-    bone_max = 0  # number of JOINTS_n sets needed (1 set = 4 influences)
     armature = None
+    skin = None
     if blender_vertex_groups and export_settings[gltf2_blender_export_keys.SKINS]:
         if modifiers is not None:
             modifiers_dict = {m.type: m for m in modifiers}
@@ -181,191 +71,201 @@ def extract_primitives(glTF, blender_mesh, library, blender_object, blender_vert
             skin = gltf2_blender_gather_skins.gather_skin(armature, export_settings)
             if not skin:
                 armature = None
-            else:
-                joint_name_to_index = {joint.name: index for index, joint in enumerate(skin.joints)}
-                group_to_joint = [joint_name_to_index.get(g.name) for g in blender_vertex_groups]
-
-                # Find out max number of bone influences
-                for blender_polygon in blender_mesh.polygons:
-                    for loop_index in blender_polygon.loop_indices:
-                        vertex_index = blender_mesh.loops[loop_index].vertex_index
-                        groups_count = len(blender_mesh.vertices[vertex_index].groups)
-                        bones_count = (groups_count + 3) // 4
-                        bone_max = max(bone_max, bones_count)
 
     use_morph_normals = use_normals and export_settings[gltf2_blender_export_keys.MORPH_NORMAL]
     use_morph_tangents = use_morph_normals and use_tangents and export_settings[gltf2_blender_export_keys.MORPH_TANGENT]
 
-    shape_keys = []
+    key_blocks = []
     if blender_mesh.shape_keys and export_settings[gltf2_blender_export_keys.MORPH]:
-        for blender_shape_key in blender_mesh.shape_keys.key_blocks:
-            if blender_shape_key == blender_shape_key.relative_key or blender_shape_key.mute:
-                continue
+        key_blocks = [
+            key_block
+            for key_block in blender_mesh.shape_keys.key_blocks
+            if not (key_block == key_block.relative_key or key_block.mute)
+        ]
 
-            split_normals = None
-            if use_morph_normals:
-                split_normals = blender_shape_key.normals_split_get()
-
-            shape_keys.append(ShapeKey(
-                blender_shape_key,
-                split_normals,
-            ))
+    use_materials = export_settings[gltf2_blender_export_keys.MATERIALS]
 
+    # Fetch vert positions and bone data (joint,weights)
 
-    use_materials = export_settings[gltf2_blender_export_keys.MATERIALS]
+    locs, morph_locs = __get_positions(blender_mesh, key_blocks, armature, blender_object, export_settings)
+    if skin:
+        vert_bones, num_joint_sets = __get_bone_data(blender_mesh, skin, blender_vertex_groups)
 
+    # In Blender there is both per-vert data, like position, and also per-loop
+    # (loop=corner-of-poly) data, like normals or UVs. glTF only has per-vert
+    # data, so we need to split Blender verts up into potentially-multiple glTF
+    # verts.
     #
-    # Gather the verts and indices for each primitive.
+    # First, we'll collect a "dot" for every loop: a struct that stores all the
+    # attributes at that loop, namely the vertex index (which determines all
+    # per-vert data), and all the per-loop data like UVs, etc.
     #
+    # Each unique dot will become one unique glTF vert.
 
-    prims = {}
+    # List all fields the dot struct needs.
+    dot_fields = [('vertex_index', np.uint32)]
+    if use_normals:
+        dot_fields += [('nx', np.float32), ('ny', np.float32), ('nz', np.float32)]
+    if use_tangents:
+        dot_fields += [('tx', np.float32), ('ty', np.float32), ('tz', np.float32), ('tw', np.float32)]
+    for uv_i in range(tex_coord_max):
+        dot_fields += [('uv%dx' % uv_i, np.float32), ('uv%dy' % uv_i, np.float32)]
+    for col_i in range(color_max):
+        dot

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list