学习threejs,对模型多个动画切换展示

👨‍⚕️ 主页: gis分享者

👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录


一、🍀前言

本文详细介绍如何基于threejs在三维场景中对模型多个动画切换展示,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.AnimationMixer 动画混合器

THREE.AnimationMixer动画混合器是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。
创建方法:

AnimationMixer( rootObject : Object3D )

rootObject 是 混合器播放的动画所属的对象
属性:

time:Number 全局的混合器时间(单位秒; 混合器创建的时刻记作0时刻)。

timeScale:全局时间(mixer time)的比例因子。

说明: 将混合器的时间比例设为0, 稍后再设置为1,可以暂停/取消暂停由该混合器控制的所有动作。
方法:

clipAction(clip : AnimationClip, optionalRoot : Object3D):AnimationAction 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。

如果不存在符合传入的剪辑和根对象这两个参数的动作, 该方法将会创建一个。传入相同的参数多次调用将会返回同一个剪辑实例。

existingAction (clip : AnimationClip, optionalRoot : Object3D) : AnimationAction 返回传入剪辑的已有AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。

第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。

update (deltaTimeInSeconds : Number) : AnimationMixer 推进混合器时间并更新动画。

deltaTimeInSeconds 参数表示当前帧与前一帧之间的时间差(以秒为单位)。

二、🍀对模型多个动画切换展示

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.PointLight点光源,设置点光源位置,设置点光源投影,scene添加点光源。
  • 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,创建THREE.PlaneBufferGeometry平面几何体、THREE.GridHelper地板割线,scene场景中加入创建的平面几何体和地板割线。创建gui控件datGui。通过THREE.FBXLoader类加载 'Naruto.fbx' 模型文件mesh,在加载模型的回调函数中,定义mesh动画,datGui加入动画控制。具体实现参考代码样例。
  • 6、加入controls控制,加入stats监控器,监控帧数信息。

2. ☘️代码样例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn50(对模型多个动画切换展示)</title>
    <script src="lib/threejs/127/three.js-master/build/three.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>
    <!--<script src="lib/js/inflate.min.js"></script>-->
    <script src="lib/threejs/127/three.js-master/examples/js/loaders/FBXLoader.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/fflate.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
    <script src="lib/js/Detector.js"></script>
</head>
<style type="text/css">
    html, body {
        margin: 0;
        height: 100%;
    }

    canvas {
        display: block;
    }

</style>
<body onload="draw()">
</body>
<script>
  var renderer
  var initRender = () => {
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setClearColor(0xeeeeee)
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.shadowMap.enabled = true
    document.body.appendChild(renderer.domElement)
  }
  var scene
  var initScene = () => {
    scene = new THREE.Scene()
    scene.backgroundColor = new THREE.Color(0xa0a0a0)
    scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000)
  }
  var camera
  var initCamera = () => {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000)
    camera.position.set(100, 200, 300)
  }
  var light
  var initLight = () => {
    scene.add(new THREE.AmbientLight(0x444444))

    light = new THREE.DirectionalLight(0xffffff)
    light.position.set(0, 200, 100)
    light.castShadow = true
    light.shadow.camera.top = 180
    light.shadow.camera.bottom = -100
    light.shadow.camera.left = -120
    light.shadow.camera.right = 120
    scene.add(light)
  }
  var gui, datGui, meshHelper, mixer
  var initGui = () => {
    gui = {
      helper: true
    }
    datGui = new dat.GUI()
    datGui.add(gui, 'helper').onChange(e => {
      meshHelper.visible = e
    })
  }
  var initModel = () => {
    var helper = new THREE.AxesHelper(50)
    scene.add(helper)
    var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshPhongMaterial({
      color: 0xffffff,
      depthWrite: false
    }))
    mesh.receiveShadow = true
    mesh.rotation.x = -0.5 * Math.PI
    scene.add(mesh)

    // var planeGeometry = new THREE.PlaneBufferGeometry(2000, 2000)
    // var planeMatarial = new THREE.MeshPhongMaterial({
    //   color: 0xffffff,
    //   depthWrite: false
    // })
    // var plane = new THREE.Mesh(planeGeometry, planeMatarial)
    // plane.rotation.x = -0.5 * Math.PI
    // plane.position.y = -0
    // plane.receiveShadow = true
    // scene.add(plane)

    // 添加地板割线
    var grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000)
    grid.material.opacity = 0.2
    grid.material.transparent = true
    scene.add(grid)

    var loader = new THREE.FBXLoader()
    loader.load('data/model/NarutoFbx/Naruto.fbx', mesh => {
      meshHelper = new THREE.SkeletonHelper(mesh)
      scene.add(meshHelper)
      mesh.traverse(child => {
        if (child.isMesh) {
          child.castShadow = true
          child.receiveShadow = true
        }
      })
      mixer = mesh.mixer = new THREE.AnimationMixer(mesh)
      var actions = []
      var animations = datGui.addFolder('animations')
      var createAction = (i) => {
        actions[i] = mixer.clipAction(mesh.animations[i])
        gui['action' + i] = () => {
          for (var j = 0; j < actions.length; j++) {
            if (j === i) {
              actions[j].play()
            } else {
              actions[j].stop()
            }
          }
        }
        animations.add(gui, 'action' + i)
      }
      for (var i = 0; i < mesh.animations.length; i++) {
        createAction(i)
      }
      gui.stop = () => {
        for (var i = 0; i < actions.length; i++) {
          actions[i].stop()
        }
      }
      datGui.add(gui, 'stop')
      mesh.position.y += 100
      scene.add(mesh)
    })
  }
  var stats
  var initStats = () => {
    stats = new Stats()
    document.body.appendChild(stats.dom)
  }
  var controls
  var initControls = () => {
    controls = new THREE.OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
  }
  var clock = new THREE.Clock()
  var render = () => {
    var time = clock.getDelta()
    if (mixer) {
      mixer.update(time)
    }
    controls.update()
  }
  var onWindowResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    render.setSize(window.innerWidth, window.innerHeight)
  }
  var animate = () => {
    render()
    stats.update()
    renderer.render(scene, camera)
    requestAnimationFrame(animate)
  }
  var draw = () => {
    initRender()
    initScene()
    initCamera()
    initGui()
    initLight()
    initModel()
    initStats()
    initControls()

    animate()

    window.onresize = onWindowResize
  }
</script>
</html>

效果如下:

相关推荐
gis分享者19 小时前
学习threejs,使用PointLight点光源
threejs·点光源·pointlight
gis分享者5 天前
学习threejs,使用HemisphereLight半球光
threejs·hemispherelight·半球光
gis分享者9 天前
学习threejs,使用Lensflare模拟镜头眩光
threejs·lensflare·眩光
gis分享者12 天前
学习threejs,tga格式图片文件贴图
threejs·贴图·tga·tgaloader
gis分享者13 天前
学习threejs,pvr格式图片文件贴图
threejs·贴图·pvr
gis分享者1 个月前
学习threejs,使用OrbitControls相机控制器
threejs·相机·相机控制器·orbitcontrols
不系舟1781 个月前
threejs 实现镜面反射,只反射指定物体,背景透明
threejs
gis分享者1 个月前
学习threejs,使用RollControls相机控制器
threejs·相机控制器·rollcontrols
gis分享者1 个月前
学习threejs,使用FlyControls相机控制器
threejs·相机控制器·flycontrols
gis分享者1 个月前
学习threejs,使用TrackballControls相机控制器
threejs·trackball·相机控制器