[Bf-extensions-cvs] [919559f3] master: glTF exporter: Sampled animation now bake all bones, including constraints

Julien Duroure noreply at git.blender.org
Sun May 26 23:57:32 CEST 2019


Commit: 919559f3deaffa77ad69bb173333f7c14c63028f
Author: Julien Duroure
Date:   Sun May 26 23:46:18 2019 +0200
Branches: master
https://developer.blender.org/rBA919559f3deaffa77ad69bb173333f7c14c63028f

glTF exporter: Sampled animation now bake all bones, including constraints

Using "Always Sample Animation" can now export complex rigs, including constraints, like rigify for example

===================================================================

M	io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py

===================================================================

diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
index 2e4ac1d7..5b2f28e8 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
@@ -24,37 +24,47 @@ from io_scene_gltf2.blender.exp import gltf2_blender_gather_joints
 @cached
 def gather_animation_channel_target(channels: typing.Tuple[bpy.types.FCurve],
                                     blender_object: bpy.types.Object,
+                                    bake_bone: typing.Union[str, None],
+                                    bake_channel: typing.Union[str, None],
                                     export_settings
                                     ) -> gltf2_io.AnimationChannelTarget:
-    return gltf2_io.AnimationChannelTarget(
-        extensions=__gather_extensions(channels, blender_object, export_settings),
-        extras=__gather_extras(channels, blender_object, export_settings),
-        node=__gather_node(channels, blender_object, export_settings),
-        path=__gather_path(channels, blender_object, export_settings)
-    )
 
+        return gltf2_io.AnimationChannelTarget(
+            extensions=__gather_extensions(channels, blender_object, export_settings, bake_bone),
+            extras=__gather_extras(channels, blender_object, export_settings, bake_bone),
+            node=__gather_node(channels, blender_object, export_settings, bake_bone),
+            path=__gather_path(channels, blender_object, export_settings, bake_bone, bake_channel)
+        )
 
 def __gather_extensions(channels: typing.Tuple[bpy.types.FCurve],
                         blender_object: bpy.types.Object,
-                        export_settings
+                        export_settings,
+                        bake_bone: typing.Union[str, None]
                         ) -> typing.Any:
     return None
 
 
 def __gather_extras(channels: typing.Tuple[bpy.types.FCurve],
                     blender_object: bpy.types.Object,
-                    export_settings
+                    export_settings,
+                    bake_bone: typing.Union[str, None]
                     ) -> typing.Any:
     return None
 
 
 def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
                   blender_object: bpy.types.Object,
-                  export_settings
+                  export_settings,
+                  bake_bone: typing.Union[str, None]
                   ) -> gltf2_io.Node:
     if blender_object.type == "ARMATURE":
         # TODO: get joint from fcurve data_path and gather_joint
-        blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])
+
+        if bake_bone is not None:
+            blender_bone = blender_object.pose.bones[bake_bone]
+        else:
+            blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])
+
         if isinstance(blender_bone, bpy.types.PoseBone):
             return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)
 
@@ -63,9 +73,14 @@ def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
 
 def __gather_path(channels: typing.Tuple[bpy.types.FCurve],
                   blender_object: bpy.types.Object,
-                  export_settings
+                  export_settings,
+                  bake_bone: typing.Union[str, None],
+                  bake_channel: typing.Union[str, None]
                   ) -> str:
-    target = channels[0].data_path.split('.')[-1]
+    if bake_channel is None:
+        target = channels[0].data_path.split('.')[-1]
+    else:
+        target = bake_channel
     path = {
         "delta_location": "translation",
         "delta_rotation_euler": "rotation",
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 1b76142c..aa81b073 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
@@ -31,26 +31,61 @@ def gather_animation_channels(blender_action: bpy.types.Action,
                               ) -> typing.List[gltf2_io.AnimationChannel]:
     channels = []
 
-    for channel_group in __get_channel_groups(blender_action, blender_object):
-        channel = __gather_animation_channel(channel_group, blender_object, export_settings)
-        if channel is not None:
-            channels.append(channel)
+    if blender_object.type == "ARMATURE" and export_settings['gltf_force_sampling'] is True:
+        # We have to store sampled animation data for every deformation bones
+
+        # First calculate range of animation for baking
+        bake_range_start = None
+        bake_range_end = None
+        groups = __get_channel_groups(blender_action, blender_object, export_settings)
+        for chans in groups:
+            ranges = [channel.range() for channel in chans]
+            if bake_range_start is None:
+                bake_range_start = min([channel.range()[0] for channel in chans])
+            else:
+                bake_range_start = min(bake_range_start, min([channel.range()[0] for channel in chans]))
+            if bake_range_end is None:
+                bake_range_end = max([channel.range()[1] for channel in chans])
+            else:
+                bake_range_end = max(bake_range_end, max([channel.range()[1] for channel in chans]))
+
+        # Then bake all bones
+        for bone in blender_object.data.bones:
+            for p in ["location", "rotation_quaternion", "scale"]:
+                channel = __gather_animation_channel(
+                    (),
+                    blender_object,
+                    export_settings,
+                    bone.name,
+                    p,
+                    bake_range_start,
+                    bake_range_end)
+                channels.append(channel)
+    else:
+        for channel_group in __get_channel_groups(blender_action, blender_object, export_settings):
+            channel = __gather_animation_channel(channel_group, blender_object, export_settings, None, None, None, None)
+            if channel is not None:
+                channels.append(channel)
 
     return channels
 
 
 def __gather_animation_channel(channels: typing.Tuple[bpy.types.FCurve],
                                blender_object: bpy.types.Object,
-                               export_settings
+                               export_settings,
+                               bake_bone: typing.Union[str, None],
+                               bake_channel: typing.Union[str, None],
+                               bake_range_start,
+                               bake_range_end
                                ) -> typing.Union[gltf2_io.AnimationChannel, None]:
     if not __filter_animation_channel(channels, blender_object, export_settings):
         return None
 
     return gltf2_io.AnimationChannel(
-        extensions=__gather_extensions(channels, blender_object, export_settings),
-        extras=__gather_extras(channels, blender_object, export_settings),
-        sampler=__gather_sampler(channels, blender_object, export_settings),
-        target=__gather_target(channels, blender_object, export_settings)
+        extensions=__gather_extensions(channels, blender_object, export_settings, bake_bone),
+        extras=__gather_extras(channels, blender_object, export_settings, bake_bone),
+        sampler=__gather_sampler(channels, blender_object, export_settings, bake_bone, bake_channel, bake_range_start, bake_range_end),
+        target=__gather_target(channels, blender_object, export_settings, bake_bone, bake_channel)
     )
 
 
@@ -63,38 +98,50 @@ def __filter_animation_channel(channels: typing.Tuple[bpy.types.FCurve],
 
 def __gather_extensions(channels: typing.Tuple[bpy.types.FCurve],
                         blender_object: bpy.types.Object,
-                        export_settings
+                        export_settings,
+                        bake_bone: typing.Union[str, None]
                         ) -> typing.Any:
     return None
 
 
 def __gather_extras(channels: typing.Tuple[bpy.types.FCurve],
                     blender_object: bpy.types.Object,
-                    export_settings
+                    export_settings,
+                    bake_bone: typing.Union[str, None]
                     ) -> typing.Any:
     return None
 
 
 def __gather_sampler(channels: typing.Tuple[bpy.types.FCurve],
                      blender_object: bpy.types.Object,
-                     export_settings
+                     export_settings,
+                     bake_bone: typing.Union[str, None],
+                     bake_channel: typing.Union[str, None],
+                     bake_range_start,
+                     bake_range_end
                      ) -> gltf2_io.AnimationSampler:
     return gltf2_blender_gather_animation_samplers.gather_animation_sampler(
         channels,
         blender_object,
+        bake_bone,
+        bake_channel,
+        bake_range_start,
+        bake_range_end,
         export_settings
     )
 
 
 def __gather_target(channels: typing.Tuple[bpy.types.FCurve],
                     blender_object: bpy.types.Object,
-                    export_settings
+                    export_settings,
+                    bake_bone: typing.Union[str, None],
+                    bake_channel: typing.Union[str, None]
                     ) -> gltf2_io.AnimationChannelTarget:
     return gltf2_blender_gather_animation_channel_target.gather_animation_channel_target(
-        channels, blender_object, export_settings)
+        channels, blender_object, bake_bone, bake_channel, export_settings)
 
 
-def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.types.Object):
+def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.types.Object, export_settings):
     targets = {}
     for fcurve in blender_action.fcurves:
         target_property = get_target_property_name(fcurve.data_path)
diff --git a/io_scene_gl

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list