Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

export_optimize_animation_size option removes keyframes with identity transform #2430

Open
LPGhatguy opened this issue Dec 4, 2024 · 6 comments
Labels
documentation question Further information is requested

Comments

@LPGhatguy
Copy link

Is your feature request related to a problem? Please describe.
I use the export_optimize_animation_size setting in a game character pipeline. We use this so that only the bones that we intentionally keyframe have animation data exported.

However, turning on this setting also seems to delete channels that are keyframed with no extra transform. This makes it so that when I layer the exported animations in-game, those bones get moved by the animation from the lower layer instead of being set to the identity transform.

The keyframes look like this:

image

As a workaround, I can rotate those bones a very slight amount (like 0.1 degrees) and they'll be exported, but now my animation is slightly off.

Describe the solution you'd like
I'd like for the exporter to either keep those keyframes, or as a backup, for there to be another option introduced to not delete these keyframes. I created them on purpose, I don't want them deleted!

Describe alternatives you've considered
I could implement animation masking in our game engine and write a Blender add-on to let artists mask bones out. Then, we could turn off this setting in the glTF exporter and just ignore the extra fields.

@julienduroure
Copy link
Collaborator

Hello,
The option Force keeping channels for bones is already here exactly for these purpose.

Can you please provide a test.blend file with all the settings used at export (by using Remember Export Settings) that show the behavior you describe?

@julienduroure julienduroure added the question Further information is requested label Dec 4, 2024
@LPGhatguy
Copy link
Author

Hey, thank you for the response!

Yes, the setting export_optimize_animation_keep_anim_armature / "Force keeping channels for bones" is enabled by default and is still on in my export. I am able to reproduce this with default exporter settings.

Here's a zip file containing a working and broken example minimized from one of my game's assets:
Test.zip

Both files have two actions, smg/Aim (the problem animation) and Jog Forward:
image

Both animations have one bone keyed, named mixamorig:Spine. In Jog Forward, the bone is keyed to rotate 90 degrees forward. In smg/Aim, the same bone has three keyframes.

In working.blend, the first keyframe of smg/Aim is identity, the second is rotated forward 0.5 degrees, and the third keyframe is identity again. It looks like this:

image

In broken.blend, smg/Aim has three keyframes that are all identity. The same keyframe in this file looks like this:

image

When exporting working.blend, the action is exported as expected.
When exporting broken.blend, the action is not exported correctly.

My game plays back the animations from this blend file layered on top of each other. smg/Aim overrides Jog Forward. When using the working version of the file, mixamorig:Spine stays still. When I use the broken version of the file, mixamorig:Spine has the pose from the jogging animation, which is not correct.

I tried exporting both files to .gltf and poking at the JSON to see if I could spot any differences. Both files seem to have a channel for every node in the file, which seems very odd to me because only one node in the file has animation data.

Thanks for taking the time to look at this!

@julienduroure
Copy link
Collaborator

I use the export_optimize_animation_size setting in a game character pipeline. We use this so that only the bones that we intentionally keyframe have animation data exported.

This is not the purpose of this option. This option is used to keep only first and last keyframes when you have a serie of identical keyframes.

Exporting or not intentionally keyframes is the purpose of export_optimize_animation_keep_anim_armature

Here is the combination logic of export_optimize_animation_size and export_optimize_animation_keep_anim_armature

For all bones of the rig:

  • if export_optimize_animation_size is True
    • If the bone channel is animated
      • If serie of identical keyframes
        • We keep the First & Last baked Keyframe
      • else (different keyframes)
        • We keep all keyframes baked
    • else (bone channel is not animated)
      • If gltf_optimize_animation_keep_armature is False
        • If serie of identical keyframes
          • No keyframe export
        • else (different keyframes)
          • We keep all keyframes baked
      • else ( gltf_optimize_animation_keep_armature is True )
        • if serie of identical keyframes
          • We keep the First & Last baked Keyframe
        • else (different keyframes)
          • We keep all keyframes baked
  • else ( no export_optimize_animation_size)
    • if the bone channel is animated
      • We keep all baked keyframes
    • else (bone channel is not animated)
      • If gltf_optimize_animation_keep_armature is False
        • if serie of identical keyframes
          • No keyframe export
        • else (different keyframes)
          • We keep all keyframes baked
      • else (gltf_optimize_animation_keep_armature is True )
        • We keep all keyframes baked

@LPGhatguy
Copy link
Author

LPGhatguy commented Dec 9, 2024

Thank you for the write-up about the options in the exporter! I worked with a member of my team and I was able to find the root cause of the original issue on our end.

The glTF exporter uses the "LINEAR" interpolation mode when exporting keyframes that are different, but uses the "STEP" interpolation mode when all keyframes are the same. Our engine ignores channels with the "STEP" interpolation mode.

I did this originally because of a different behavior that seems like a bug. The test case files I linked have only one bone animated (mixamorig:Spine) but have many other bones with no keyframes. Despite only one bone being animated, the glTF exporter (with default settings) exports a channel for every property (Translation, Rotation, Scale) of every bone. This is unexpected to me because there is no animation data for those bones. These channels all have the "STEP" interpolation mode and so they end up ignored by the engine.

export_optimize_animation_size is True (the default)
export_optimize_animation_keep_anim_armature is True (the default)
export_animation_mode is 'ACTIONS' (the default)
export_bake_animation is False (the default)

We've been diving into the code to try to figure out why that is the case.

How can I configure the exporter to not include channels for bones that are not keyframed?

@LPGhatguy
Copy link
Author

I see what you mean about export_optimize_animation_keep_anim_armature. The documentation says:

Force keeping channels for bones, If all keyframes are identical in a rig, force keeping the minimal animation. When off, all possible channels for the bones will be exported, even if empty (minimal animation, 2 keyframes)

I think these two sentences contradict each other about the behavior of the property. The first sentence makes me believe that having the property set to True will cause all bones to always be keyframed. The second sentence says that when the property is False, all bones will always be keyframed. The actual behavior looks to be the first sentence.

I thought I needed to have export_optimize_animation_keep_anim_armature set to True, but the behavior I want is if I set it to False.

Are you open to accepting PRs to improve documentation on this configuration? I think I understand what these properties are for now and I'd love to help make the documentation reflect that.

@julienduroure
Copy link
Collaborator

Are you open to accepting PRs to improve documentation on this configuration? I think I understand what these properties are for now and I'd love to help make the documentation reflect that.

Hello,
Sure, any help is welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants