Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Duroure <julien.duroure@gmail.com>2020-07-21 21:19:01 +0300
committerJulien Duroure <julien.duroure@gmail.com>2020-07-21 21:19:01 +0300
commit3ea1673580ab68ecb713da3233a4f6beaafff5d9 (patch)
tree2464ed49e12a5d244b5003013b45f085cea63893
parent2b4bf943d0a323e6b0430179cee7fa7ffb5907d3 (diff)
glTF exporter: performance: using numpy
Thanks scurest!
-rwxr-xr-xio_scene_gltf2/__init__.py2
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py185
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py58
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_utils.py67
-rwxr-xr-xio_scene_gltf2/io/com/gltf2_io_constants.py12
5 files changed, 96 insertions, 228 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 16fc681e..0beb10a1 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": (1, 3, 33),
+ "version": (1, 3, 34),
'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_gather_primitive_attributes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
index f5856257..8912d921 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py
@@ -12,12 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import numpy as np
+
from . import gltf2_blender_export_keys
from io_scene_gltf2.io.com import gltf2_io
from io_scene_gltf2.io.com import gltf2_io_constants
from io_scene_gltf2.io.com import gltf2_io_debug
from io_scene_gltf2.io.exp import gltf2_io_binary_data
-from io_scene_gltf2.blender.exp import gltf2_blender_utils
def gather_primitive_attributes(blender_primitive, export_settings):
@@ -36,72 +37,79 @@ def gather_primitive_attributes(blender_primitive, export_settings):
return attributes
+def array_to_accessor(array, component_type, data_type, include_max_and_min=False):
+ dtype = gltf2_io_constants.ComponentType.to_numpy_dtype(component_type)
+ num_elems = gltf2_io_constants.DataType.num_elements(data_type)
+
+ if type(array) is not np.ndarray:
+ array = np.array(array, dtype=dtype)
+ array = array.reshape(len(array) // num_elems, num_elems)
+
+ assert array.dtype == dtype
+ assert array.shape[1] == num_elems
+
+ amax = None
+ amin = None
+ if include_max_and_min:
+ amax = np.amax(array, axis=0).tolist()
+ amin = np.amin(array, axis=0).tolist()
+
+ return gltf2_io.Accessor(
+ buffer_view=gltf2_io_binary_data.BinaryData(array.tobytes()),
+ byte_offset=None,
+ component_type=component_type,
+ count=len(array),
+ extensions=None,
+ extras=None,
+ max=amax,
+ min=amin,
+ name=None,
+ normalized=None,
+ sparse=None,
+ type=data_type,
+ )
+
+
def __gather_position(blender_primitive, export_settings):
position = blender_primitive["attributes"]["POSITION"]
- componentType = gltf2_io_constants.ComponentType.Float
return {
- "POSITION": gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(position, componentType),
- byte_offset=None,
- component_type=componentType,
- count=len(position) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec3),
- extensions=None,
- extras=None,
- max=gltf2_blender_utils.max_components(position, gltf2_io_constants.DataType.Vec3),
- min=gltf2_blender_utils.min_components(position, gltf2_io_constants.DataType.Vec3),
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec3
+ "POSITION": array_to_accessor(
+ position,
+ component_type=gltf2_io_constants.ComponentType.Float,
+ data_type=gltf2_io_constants.DataType.Vec3,
+ include_max_and_min=True
)
}
def __gather_normal(blender_primitive, export_settings):
- if export_settings[gltf2_blender_export_keys.NORMALS]:
- normal = blender_primitive["attributes"]['NORMAL']
- return {
- "NORMAL": gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(normal, gltf2_io_constants.ComponentType.Float),
- byte_offset=None,
- component_type=gltf2_io_constants.ComponentType.Float,
- count=len(normal) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec3),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec3
- )
- }
- return {}
+ if not export_settings[gltf2_blender_export_keys.NORMALS]:
+ return {}
+ normal = blender_primitive["attributes"].get('NORMAL')
+ if not normal:
+ return {}
+ return {
+ "NORMAL": array_to_accessor(
+ normal,
+ component_type=gltf2_io_constants.ComponentType.Float,
+ data_type=gltf2_io_constants.DataType.Vec3,
+ )
+ }
def __gather_tangent(blender_primitive, export_settings):
- if export_settings[gltf2_blender_export_keys.TANGENTS]:
- if blender_primitive["attributes"].get('TANGENT') is not None:
- tangent = blender_primitive["attributes"]['TANGENT']
- return {
- "TANGENT": gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(
- tangent, gltf2_io_constants.ComponentType.Float),
- byte_offset=None,
- component_type=gltf2_io_constants.ComponentType.Float,
- count=len(tangent) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec4),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec4
- )
- }
-
- return {}
+ if not export_settings[gltf2_blender_export_keys.TANGENTS]:
+ return {}
+ tangent = blender_primitive["attributes"].get('TANGENT')
+ if not tangent:
+ return {}
+ return {
+ "TANGENT": array_to_accessor(
+ tangent,
+ component_type=gltf2_io_constants.ComponentType.Float,
+ data_type=gltf2_io_constants.DataType.Vec4,
+ )
+ }
def __gather_texcoord(blender_primitive, export_settings):
@@ -111,20 +119,10 @@ def __gather_texcoord(blender_primitive, export_settings):
tex_coord_id = 'TEXCOORD_' + str(tex_coord_index)
while blender_primitive["attributes"].get(tex_coord_id) is not None:
tex_coord = blender_primitive["attributes"][tex_coord_id]
- attributes[tex_coord_id] = gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(
- tex_coord, gltf2_io_constants.ComponentType.Float),
- byte_offset=None,
+ attributes[tex_coord_id] = array_to_accessor(
+ tex_coord,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(tex_coord) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec2),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec2
+ data_type=gltf2_io_constants.DataType.Vec2,
)
tex_coord_index += 1
tex_coord_id = 'TEXCOORD_' + str(tex_coord_index)
@@ -138,20 +136,10 @@ def __gather_colors(blender_primitive, export_settings):
color_id = 'COLOR_' + str(color_index)
while blender_primitive["attributes"].get(color_id) is not None:
internal_color = blender_primitive["attributes"][color_id]
- attributes[color_id] = gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(
- internal_color, gltf2_io_constants.ComponentType.Float),
- byte_offset=None,
+ attributes[color_id] = array_to_accessor(
+ internal_color,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(internal_color) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec4),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec4
+ data_type=gltf2_io_constants.DataType.Vec4,
)
color_index += 1
color_id = 'COLOR_' + str(color_index)
@@ -173,20 +161,10 @@ def __gather_skins(blender_primitive, export_settings):
# joints
internal_joint = blender_primitive["attributes"][joint_id]
- joint = gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(
- internal_joint, gltf2_io_constants.ComponentType.UnsignedShort),
- byte_offset=None,
+ joint = array_to_accessor(
+ internal_joint,
component_type=gltf2_io_constants.ComponentType.UnsignedShort,
- count=len(internal_joint) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Vec4),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec4
+ data_type=gltf2_io_constants.DataType.Vec4,
)
attributes[joint_id] = joint
@@ -201,21 +179,10 @@ def __gather_skins(blender_primitive, export_settings):
factor = 1.0 / total
internal_weight[idx:idx + 4] = [w * factor for w in weight_slice]
- weight = gltf2_io.Accessor(
- buffer_view=gltf2_io_binary_data.BinaryData.from_list(
- internal_weight, gltf2_io_constants.ComponentType.Float),
- byte_offset=None,
+ weight = array_to_accessor(
+ internal_weight,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(internal_weight) // gltf2_io_constants.DataType.num_elements(
- gltf2_io_constants.DataType.Vec4),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec4
+ data_type=gltf2_io_constants.DataType.Vec4,
)
attributes[weight_id] = weight
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
index 22f0bc6d..1a2ae00d 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
@@ -21,7 +21,6 @@ from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached
from io_scene_gltf2.blender.exp import gltf2_blender_extract
from io_scene_gltf2.blender.exp import gltf2_blender_gather_accessors
from io_scene_gltf2.blender.exp import gltf2_blender_gather_primitive_attributes
-from io_scene_gltf2.blender.exp import gltf2_blender_utils
from io_scene_gltf2.blender.exp import gltf2_blender_gather_materials
from io_scene_gltf2.io.com import gltf2_io
@@ -160,26 +159,11 @@ def __gather_targets(blender_primitive, blender_mesh, modifiers, export_settings
if blender_primitive["attributes"].get(target_position_id):
target = {}
internal_target_position = blender_primitive["attributes"][target_position_id]
- binary_data = gltf2_io_binary_data.BinaryData.from_list(
+ target["POSITION"] = gltf2_blender_gather_primitive_attributes.array_to_accessor(
internal_target_position,
- gltf2_io_constants.ComponentType.Float
- )
- target["POSITION"] = gltf2_io.Accessor(
- buffer_view=binary_data,
- byte_offset=None,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(internal_target_position) // gltf2_io_constants.DataType.num_elements(
- gltf2_io_constants.DataType.Vec3),
- extensions=None,
- extras=None,
- max=gltf2_blender_utils.max_components(
- internal_target_position, gltf2_io_constants.DataType.Vec3),
- min=gltf2_blender_utils.min_components(
- internal_target_position, gltf2_io_constants.DataType.Vec3),
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec3
+ data_type=gltf2_io_constants.DataType.Vec3,
+ include_max_and_min=True,
)
if export_settings[NORMALS] \
@@ -187,48 +171,20 @@ def __gather_targets(blender_primitive, blender_mesh, modifiers, export_settings
and blender_primitive["attributes"].get(target_normal_id):
internal_target_normal = blender_primitive["attributes"][target_normal_id]
- binary_data = gltf2_io_binary_data.BinaryData.from_list(
+ target['NORMAL'] = gltf2_blender_gather_primitive_attributes.array_to_accessor(
internal_target_normal,
- gltf2_io_constants.ComponentType.Float,
- )
- target['NORMAL'] = gltf2_io.Accessor(
- buffer_view=binary_data,
- byte_offset=None,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(internal_target_normal) // gltf2_io_constants.DataType.num_elements(
- gltf2_io_constants.DataType.Vec3),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec3
+ data_type=gltf2_io_constants.DataType.Vec3,
)
if export_settings[TANGENTS] \
and export_settings[MORPH_TANGENT] \
and blender_primitive["attributes"].get(target_tangent_id):
internal_target_tangent = blender_primitive["attributes"][target_tangent_id]
- binary_data = gltf2_io_binary_data.BinaryData.from_list(
+ target['TANGENT'] = gltf2_blender_gather_primitive_attributes.array_to_accessor(
internal_target_tangent,
- gltf2_io_constants.ComponentType.Float,
- )
- target['TANGENT'] = gltf2_io.Accessor(
- buffer_view=binary_data,
- byte_offset=None,
component_type=gltf2_io_constants.ComponentType.Float,
- count=len(internal_target_tangent) // gltf2_io_constants.DataType.num_elements(
- gltf2_io_constants.DataType.Vec3),
- extensions=None,
- extras=None,
- max=None,
- min=None,
- name=None,
- normalized=None,
- sparse=None,
- type=gltf2_io_constants.DataType.Vec3
+ data_type=gltf2_io_constants.DataType.Vec3,
)
targets.append(target)
morph_index += 1
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_utils.py b/io_scene_gltf2/blender/exp/gltf2_blender_utils.py
deleted file mode 100755
index 8d5baae7..00000000
--- a/io_scene_gltf2/blender/exp/gltf2_blender_utils.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright 2018 The glTF-Blender-IO authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import math
-from io_scene_gltf2.io.com import gltf2_io_constants
-
-
-# TODO: we could apply functional programming to these problems (currently we only have a single use case)
-
-def split_list_by_data_type(l: list, data_type: gltf2_io_constants.DataType):
- """
- Split a flat list of components by their data type.
-
- E.g.: A list [0,1,2,3,4,5] of data type Vec3 would be split to [[0,1,2], [3,4,5]]
- :param l: the flat list
- :param data_type: the data type of the list
- :return: a list of lists, where each element list contains the components of the data type
- """
- if not (len(l) % gltf2_io_constants.DataType.num_elements(data_type) == 0):
- raise ValueError("List length does not match specified data type")
- num_elements = gltf2_io_constants.DataType.num_elements(data_type)
- return [l[i:i + num_elements] for i in range(0, len(l), num_elements)]
-
-
-def max_components(l: list, data_type: gltf2_io_constants.DataType) -> list:
- """
- Find the maximum components in a flat list.
-
- This is required, for example, for the glTF2.0 accessor min and max properties
- :param l: the flat list of components
- :param data_type: the data type of the list (determines the length of the result)
- :return: a list with length num_elements(data_type) containing the maximum per component along the list
- """
- components_lists = split_list_by_data_type(l, data_type)
- result = [-math.inf] * gltf2_io_constants.DataType.num_elements(data_type)
- for components in components_lists:
- for i, c in enumerate(components):
- result[i] = max(result[i], c)
- return result
-
-
-def min_components(l: list, data_type: gltf2_io_constants.DataType) -> list:
- """
- Find the minimum components in a flat list.
-
- This is required, for example, for the glTF2.0 accessor min and max properties
- :param l: the flat list of components
- :param data_type: the data type of the list (determines the length of the result)
- :return: a list with length num_elements(data_type) containing the minimum per component along the list
- """
- components_lists = split_list_by_data_type(l, data_type)
- result = [math.inf] * gltf2_io_constants.DataType.num_elements(data_type)
- for components in components_lists:
- for i, c in enumerate(components):
- result[i] = min(result[i], c)
- return result
diff --git a/io_scene_gltf2/io/com/gltf2_io_constants.py b/io_scene_gltf2/io/com/gltf2_io_constants.py
index 873e004e..983fe9ab 100755
--- a/io_scene_gltf2/io/com/gltf2_io_constants.py
+++ b/io_scene_gltf2/io/com/gltf2_io_constants.py
@@ -35,6 +35,18 @@ class ComponentType(IntEnum):
}[component_type]
@classmethod
+ def to_numpy_dtype(cls, component_type):
+ import numpy as np
+ return {
+ ComponentType.Byte: np.int8,
+ ComponentType.UnsignedByte: np.uint8,
+ ComponentType.Short: np.int16,
+ ComponentType.UnsignedShort: np.uint16,
+ ComponentType.UnsignedInt: np.uint32,
+ ComponentType.Float: np.float32,
+ }[component_type]
+
+ @classmethod
def from_legacy_define(cls, type_define):
return {
GLTF_COMPONENT_TYPE_BYTE: ComponentType.Byte,