Page MenuHome

Curves for Actions exported despite no channel
Open, NormalPublic

Description

System Information
Windows 10 - GTX1080

Blender Version
Broken: 2.78 223aff987a
Worked: Probably never

When using either the newer "FBX 7.4 binary" io_scene_fbx.export_fbx_bin exporter or the older "FBX 6.1 ASCII" io_scene_fbx.export_fbx exporters, for each exported Action, all curves are exported whether or not there is an associated channel for that Action.

Exact steps for others to reproduce the error

Generalized:
Delete curve channels from any Action. Export the scene as an FBX using either the binary or ascii exporter. Import FBX into another program (such as Unity). The animations contain curves for channels that were explicitly deleted in Blender.

Reproduction:
Create a 5 unit long cylinder. Rotate it onto its side. Add an armature. Add a single bone in center. From that bone, extrude once to each end of the cylinder for a total of three bones. Subdivide the two bones just extruded for a total of 5 bones.

Select all bones in pose mode. Create a new pose-library named "Rest" and add a pose to it. Leave the default pose name.

Rotate the two bones on one side of the armature. Create a new pose-library named "Left" and add a single pose. Using the Dope Sheet's Action Editor, delete any channels unaffected by your bone changes.

Use the Action Editor to select the "Rest" pose which will reset the bones of the armature.

Rotate the two bones on the other side of the armature. Create a new pose-library named "Right" and add a single pose. Using the Dope Sheet's Action Editor, delete any channels unaffected by your bone changes.

Use the Action Editor to select the "Rest" pose to reset the bones once more.

Save the .blend. Export to FBX and open in Unity.

Select the imported animations in the Project View while the Animation Window is open. Every animation contains curves for every bone.

The following patch produces the indented behavior for both exporters but is likely not the best changes for the surrounding code. Just a proof-of-concept that a change in Blender results in the intended result in, say, Unity:

$ git diff master...HEAD
diff --git a/io_scene_fbx/export_fbx.py b/io_scene_fbx/export_fbx.py
index ff39ff44..58922aa4 100644
--- a/io_scene_fbx/export_fbx.py
+++ b/io_scene_fbx/export_fbx.py
@@ -2595,6 +2595,10 @@ Takes:  {''')

                 for my_ob in ob_generic:

+                    blenName = getattr(my_ob, "blenName", None)
+                    if blenAction and blenName not in blenAction.groups.keys():
+                        continue
+
                     if ob_generic == ob_meshes and my_ob.fbxArm:
                         # do nothing,
                         pass
diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index 70d149bf..109f2bc2 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -1856,6 +1856,7 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No
     """
     Generate animation data (a single AnimStack) from objects, for a given frame range.
     """
+    (_, act) = ref_id
     bake_step = scene_data.settings.bake_anim_step
     simplify_fac = scene_data.settings.bake_anim_simplify_factor
     scene = scene_data.scene
@@ -1884,6 +1885,8 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No
     for ob_obj in objects:
         if ob_obj.parented_to_armature:
             continue
+        if ob_obj.name not in act.groups.keys():
+            continue
         ACNW = AnimationCurveNodeWrapper
         loc, rot, scale, _m, _mr = ob_obj.fbx_object_tx(scene_data)
         rot_deg = tuple(convert_rad_to_deg_iter(rot))

The following images illustrate the described reproduction:

Details

Type
Bug

Event Timeline

Here is the associated blend file!

Bastien Montagne (mont29) triaged this task as Normal priority.Feb 6 2017, 5:07 PM
Bastien Montagne (mont29) claimed this task.

Suggested fix is not acceptable, thing is, we *bake* animation, which implies catching non-fcurve animations (like those generated by constraints, drivers, etc.). So we do have to evaluate all (fake) objects.

Still, not sure why those bones get included, will check further.