“This is the 24th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Introduction to the

Animation is also an important part of three.js. When using software to create a model, it is common to create a skeleton animation of the model for use in development. Next we load the file model in.fBx format (which contains geometry, material information and can store data such as bone animation) to realize the animation.

AnimationMixer

  • An animation mixer is a player that animates specific objects in a scene. When multiple objects in a scene are animated independently, each object can use the same animation mixer.
  • Parameters:rootObjectThe object to which the animation played by the mixer belongs. This is the scene object that contains the animation model.
  • Common parameters and attributes:
  1. .timeGlobal mixer time.
  2. .clipAction(AnimationClip)Of the clip parameter passed inAnimationActionObject.AnimationActionUsed to schedule storage inAnimationClipAnimation in.
  • AnimationClipAnimation clip is a reusable set of keyframe tracks that represent animation.
  1. .getRoot()Returns the root object of the mixer.
  2. .update()Advance the mixer time and update the animation. Call the update animation in the render function.

Begin to use

Basic scenario

<! DOCTYPE html><html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>learning</title>
  </head>
  <body>
    <canvas id="c2d" class="c2d" width="1000" height="500"></canvas>
    <script type="module">
      import * as THREE from './file/three.js-dev/build/three.module.js'
      import { OrbitControls } from './file/three.js-dev/examples/jsm/controls/OrbitControls.js'
      import { FBXLoader } from './file/three.js-dev/examples/jsm/loaders/FBXLoader.js'

      const canvas = document.querySelector('#c2d')
      / / the renderer
      const renderer = new THREE.WebGLRenderer({ canvas })

      const fov = 40 // Scope of view
      const aspect = 2 // The camera defaults to the width ratio of the canvas
      const near = 0.1 / / nearly flat
      const far = 10000 / / far plane
      // Perspective projection camera
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
      camera.position.set(1000.500.1500)
      camera.lookAt(0.0.0)
      // Control the camera
      const controls = new OrbitControls(camera, canvas)
      controls.update()

      / / the scene
      const scene = new THREE.Scene()

      / / the background
      scene.background = new THREE.Color(0x87ceeb)
      / / fog
      scene.fog = new THREE.Fog(0x87ceeb.200.10000)

      / / auxiliary
      const axes = new THREE.AxisHelper(700)
      scene.add(axes)

      {
        / / light
        const skyColor = 0xffffff // Sky is white
        const groundColor = 0x000000 // The floor is black
        const intensity = 1
        const light = new THREE.HemisphereLight(skyColor, groundColor, intensity)
        scene.add(light)
      }

      {
        / / the ground
        const loader = new THREE.TextureLoader()
        const texture = loader.load('./file/23/1.jpg')
        texture.wrapS = THREE.RepeatWrapping
        texture.wrapT = THREE.RepeatWrapping
        texture.magFilter = THREE.NearestFilter
        // The texture repeats
        texture.repeat.set(100.100)

        const planeGeo = new THREE.PlaneGeometry(10000.10000)
        const planeMat = new THREE.MeshPhongMaterial({
          map: texture,
          side: THREE.DoubleSide
        })
        const mesh = new THREE.Mesh(planeGeo, planeMat)
        mesh.rotation.x = Math.PI * -0.5

        scene.add(mesh)
      }

      / / rendering
      function render() {
        renderer.render(scene, camera)
        requestAnimationFrame(render)
      }
      requestAnimationFrame(render)
    </script>
  </body>
</html>
Copy the code

Load the.fbx model

  const loader = new FBXLoader()
  loader.load('./file/Naruto.fbx'.function (mesh) {
    console.log('AnimationMixer (24).html ~ line 73 ~ mesh', mesh)
    mesh.position.y = 110
    scene.add(mesh)
  })
Copy the code

  • You can see that in the parsed object, there isanimationsProperty and 27 pieces of data, representing 27 animations.

Use the AnimationMixer to control the animation

  1. Create global parameters to get the animation-related object.
let actions = [] // Array of all animations
let gui = {} // Animation control
let mixer = null / / AnimationMixer object
Copy the code
  1. Parses the animation and executes the 24th animation.
    mixer = new THREE.AnimationMixer(mesh)
    for (var i = 0; i < mesh.animations.length; i++) {
      actions[i] = mixer.clipAction(mesh.animations[i])
    }
    gui['action'] = function (s) {
      for (var j = 0; j < actions.length; j++) {
        if (j === s) {
          actions[j].play()
        } else {
          actions[j].stop()
        }
      }
    }
    // The 24th movement is naruto standing up
    gui['action'] (24)
Copy the code
  1. Execute in the render function.update()Function to advance the animation.
  • .Clock()This object is used to track time.
  const clock = new THREE.Clock()
  / / rendering
  function render() {
    const time = clock.getDelta()
    if (mixer) {
      mixer.update(time)
    }

    renderer.render(scene, camera)
    requestAnimationFrame(render)
  }
Copy the code

Toggle animations with keyboard Spaces

  • Listen for keyboard events, callguiObject to perform the new animation.
  let keyNum = 24 / / action
  document.onkeydown = function (e) {
    if (e && e.keyCode == 32) {
      if (keyNum === 27) {
        keyNum = 1
      }
      keyNum += 1
      gui['action'](keyNum)
    }
  }
Copy the code