[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