本文主要是介绍图形化开发(七)03-Three.js之动画——区别-变形动画(精度要求高-人物表情) 骨骼动画(精度要求低-人物走动),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
图形化开发(七)03-Three.js之动画——区别-变形动画(精度要求高-人物表情) & 骨骼动画(精度要求低-人物走动)
两种动画的区别
变形动画主要用于精度要求高的动画,比如人物的面部表情。优点是动画表达会很到位,缺点就是扩展性不强,只能执行设置好的相关动画。
骨骼动画主要用于那种精度要求低,而且需要丰富多样的动画,就比如人物的走动,攻击防御等动画,我们可以通过一套骨骼,修改相应骨骼的位置的信息直接实现相应的效果。确定是没有变形动画的精度高,但是可以实现多种多样的效果。
总结:我们可以根据项目的需求来设置不同的动画,就比如一个人物模型,说话我们使用变形动画去实现,而肢体动作使用骨骼动画去实现。
导入动画
https://sketchfab.com/3d-models?date=week&features=downloadable&sort_by=-likeCount
在Three.js的动画系统中,你可以为模型的各种属性设置动画:骨骼动画,变形动画,材质的相关属性(颜色,透明度, 是否可见)。动画属性可以设置淡入淡出效果以及各种扭曲特效。也可以单独的改变一个对象或者多个对象上的动画的影响程度和动画时间。
为了实现这些,Three.js动画系统在2015年修改为了一个类似于Unity和虚幻引擎4的架构。接下来我们了解一下这套动画系统的主要组件以及它们时如何协同工作。
-
在模型加载成功以后,我们首先将模型创建出来,并将材质的
morphTargets
设置为ture,可以使用变形动画:mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({vertexColors: THREE.FaceColors,morphTargets: true })); mesh.castShadow = true; mesh.scale.set(0.1, 0.1, 0.1); scene.add(mesh);
-
然后我们创建了一个针对于该模型的混合器:
mixer = new THREE.AnimationMixer(mesh);
-
接着使用变形目标数据创建一个动画片段:
var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('gallop', geometry.morphTargets, 30);
-
使用混合器和动画片段创建一个动画播放器来播放:
var action = mixer.clipAction(clip); //创建动画播放器 action.setDuration(1); //设置当前动画一秒为一个周期 action.play(); //设置当前动画播放
-
最后,我们还需要在重新绘制循环中更新混合器,进行动作更新:
function render() {control.update();var time = clock.getDelta();//由于模型导入是异步的,所以我们再模型没有加载完之前是获取不到混合器的if (mixer) {mixer.update(time);}renderer.render(scene, camera); }
实例
效果-live server打开
代码
import.html
<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8"><title>JSON模型动画案例</title><style type="text/css">html,body {margin: 0;height: 100%;}canvas {display: block;}</style>
</head><body onload="draw();"></body>
<script src="https://cdn.bootcss.com/three.js/92/three.js"></script>
<script src="./control.js"></script>
<script src="http://www.wjceo.com/lib/js/libs/stats.min.js"></script>
<script src="https://cdn.bootcss.com/dat-gui/0.7.1/dat.gui.min.js"></script>
<script>var renderer, camera, scene, gui, stats, ambientLight, directionalLight, control;var mixer, clock = new THREE.Clock();function initRender() {renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);//告诉渲染器需要阴影效果renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是,没有设置的这个清晰 THREE.PCFShadowMapdocument.body.appendChild(renderer.domElement);}function initCamera() {camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(0, 50, 100);camera.lookAt(new THREE.Vector3(0, 0, 0));}function initScene() {scene = new THREE.Scene();}function initGui() {//声明一个保存需求修改的相关数据的对象gui = {};var datGui = new dat.GUI();}function initLight() {ambientLight = new THREE.AmbientLight("#111111");scene.add(ambientLight);directionalLight = new THREE.DirectionalLight("#ffffff");directionalLight.position.set(40, 60, 10);directionalLight.shadow.camera.near = 1; //产生阴影的最近距离directionalLight.shadow.camera.far = 400; //产生阴影的最远距离directionalLight.shadow.camera.left = -50; //产生阴影距离位置的最左边位置directionalLight.shadow.camera.right = 50; //最右边directionalLight.shadow.camera.top = 50; //最上边directionalLight.shadow.camera.bottom = -50; //最下面//这两个值决定生成阴影密度 默认512directionalLight.shadow.mapSize.height = 1024;directionalLight.shadow.mapSize.width = 1024;//告诉平行光需要开启阴影投射directionalLight.castShadow = true;scene.add(directionalLight);}function initModel() {//底部平面var planeGeometry = new THREE.PlaneGeometry(100, 100);var planeMaterial = new THREE.MeshLambertMaterial({ color: 0xaaaaaa, side: THREE.DoubleSide });var plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotation.x = -0.5 * Math.PI;plane.position.y = -.1;plane.receiveShadow = true; //可以接收阴影scene.add(plane);var loader = new THREE.JSONLoader(); // 原生自带loader.load("./source/horse.js", function (geometry) {mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({vertexColors: THREE.FaceColors,morphTargets: true // morphTargets 强调是动画}));mesh.castShadow = true;mesh.scale.set(0.2, 0.2, 0.2);//调节动画大小scene.add(mesh);mixer = new THREE.AnimationMixer(mesh); // 需要实例化var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('gallop', geometry.morphTargets, 30); // 可以去优化性能mixer.clipAction(clip).setDuration(0.5).play(); //setDuration 调节时间-越小动画越快});}function initStats() {stats = new Stats();document.body.appendChild(stats.dom);}function initControl() {control = new THREE.OrbitControls(camera, renderer.domElement);}function render() {control.update();var time = clock.getDelta();if (mixer) {mixer.update(time);}renderer.render(scene, camera);}function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}function animate() {//更新控制器render();//更新性能插件stats.update();requestAnimationFrame(animate);}function draw() {initRender();initScene();initCamera();initLight();initStats();initModel();initGui();initControl();animate();window.onresize = onWindowResize;}
</script></html>
附
注意参数:
//创建模型
function initModel() {}//调节光线function initLight() {}
这篇关于图形化开发(七)03-Three.js之动画——区别-变形动画(精度要求高-人物表情) 骨骼动画(精度要求低-人物走动)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!