👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
- 1.1 ☘️THREE.AnimationMixer 动画混合器
- 二、🍀使用AnimationMixer实现变形动画
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中使用AnimationMixer实现变形动画,亲测可用。希望能帮助到您。一起学习,加油!加油!
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 参数表示当前帧与前一帧之间的时间差(以秒为单位)。
二、🍀使用AnimationMixer实现变形动画
1. ☘️实现思路
- 1、初始化renderer渲染器
- 2、初始化Scene三维场景
- 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
- 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.PointLight点光源,设置点光源位置,设置点光源投影,scene添加点光源。
- 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,创建THREE.JSONLoader加载器加载horse.js json模型文件,生成mesh物体,scene场景加入mesh和THREE.AxesHelper坐标辅助工具。创建THREE.AnimationMixer 动画混合器,创建模型动画片段THREE.AnimationClip,根据创建的动画混合器和动画片段创建AnimationAction动画调度器,播放动画。
- 6、加入controls、gui控制,加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>learn48(使用AnimationMixer实现变形动画)</title>
<!--<script src="lib/threejs/127/three.js-master/build/three.js"></script>-->
<script src="lib/threejs/91/three.js"></script>
<!--<script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>-->
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.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.setClearColor(0xeeeeee)
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
}
var scene
var initScene = () => {
scene = new THREE.Scene()
}
var camera
var initCamera = () => {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(0, 40, 50)
}
var light
var initLight = () => {
scene.add(new THREE.AmbientLight(0x444444))
light = new THREE.PointLight(0xffffff)
light.position.set(0, 50, 0)
light.castShadow = true
scene.add(light)
}
var mesh, mixer, action
var initModel = () => {
var helper = new THREE.AxesHelper(50)
scene.add(helper)
var loader = new THREE.JSONLoader()
loader.load('data/model/horse/horse.js', geometry => {
mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
vertexColors: THREE.FaceColors,
morphTargets: true
}))
mesh.scale.set(0.1, 0.1, 0.1)
scene.add(mesh)
// AnimationMixer是场景中特定对象的动画播放器。当场景中的多个对象独立动画时,可以为每个对象使用一个AnimationMixer
mixer = new THREE.AnimationMixer(mesh)
// CreateFromMorphTargetSequence 通过geometry.morphTargets创建一个AnimationClip对象,其中包含每帧的内容和总帧数
var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('run', geometry.morphTargets, 30)
// mixer.clipAction 返回一个可以控制动画的AnimationAction对象 参数需要一个AnimationClip 对象
// AnimationAction.setDuration 设置一个循环所需要的时间,当前设置了一秒
action = mixer.clipAction(clip)
action.setDuration(1).play()
})
}
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 gui
var initGui = () => {
gui = {
animation: true
}
var datGui = new dat.GUI()
datGui.add(gui, 'animation').onChange(e => {
if (e) {
action.play()
} else {
action.stop()
}
})
}
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()
renderer.setSize(window.innerWidth, window.innerHeight)
}
var animate = () => {
render()
stats.update()
// controls.update()
renderer.render(scene, camera)
requestAnimationFrame(animate)
}
var draw = () => {
if (!Detector.webgl) Detector.addGetWebGLMessage()
initRender()
initScene()
initCamera()
initLight()
initModel()
initStats()
initControls()
initGui()
animate()
window.onresize = onWindowResize
}
</script>
</html>
效果如下: