glTF-Blender-IO icon indicating copy to clipboard operation
glTF-Blender-IO copied to clipboard

>1 Strips per NLA track are not exported

Open thirite2 opened this issue 4 years ago • 25 comments

Describe the bug When more than one strip is placed in an NLA track, only the first one is exported.

To Reproduce Put two strips on the same track and export.

Expected behavior All strips in an NLA track should be exported as individual animations.

Screenshots https://imgur.com/a/9oIduya

.blend file/ .gltf blend file, and correctly exported gltf (via seperate NLA tracks) and incorrectly exported gltf (via single NLA track) files https://drive.google.com/open?id=18hnOean2kkeUN8Qsp22P0EQEU3G_M7uR

Version

  • OS: Win7 64bit SP2
  • Blender 2.81
  • glTF exporter from current head (406a409d4740e6a67ec3e8699c7dec40afe5067e)

Additional context Confirmed both by reimporting to blender, importing to Godot engine, and opening the human-readable gltf.

thirite2 avatar Nov 07 '19 20:11 thirite2

Yes, only a single strip is exported per NLA track. I tried to figure out how to bake multiple strips into a single animation for export, but couldn't figure out the Blender Python APIs for that. Would be curious if anyone has ideas.

donmccurdy avatar Nov 07 '19 22:11 donmccurdy

Oh, I wasn't expecting adjacent strips to be exported as a single animation, just have all strips within a track actually export. When I was animating for a Unity project with FBX, I simply put them all into a single "Animations" NLA track. I did the same with DAE export in blender a while back. See: https://i.imgur.com/xYUsAYJ.png

thirite2 avatar Nov 08 '19 04:11 thirite2

Confirmed that currently, we don't manage multiple action on same track Not sure how this should work if we want to implement it :

  • Merging/baking in a single one animation
  • Exporting all actions separately, based on timing of each action
  • Exporting all action separately, based on timing of track
  • ...

Every one has different request/pipeline/way of working, so we have to find the best way to perform this kind of export.

For now, @thirite2 , you can workaround by creating multiple track, with only 1 strip per track

Note that strips can be modified (timing, repeat, ...) or merged / crossed ... But this is not taken into account, and will probably not (at least in short/middle term)

julienduroure avatar Nov 08 '19 09:11 julienduroure

If we took this approach — exporting all actions used as a strip in any NLA track to a separate animation — and also kept our current convention of applying the NLA track's name to the generated animation, we wouldn't be able to merge the animations based on their names. This would break the case where users want to animate multiple objects in a single animation. We could avoid that with yet another option, to disable use of the NLA track's name... hm. 😕

My ideal outcome, I think, would be to be able to export the entire NLA track (including all strips, timing, repeat, etc.) as a single animation. That would provide artists with quite a lot of control. I don't know how to implement that in the short term, but if it really is the long-term goal, I'm not sure we should encourage stacking strips on a single NLA track in the meantime.

donmccurdy avatar Nov 09 '19 19:11 donmccurdy

The exporter doesn't seem to take into account NLA track offset either. I tried to export duplicate animations with offsets in timing and they all start at the same time.

I tried using f-curve cycle modifiers on the animation properties and offset the curves and the offsets worked there because the keyframes are moved but they don't export the repeating loops.

Normally exporters bake the keyframes to ensure the playback is the same but it can mean higher files sizes and slower exports. An option to bake the keyframes on export would be useful. I think I'm going to have to do that manually for now using the NLA Action Bake command or insert new keyframes at the start/end of each cycle.

adevart avatar Dec 16 '19 20:12 adevart

When more than one strip is placed in an NLA track, only the first one is exported.

I'm experiencing something different (at least in 2.83+), I'm not seeing any animation exported where there is more than one strip in a track. I was confused why animation was breaking, I feel like there should at least be a warning when this happens rather than silently failing.

All strips in an NLA track should be exported as individual animations.

I disagree with this, I expected that it would just merge the actions into a single animation, e.g. this would turn into one "Idle" animation: image If I wanted separate animations I would put them on separate tracks.

mattrossman avatar Nov 22 '20 02:11 mattrossman

@mattrossman What you describes is not implemented for now

julienduroure avatar Nov 23 '20 10:11 julienduroure

I expected that it would just merge the actions into a single animation

We all agree this would be ideal, but have found no way to do this, and haven't found any other Blender exporters (to any format) capable of doing so either. I think it may need to be requested in the Blender Python API itself.

So for now, the expected result is just as described above.

Similarly -- it would be nice to have the ability to both (1) show user-visible warnings AND (2) export the file anyway, but this is not straightforward through the addon API. I'm not sure if Blender itself doesn't allow it or if there are more options we need to explore.

donmccurdy avatar Nov 23 '20 16:11 donmccurdy

@donmccurdy It's not hard, you just bake it like

setup animation (star the tracks, etc.)
for each frame in frame range
    seek to frame
    read all data you need (object matrices, etc.)

The FBX exporter works like this.

Similarly -- it would be nice to have the ability to both (1) show user-visible warnings AND (2) export the file anyway

https://github.com/KhronosGroup/glTF-Blender-IO/issues/172#issuecomment-656458523 ?

scurest avatar Nov 23 '20 16:11 scurest

Branch with very rough proof of concept: anim-bake
(no morph weight support)

scurest avatar Nov 23 '20 21:11 scurest

That's promising, awesome! How do you feel about the NLA baking approach? I.e. any thoughts on whether it's easier or harder to maintain than what we're doing now, and whether the performance takes much of a hit? This feels like something I wish Blender's own APIs provided for us (and for the FBX addon) but maybe I'm overthinking it.

#172 (comment) ?

Ah I'd forgotten that – filing https://github.com/KhronosGroup/glTF-Blender-IO/issues/1273 to track, I think we should set it up for several cases.

donmccurdy avatar Nov 28 '20 04:11 donmccurdy

I don't know, I don't understand the current animation code. It already does some kind of baking like this (source).

scurest avatar Nov 28 '20 06:11 scurest

Yes, I confirm that baking for bones are already in place. I think the enhancement can be easily be done by exporting actions as usual, and then concatenate actions (keeping values, and shifting timing in time)

julienduroure avatar Nov 28 '20 11:11 julienduroure

Strips are not just shifted in time, they're scaled, reversed, repeated, extrapolated, they have modifiers, etc.

scurest avatar Nov 28 '20 12:11 scurest

yeah, good point.

Currently, we manage animation in 3 times :

  • 1 - first looping on animation data, to check what animation when need to keep (active action, NLA, ...)
  • 2 - Looping on these kept actions, and bake them (or keeping action without baking)
  • 3 - Manage merging animation based on NLA tracks if needed

What we can do, and can possibly work (need to be investigated, of course):

  • 1 - keep also tracks that need to be exported (if more than 1 strip in track for example)
  • 2 - Looping in actions to be exported as usual, and then looping on tracks (force baking, start / end frame based on track, no more on action)
  • 3 - Manage merging as usual

julienduroure avatar Nov 28 '20 13:11 julienduroure

Here is a mokup: https://github.com/KhronosGroup/glTF-Blender-IO/tree/tracks

julienduroure avatar Nov 29 '20 21:11 julienduroure

There shouldn't be separate ways to handle 1 strip vs >1 strip tracks. A single strip can be repeated, reversed, etc. too.

Isn't this doing something like

for each object
    for each track we want to export
        star the track

        # bake action
        for each frame
            set frame
            collect data into the baked action

        gather an animation for this object,action pair
merge animations that go together (eg. per NLA track name)

I'm saying it should do

for each animation we want to export (eg. one per NLA track name)
    setup the whole scene so the animation is playing (star all the right tracks)
    for each frame
        set frame
        for each object
            collect data into a list
    make animation from data in lists

(btw you need animation_data.use_nla = True for is_solo to work; I forgot that too)

scurest avatar Nov 29 '20 22:11 scurest

That's a way we need to investigate more, looks promising.

I can see some problems/questions that need to be solved/investigated if using track system instead of action one:

  • Need to manage active action that are not in NLA
  • Check if we need to sample or not (mostly if user ask to not sample, we have to for technical reason sometimes) will be more complicated (need to check if strip only use action as-is, or use some "modifier" (repet, reverse, ...) )
  • Need to check what happen with driven shapekeys (should be fine if not using bpy.ops.nla.bake, but if using it, have to check)

julienduroure avatar Nov 30 '20 05:11 julienduroure

I feel that trying to manage this in raw glTF may be complicated. In the NLA you can mix two different animations so they are played together and the result blended. That will requires baking the animation and computing the result before exporting. If the same action is used in several places, you need to bake it several times.

Would it make sense to export actions as they are and add a new extension which can be specify how glTF animations should be played? My idea is that the extension would create animation trees or something like that.

jjcasmar avatar Feb 25 '21 19:02 jjcasmar

Blender's concepts of "Actions" and "NLA tracks" do not really map directly to other software; I'm not sure we should be trying to replicate them in glTF. If there is real overlap between different applications that could be standardized though, do feel free to suggest an extension.

For now, I do think that baking each NLA track is the right solution. Blender continues to evolve its animation features pretty regularly, it seems to me that baking is just something we should accept (and optimize as much as we can).

donmccurdy avatar Feb 25 '21 19:02 donmccurdy

As a special failure case, tracks that contain strips which share action data with other strips seem to not be exported at all (rather than being exported only partially).


Also, as my two cents for how this should be integrated with grouping, I think activating each grouping of strips based on their names and creating a new GLTF animation in that state could work:

for trackname in set(obj.animation_data.nla_tracks.keys()):
	for track in obj.animation_data.nla_tracks:
		track.mute = track.name != trackname
	#Then read out matrices per frame, or `ops.nla.bake()`, whatever.

This is basically how I expected it to already work based on the tooltip for the "Group by NLA Track" option.

will-ca avatar May 05 '21 20:05 will-ca

I'm trying to help a user export content to glTF and they are hitting a wall.

Here you can see an example file with all the actions: image It looks like this blend file does use NLA track, but only one animation is being exported. I confirmed this by opening up the resulting glTF file and there's only one item in the "animations" array. (If it would be helpful for debugging, I could try to share the blend file.)

The file exports to FBX correctly with all animations intact, so the issue clearly lies with the glTF exporter. Since it hinders the adoption of glTF and it's been open for two years, I think this should be considered a bug not an enhancement.

Related stackexchange post explaining how to fix this manually but I couldn't understand half the things it asked me to do: https://blender.stackexchange.com/questions/228453/exporting-multiple-nla-actions-to-gltf

Here you can see that if I use FBX export the exact same blend file, all the NLA animations show up fine in Unity: multiple animations imported in unity If FBX export is able to do it, and stackexchange has a list of steps to fix the issue, surely that means it can be fixed, or at the very least those steps can be automated into a single command ("Make NLA Tracks Exportable") or something.

lyuma avatar Jul 02 '21 08:07 lyuma

@lyuma I think your screenshot is showing different channels in the the Action Editor rather than multiple tracks the NLA Editor, and in fact the Outliner panel shows that there are only 2 NLA tracks on the Armature, both of which have been stashed rather than pushed down, and are thus locked and muted with generic names that may be in conflict with each other and with the valid character set?

Am I reading it incorrectly?

This bug isn't lack of support for multiple actions. Multiple actions work fine last I checked, as long as you have multiple NLA tracks. The only limitation is that each exported action has to map directly to exactly to one Action strip on each NLA track, as any greater number would obviously require re-sampling in some way or another. There isn't anything in the screenshot that suggests that that's whats happening here.

The .FBX exporter has an "All Actions" checkbox option enabled by default, which (1) exports all actions in the file and (2) removes associations between specific actions and what objects they map to, so any animated object can use any action. By contrast, this add-on (and maybe the way actions are bound in the GLTF spec itself— Not sure) requires you to associate each action explicitly to the objects to which it's applied, which is done by placing them on an NLA track of their own, which doesn't seem to have happened here.

TL;DR: The screenshot and description look like user error to me. The Stackexchange link describes the usual workflow, not any special "fix". TBH, if you "couldn't understand half the things it" asked you to do, then maybe figuring out how to use the software would be a better first step to solving the problem.

will-ca avatar Jul 02 '21 12:07 will-ca

The .FBX exporter has an "All Actions" checkbox option enabled by default, which (1) exports all actions in the file and (2) removes associations between specific actions and what objects they map to, so any animated object can use any action.

THIS. The "All Actions" default is the behavior I want for glTF, too. I know enough about glTF to know that there is nothing "special" here about how glTF does animations. if FBX can do this, so can glTF. As proof, I used FBX2glTF.exe to convert FBX to glTF, and the resulting file works perfectly, with all animations in tact.

... there are only 2 NLA tracks on the Armature, both of which have been stashed rather than pushed down, and are thus locked and muted with generic names that may be in conflict with each other and with the valid character set?

Character set and duplicate names should be irrelevant. I don't want those NLA Stash names showing up in the glTF export anyway. See the names of the FBX animations in that Unity screenshot: the names are exactly as I want: "Armature|Action-Name"

Yeah I see that Stash button. When I click it, it creates a new copy of the [Action Stash] thing, so it seems clear to me that this issue could have been caused by some sort of user error. But whether or not the stashes were intentional, the fact remains that I am able to preview the animations in blender, so they should be able to export regardless of which format I select.

The screenshot and description look like user error to me

While it can be convenient to blame the user ad hominem, I'm here to discuss how the software deals with these edge cases. The facts are: FBX is able to export this file; I can convert the exported FBX to glTF using an external program; and I can preview the animations in blender just fine.

I didn't make this blend file, and I've never worked with NLA Tracks before, so I admit that my knowledge of blender is incomplete. However, I do know how to export a file, and all I'm asking is for that to work.

"any greater number would obviously require re-sampling in some way or another"

Again, FBX is able to export these: the fix may require doing the same thing they do. If this causes quality loss due to re-sampling, perhaps it could be hidden behind a checkbox.

lyuma avatar Jul 02 '21 14:07 lyuma

@lyuma I'm not a developer of this add-on. I am also a user, and I find it works great for exporting multiple actions.

NLA tracks are a Blender feature, and their use is both exposed in both the UI and described in the docs. They are not an "edge case"; They are a normal part of the animation workflow with a documented role in this addon. Refusing to use them and then complaining about missing animations is like refusing to enter Edit Mode and then complaining that there's no way to modify geometry.

I had never used NLAs either before needing to export to GLTF with this add-on, and I also opened an issue or two here because I wasn't sure what was happening and it didn't seem right. But I figured out how to use NLAs once it was explained to me what role they played— Instead of demanding that a project run by volunteers change a fundamental aspect of their technical design on a whim to emulate a different format.

Frankly, you shouldn't be blaming your software because you don't know how to use it to do something that it is in fact fully able to do, and IMO you definitely shouldn't be asking a volunteer project to completely backtrack on a major technical choice without at least some effort at understanding why it's currently implemented the way it is and how to actually use it.

"The fact is": This add-on is able to export files like the one you described, provided you set them up correctly. It does work. You may try to use a screwdriver as a hammer, but that doesn't mean it's broken.

This is also completely irrelevant to the GH issue on which you are posting these rants. The actual issue reported here is about having multiple NLA strips on each NLA track, not about a request for a totally different new feature that automatically collects and remaps actions datablocks onto objects without NLA bindings. Nine different people expressed interest in the actual topic of this issue, and they get an irrelevant notification or e-mail with every further comment that gets left here, so if you'd like to ask for a different new feature and be heard by the right audience, I think it may be better to open a new ticket.

will-ca avatar Jul 02 '21 20:07 will-ca