Mugen87 / three-m2loader

three.js loader for importing M2 assets from World of Warcraft.
MIT License
25 stars 8 forks source link

Synchronize animations with different durations #16

Open Mat2095 opened 10 months ago

Mat2095 commented 10 months ago

I've noticed an issue with the WotLK-Version of the airelemental:

https://github.com/Mugen87/three-m2loader/assets/11258252/9ef99c1b-b53e-48e2-8fa1-e174122d81df

When playing the death-sequence, the "main body" of the elemental should disappear, but that doesn't work. This is because the sequence consists of animations with different duration. Some are 3 seconds long, but some (those that fade out the body) are only ~0.9 seconds long. They set the opacity to 0 right at the end of those 0.9 seconds, but then the animation already loops and opacity is back at 1. Instead the animation should wait until all animations of that sequence are finished. This is almost the opposite of #13.

I tried synchronizing the animations in this commit: https://github.com/Mugen87/three-m2loader/commit/fcbeb7b26b127678193d46dcdf27c908ad842b26 And it works for that case:

https://github.com/Mugen87/three-m2loader/assets/11258252/e75d9ae8-e0f5-4b72-868d-3309e9a93f25

That looks like it does in game, except the hands and eyes should disappear as well, not sure what's the issue with that.

But I'm not too happy with the code as it really takes active control over the animation-orchestration. I'd rather let tree.js handle it, but I don't think that's possible, since the animations might have different root-objects and thus different mixers, which is why I couldn't get it done with https://threejs.org/docs/index.html#api/en/animation/AnimationAction.syncWith (according to ChatGPT, I have no idea if that's true). Also I have no idea if doing it this way is always correct or if for some sequences this is wrong. Especially since the death-sequence doesn't really loop ingame anyway, so having the animations loop doesn't make sense. But for sequences like Stand/Walk/Run, maybe it is correct that animations loop individually instead of waiting.

Mugen87 commented 10 months ago

Maybe we can update the keyframes to fix this issue.

A sequence can animate different things and I have assumed so far keyframe tracks targeting different properties all have equal duration. If that is not the case, we can extract the duration from the sequence object and check if a keyframe track has this value in its times array. If not, we can add it and duplicate the last value. In this case, all keyframe tracks have the same length and nothing will loop unexpectedly.

Do you think you can give this approach a try? It would also be great if you could share the WotLK version of the asset in this thread (I'll delete the link after I have downloaded it).

Mat2095 commented 10 months ago

Oh yes, I forgot to mention that. I thought about that, too, but I'm not sure if one animation could be used in multiple Sequences. For example if one of those 0.9s animations is used in a 3s sequence and a 4s sequence, that would cause issues. Do you know if that can happen?

I sent you the WotLK-model in an E-Mail a few weeks ago. I'm not aware of a site where you could download WotLK-models. If E-Mail doesn't work for you, I guess I'll have to upload the models somewhere.

Mugen87 commented 10 months ago

For example if one of those 0.9s animations is used in a 3s sequence and a 4s sequence, that would cause issues. Do you know if that can happen?

No, that can't happen. The loader generates keyframe tracks from the M2 keyframe definitions (which are on a per sequence basis). So a single keyframe track can only appear in a single clip. And a clip can only appear in one sequence.

Ops, your mail went into the Spam directory^^. I've recovered it now.

Mat2095 commented 10 months ago

Okay, that's good, sounds way better than my current idea. I'll try that.

Ah, it probably seemed suspicious. From an unknown address with attached ZIP, I can see why it would get flagged.

Mugen87 commented 9 months ago

I've tested the suggested fix in https://github.com/Mugen87/three-m2loader/issues/16#issuecomment-1887475562 today.

TBH, I do not fully understand yet how a client is supposed to animate both assets correctly. If I force the sequence length for all keyframe tracks, the death animation of the elemental is right. However, the pulse effect of g_scourgerunecirclecrystal ends up wrong. If I don't force the sequence length (status quo), the spell is correctly animated.

Maybe there are some additional sequence flags that the loader does not yet evaluate.