Baked Texture Animations with Animation Groups?

Ok thanks for the clarifications @Evgeni_Popov, shadows were the cultprit, removing them brings render targets to close to 0


Abour the weapon issue, here is a playground, not quite the same code, but has the same with issue, it’s in the right position, but it’s not following the animation.

With BVA, there’s no more skeleton or bones, only a texture with the list of transformed vertices for all the frames of the animation, so attaching a mesh to a bone won’t work.

It’s possible to get it to work to some extent, though, but it’s a bit involved.

You need a skeleton to attach the weapon to, there’s no way around that. So, a skeleton should be created for each animation (5 in the PG). As each skeleton must drive a different transform node hierarchy (actually it’s the other way around for glTF animations, but it does not change the explanation), we need to duplicate the mesh hierarchy 5 times too and connect this hierarchy to the skeleton hierarchy: the 5 skeletons and the 5 mesh hierarchies are in the skeletonForAnim and rootForAnim arrays in the PG below, respectively.

Once these objects are created, you have to retarget the animation group so that it animates the transform nodes of the corresponding rootForAnim: AnimationHelper.RetargetAnimationGroupToRoot is doing that. Also, the skeleton must be retargeted so that the bones correspond to the transform nodes animated by the animation group: AnimationHelper.RetargetSkeletonToAnimationGroup is doing that.

Now that everything is in place, you have two things to do each frame (lines 139-147):

  • update the bones in the skeleton with the corresponding transform node matrices: call skeleton.prepare(). That’s normally done automatically for you by the framework for all meshes that have a skeleton, but in this case we don’t have any mesh that is using the skeletons we created.
  • synchronize the animations of the weapons (coming from the animation groups) with the BVA => we use the current time of the BVA manager to compute the frame to go to in the animation groups

Now, the caveat…

We have a single animation group / skeleton for each animation (run, idle, …), so the weapon animation for run / idle / … is the same for all instances that uses this animation. If you use a random starting offset for a BVA animation (line 96), then the weapon animation won’t be synchronized with the BVA animation. That’s why in the PG I use a constant offset for all instances. It does not have to be 0 (as you can see in the PG), but it must be the same value for all animations of the same type (you could have a different value for the run animation vs the idle animation, for eg).

If you want to be able to use different offsets for a given animation, you will have to duplicate the animation group / skeleton so that you have as many (animation group / skeleton) as there are different offsets (for a given animation).

PG:

Thanks @Evgeni_Popov for a very detailled post, however it will take me a while to digest to fully understand what is happening there.

Another way to make it work, is by skinning the weapon instead of attaching it
Skin the weapon using the player skeleton, and weight all of its vertices to the hand bone. Then parent the weapon mesh to the player mesh. Make the weapon use the same VAT texture as the player mesh, as they have the same skeleton, and it should follow the rotation, position as well as animation.

1 Like

I’m not sure if I understand the caveat you’re explaining: Are you talking about the animation offset? If so what would be the use case were you would want a different animation offset?

Anyway, I now understand what is happening behind the scenes thanks to your great explanation and I quite easily managed to integrate it to my debug screen: with 100 entities, results are great:

I have a last question: I would have to have a vat manager per different type of entity (player, pirate, rats, horses, etc…)?


The only real issue I have is the amount of complexity it adds to the project, and I’m little unsure whether to add to add it to the project at this stage.

@Raggar Yes, that’s another way to do it, but it brings it’s own complexity: I’d have to skin every new item I add to the game.

Thats why any solution has its own pros and cons :grinning:

VAT gives you performance, but increase complexity.

With items(I think in 99%), you can add bones weight via code because all vertices have 1 or 0 in most cases. Like Sword - you need to set 1 for the Hand bone and 0 for others. Same for Weapons, Helms, Boots. In some cases you can use it for Armors and Pants too(I think @oriongu in your cases you can also use it for these parts too).

Yes, it’s the animation offset. It is used (at least in the demo PG) to desynchronize the avatars and have all the walk, run, … animations to be in sync.

Hi there,

Sorry to bother you again,

To improve performace, I’m going to have to implement VAT eventually, and I was working on updating the playground, but cannot seem to get the sword attached to my player, could you have a look?

Alternatively, the weight solution you were talking about make sense, but I do not see anything about bone weight in the documentation? Would you have any playground lying around showing how I could achieve that?

The main problem is that the hierarchy of the skeleton is not the same for your character than for the character in the other PG. It seems you should use index #38 to properly attach the sword to the hand.

Also:

  • the order of the anims in PICKED_ANIMS should be given in the order they appear in the scene.animationGroups array
  • I changed how to compute the value passed to goToFrame (line 161), I’m not sure how the previous code could properly loop…
2 Likes

@Evgeni_Popov Thanks and noted.

I’ve been working on using multiples entity types and animations and make it all work together following the playground example, it’s a slow progress, but I will get there :wink:

Hi there,

It’s me again, It’s feels a little like harrassment at this stage :wink:

After quite a few tries, I cannot seem to find how to stop weapon animation from looping (upon death for example), I’m guessing I must work on lines 68-72 but I’m not clear what to do.

  • USE W TO MOVE
  • USE SPACE TO PLAY DEATH ANIMATION AND MOVE TO ANOTHR INSTANCE

PG HERE: https://playground.babylonjs.com/#3NIXCL#198

You should not retarget the anims each frame (lines 44-50), this is a process that should happen only once => I moved the block of code to line 312 in the PG below.

The purpose of the block at lines 61-66 is to play the skeletal animations exactly synchronized with the VAT frame. If you don’t do this, you will see that the sword animation is desynchronized.

For the sword anim to stop playing when the player is dead, you should just stop the animation group (line 378).

Here’s a fixed PG:

However, you will see that it does not work for the second, third, etc player deaths. That’s because you have a single skeleton for the death animation for all the (sword) players. So, the same death animation is played for all swords that are using this animation. You will have to clone the skeleton for each (sword) player to avoid this problem.

1 Like

I have only one skeleton for many instanced meshes and it works! But I have only one unique mesh.

Should I use cloned skeleton for each unique mesh with the same bones structure?

I thought bakedVertexAnimationSettingsInstanced does all job with offsetting etc.

If you have a single skeleton for many meshes, it means all meshes will animate the same way (I assume you speak about skeletal animations, as VAT don’t use skeletons at replay time), that is, their animations will be synchronized (you don’t have an offset - as you have in VAT - to desynchronize skeletal animations).

I updated the PG to desynchronize the animations, so that each character instance can have its own sword animations:

Note that to show that desynchronized animations work, when you press “W”, all characters switches to the “run” animation (you can already see it with the “idle” animations, but it is harder to notice).

It required to create a skeleton per instance, and that the 4 animations be cloned and retargeted to the skeleton of each instance.

So, in the end, you end up with as many played skeletal animations as the number of instances, if each one holds a sword…

It nullifies the benefits of VAT, except that you could simplify the skeleton / the animations because you only need the bones and animation data that move the left hand. In the example PG, you only need 8 bones to get to the left hand, so you could simplify the skeleton from 41 bones to 8, as well as remove from the animations all data that don’t target these 8 bones. You could even simplify further, as you don’t really need the intermediate bones, you only need the transformation of the left hand: you could keep a single bone in the skeleton and only keep the transformations of this bone in the animation data.

2 Likes

Sorry, Yeah! I mean I use VAT. What I want to say:

I have a one skeleton and different parts - pants, weapons, bodies etc.

Right now I merge it all to one a single mesh(because that’s how my custom shader works to colorise different parts via vertex color…)

But I can use it without merging the meshes and it should works with only one skeleton. Like this:

const weponMesh.skeleton = skeleton;
const bodyMesh.skeleton = skeleton;
...

So to synchronise the animation state on all parts I need to set bakedVertexAnimationSettingsInstanced to the same values like

setTheSameAnimationForAllParts(from, to, offset, fps) {
  const parts = [weaponMesh, bodyMesh, ...];
  parts.forEach(partMesh => {
    partMesh.instancedBuffers.bakedVertexAnimationSettingsInstanced = new BABYLON.Vector4(from, to, offset, fps)
  });
}

So we don’t need to clone skeleton for each part in this case.

Am I right?

I think you meant the list of transformed bones instead of vertices.(maybe we need to rename vertexData to bonesData, because we work with bones, not with vertices)

Yes, if you are using a VAT for each part (in my PG above, the sword is not a VAT).

Indeed!

1 Like