...

/

Animation with Morph Targets

Animation with Morph Targets

Learn how to create animation using morph targets and use different functions to control animations.

Morph targets

Morph targets are the most straightforward way of defining an animation. We define all the vertices for each important position (also called keyframes) and tell Three.js to move the vertices from one position to the other.

We’ll show how to work with morph targets using two examples.

  • In the first example, we’ll let Three.js handle the transition between the various keyframes (or morph targets, as we’ll call them from now on).

  • In the second one, we’ll do this manually.

Keep in mind that we are only scratching the surface of what is possible with animations in Three.js. As we’ll see in this lesson, Three.js has excellent support for controlling animations, supports syncing of animations, and provides ways to smoothly transition from one animation to another.

Animation with a mixer and morph targets

Before we dive into the examples, first, we’ll look at the three core classes that we can use to animate with Three.js. Later in this lesson, we’ll show all the functions and properties provided by these objects:

  • THREE.AnimationClip: When we load a model that contains animations, we can look in the response object for a field usually called animations. This field will contain a list of THREE.AnimationClip objects. Note that depending on the loader, an animation might be defined on a Mesh, a Scene, or be provided completely separately. A THREE.AnimationClip most often holds the data for a certain animation the model we loaded can perform. For instance, if we loaded a model of a bird, one THREE.AnimationClip would contain the information needed to flap the wings, and another one might be opening and closing its beak.

  • THREE.AnimationMixer: It is used to control several THREE.AnimationClip objects. It makes sure the timing of the animation is correct and makes it possible to sync animations together, or cleanly move from one animation to another.

  • THREE.AnimationAction: The THREE.AnimationMixer itself doesn’t expose a large number of functions to control the animation, though. This is done through THREE.AnimationAction objects, which are returned when we add a THREE.AnimationClip to a THREE.AnimationMixer (though we can get them at a later time by using functions provided by THREE.AnimationMixer).

There is also an AnimationObjectGroup, which we can use to provide the animation state not just to a single Mesh but to a group of objects.

In the following example, we can control a THREE.AnimationMixer and a THREE.AnimationAction, which were created using a THREE.AnimationClip from the model. The THREE.AnimationClip objects used in this example morph a model into a cube and then into a cylinder.

Example: Morph targets

For this first morphing example, the easiest way to understand how a morph targets-based animation works is by executing the morph-targets.js example in the playground below. The following screenshot shows a still image of this example:

Press + to interact
Animation using morph targets
Animation using morph targets

Click the “Run” button to execute the above example:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// const CopyWebpackPlugin = require('copy-webpack-plugin')
const fs = require('fs').promises

// we should search through the directories in examples, and use
// the name from the files to generate the HtmlWebpackPlugin settings.
module.exports = async () => {

  return {
    module: {
      rules: [
        {
          test: /\.glsl$/i,
          use: 'raw-loader'
        }
      ]
    },
    mode: 'development',
    entry: {
      'chapter-9': './samples/chapters/chapter-9/morph-targets.js',
    },
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js',
      publicPath: '/',
    },
    plugins: [
      new HtmlWebpackPlugin(),
    ],
    experiments: {
      asyncWebAssembly: true
    },
    devServer: {
       allowedHosts: 'all',
       host: '0.0.0.0',
       port: '3000',
       static: [
        {
          directory: path.join(__dirname, 'assets'),
          publicPath: '/assets'
        },
        {
          directory: path.join(__dirname, 'dist')
        }
      ] 
    },
  mode: 'development',
  }
}
Load model and add animation with morph targets

Note: ...