From 9c76d5b39aa7d3531781637b93bd744849af4e3d Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Tue, 12 Mar 2019 17:36:02 +0100 Subject: glTF exporter: Deduplicate cameras, animation sampler and accessors --- .../blender/exp/gltf2_blender_gather_accessors.py | 48 +++++++++++++++++++++ .../exp/gltf2_blender_gather_animation_samplers.py | 44 +++++++++---------- .../blender/exp/gltf2_blender_gather_cameras.py | 50 +++++++++------------- .../blender/exp/gltf2_blender_gather_nodes.py | 5 ++- .../blender/exp/gltf2_blender_gather_primitives.py | 22 ++++------ .../blender/exp/gltf2_blender_gather_skins.py | 22 ++++------ io_scene_gltf2/io/exp/gltf2_io_binary_data.py | 6 +++ 7 files changed, 119 insertions(+), 78 deletions(-) create mode 100644 io_scene_gltf2/blender/exp/gltf2_blender_gather_accessors.py diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_accessors.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_accessors.py new file mode 100644 index 00000000..949720d1 --- /dev/null +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_accessors.py @@ -0,0 +1,48 @@ +# 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 typing + +import bpy +from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached +from io_scene_gltf2.io.com import gltf2_io +from io_scene_gltf2.io.com import gltf2_io_constants +from io_scene_gltf2.io.exp import gltf2_io_binary_data +from . import gltf2_blender_export_keys + + +@cached +def gather_accessor(buffer_view: gltf2_io_binary_data.BinaryData, + component_type: gltf2_io_constants.ComponentType, + count, + max, + min, + type: gltf2_io_constants.DataType, + export_settings) -> gltf2_io.Accessor: + return gltf2_io.Accessor( + buffer_view=buffer_view, + byte_offset=None, + component_type=component_type, + count=count, + extensions=None, + extras=None, + max=list(max) if max is not None else None, + min=list(min) if min is not None else None, + name=None, + normalized=None, + sparse=None, + type=type + ) + diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py index 4000ce5e..981428c9 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py @@ -20,6 +20,7 @@ from io_scene_gltf2.blender.com import gltf2_blender_math from io_scene_gltf2.blender.com.gltf2_blender_data_path import get_target_property_name, get_target_object_path from io_scene_gltf2.blender.exp import gltf2_blender_gather_animation_sampler_keyframes from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached +from io_scene_gltf2.blender.exp import gltf2_blender_gather_accessors from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.com import gltf2_io_constants from io_scene_gltf2.io.exp import gltf2_io_binary_data @@ -34,9 +35,11 @@ def gather_animation_sampler(channels: typing.Tuple[bpy.types.FCurve], return gltf2_io.AnimationSampler( extensions=__gather_extensions(channels, blender_object, export_settings), extras=__gather_extras(channels, blender_object, export_settings), - input=__gather_input(channels, blender_object, export_settings), + input=__gather_input(channels, export_settings), interpolation=__gather_interpolation(channels, blender_object, export_settings), - output=__gather_output(channels, blender_object, export_settings) + output=__gather_output(channels, blender_object.matrix_parent_inverse.copy().freeze(), + blender_object if blender_object.type == "ARMATURE" else None, + export_settings) ) @@ -54,27 +57,22 @@ def __gather_extras(channels: typing.Tuple[bpy.types.FCurve], return None +@cached def __gather_input(channels: typing.Tuple[bpy.types.FCurve], - blender_object: bpy.types.Object, export_settings ) -> gltf2_io.Accessor: """Gather the key time codes.""" keyframes = gltf2_blender_gather_animation_sampler_keyframes.gather_keyframes(channels, export_settings) times = [k.seconds for k in keyframes] - return gltf2_io.Accessor( - buffer_view=gltf2_io_binary_data.BinaryData.from_list(times, gltf2_io_constants.ComponentType.Float), - byte_offset=None, - component_type=gltf2_io_constants.ComponentType.Float, - count=len(times), - extensions=None, - extras=None, - max=[max(times)], - min=[min(times)], - name=None, - normalized=None, - sparse=None, - type=gltf2_io_constants.DataType.Scalar + return gltf2_blender_gather_accessors.gather_accessor( + gltf2_io_binary_data.BinaryData.from_list(times, gltf2_io_constants.ComponentType.Float), + gltf2_io_constants.ComponentType.Float, + len(times), + tuple([max(times)]), + tuple([min(times)]), + gltf2_io_constants.DataType.Scalar, + export_settings ) @@ -95,8 +93,10 @@ def __gather_interpolation(channels: typing.Tuple[bpy.types.FCurve], }[blender_keyframe.interpolation] +@cached def __gather_output(channels: typing.Tuple[bpy.types.FCurve], - blender_object: bpy.types.Object, + parent_inverse, + blender_object_if_armature: typing.Optional[bpy.types.Object], export_settings ) -> gltf2_io.Accessor: """Gather the data of the keyframes.""" @@ -104,14 +104,14 @@ def __gather_output(channels: typing.Tuple[bpy.types.FCurve], target_datapath = channels[0].data_path - transform = blender_object.matrix_parent_inverse + transform = parent_inverse is_yup = export_settings[gltf2_blender_export_keys.YUP] object_path = get_target_object_path(target_datapath) - is_armature_animation = blender_object.type == "ARMATURE" and object_path != "" + is_armature_animation = blender_object_if_armature is not None and object_path != "" if is_armature_animation: - bone = blender_object.path_resolve(object_path) + bone = blender_object_if_armature.path_resolve(object_path) if isinstance(bone, bpy.types.PoseBone): if bone.parent is not None: parent_transform = bone.parent.bone.matrix_local @@ -134,12 +134,12 @@ def __gather_output(channels: typing.Tuple[bpy.types.FCurve], keyframe_value = gltf2_blender_math.mathutils_to_gltf(value) if keyframe.in_tangent is not None: in_tangent = gltf2_blender_math.transform(keyframe.in_tangent, target_datapath, transform) - if is_yup and not blender_object.type == "ARMATURE": + if is_yup and blender_object_if_armature is None: in_tangent = gltf2_blender_math.swizzle_yup(in_tangent, target_datapath) keyframe_value = gltf2_blender_math.mathutils_to_gltf(in_tangent) + keyframe_value if keyframe.out_tangent is not None: out_tangent = gltf2_blender_math.transform(keyframe.out_tangent, target_datapath, transform) - if is_yup and not blender_object.type == "ARMATURE": + if is_yup and blender_object_if_armature is None: out_tangent = gltf2_blender_math.swizzle_yup(out_tangent, target_datapath) keyframe_value = keyframe_value + gltf2_blender_math.mathutils_to_gltf(out_tangent) values += keyframe_value diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py index 9640a7ce..a34048a0 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py @@ -21,43 +21,38 @@ import math @cached -def gather_camera(blender_object, export_settings): - if not __filter_camera(blender_object, export_settings): +def gather_camera(blender_camera, export_settings): + if not __filter_camera(blender_camera, export_settings): return None return gltf2_io.Camera( - extensions=__gather_extensions(blender_object, export_settings), - extras=__gather_extras(blender_object, export_settings), - name=__gather_name(blender_object, export_settings), - orthographic=__gather_orthographic(blender_object, export_settings), - perspective=__gather_perspective(blender_object, export_settings), - type=__gather_type(blender_object, export_settings) + extensions=__gather_extensions(blender_camera, export_settings), + extras=__gather_extras(blender_camera, export_settings), + name=__gather_name(blender_camera, export_settings), + orthographic=__gather_orthographic(blender_camera, export_settings), + perspective=__gather_perspective(blender_camera, export_settings), + type=__gather_type(blender_camera, export_settings) ) -def __filter_camera(blender_object, export_settings): - if blender_object.type != 'CAMERA': - return False - if not __gather_type(blender_object, export_settings): - return False +def __filter_camera(blender_camera, export_settings): + return bool(__gather_type(blender_camera, export_settings)) - return True - -def __gather_extensions(blender_object, export_settings): +def __gather_extensions(blender_camera, export_settings): return None -def __gather_extras(blender_object, export_settings): +def __gather_extras(blender_camera, export_settings): return None -def __gather_name(blender_object, export_settings): - return blender_object.data.name +def __gather_name(blender_camera, export_settings): + return blender_camera.name -def __gather_orthographic(blender_object, export_settings): - if __gather_type(blender_object, export_settings) == "orthographic": +def __gather_orthographic(blender_camera, export_settings): + if __gather_type(blender_camera, export_settings) == "orthographic": orthographic = gltf2_io.CameraOrthographic( extensions=None, extras=None, @@ -66,7 +61,6 @@ def __gather_orthographic(blender_object, export_settings): zfar=None, znear=None ) - blender_camera = blender_object.data orthographic.xmag = blender_camera.ortho_scale orthographic.ymag = blender_camera.ortho_scale @@ -78,8 +72,8 @@ def __gather_orthographic(blender_object, export_settings): return None -def __gather_perspective(blender_object, export_settings): - if __gather_type(blender_object, export_settings) == "perspective": +def __gather_perspective(blender_camera, export_settings): + if __gather_type(blender_camera, export_settings) == "perspective": perspective = gltf2_io.CameraPerspective( aspect_ratio=None, extensions=None, @@ -88,7 +82,6 @@ def __gather_perspective(blender_object, export_settings): zfar=None, znear=None ) - blender_camera = blender_object.data width = bpy.context.scene.render.pixel_aspect_x * bpy.context.scene.render.resolution_x height = bpy.context.scene.render.pixel_aspect_y * bpy.context.scene.render.resolution_y @@ -112,11 +105,10 @@ def __gather_perspective(blender_object, export_settings): return None -def __gather_type(blender_object, export_settings): - camera = blender_object.data - if camera.type == 'PERSP': +def __gather_type(blender_camera, export_settings): + if blender_camera.type == 'PERSP': return "perspective" - elif camera.type == 'ORTHO': + elif blender_camera.type == 'ORTHO': return "orthographic" return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py index 64895459..0774c8ee 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py @@ -80,7 +80,10 @@ def __filter_node(blender_object, export_settings): def __gather_camera(blender_object, export_settings): - return gltf2_blender_gather_cameras.gather_camera(blender_object, export_settings) + if blender_object.type != 'CAMERA': + return None + + return gltf2_blender_gather_cameras.gather_camera(blender_object.data, export_settings) def __gather_children(blender_object, export_settings): 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 5b2d8ae2..79ed5fd7 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py @@ -19,6 +19,7 @@ from .gltf2_blender_export_keys import NORMALS, MORPH_NORMAL, TANGENTS, MORPH_TA 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 @@ -90,19 +91,14 @@ def __gather_indices(blender_primitive, blender_mesh, modifiers, export_settings element_type = gltf2_io_constants.DataType.Scalar binary_data = gltf2_io_binary_data.BinaryData.from_list(indices, component_type) - return gltf2_io.Accessor( - buffer_view=binary_data, - byte_offset=None, - component_type=component_type, - count=len(indices) // gltf2_io_constants.DataType.num_elements(element_type), - extensions=None, - extras=None, - max=None, - min=None, - name=None, - normalized=None, - sparse=None, - type=element_type + return gltf2_blender_gather_accessors.gather_accessor( + binary_data, + component_type, + len(indices) // gltf2_io_constants.DataType.num_elements(element_type), + None, + None, + element_type, + export_settings ) diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py index 1a43b6d4..c3b975c3 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py @@ -18,6 +18,7 @@ from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.exp import gltf2_io_binary_data from io_scene_gltf2.io.com import gltf2_io_constants +from io_scene_gltf2.blender.exp import gltf2_blender_gather_accessors from io_scene_gltf2.blender.exp import gltf2_blender_gather_joints from io_scene_gltf2.blender.com import gltf2_blender_math @@ -91,19 +92,14 @@ def __gather_inverse_bind_matrices(blender_object, mesh_object, export_settings) inverse_matrices.append(inverse_bind_matrix[row][column]) binary_data = gltf2_io_binary_data.BinaryData.from_list(inverse_matrices, gltf2_io_constants.ComponentType.Float) - return gltf2_io.Accessor( - buffer_view=binary_data, - byte_offset=None, - component_type=gltf2_io_constants.ComponentType.Float, - count=len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Mat4), - extensions=None, - extras=None, - max=None, - min=None, - name=None, - normalized=None, - sparse=None, - type=gltf2_io_constants.DataType.Mat4 + return gltf2_blender_gather_accessors.gather_accessor( + binary_data, + gltf2_io_constants.ComponentType.Float, + len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Mat4), + None, + None, + gltf2_io_constants.DataType.Mat4, + export_settings ) diff --git a/io_scene_gltf2/io/exp/gltf2_io_binary_data.py b/io_scene_gltf2/io/exp/gltf2_io_binary_data.py index 42f6d5d7..c4e0dd20 100755 --- a/io_scene_gltf2/io/exp/gltf2_io_binary_data.py +++ b/io_scene_gltf2/io/exp/gltf2_io_binary_data.py @@ -25,6 +25,12 @@ class BinaryData: raise TypeError("Data is not a bytes array") self.data = data + def __eq__(self, other): + return self.data == other.data + + def __hash__(self): + return hash(self.data) + @classmethod def from_list(cls, lst: typing.List[typing.Any], gltf_component_type: gltf2_io_constants.ComponentType): format_char = gltf2_io_constants.ComponentType.to_type_code(gltf_component_type) -- cgit v1.2.3