Looping an animation by interpolating

Hello there,

As I am fairly new to the API, I am not sure whether what I want to do is possible or not, but I figured here is the best place to ask :slight_smile:

I have a .glb model with an animation attached, which targets the different parts of my model, such as pelvis, spine etc. The animation is taken from Mixamo

My goal is to cut the animation right before the end, so the character will be almost in the initial T-pose, then I want to linearly interpolate between that state and the start state of my animation, so as to create the illusion of the animation looping. I have a couple of questions about this.

  1. How can I get a subclip of an animation? I looked at AnimationRange, but I am not sure whether this is the right class to use.

  2. Firstly I would need to get the state of my model when in T-pose and in the last frame of the subclip. How does one do this in bjs?

  3. How do I interpolate from one state of the character where the components like pelvis, spine,ā€¦ controlled by different animation channels have specific values to the initial T-pose? Assuming I have state1 = s1 of my model and state2 = s2 of my model, I need to get from s1 to s2 in a smooth way via interpolation.

If parts of the question are unclear, I am happy to clarify them. Thank you for any help provided!

I would advice to get your animation ready in your art tool of choice :slight_smile: as it would be much simpler if it is possible

I would like to be able to control a bit of the animations via Babylon after exporting the model. Is this sort of thing not supported? I looked at stuff like tween.js but not sure if that is already too much.

The thing is it totally depend of the complexity of your animations and such. You can for sure do all of it by hand but it might not always be simple.

You should create a repro in the Playground so that the community could try to find the best solution.

Ok, I managed to set up a playground here: Babylon.js Playground, I am also having issues calling the setParent Method on the BABYLON.Node object, using type predicates in TS works, but I canā€™t do the same in JS.

Is this sort of animation too complex for my needs?

Seems like setParent works ? https://playground.babylonjs.com/#IENMIY#1

It sounds even quite involved indeed, basically, you would need to go over all the different bones animations and cut them by inserting the right computed keyframe at the correct time.Then insert new key frames and such. All doable for sure but a tiny bit intense :slight_smile:

@bghgary (Animation GURU ;-)) how involved would you think the process could be ?

Iā€™m not sure this is the only way, but you can clone the animation group and then set the from/to arguments when starting the animation group.

Iā€™m not sure I understand the question. If you have an animation group, you can use the from and to properties to determine the begin and end values.

I think you can achieve this with animation blending. If you duplicate the animation and blend between them the way you described, I think it will work.

So I tried using the information in the documentation, but there is still a noticeable ā€œjumpā€ between the animations. Maybe I am blending in the wrong way?

Here is the playground: https://playground.babylonjs.com/#IENMIY#4

I have two animations: The ā€œcutā€ animation, which ends prematurely and the original animation. I enable blending for the original animation by enabling blending for each of the targetedAnimations in the animation group. Then once the cut animation ends (I check this using .onAnimationEndObservable) I start playing the original animation (whose targetedAnimations now all have blending enabled).

According to the docs for Animation Blending: Y

You can start an animation with enableBlending = true to enable blending mode. This blended animation will interpolate FROM the current objectā€™s state

However, there seems to be no interpolation at all from the first animation to the second.

I want the first animation to end and then smoothly interpolate to playing the second, but maybe animation blending only works if both animations are playing.

Yup it is blending between two running animations.

Let s summon @Deltakosh to see if he already had this ?

See how I switch from one animation to another one on this sample:

(Iā€™m on my phone so I did not check your pg but you should have everything you need in my sample)

Hey, thanks for the useful playground. I have a few questions regarding it.

So AnimationPropertiesOverride() can be used to quickly set properties like enableBlending for all ā€œsubā€ animations for a particular bone?

In the pg there always needs to be one active animation for the blending to work right? So I canā€™t do what I wanted where: I clone my animation, when I start playing the cloned animation I donā€™t play to the end (by reducing .to()), once the cloned animation stops, I smoothly interpolate from the state of the model to the beginning of the original animation.

So to get the effect described above I would need to overlap my two animations by a tiny bit so as to blend between them right? The issue I am having is deciding when to start the animation blending, without waiting for my first animation to end.

nope blending can work from the current state meaning that it is not required for an animation to already be playing.

But if you are using animation blending (without synchronizing them like here: Animation weights demo | Babylon.js Playground (babylonjs.com)) you have to make sure the first one is stopped before starting the second one or they will overload each other

w0000t :slight_smile:

Ah cool :smile:. But the blending doesnā€™t seem to work, even if I explicitly stop the animation once it ends, there is still an abrupt transition between animation 1 and animation 2. Maybe I am misunderstanding how blending works. I currently enabling it for the Targeted Animations, but you seem to do it on the skeleton directly.

Ok I see two big issues in your PG:

  • First the property name is ā€˜enableBlendingā€™ and not ā€˜enablesBlendingā€™
  • and then, you are cloning the animationgroup but the cloned group and the original group will still point to the same animation. There is an option in the animationGroup clone to not have that

Something better I guess: Animation demo | Babylon.js Playground (babylonjs.com)

2 Likes

So because my clone pointed to the same animation I was basically just restarting it without any blending happening?

But now it works fairly well by altering the blending speed. Pretty cool! Thanks for all the prompt help!

2 Likes

Sorry for the small follow-up, but I was trying to run this locally and the clone method for me only takes 2 arguments and not the 3rd. I have my project set up with npm and ES6 packages and my package.json file shows the dependency: ā€œ@babylonjs/coreā€:^4.4.2.

Here is what the clone method looks like for me

There is also a small typo in the comment above the method i.e. @returns the new aniamtion group.