Optimize mesh instantiation with many morph targets

I am working on a character creator and the face mesh has 30 morph targets. Instantiating many of these meshes and applying morph targets is slow.

So I was wondering if generating a version of the mesh with the morph targets and influences baked in, using that as a base mesh for instantiation, would be faster. I’ve already created a fork so there isn’t an existing solution I can implement it myself with some starting direction.

I’m not sure why having morph targets would slow down instantiation because the morph target manager should be shared by all the instances, so no recreation should take place.

Are you able to setup a repro in the Playground so we can have a better view on what’s going on?

Sorry I realize now there’s a difference between instances and clones, and I believe I meant clones.

So lets say I have a relatively simple mesh, but an arbitrarily large number of morph targets. When using IAssetContainer.instantiateModelsToScene() it takes a while to clone it. So is it possible to clone just the mesh, and apply all the morph targets from the original to it (baking them in)?

The instantiateModelsToScene method will clone the morph target manager if the source mesh has one, there’s no way to avoid this.

What you could try to do to get around this is to set the morphTargetManager property of the source mesh(es) to null before calling instantiateModelsToScene and write back the value to morphTargetManager for the source mesh + cloned meshes afterwards. This way, the morph target manager won’t be cloned.

Each clone has their own unique face, so their own set of influences. So it sounds like each clone would need their own morph target manager and influences for each target set.

So it seems I need to get into the weeds and generate my own mesh + morph targets on the CPU side. Or perhaps refactor the morph target manager to share morph targets.

A MorphTarget has no link to a MorphTargetManager, so you should be able to add the same morph target to multiple morph target managers without having to refactor the morph target manager.

1 Like

Hello @unsigned just checking in if you need any more help?

@Evgeni_Popov Got around to looking at this. I got it down from 12 seconds to 1.2 seconds. 30% of the improvement came from your suggestion of sharing morph targets. The rest was actually removing the calls to rebuild the morph target texture after every add/remove of morph targets.

I am trying to share the RawTexture2DArray amongst different morph target managers (using the same mesh) to cut another 700ms, but the texture data gives bad results when not used with the original. I don’t know why I can’t use the same morph target texture for different instances of same mesh using shared morph targets.

As long as you have the exact same targets and in the same order it should work, because the texture is built only using the targets.

If you have a repro we could have a look.

1 Like