diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2019-10-12 14:21:42 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2019-10-12 14:21:42 +0300 |
commit | 06766ff5d5932a7acb05a45d6cd045e5374e6b38 (patch) | |
tree | 119b1958997d5b590465da4a550ad479e5ab52a2 /io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py | |
parent | 2476c0b4b2789e65f1ef95989d4e42dfd784be45 (diff) |
glTF exporter: fix exporting shapekeys animation when some sk are not animated
Diffstat (limited to 'io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py')
-rwxr-xr-x | io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py | 65 |
1 files changed, 37 insertions, 28 deletions
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 8a4f011a..8b6f0db6 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 @@ -29,9 +29,15 @@ class Keyframe: self.seconds = frame / bpy.context.scene.render.fps self.frame = frame self.fps = bpy.context.scene.render.fps + self.__length_morph = 0 + # Note: channels has some None items only for SK if some SK are not animated if bake_channel is None: - self.target = channels[0].data_path.split('.')[-1] - self.__indices = [c.array_index for c in channels] + self.target = [c for c in channels if c is not None][0].data_path.split('.')[-1] + if self.target != "value": + self.__indices = [c.array_index for c in channels] + else: + self.__indices = [i for i, c in enumerate(channels) if c is not None] + self.__length_morph = len(channels) else: self.target = bake_channel self.__indices = [] @@ -53,7 +59,7 @@ class Keyframe: "rotation_euler": 3, "rotation_quaternion": 4, "scale": 3, - "value": 1 + "value": self.__length_morph }.get(self.target) if length is None: @@ -62,17 +68,18 @@ class Keyframe: return length def __set_indexed(self, value): - # 'value' targets don't use keyframe.array_index - if self.target == "value": - return value # Sometimes blender animations only reference a subset of components of a data target. Keyframe should always # contain a complete Vector/ Quaternion --> use the array_index value of the keyframe to set components in such # structures + # For SK, must contains all SK values result = [0.0] * self.get_target_len() for i, v in zip(self.__indices, value): result[i] = v - result = gltf2_blender_math.list_to_mathutils(result, self.target) - return result + if self.target == "value": + return result + else: + result = gltf2_blender_math.list_to_mathutils(result, self.target) + return result def get_indices(self): return self.__indices @@ -164,10 +171,11 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec """Convert the blender action groups' fcurves to keyframes for use in glTF.""" if bake_bone is None: # Find the start and end of the whole action group - ranges = [channel.range() for channel in channels] + # Note: channels has some None items only for SK if some SK are not animated + ranges = [channel.range() for channel in channels if channel is not None] - start_frame = min([channel.range()[0] for channel in channels]) - end_frame = max([channel.range()[1] for channel in channels]) + start_frame = min([channel.range()[0] for channel in channels if channel is not None]) + end_frame = max([channel.range()[1] for channel in channels if channel is not None]) else: start_frame = bake_range_start end_frame = bake_range_end @@ -218,25 +226,27 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec "scale": scale }[target_property] else: - key.value = [c.evaluate(frame) for c in channels] + # Note: channels has some None items only for SK if some SK are not animated + key.value = [c.evaluate(frame) for c in channels if c is not None] complete_key(key, non_keyed_values) keyframes.append(key) frame += step else: # Just use the keyframes as they are specified in blender - frames = [keyframe.co[0] for keyframe in channels[0].keyframe_points] + # Note: channels has some None items only for SK if some SK are not animated + frames = [keyframe.co[0] for keyframe in [c for c in channels if c is not None][0].keyframe_points] # some weird files have duplicate frame at same time, removed them frames = sorted(set(frames)) for i, frame in enumerate(frames): key = Keyframe(channels, frame, bake_channel) # key.value = [c.keyframe_points[i].co[0] for c in action_group.channels] - key.value = [c.evaluate(frame) for c in channels] + key.value = [c.evaluate(frame) for c in channels if c is not None] # Complete key with non keyed values, if needed - if len(channels) != key.get_target_len(): + if len([c for c in channels if c is not None]) != key.get_target_len(): complete_key(key, non_keyed_values) # compute tangents for cubic spline interpolation - if channels[0].keyframe_points[0].interpolation == "BEZIER": + if [c for c in channels if c is not None][0].keyframe_points[0].interpolation == "BEZIER": # Construct the in tangent if frame == frames[0]: # start in-tangent should become all zero @@ -248,7 +258,7 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec key.in_tangent = [ c.keyframe_points[i].co[1] + ((c.keyframe_points[i].co[1] - c.keyframe_points[i].handle_left[1] ) / (frame - frames[i - 1])) - for c in channels + for c in channels if c is not None ] # Construct the out tangent if frame == frames[-1]: @@ -261,7 +271,7 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec key.out_tangent = [ c.keyframe_points[i].co[1] + ((c.keyframe_points[i].handle_right[1] - c.keyframe_points[i].co[1] ) / (frames[i + 1] - frame)) - for c in channels + for c in channels if c is not None ] keyframes.append(key) @@ -273,12 +283,9 @@ def complete_key(key: Keyframe, non_keyed_values: typing.Tuple[typing.Optional[f """ Complete keyframe with non keyed values """ - - if key.target == "value": - return # No array_index for i in range(0, key.get_target_len()): if i in key.get_indices(): - continue # this is a keyed array_index + continue # this is a keyed array_index or a SK animated key.set_value_index(i, non_keyed_values[i]) def needs_baking(blender_object_if_armature: typing.Optional[bpy.types.Object], @@ -293,12 +300,14 @@ def needs_baking(blender_object_if_armature: typing.Optional[bpy.types.Object], def all_equal(lst): return lst[1:] == lst[:-1] + # Note: channels has some None items only for SK if some SK are not animated + # Sampling is forced if export_settings[gltf2_blender_export_keys.FORCE_SAMPLING]: return True # Sampling due to unsupported interpolation - interpolation = channels[0].keyframe_points[0].interpolation + interpolation = [c for c in channels if c is not None][0].keyframe_points[0].interpolation if interpolation not in ["BEZIER", "LINEAR", "CONSTANT"]: gltf2_io_debug.print_console("WARNING", "Baking animation because of an unsupported interpolation method: {}".format( @@ -306,7 +315,7 @@ def needs_baking(blender_object_if_armature: typing.Optional[bpy.types.Object], ) return True - if any(any(k.interpolation != interpolation for k in c.keyframe_points) for c in channels): + if any(any(k.interpolation != interpolation for k in c.keyframe_points) for c in channels if c is not None): # There are different interpolation methods in one action group gltf2_io_debug.print_console("WARNING", "Baking animation because there are keyframes with different " @@ -314,24 +323,24 @@ def needs_baking(blender_object_if_armature: typing.Optional[bpy.types.Object], ) return True - if not all_equal([len(c.keyframe_points) for c in channels]): + if not all_equal([len(c.keyframe_points) for c in channels if c is not None]): gltf2_io_debug.print_console("WARNING", "Baking animation because the number of keyframes is not " "equal for all channel tracks") return True - if len(channels[0].keyframe_points) <= 1: + if len([c for c in channels if c is not None][0].keyframe_points) <= 1: # we need to bake to 'STEP', as at least two keyframes are required to interpolate return True - if not all_equal(list(zip([[k.co[0] for k in c.keyframe_points] for c in channels]))): + if not all_equal(list(zip([[k.co[0] for k in c.keyframe_points] for c in channels if c is not None]))): # The channels have differently located keyframes gltf2_io_debug.print_console("WARNING", "Baking animation because of differently located keyframes in one channel") return True if blender_object_if_armature is not None: - animation_target = gltf2_blender_get.get_object_from_datapath(blender_object_if_armature, channels[0].data_path) + animation_target = gltf2_blender_get.get_object_from_datapath(blender_object_if_armature, [c for c in channels if c is not None][0].data_path) if isinstance(animation_target, bpy.types.PoseBone): if len(animation_target.constraints) != 0: # Constraints such as IK act on the bone -> can not be represented in glTF atm |