From 58db76bcc6ae799084d5ee8094515d0fad0fa01b Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 19 Sep 2022 09:24:35 +0200 Subject: glTF exporter: manage delta transform animation --- io_scene_gltf2/__init__.py | 2 +- .../blender/com/gltf2_blender_data_path.py | 27 +++++++++--- .../exp/gltf2_blender_gather_animation_channels.py | 50 ++++++++++++++++------ ...2_blender_gather_animation_sampler_keyframes.py | 6 ++- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 3034595b..4fad230d 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -4,7 +4,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": (3, 4, 15), + "version": (3, 4, 16), 'blender': (3, 3, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/com/gltf2_blender_data_path.py b/io_scene_gltf2/blender/com/gltf2_blender_data_path.py index a329193a..9aeeb5dc 100755 --- a/io_scene_gltf2/blender/com/gltf2_blender_data_path.py +++ b/io_scene_gltf2/blender/com/gltf2_blender_data_path.py @@ -15,20 +15,33 @@ def get_target_object_path(data_path: str) -> str: return "" return path_split[0] -def get_rotation_modes(target_property: str) -> str: +def get_rotation_modes(target_property: str): """Retrieve rotation modes based on target_property""" if target_property == "rotation_euler": - return True, False, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] + return True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] elif target_property == "delta_rotation_euler": - return True, True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] + return True, ["XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"] elif target_property == "rotation_quaternion": - return True, False, ["QUATERNION"] + return True, ["QUATERNION"] elif target_property == "delta_rotation_quaternion": - return True, True, ["QUATERNION"] + return True, ["QUATERNION"] elif target_property in ["rotation_axis_angle"]: - return True, False, ["AXIS_ANGLE"] + return True, ["AXIS_ANGLE"] else: - return False, False, [] + return False, [] + +def is_location(target_property): + return "location" in target_property + +def is_rotation(target_property): + return "rotation" in target_property + +def is_scale(target_property): + return "scale" in target_property + +def get_delta_modes(target_property: str) -> str: + """Retrieve location based on target_property""" + return target_property.startswith("delta_") def is_bone_anim_channel(data_path: str) -> bool: return data_path[:10] == "pose.bones" \ No newline at end of file diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py index 3e67f1f7..e7235254 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py @@ -4,7 +4,7 @@ import bpy import typing -from ..com.gltf2_blender_data_path import get_target_object_path, get_target_property_name, get_rotation_modes +from ..com.gltf2_blender_data_path import get_target_object_path, get_target_property_name, get_rotation_modes, get_delta_modes, is_location, is_rotation, is_scale from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.com import gltf2_io_debug from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached @@ -364,6 +364,8 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t targets = {} multiple_rotation_mode_detected = False delta_rotation_detection = [False, False] # Normal / Delta + delta_location_detection = [False, False] # Normal / Delta + delta_scale_detection = [False, False] # Normal / Delta for fcurve in blender_action.fcurves: # In some invalid files, channel hasn't any keyframes ... this channel need to be ignored if len(fcurve.keyframe_points) == 0: @@ -405,24 +407,46 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t # Detect that object or bone are not multiple keyed for euler and quaternion # Keep only the current rotation mode used by object - rotation, delta, rotation_modes = get_rotation_modes(target_property) + rotation, rotation_modes = get_rotation_modes(target_property) + delta = get_delta_modes(target_property) # Delta rotation management - if delta is False: - if delta_rotation_detection[1] is True: # normal rotation coming, but delta is already present - multiple_rotation_mode_detected = True - continue - delta_rotation_detection[0] = True - else: - if delta_rotation_detection[0] is True: # delta rotation coming, but normal is already present + if is_rotation(target_property) : + if delta is False: + if delta_rotation_detection[1] is True: # normal rotation coming, but delta is already present + continue + delta_rotation_detection[0] = True + else: + if delta_rotation_detection[0] is True: # delta rotation coming, but normal is already present + continue + delta_rotation_detection[1] = True + + + if rotation and target.rotation_mode not in rotation_modes: multiple_rotation_mode_detected = True continue - delta_rotation_detection[1] = True + # Delta location management + if is_location(target_property): + if delta is False: + if delta_location_detection[1] is True: # normal location coming, but delta is already present + continue + delta_location_detection[0] = True + else: + if delta_location_detection[0] is True: # delta location coming, but normal is already present + continue + delta_location_detection[1] = True - if rotation and target.rotation_mode not in rotation_modes: - multiple_rotation_mode_detected = True - continue + # Delta scale management + if is_scale(target_property): + if delta is False: + if delta_scale_detection[1] is True: # normal scale coming, but delta is already present + continue + delta_scale_detection[0] = True + else: + if delta_scale_detection[0] is True: # delta scale coming, but normal is already present + continue + delta_scale_detection[1] = True # group channels by target object and affected property of the target target_properties = targets.get(target, {}) diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py index 53d78945..b73c61b8 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py @@ -45,6 +45,7 @@ class Keyframe: length = { "delta_location": 3, "delta_rotation_euler": 3, + "delta_scale": 3, "location": 3, "rotation_axis_angle": 4, "rotation_euler": 3, @@ -367,7 +368,10 @@ def gather_keyframes(blender_obj_uuid: str, "rotation_axis_angle": [rot.to_axis_angle()[1], rot.to_axis_angle()[0][0], rot.to_axis_angle()[0][1], rot.to_axis_angle()[0][2]], "rotation_euler": rot.to_euler(), "rotation_quaternion": rot, - "scale": sca + "scale": sca, + "delta_location": trans, + "delta_rotation_euler": rot.to_euler(), + "delta_scale": sca }[target] else: key.value = get_sk_driver_values(driver_obj_uuid, frame, channels, export_settings) -- cgit v1.2.3