From 4cb6ebd8747e15b417e565afb5b1c4623a66d381 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 19 Sep 2022 09:34:10 +0200 Subject: glTF exporter: fix objects parented to bone animated when using rest pose as default --- io_scene_gltf2/__init__.py | 2 +- .../exp/gltf2_blender_gather_animation_channels.py | 44 ++++++++++++++++++++++ .../blender/exp/gltf2_blender_gather_animations.py | 31 +-------------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 4fad230d..f75d6c4f 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, 16), + "version": (3, 4, 17), 'blender': (3, 3, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', 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 e7235254..b68c1fdc 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 @@ -19,6 +19,35 @@ from io_scene_gltf2.blender.exp.gltf2_blender_gather_tree import VExportNode from . import gltf2_blender_export_keys +def gather_channels_baked(obj_uuid, export_settings): + channels = [] + + # If no animation in file, no need to bake + if len(bpy.data.actions) == 0: + return None + + start_frame = min([v[0] for v in [a.frame_range for a in bpy.data.actions]]) + end_frame = max([v[1] for v in [a.frame_range for a in bpy.data.actions]]) + + for p in ["location", "rotation_quaternion", "scale"]: + channel = gather_animation_channel( + obj_uuid, + (), + export_settings, + None, + p, + start_frame, + end_frame, + False, + obj_uuid, # Use obj uuid as action name for caching + None, + False #If Object is not animated, don't keep animation for this channel + ) + if channel is not None: + channels.append(channel) + + return channels if len(channels) > 0 else None + @cached def gather_animation_channels(obj_uuid: int, blender_action: bpy.types.Action, @@ -118,6 +147,21 @@ def gather_animation_channels(obj_uuid: int, if channel is not None: channels.append(channel) + # When An Object is parented to bone, and rest pose is used (not current frame) + # If parenting is not done with same TRS than rest pose, this can lead to inconsistencies + # So we need to bake object animation too, to be sure that correct TRS animation are used + # Here, we want add these channels to same action that the armature + if export_settings['gltf_selected'] is False and export_settings['gltf_current_frame'] is False: + + children_obj_parent_to_bones = [] + for bone_uuid in bones_uuid: + children_obj_parent_to_bones.extend([child for child in export_settings['vtree'].nodes[bone_uuid].children if export_settings['vtree'].nodes[child].blender_type != VExportNode.BONE]) + for child_uuid in children_obj_parent_to_bones: + + channels_baked = gather_channels_baked(child_uuid, export_settings) + if channels_baked is not None: + channels.extend(channels_baked) + else: done_paths = [] for channel_group in __get_channel_groups(blender_action, blender_object, export_settings): diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py index bdb2ee00..fe0425fd 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py @@ -13,35 +13,6 @@ from io_scene_gltf2.blender.exp.gltf2_blender_gather_tree import VExportNode from ..com.gltf2_blender_data_path import is_bone_anim_channel -def __gather_channels_baked(obj_uuid, export_settings): - channels = [] - - # If no animation in file, no need to bake - if len(bpy.data.actions) == 0: - return None - - start_frame = min([v[0] for v in [a.frame_range for a in bpy.data.actions]]) - end_frame = max([v[1] for v in [a.frame_range for a in bpy.data.actions]]) - - for p in ["location", "rotation_quaternion", "scale"]: - channel = gltf2_blender_gather_animation_channels.gather_animation_channel( - obj_uuid, - (), - export_settings, - None, - p, - start_frame, - end_frame, - False, - obj_uuid, # Use obj uuid as action name for caching - None, - False #If Object is not animated, don't keep animation for this channel - ) - if channel is not None: - channels.append(channel) - - return channels if len(channels) > 0 else None - def gather_animations( obj_uuid: int, tracks: typing.Dict[str, typing.List[int]], offset: int, @@ -69,7 +40,7 @@ def gather_animations( obj_uuid: int, # We also have to check if this is a skinned mesh, because we don't have to force animation baking on this case # (skinned meshes TRS must be ignored, says glTF specification) if export_settings['vtree'].nodes[obj_uuid].skin is None: - channels = __gather_channels_baked(obj_uuid, export_settings) + channels = gltf2_blender_gather_animation_channels.gather_channels_baked(obj_uuid, export_settings) if channels is not None: animation = gltf2_io.Animation( channels=channels, -- cgit v1.2.3