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:
Diffstat (limited to 'io_scene_gltf2/blender')
-rwxr-xr-xio_scene_gltf2/blender/com/gltf2_blender_image_util.py121
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_animate.py638
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_filter.py455
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_search_scene.py89
4 files changed, 0 insertions, 1303 deletions
diff --git a/io_scene_gltf2/blender/com/gltf2_blender_image_util.py b/io_scene_gltf2/blender/com/gltf2_blender_image_util.py
deleted file mode 100755
index e2563a52..00000000
--- a/io_scene_gltf2/blender/com/gltf2_blender_image_util.py
+++ /dev/null
@@ -1,121 +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 os
-import shutil
-import bpy
-import zlib
-import struct
-from io_scene_gltf2.blender.exp import gltf2_blender_get
-
-
-def create_image_file(context, blender_image, dst_path, file_format):
- """Create JPEG or PNG file from a given Blender image."""
- # Check, if source image exists e.g. does not exist if image is packed.
- file_exists = 1
- try:
- src_path = bpy.path.abspath(blender_image.filepath, library=blender_image.library)
- file = open(src_path)
- except IOError:
- file_exists = 0
- else:
- file.close()
-
- if file_exists == 0:
- # Image does not exist on disk ...
- blender_image.filepath = dst_path
- # ... so save it.
- blender_image.save()
-
- elif file_format == blender_image.file_format:
- # Copy source image to destination, keeping original format.
-
- src_path = bpy.path.abspath(blender_image.filepath, library=blender_image.library)
-
- # Required for comapre.
- src_path = src_path.replace('\\', '/')
- dst_path = dst_path.replace('\\', '/')
-
- # Check that source and destination path are not the same using os.path.abspath
- # because bpy.path.abspath seems to not always return an absolute path
- if os.path.abspath(dst_path) != os.path.abspath(src_path):
- shutil.copyfile(src_path, dst_path)
-
- else:
- # Render a new image to destination, converting to target format.
-
- # TODO: Reusing the existing scene means settings like exposure are applied on export,
- # which we don't want, but I'm not sure how to create a new Scene object through the
- # Python API. See: https://github.com/KhronosGroup/glTF-Blender-Exporter/issues/184.
-
- tmp_file_format = context.scene.render.image_settings.file_format
- tmp_color_depth = context.scene.render.image_settings.color_depth
-
- context.scene.render.image_settings.file_format = file_format
- context.scene.render.image_settings.color_depth = '8'
- blender_image.save_render(dst_path, context.scene)
-
- context.scene.render.image_settings.file_format = tmp_file_format
- context.scene.render.image_settings.color_depth = tmp_color_depth
-
-
-def create_image_data(context, export_settings, blender_image, file_format):
- """Create JPEG or PNG byte array from a given Blender image."""
- if blender_image is None:
- return None
-
- if file_format == 'PNG':
- return _create_png_data(blender_image)
- else:
- return _create_jpg_data(context, export_settings, blender_image)
-
-
-def _create_jpg_data(context, export_settings, blender_image):
- """Create a JPEG byte array from a given Blender image."""
- uri = gltf2_blender_get.get_image_uri(export_settings, blender_image)
- path = export_settings['gltf_filedirectory'] + uri
-
- create_image_file(context, blender_image, path, 'JPEG')
-
- jpg_data = open(path, 'rb').read()
- os.remove(path)
-
- return jpg_data
-
-
-def _create_png_data(blender_image):
- """Create a PNG byte array from a given Blender image."""
- width, height = blender_image.size
-
- buf = bytearray([int(channel * 255.0) for channel in blender_image.pixels])
-
- #
- # Taken from 'blender-thumbnailer.py' in Blender.
- #
-
- # reverse the vertical line order and add null bytes at the start
- width_byte_4 = width * 4
- raw_data = b"".join(
- b'\x00' + buf[span:span + width_byte_4] for span in range((height - 1) * width * 4, -1, - width_byte_4))
-
- def png_pack(png_tag, data):
- chunk_head = png_tag + data
- return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
-
- return b"".join([
- b'\x89PNG\r\n\x1a\n',
- png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
- png_pack(b'IDAT', zlib.compress(raw_data, 9)),
- png_pack(b'IEND', b'')])
-
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_animate.py b/io_scene_gltf2/blender/exp/gltf2_blender_animate.py
deleted file mode 100755
index e4b11487..00000000
--- a/io_scene_gltf2/blender/exp/gltf2_blender_animate.py
+++ /dev/null
@@ -1,638 +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.
-
-#
-# Imports
-#
-
-import bpy
-from . import gltf2_blender_export_keys
-from . import gltf2_blender_extract
-from mathutils import Matrix, Quaternion, Euler
-
-
-#
-# Globals
-#
-
-JOINT_NODE = 'JOINT'
-
-NEEDS_CONVERSION = 'CONVERSION_NEEDED'
-CUBIC_INTERPOLATION = 'CUBICSPLINE'
-LINEAR_INTERPOLATION = 'LINEAR'
-STEP_INTERPOLATION = 'STEP'
-BEZIER_INTERPOLATION = 'BEZIER'
-CONSTANT_INTERPOLATION = 'CONSTANT'
-
-
-#
-# Functions
-#
-
-def animate_get_interpolation(export_settings, blender_fcurve_list):
- """
- Retrieve the glTF interpolation, depending on a fcurve list.
-
- Blender allows mixing and more variations of interpolations.
- In such a case, a conversion is needed.
- """
- if export_settings[gltf2_blender_export_keys.FORCE_SAMPLING]:
- return NEEDS_CONVERSION
-
- #
-
- interpolation = None
-
- keyframe_count = None
-
- for blender_fcurve in blender_fcurve_list:
- if blender_fcurve is None:
- continue
-
- #
-
- current_keyframe_count = len(blender_fcurve.keyframe_points)
-
- if keyframe_count is None:
- keyframe_count = current_keyframe_count
-
- if current_keyframe_count > 0 > blender_fcurve.keyframe_points[0].co[0]:
- return NEEDS_CONVERSION
-
- if keyframe_count != current_keyframe_count:
- return NEEDS_CONVERSION
-
- #
-
- for blender_keyframe in blender_fcurve.keyframe_points:
- is_bezier = blender_keyframe.interpolation == BEZIER_INTERPOLATION
- is_linear = blender_keyframe.interpolation == LINEAR_INTERPOLATION
- is_constant = blender_keyframe.interpolation == CONSTANT_INTERPOLATION
-
- if interpolation is None:
- if is_bezier:
- interpolation = CUBIC_INTERPOLATION
- elif is_linear:
- interpolation = LINEAR_INTERPOLATION
- elif is_constant:
- interpolation = STEP_INTERPOLATION
- else:
- interpolation = NEEDS_CONVERSION
- return interpolation
- else:
- if is_bezier and interpolation != CUBIC_INTERPOLATION:
- interpolation = NEEDS_CONVERSION
- return interpolation
- elif is_linear and interpolation != LINEAR_INTERPOLATION:
- interpolation = NEEDS_CONVERSION
- return interpolation
- elif is_constant and interpolation != STEP_INTERPOLATION:
- interpolation = NEEDS_CONVERSION
- return interpolation
- elif not is_bezier and not is_linear and not is_constant:
- interpolation = NEEDS_CONVERSION
- return interpolation
-
- if interpolation is None:
- interpolation = NEEDS_CONVERSION
-
- return interpolation
-
-
-def animate_convert_rotation_axis_angle(axis_angle):
- """Convert an axis angle to a quaternion rotation."""
- q = Quaternion((axis_angle[1], axis_angle[2], axis_angle[3]), axis_angle[0])
-
- return [q.x, q.y, q.z, q.w]
-
-
-def animate_convert_rotation_euler(euler, rotation_mode):
- """Convert an euler angle to a quaternion rotation."""
- rotation = Euler((euler[0], euler[1], euler[2]), rotation_mode).to_quaternion()
-
- return [rotation.x, rotation.y, rotation.z, rotation.w]
-
-
-def animate_convert_keys(key_list):
- """Convert Blender key frames to glTF time keys depending on the applied frames per second."""
- times = []
-
- for key in key_list:
- times.append(key / bpy.context.scene.render.fps)
-
- return times
-
-
-def animate_gather_keys(export_settings, fcurve_list, interpolation):
- """
- Merge and sort several key frames to one set.
-
- If an interpolation conversion is needed, the sample key frames are created as well.
- """
- keys = []
-
- frame_start = bpy.context.scene.frame_start
- frame_end = bpy.context.scene.frame_end
-
- if interpolation == NEEDS_CONVERSION:
- start = None
- end = None
-
- for blender_fcurve in fcurve_list:
- if blender_fcurve is None:
- continue
-
- if start is None:
- start = blender_fcurve.range()[0]
- else:
- start = min(start, blender_fcurve.range()[0])
-
- if end is None:
- end = blender_fcurve.range()[1]
- else:
- end = max(end, blender_fcurve.range()[1])
-
- #
-
- add_epsilon_keyframe = False
- for blender_keyframe in blender_fcurve.keyframe_points:
- if add_epsilon_keyframe:
- key = blender_keyframe.co[0] - 0.001
-
- if key not in keys:
- keys.append(key)
-
- add_epsilon_keyframe = False
-
- if blender_keyframe.interpolation == CONSTANT_INTERPOLATION:
- add_epsilon_keyframe = True
-
- if add_epsilon_keyframe:
- key = end - 0.001
-
- if key not in keys:
- keys.append(key)
-
- key = start
- while key <= end:
- if not export_settings[gltf2_blender_export_keys.FRAME_RANGE] or (frame_start <= key <= frame_end):
- keys.append(key)
- key += export_settings[gltf2_blender_export_keys.FRAME_STEP]
-
- keys.sort()
-
- else:
- for blender_fcurve in fcurve_list:
- if blender_fcurve is None:
- continue
-
- for blender_keyframe in blender_fcurve.keyframe_points:
- key = blender_keyframe.co[0]
- if not export_settings[gltf2_blender_export_keys.FRAME_RANGE] or (frame_start <= key <= frame_end):
- if key not in keys:
- keys.append(key)
-
- keys.sort()
-
- return keys
-
-
-def animate_location(export_settings, location, interpolation, node_type, node_name, action_name, matrix_correction,
- matrix_basis):
- """Calculate/gather the key value pairs for location transformations."""
- joint_cache = export_settings[gltf2_blender_export_keys.JOINT_CACHE][action_name]
- if not joint_cache.get(node_name):
- joint_cache[node_name] = {}
-
- keys = animate_gather_keys(export_settings, location, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
- result_in_tangent = {}
- result_out_tangent = {}
-
- keyframe_index = 0
- for timeIndex, time in enumerate(times):
- translation = [0.0, 0.0, 0.0]
- in_tangent = [0.0, 0.0, 0.0]
- out_tangent = [0.0, 0.0, 0.0]
-
- if node_type == JOINT_NODE:
- if joint_cache[node_name].get(keys[keyframe_index]):
- translation, tmp_rotation, tmp_scale = joint_cache[node_name][keys[keyframe_index]]
- else:
- bpy.context.scene.frame_set(keys[keyframe_index])
-
- matrix = matrix_correction * matrix_basis
-
- translation, tmp_rotation, tmp_scale = matrix.decompose()
-
- joint_cache[node_name][keys[keyframe_index]] = [translation, tmp_rotation, tmp_scale]
- else:
- channel_index = 0
- for blender_fcurve in location:
-
- if blender_fcurve is not None:
-
- if interpolation == CUBIC_INTERPOLATION:
- blender_key_frame = blender_fcurve.keyframe_points[keyframe_index]
-
- translation[channel_index] = blender_key_frame.co[1]
-
- if timeIndex == 0:
- in_tangent_value = 0.0
- else:
- factor = 3.0 / (time - times[timeIndex - 1])
- in_tangent_value = (blender_key_frame.co[1] - blender_key_frame.handle_left[1]) * factor
-
- if timeIndex == len(times) - 1:
- out_tangent_value = 0.0
- else:
- factor = 3.0 / (times[timeIndex + 1] - time)
- out_tangent_value = (blender_key_frame.handle_right[1] - blender_key_frame.co[1]) * factor
-
- in_tangent[channel_index] = in_tangent_value
- out_tangent[channel_index] = out_tangent_value
- else:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- translation[channel_index] = value
-
- channel_index += 1
-
- # handle parent inverse
- matrix = Matrix.Translation(translation)
- matrix = matrix_correction * matrix
- translation = matrix.to_translation()
-
- translation = gltf2_blender_extract.convert_swizzle_location(translation, export_settings)
- in_tangent = gltf2_blender_extract.convert_swizzle_location(in_tangent, export_settings)
- out_tangent = gltf2_blender_extract.convert_swizzle_location(out_tangent, export_settings)
-
- result[time] = translation
- result_in_tangent[time] = in_tangent
- result_out_tangent[time] = out_tangent
-
- keyframe_index += 1
-
- return result, result_in_tangent, result_out_tangent
-
-
-def animate_rotation_axis_angle(export_settings, rotation_axis_angle, interpolation, node_type, node_name, action_name,
- matrix_correction, matrix_basis):
- """Calculate/gather the key value pairs for axis angle transformations."""
- joint_cache = export_settings[gltf2_blender_export_keys.JOINT_CACHE][action_name]
- if not joint_cache.get(node_name):
- joint_cache[node_name] = {}
-
- keys = animate_gather_keys(export_settings, rotation_axis_angle, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
-
- keyframe_index = 0
- for time in times:
- axis_angle_rotation = [1.0, 0.0, 0.0, 0.0]
-
- if node_type == JOINT_NODE:
- if joint_cache[node_name].get(keys[keyframe_index]):
- tmp_location, rotation, tmp_scale = joint_cache[node_name][keys[keyframe_index]]
- else:
- bpy.context.scene.frame_set(keys[keyframe_index])
-
- matrix = matrix_correction * matrix_basis
-
- tmp_location, rotation, tmp_scale = matrix.decompose()
-
- joint_cache[node_name][keys[keyframe_index]] = [tmp_location, rotation, tmp_scale]
- else:
- channel_index = 0
- for blender_fcurve in rotation_axis_angle:
- if blender_fcurve is not None:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- axis_angle_rotation[channel_index] = value
-
- channel_index += 1
-
- rotation = animate_convert_rotation_axis_angle(axis_angle_rotation)
-
- # handle parent inverse
- rotation = Quaternion((rotation[3], rotation[0], rotation[1], rotation[2]))
- matrix = rotation.to_matrix().to_4x4()
- matrix = matrix_correction * matrix
- rotation = matrix.to_quaternion()
-
- # Bring back to internal Quaternion notation.
- rotation = gltf2_blender_extract.convert_swizzle_rotation(
- [rotation[0], rotation[1], rotation[2], rotation[3]], export_settings)
-
- # Bring back to glTF Quaternion notation.
- rotation = [rotation[1], rotation[2], rotation[3], rotation[0]]
-
- result[time] = rotation
-
- keyframe_index += 1
-
- return result
-
-
-def animate_rotation_euler(export_settings, rotation_euler, rotation_mode, interpolation, node_type, node_name,
- action_name, matrix_correction, matrix_basis):
- """Calculate/gather the key value pairs for euler angle transformations."""
- joint_cache = export_settings[gltf2_blender_export_keys.JOINT_CACHE][action_name]
- if not joint_cache.get(node_name):
- joint_cache[node_name] = {}
-
- keys = animate_gather_keys(export_settings, rotation_euler, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
-
- keyframe_index = 0
- for time in times:
- euler_rotation = [0.0, 0.0, 0.0]
-
- if node_type == JOINT_NODE:
- if joint_cache[node_name].get(keys[keyframe_index]):
- tmp_location, rotation, tmp_scale = joint_cache[node_name][keys[keyframe_index]]
- else:
- bpy.context.scene.frame_set(keys[keyframe_index])
-
- matrix = matrix_correction * matrix_basis
-
- tmp_location, rotation, tmp_scale = matrix.decompose()
-
- joint_cache[node_name][keys[keyframe_index]] = [tmp_location, rotation, tmp_scale]
- else:
- channel_index = 0
- for blender_fcurve in rotation_euler:
- if blender_fcurve is not None:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- euler_rotation[channel_index] = value
-
- channel_index += 1
-
- rotation = animate_convert_rotation_euler(euler_rotation, rotation_mode)
-
- # handle parent inverse
- rotation = Quaternion((rotation[3], rotation[0], rotation[1], rotation[2]))
- matrix = rotation.to_matrix().to_4x4()
- matrix = matrix_correction * matrix
- rotation = matrix.to_quaternion()
-
- # Bring back to internal Quaternion notation.
- rotation = gltf2_blender_extract.convert_swizzle_rotation(
- [rotation[0], rotation[1], rotation[2], rotation[3]], export_settings)
-
- # Bring back to glTF Quaternion notation.
- rotation = [rotation[1], rotation[2], rotation[3], rotation[0]]
-
- result[time] = rotation
-
- keyframe_index += 1
-
- return result
-
-
-def animate_rotation_quaternion(export_settings, rotation_quaternion, interpolation, node_type, node_name, action_name,
- matrix_correction, matrix_basis):
- """Calculate/gather the key value pairs for quaternion transformations."""
- joint_cache = export_settings[gltf2_blender_export_keys.JOINT_CACHE][action_name]
- if not joint_cache.get(node_name):
- joint_cache[node_name] = {}
-
- keys = animate_gather_keys(export_settings, rotation_quaternion, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
- result_in_tangent = {}
- result_out_tangent = {}
-
- keyframe_index = 0
- for timeIndex, time in enumerate(times):
- rotation = [1.0, 0.0, 0.0, 0.0]
- in_tangent = [1.0, 0.0, 0.0, 0.0]
- out_tangent = [1.0, 0.0, 0.0, 0.0]
-
- if node_type == JOINT_NODE:
- if joint_cache[node_name].get(keys[keyframe_index]):
- tmp_location, rotation, tmp_scale = joint_cache[node_name][keys[keyframe_index]]
- else:
- bpy.context.scene.frame_set(keys[keyframe_index])
-
- matrix = matrix_correction * matrix_basis
-
- tmp_location, rotation, tmp_scale = matrix.decompose()
-
- joint_cache[node_name][keys[keyframe_index]] = [tmp_location, rotation, tmp_scale]
- else:
- channel_index = 0
- for blender_fcurve in rotation_quaternion:
-
- if blender_fcurve is not None:
- if interpolation == CUBIC_INTERPOLATION:
- blender_key_frame = blender_fcurve.keyframe_points[keyframe_index]
-
- rotation[channel_index] = blender_key_frame.co[1]
-
- if timeIndex == 0:
- in_tangent_value = 0.0
- else:
- factor = 3.0 / (time - times[timeIndex - 1])
- in_tangent_value = (blender_key_frame.co[1] - blender_key_frame.handle_left[1]) * factor
-
- if timeIndex == len(times) - 1:
- out_tangent_value = 0.0
- else:
- factor = 3.0 / (times[timeIndex + 1] - time)
- out_tangent_value = (blender_key_frame.handle_right[1] - blender_key_frame.co[1]) * factor
-
- in_tangent[channel_index] = in_tangent_value
- out_tangent[channel_index] = out_tangent_value
- else:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- rotation[channel_index] = value
-
- channel_index += 1
-
- rotation = Quaternion((rotation[0], rotation[1], rotation[2], rotation[3]))
- in_tangent = gltf2_blender_extract.convert_swizzle_rotation(in_tangent, export_settings)
- out_tangent = gltf2_blender_extract.convert_swizzle_rotation(out_tangent, export_settings)
-
- # handle parent inverse
- matrix = rotation.to_matrix().to_4x4()
- matrix = matrix_correction * matrix
- rotation = matrix.to_quaternion()
-
- # Bring back to internal Quaternion notation.
- rotation = gltf2_blender_extract.convert_swizzle_rotation(
- [rotation[0], rotation[1], rotation[2], rotation[3]], export_settings)
-
- # Bring to glTF Quaternion notation.
- rotation = [rotation[1], rotation[2], rotation[3], rotation[0]]
- in_tangent = [in_tangent[1], in_tangent[2], in_tangent[3], in_tangent[0]]
- out_tangent = [out_tangent[1], out_tangent[2], out_tangent[3], out_tangent[0]]
-
- result[time] = rotation
- result_in_tangent[time] = in_tangent
- result_out_tangent[time] = out_tangent
-
- keyframe_index += 1
-
- return result, result_in_tangent, result_out_tangent
-
-
-def animate_scale(export_settings, scale, interpolation, node_type, node_name, action_name, matrix_correction,
- matrix_basis):
- """Calculate/gather the key value pairs for scale transformations."""
- joint_cache = export_settings[gltf2_blender_export_keys.JOINT_CACHE][action_name]
- if not joint_cache.get(node_name):
- joint_cache[node_name] = {}
-
- keys = animate_gather_keys(export_settings, scale, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
- result_in_tangent = {}
- result_out_tangent = {}
-
- keyframe_index = 0
- for timeIndex, time in enumerate(times):
- scale_data = [1.0, 1.0, 1.0]
- in_tangent = [0.0, 0.0, 0.0]
- out_tangent = [0.0, 0.0, 0.0]
-
- if node_type == JOINT_NODE:
- if joint_cache[node_name].get(keys[keyframe_index]):
- tmp_location, tmp_rotation, scale_data = joint_cache[node_name][keys[keyframe_index]]
- else:
- bpy.context.scene.frame_set(keys[keyframe_index])
-
- matrix = matrix_correction * matrix_basis
-
- tmp_location, tmp_rotation, scale_data = matrix.decompose()
-
- joint_cache[node_name][keys[keyframe_index]] = [tmp_location, tmp_rotation, scale_data]
- else:
- channel_index = 0
- for blender_fcurve in scale:
-
- if blender_fcurve is not None:
- if interpolation == CUBIC_INTERPOLATION:
- blender_key_frame = blender_fcurve.keyframe_points[keyframe_index]
-
- scale_data[channel_index] = blender_key_frame.co[1]
-
- if timeIndex == 0:
- in_tangent_value = 0.0
- else:
- factor = 3.0 / (time - times[timeIndex - 1])
- in_tangent_value = (blender_key_frame.co[1] - blender_key_frame.handle_left[1]) * factor
-
- if timeIndex == len(times) - 1:
- out_tangent_value = 0.0
- else:
- factor = 3.0 / (times[timeIndex + 1] - time)
- out_tangent_value = (blender_key_frame.handle_right[1] - blender_key_frame.co[1]) * factor
-
- in_tangent[channel_index] = in_tangent_value
- out_tangent[channel_index] = out_tangent_value
- else:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- scale_data[channel_index] = value
-
- channel_index += 1
-
- scale_data = gltf2_blender_extract.convert_swizzle_scale(scale_data, export_settings)
- in_tangent = gltf2_blender_extract.convert_swizzle_scale(in_tangent, export_settings)
- out_tangent = gltf2_blender_extract.convert_swizzle_scale(out_tangent, export_settings)
-
- # handle parent inverse
- matrix = Matrix()
- matrix[0][0] = scale_data.x
- matrix[1][1] = scale_data.y
- matrix[2][2] = scale_data.z
- matrix = matrix_correction * matrix
- scale_data = matrix.to_scale()
-
- result[time] = scale_data
- result_in_tangent[time] = in_tangent
- result_out_tangent[time] = out_tangent
-
- keyframe_index += 1
-
- return result, result_in_tangent, result_out_tangent
-
-
-def animate_value(export_settings, value_parameter, interpolation,
- node_type, node_name, matrix_correction, matrix_basis):
- """Calculate/gather the key value pairs for scalar anaimations."""
- keys = animate_gather_keys(export_settings, value_parameter, interpolation)
-
- times = animate_convert_keys(keys)
-
- result = {}
- result_in_tangent = {}
- result_out_tangent = {}
-
- keyframe_index = 0
- for timeIndex, time in enumerate(times):
- value_data = []
- in_tangent = []
- out_tangent = []
-
- for blender_fcurve in value_parameter:
-
- if blender_fcurve is not None:
- if interpolation == CUBIC_INTERPOLATION:
- blender_key_frame = blender_fcurve.keyframe_points[keyframe_index]
-
- value_data.append(blender_key_frame.co[1])
-
- if timeIndex == 0:
- in_tangent_value = 0.0
- else:
- factor = 3.0 / (time - times[timeIndex - 1])
- in_tangent_value = (blender_key_frame.co[1] - blender_key_frame.handle_left[1]) * factor
-
- if timeIndex == len(times) - 1:
- out_tangent_value = 0.0
- else:
- factor = 3.0 / (times[timeIndex + 1] - time)
- out_tangent_value = (blender_key_frame.handle_right[1] - blender_key_frame.co[1]) * factor
-
- in_tangent.append(in_tangent_value)
- out_tangent.append(out_tangent_value)
- else:
- value = blender_fcurve.evaluate(keys[keyframe_index])
-
- value_data.append(value)
-
- result[time] = value_data
- result_in_tangent[time] = in_tangent
- result_out_tangent[time] = out_tangent
-
- keyframe_index += 1
-
- return result, result_in_tangent, result_out_tangent
-
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_filter.py b/io_scene_gltf2/blender/exp/gltf2_blender_filter.py
deleted file mode 100755
index 6a4e18f9..00000000
--- a/io_scene_gltf2/blender/exp/gltf2_blender_filter.py
+++ /dev/null
@@ -1,455 +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.
-
-#
-# Imports
-#
-
-import bpy
-from . import gltf2_blender_export_keys
-from . import gltf2_blender_get
-from ...io.com.gltf2_io_debug import print_console
-from ..com.gltf2_blender_image import create_img_from_blender_image
-from ...io.com import gltf2_io_image
-
-#
-# Globals
-#
-
-PREVIEW = 'PREVIEW'
-GLOSSINESS = 'glTF Specular Glossiness'
-ROUGHNESS = 'glTF Metallic Roughness'
-
-
-#
-# Functions
-#
-
-def filter_merge_image(export_settings, blender_image):
- metallic_channel = gltf2_blender_get.get_image_material_usage_to_socket(blender_image, "Metallic")
- roughness_channel = gltf2_blender_get.get_image_material_usage_to_socket(blender_image, "Roughness")
-
- if metallic_channel < 0 and roughness_channel < 0:
- return False
-
- output = export_settings[gltf2_blender_export_keys.METALLIC_ROUGHNESS_IMAGE]
- if export_settings.get(export_keys.METALLIC_ROUGHNESS_IMAGE) is None:
- width = blender_image.image.size[0]
- height = blender_image.image.size[1]
- output = gltf2_io_image.create_img(width, height, r=1.0, g=1.0, b=1.0, a=1.0)
-
- source = create_img_from_blender_image(blender_image.image)
-
- if metallic_channel >= 0:
- gltf2_io_image.copy_img_channel(output, dst_channel=2, src_image=source, src_channel=metallic_channel)
- output.name = blender_image.image.name + output.name
- if roughness_channel >= 0:
- gltf2_io_image.copy_img_channel(output, dst_channel=1, src_image=source, src_channel=roughness_channel)
- if metallic_channel < 0:
- output.name = output.name + blender_image.image.name
- return True
-
-
-def filter_used_materials():
- """Gather and return all unfiltered, valid Blender materials."""
- materials = []
-
- for blender_material in bpy.data.materials:
- if blender_material.node_tree and blender_material.use_nodes:
- for currentNode in blender_material.node_tree.nodes:
- if isinstance(currentNode, bpy.types.ShaderNodeGroup):
- if currentNode.node_tree.name.startswith(ROUGHNESS):
- materials.append(blender_material)
- elif currentNode.node_tree.name.startswith(GLOSSINESS):
- materials.append(blender_material)
- elif isinstance(currentNode, bpy.types.ShaderNodeBsdfPrincipled):
- materials.append(blender_material)
- else:
- materials.append(blender_material)
-
- return materials
-
-
-def filter_apply(export_settings):
- """
- Gathers and filters the objects and assets to export.
-
- Also filters out invalid, deleted and not exportable elements.
- """
- filtered_objects = []
- implicit_filtered_objects = []
-
- for blender_object in bpy.data.objects:
-
- if blender_object.users == 0:
- continue
-
- if export_settings[gltf2_blender_export_keys.SELECTED] and blender_object.select_get() is False:
- continue
-
- if not export_settings[gltf2_blender_export_keys.LAYERS] and not blender_object.layers[0]:
- continue
-
- filtered_objects.append(blender_object)
-
- if export_settings[gltf2_blender_export_keys.SELECTED] or not export_settings[gltf2_blender_export_keys.LAYERS]:
- current_parent = blender_object.parent
- while current_parent:
- if current_parent not in implicit_filtered_objects:
- implicit_filtered_objects.append(current_parent)
-
- current_parent = current_parent.parent
-
- export_settings[gltf2_blender_export_keys.FILTERED_OBJECTS] = filtered_objects
-
- # Meshes
-
- filtered_meshes = {}
- filtered_vertex_groups = {}
- temporary_meshes = []
-
- for blender_mesh in bpy.data.meshes:
-
- if blender_mesh.users == 0:
- continue
-
- current_blender_mesh = blender_mesh
-
- current_blender_object = None
-
- skip = True
-
- for blender_object in filtered_objects:
-
- current_blender_object = blender_object
-
- if current_blender_object.type != 'MESH':
- continue
-
- if current_blender_object.data == current_blender_mesh:
-
- skip = False
-
- use_auto_smooth = current_blender_mesh.use_auto_smooth
-
- if use_auto_smooth:
-
- if current_blender_mesh.shape_keys is None:
- current_blender_object = current_blender_object.copy()
- else:
- use_auto_smooth = False
-
- print_console('WARNING',
- 'Auto smooth and shape keys cannot be exported in parallel. '
- 'Falling back to non auto smooth.')
-
- if export_settings[gltf2_blender_export_keys.APPLY] or use_auto_smooth:
- # TODO: maybe add to new exporter
- if not export_settings[gltf2_blender_export_keys.APPLY]:
- current_blender_object.modifiers.clear()
-
- if use_auto_smooth:
- blender_modifier = current_blender_object.modifiers.new('Temporary_Auto_Smooth', 'EDGE_SPLIT')
-
- blender_modifier.split_angle = current_blender_mesh.auto_smooth_angle
- blender_modifier.use_edge_angle = not current_blender_mesh.has_custom_normals
-
- current_blender_mesh = current_blender_object.to_mesh(bpy.context.scene, True, PREVIEW)
- temporary_meshes.append(current_blender_mesh)
-
- break
-
- if skip:
- continue
-
- filtered_meshes[blender_mesh.name] = current_blender_mesh
- filtered_vertex_groups[blender_mesh.name] = current_blender_object.vertex_groups
-
- # Curves
-
- for blender_curve in bpy.data.curves:
-
- if blender_curve.users == 0:
- continue
-
- current_blender_curve = blender_curve
-
- current_blender_mesh = None
-
- current_blender_object = None
-
- skip = True
-
- for blender_object in filtered_objects:
-
- current_blender_object = blender_object
-
- if current_blender_object.type not in ('CURVE', 'FONT'):
- continue
-
- if current_blender_object.data == current_blender_curve:
-
- skip = False
-
- current_blender_object = current_blender_object.copy()
-
- if not export_settings[gltf2_blender_export_keys.APPLY]:
- current_blender_object.modifiers.clear()
-
- current_blender_mesh = current_blender_object.to_mesh(bpy.context.scene, True, PREVIEW)
- temporary_meshes.append(current_blender_mesh)
-
- break
-
- if skip:
- continue
-
- filtered_meshes[blender_curve.name] = current_blender_mesh
- filtered_vertex_groups[blender_curve.name] = current_blender_object.vertex_groups
-
- #
-
- export_settings[gltf2_blender_export_keys.FILTERED_MESHES] = filtered_meshes
- export_settings[gltf2_blender_export_keys.FILTERED_VERTEX_GROUPS] = filtered_vertex_groups
- export_settings[gltf2_blender_export_keys.TEMPORARY_MESHES] = temporary_meshes
-
- #
-
- filtered_materials = []
-
- for blender_material in filter_used_materials():
-
- if blender_material.users == 0:
- continue
-
- for mesh_name, blender_mesh in filtered_meshes.items():
- for compare_blender_material in blender_mesh.materials:
- if compare_blender_material == blender_material and blender_material not in filtered_materials:
- filtered_materials.append(blender_material)
-
- #
-
- for blender_object in filtered_objects:
- if blender_object.material_slots:
- for blender_material_slot in blender_object.material_slots:
- if blender_material_slot.link == 'DATA':
- continue
-
- if blender_material_slot.material not in filtered_materials:
- filtered_materials.append(blender_material_slot.material)
-
- export_settings[gltf2_blender_export_keys.FILTERED_MATERIALS] = filtered_materials
-
- #
-
- filtered_textures = []
- filtered_merged_textures = []
-
- temp_filtered_texture_names = []
-
- for blender_material in filtered_materials:
- if blender_material.node_tree and blender_material.use_nodes:
-
- per_material_textures = []
-
- for blender_node in blender_material.node_tree.nodes:
-
- if is_valid_node(blender_node) and blender_node not in filtered_textures:
- add_node = False
- add_merged_node = False
- for blender_socket in blender_node.outputs:
- if blender_socket.is_linked:
- for blender_link in blender_socket.links:
- if isinstance(blender_link.to_node, bpy.types.ShaderNodeGroup):
- is_roughness = blender_link.to_node.node_tree.name.startswith(ROUGHNESS)
- is_glossiness = blender_link.to_node.node_tree.name.startswith(GLOSSINESS)
- if is_roughness or is_glossiness:
- add_node = True
- break
- elif isinstance(blender_link.to_node, bpy.types.ShaderNodeBsdfPrincipled):
- add_node = True
- break
- elif isinstance(blender_link.to_node, bpy.types.ShaderNodeNormalMap):
- add_node = True
- break
- elif isinstance(blender_link.to_node, bpy.types.ShaderNodeSeparateRGB):
- add_merged_node = True
- break
-
- if add_node or add_merged_node:
- break
-
- if add_node:
- filtered_textures.append(blender_node)
- # TODO: Add displacement texture, as not stored in node tree.
-
- if add_merged_node:
- if len(per_material_textures) == 0:
- filtered_merged_textures.append(per_material_textures)
-
- per_material_textures.append(blender_node)
-
- else:
-
- for blender_texture_slot in blender_material.texture_slots:
-
- if is_valid_texture_slot(blender_texture_slot) and \
- blender_texture_slot not in filtered_textures and \
- blender_texture_slot.name not in temp_filtered_texture_names:
- accept = False
-
- if blender_texture_slot.use_map_color_diffuse:
- accept = True
-
- if blender_texture_slot.use_map_ambient:
- accept = True
- if blender_texture_slot.use_map_emit:
- accept = True
- if blender_texture_slot.use_map_normal:
- accept = True
-
- if export_settings[gltf2_blender_export_keys.DISPLACEMENT]:
- if blender_texture_slot.use_map_displacement:
- accept = True
-
- if accept:
- filtered_textures.append(blender_texture_slot)
- temp_filtered_texture_names.append(blender_texture_slot.name)
-
- export_settings[gltf2_blender_export_keys.FILTERED_TEXTURES] = filtered_textures
-
- #
-
- filtered_images = []
- filtered_merged_images = []
- filtered_images_use_alpha = {}
-
- for blender_texture in filtered_textures:
-
- if isinstance(blender_texture, bpy.types.ShaderNodeTexImage):
- if is_valid_image(blender_texture.image) and blender_texture.image not in filtered_images:
- filtered_images.append(blender_texture.image)
- alpha_socket = blender_texture.outputs.get('Alpha')
- if alpha_socket is not None and alpha_socket.is_linked:
- filtered_images_use_alpha[blender_texture.image.name] = True
-
- else:
- if is_valid_image(blender_texture.texture.image) and blender_texture.texture.image not in filtered_images:
- filtered_images.append(blender_texture.texture.image)
- if blender_texture.use_map_alpha:
- filtered_images_use_alpha[blender_texture.texture.image.name] = True
-
- #
-
- for per_material_textures in filtered_merged_textures:
-
- export_settings[gltf2_blender_export_keys.METALLIC_ROUGHNESS_IMAGE] = None
-
- for blender_texture in per_material_textures:
-
- if isinstance(blender_texture, bpy.types.ShaderNodeTexImage):
- if is_valid_image(blender_texture.image) and blender_texture.image not in filtered_images:
- filter_merge_image(export_settings, blender_texture)
-
- img = export_settings.get(export_keys.METALLIC_ROUGHNESS_IMAGE)
- if img is not None:
- filtered_merged_images.append(img)
- export_settings[gltf2_blender_export_keys.FILTERED_TEXTURES].append(img)
-
- export_settings[gltf2_blender_export_keys.FILTERED_MERGED_IMAGES] = filtered_merged_images
- export_settings[gltf2_blender_export_keys.FILTERED_IMAGES] = filtered_images
- export_settings[gltf2_blender_export_keys.FILTERED_IMAGES_USE_ALPHA] = filtered_images_use_alpha
-
- #
-
- filtered_cameras = []
-
- for blender_camera in bpy.data.cameras:
-
- if blender_camera.users == 0:
- continue
-
- if export_settings[gltf2_blender_export_keys.SELECTED]:
- if blender_camera not in filtered_objects:
- continue
-
- filtered_cameras.append(blender_camera)
-
- export_settings[gltf2_blender_export_keys.FILTERED_CAMERAS] = filtered_cameras
-
- #
- #
-
- filtered_lights = []
-
- for blender_light in bpy.data.lamps:
-
- if blender_light.users == 0:
- continue
-
- if export_settings[gltf2_blender_export_keys.SELECTED]:
- if blender_light not in filtered_objects:
- continue
-
- if blender_light.type == 'HEMI':
- continue
-
- filtered_lights.append(blender_light)
-
- export_settings[gltf2_blender_export_keys.FILTERED_LIGHTS] = filtered_lights
-
- #
- #
-
- for implicit_object in implicit_filtered_objects:
- if implicit_object not in filtered_objects:
- filtered_objects.append(implicit_object)
-
- #
- #
- #
-
- group_index = {}
-
- if export_settings[gltf2_blender_export_keys.SKINS]:
- for blender_object in filtered_objects:
- if blender_object.type != 'ARMATURE' or len(blender_object.pose.bones) == 0:
- continue
- for blender_bone in blender_object.pose.bones:
- group_index[blender_bone.name] = len(group_index)
-
- export_settings[gltf2_blender_export_keys.GROUP_INDEX] = group_index
-
-
-def is_valid_node(blender_node):
- return isinstance(blender_node, bpy.types.ShaderNodeTexImage) and is_valid_image(blender_node.image)
-
-
-def is_valid_image(image):
- return image is not None and \
- image.users != 0 and \
- image.size[0] > 0 and \
- image.size[1] > 0
-
-
-def is_valid_texture_slot(blender_texture_slot):
- return blender_texture_slot is not None and \
- blender_texture_slot.texture and \
- blender_texture_slot.texture.users != 0 and \
- blender_texture_slot.texture.type == 'IMAGE' and \
- blender_texture_slot.texture.image is not None and \
- blender_texture_slot.texture.image.users != 0 and \
- blender_texture_slot.texture.image.size[0] > 0 and \
- blender_texture_slot.texture.image.size[1] > 0
-
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_search_scene.py b/io_scene_gltf2/blender/exp/gltf2_blender_search_scene.py
deleted file mode 100755
index 0fa7db6e..00000000
--- a/io_scene_gltf2/blender/exp/gltf2_blender_search_scene.py
+++ /dev/null
@@ -1,89 +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 bpy
-import typing
-
-
-class Filter:
- """Base class for all node tree filter operations."""
-
- def __call__(self, obj: bpy.types.Object):
- return True
-
-
-class ByName(Filter):
- """
- Filter the objects by name.
-
- example usage:
- find_objects(FilterByName("Cube"))
- """
-
- def __init__(self, name):
- self.name = name
-
- def __call__(self, obj: bpy.types.Object):
- return obj.name == self.name
-
-
-class ByDataType(Filter):
- """Filter the scene objects by their data type."""
-
- def __init__(self, data_type: str):
- self.type = data_type
-
- def __call__(self, obj: bpy.types.Object):
- return obj.type == self.type
-
-
-class ByDataInstance(Filter):
- """Filter the scene objects by a specific ID instance."""
-
- def __init__(self, data_instance: bpy.types.ID):
- self.data = data_instance
-
- def __call__(self, obj: bpy.types.Object):
- return self.data == obj.data
-
-
-def find_objects(object_filter: typing.Union[Filter, typing.Callable]):
- """
- Find objects in the scene where the filter expression is true.
-
- :param object_filter: should be a function(x: object) -> bool
- :return: a list of shader nodes for which filter is true
- """
- results = []
- for obj in bpy.context.scene.objects:
- if object_filter(obj):
- results.append(obj)
- return results
-
-
-def find_objects_from(obj: bpy.types.Object, object_filter: typing.Union[Filter, typing.Callable]):
- """
- Search for objects matching a filter function below a specified object.
-
- :param obj: the starting point of the search
- :param object_filter: a function(x: object) -> bool
- :return: a list of objects which passed the filter
- """
- results = []
- if object_filter(obj):
- results.append(obj)
- for child in obj.children:
- results += find_objects_from(child, object_filter)
- return results
-