Animation and Morph Target GLTF Export

I have a GLTF created in Blender. It has a couple of animations and several morph targets. When I export the model in three.js to GLB it has all the animations and morph targets. That’s good because it tells me the exporter is working well. However, in the exported version I want to eliminate the animations and have only a selected number of morph targets.

Now, I envision from my research I can eliminate the animations by using the animationclip option and just leaving the list null… tell me if that’s the appropriate way to do this please. I cannot figure how to limit the number of morph targets exported. I could possibly eliminate them all doing something like:

var finalRenderModel = mainScene.children[2]
finalRenderModel.children[0].children[1].geometry.morphAttributes = {};

But that’s not what I want to accomplish. Any tips from the pros on how I might control which morph targets get exported?

Thanks…

Still researching the question… so I read this here that animation and morphs are held in clips… If I understanding this properly, I just include the morphs in the animationclip list correct? If so, how would I identify them? I can use morphTargetDictionary to get a list of morph targets and they are retrieved using their index number, not name.

Blockquote I don’t think you’d commonly need that CreateClipsFromMorphTargetSequences method. The document above does not go into the details of using any particular loader (as you mention, they’re inconsistent), but the GLTFLoader docs do …In this case it doesn’t matter whether the clips are TRS, skinned, or morph targets — you can play the animations all alike.

Note that each morph target is just a shape the mesh can morph to. Animation clips control the timing, speed, and order of that transition — or you can do that manually in your code. So, I’m not sure I understand what you’re asking… if you want to delete the animations but not the morph targets you can do that in Blender, or you can just not play the animations and control the morph targets manually.

Is your goal to get a particular effect? Or do you need to reduce the size of the file?

Thanks Don… Well I am allowing others to use my model to create custom models online. They will then save those models after they have used the morphs to manipulate the model. I don’t want them to download all the morphs. One, it will be too large and two, they are proprietary to me. I have animations and it is clear I can determine they will not be created in the copy. I also have a subsets of the morphs I want them to download with the model. So, I want them to be able to export with only a limited set of morphs. I hope that makes more sense. Thanks

I really could use some suggestions here. Am I not speaking the right language or is this something extremely difficult to perform?

I’m still not sure I fully understand what you’re trying to do, but exporting a model with only a subset of its morph targets makes sense at least. The Blender exporter does not include muted shape keys. Can you name your shape keys there, mute the ones you don’t want, and then export?

Oh, that would certainly work. But we are working with a GLTF model loaded by three.js… the user is making changes to the model online and we want to use the GLTFExporter to export the model they create with limited shape keys. The shape keys are necessary in the loaded model to perform the task of morphing the model the user wants to download. Imagine something like Spore creature creator. We don’t want the user to download all the shape keys necessary to create the model. We want to limit the number of shape keys that get exported. Not the complete set. If there were a way to mute it in three.js when using the GLTFExporter that would be fine.

Ok I see (hopefully). So to rephrase that and make sure I’ve got it right, you want:

  1. All shape keys are exported from Blender in one model.
  2. Three.js only loads a subset of the shape keys in the model, as needed.
  3. After some interaction in three.js, the user can export with GLTFExporter and only the shape keys that were needed are included in that final export.

Is that right?

If so, (2) is kind of the tricky part here. It’s possible if you construct your glTF file very carefully, but that’s well beyond what a 3D modeling tool exporter would do by itself. It might be better to export each shape key as a separate GLB, each containing a single mesh. If you load three meshes that way, and make sure they all have the same number of vertices, turning them into a single base mesh with two shape keys is not too hard.

  1. All shape keys are already exported from Blender in one model
  2. Three.js loads all the shape keys.
  3. After some interaction in three.js, the user can export with GLTFExport and only the shape keys we permit are included in the final export.

Exporting the shape keys in a separate GLB sounds like an interesting prospect. I will explore that approach… any links to examples come to mind?

If you don’t mind three.js loading all the shape keys at step (2), then you probably don’t need separate GLBs. At step (3), can you remove the shape keys you don’t need before passing the model into GLTFExporter? Or clone() first if you need to keep the original. Something like:

const morphAttributeNames = ['position', 'normal'];
const morphTargetsNeeded = ['Happy', 'Sad'];
const morphTargetNameDictionary = {};

// Create lookup table from target index to target name.
for (const targetName in mesh.morphTargetDictionary {
  morphTargetNameDictionary[mesh.morphTargetDictionary[targetName]] = targetName;
}

// Remove unwanted morph target attributes.
for (const k of morphAttributeNames) {
  const geometry = mesh.geometry;
  geometry.morphAttributes[k] = geometry.morphAttributes[k].filter((attribute, index) => {
    const targetName = morphTargetNameDictionary[index];
    attribute.name = targetName; // Ensures .updateMorphTargets() gets the right name.
    return morphTargetsNeeded.includes(targetName);
  });
}

// Update mesh properties.
mesh.updateMorphTargets();

That’s exactly what I needed… that looks like a good direction. Thank you so very much for your time!

1 Like