js实例教程-Three.js通过SkinnedMesh来创建骨骼和蒙皮动画(代码实例)

发布时间:2018-12-01 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了js实例教程-Three.js通过SkinnedMesh来创建骨骼和蒙皮动画(代码实例)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

简介

变形动画十分简洁。Three.js知道所有目标顶点的位置,实现变形动画所要做的就是将每一个顶点从一个位置变换到另一个位置。而骨骼和蒙皮则要复杂一些。当你使用骨骼创建动画时,你移动一下骨骼,Three.js需要决定如何响应地移动相应的皮肤(一系列顶点)。

实现案例

这次案例是导入了一只手的模型,并且模型上面带有骨骼点。我们要实现的是通过控制这些个骨骼点bones,来实现这只手模型有一个握的动作。

- 首先,正常导入模型。模型文件包含了顶点、面和骨骼的定义。在回调中,我们获得了模型的几何体geometry,我们通过模型的geometry来实例出一个SkinnedMesh对象。并且将模型所使用的MATErial的skinning属性设置为true,否则骨头不会运动。

 loader.load("/lib/assets/models/hand-1.js", function (geometry) {      mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshLambertMaterial({         color:0xf4b397,         skinning: true     }));      mesh.rotation.x = 0.5 * Math.PI;     mesh.rotation.z = 0.7 * Math.PI;      mesh.scale.set(10, 10, 10);      scene.add(mesh); });

然后,我们使用TWEEN来创建补间动画,动态修改某些骨骼点的方向,来实现模拟手握的动作。

 tween = new TWEEN.Tween({pos: -1})     .to({pos: 0}, 3000)     .easing(TWEEN.Easing.Cubic.InOut) //动画曲线     .yoyo(true) //实现来回动画     .rePEat(InfinITy); //一直循环 tween.onUpdate(function () {         VAR pos = this.pos;         // 旋转手指的方向         mesh.skeleton.bones[5].rotation.set(0, 0, pos);         mesh.skeleton.bones[6].rotation.set(0, 0, pos);         mesh.skeleton.bones[10].rotation.set(0, 0, pos);         mesh.skeleton.bones[11].rotation.set(0, 0, pos);         mesh.skeleton.bones[15].rotation.set(0, 0, pos);         mesh.skeleton.bones[16].rotation.set(0, 0, pos);         mesh.skeleton.bones[20].rotation.set(0, 0, pos);         mesh.skeleton.bones[21].rotation.set(0, 0, pos);          // 旋转手腕         mesh.skeleton.bones[1].rotation.set(pos, 0, 0);     });

最后,为了方便我们理解骨骼点的位置,添加辅助SkeletonHelper来显示位置:

 skeletonHelper = new THREE.SkeletonHelper( mesh ); skeletonHelper.visible = false; scene.add( skeletonHelper );

在这个案例当中,我们只改变了骨骼的旋转方向,除此之外,我们还可以修改骨骼的位置和缩放比例。我们将在下一节中演示。

案例代码

 <!DOCTYPE htML> <html lang="en"> <head>     <;meta charset="UTF-8">     <title>Title</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/91/three.min.js"></script> <script src="/lib/js/controls/OrbitControls.js"></script> <script src="https://cdn.bootcss.com/tween.js/r14/Tween.min.js"></script> <script src="https://cdn.bootcss.com/stats.js/r17/Stats.min.js"></script> <script src="https://cdn.bootcss.com/dat-gui/0.7.1/dat.gui.min.js"></script> <script src="/lib/js/detector.js"></script>  <script>     var renderer, camera, scene, gui, light, stats, controls, mesh, skeletonHelper, tween, animation = true;     var clock = new THREE.Clock();      function initRender() {         renderer = new THREE.WebGLRenderer({antialias: true});         renderer.setPixelRatio(window.devicePixelRatio);         renderer.setSize(window.innerWidth, window.innerHeight);         renderer.setClearColor(0xeeeeee);         //告诉渲染器需要阴影效果         document.body.appendChild(renderer.domElement);     }      function initCamera() {         camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);         camera.position.set(0, 40, 50);     }      function initScene() {         scene = new THREE.Scene();     }      //初始化dat.GUI简化试验流程     function initGui() {         //声明一个保存需求修改的相关数据的对象         gui = {             animation: true,             helper: false         };         var datGui = new dat.GUI();         //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)         datGui.add(gui, "animation").onChange(function (e) {             animation = e;         });         datGui.add(gui, "helper").onChange(function (e) {             skeletonHelper.visible = e;         });     }      function initLight() {         scene.add(new THREE.AmbientLight(0x444444));          light = new THREE.PointLight(0xffffff);         light.position.set(0, 50, 0);          //告诉平行光需要开启阴影投射         light.castShadow = true;          scene.add(light);     }      function initModel() {          //辅助工具         var helper = new THREE.AxesHelper(50);         scene.add(helper);          //加载模型         var loader = new THREE.JSONLoader();         loader.load("/lib/assets/models/hand-1.js", function (geometry) {              mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshLambertMaterial({                 color:0xf4b397,                 skinning: true             }));              mesh.rotation.x = 0.5 * Math.PI;             mesh.rotation.z = 0.7 * Math.PI;              mesh.scale.set(10, 10, 10);              skeletonHelper = new THREE.SkeletonHelper( mesh );             skeletonHelper.visible = false;             scene.add( skeletonHelper );             console.LOG(mesh);              scene.add(mesh);              tween.start();         });     }      function initTween() {         tween = new TWEEN.Tween({pos: -1})             .to({pos: 0}, 3000)             .easing(TWEEN.Easing.Cubic.InOut)             .yoyo(true)             .repeat(Infinity); //一直循环         tween.onUpdate(function () {                 var pos = this.pos;                 // 旋转手指的方向                 mesh.skeleton.bones[5].rotation.set(0, 0, pos);                 mesh.skeleton.bones[6].rotation.set(0, 0, pos);                 mesh.skeleton.bones[10].rotation.set(0, 0, pos);                 mesh.skeleton.bones[11].rotation.set(0, 0, pos);                 mesh.skeleton.bones[15].rotation.set(0, 0, pos);                 mesh.skeleton.bones[16].rotation.set(0, 0, pos);                 mesh.skeleton.bones[20].rotation.set(0, 0, pos);                 mesh.skeleton.bones[21].rotation.set(0, 0, pos);                  // 旋转手腕                 mesh.skeleton.bones[1].rotation.set(pos, 0, 0);             });     }      //初始化性能插件     function initStats() {         stats = new Stats();         document.body.appendChild(stats.dom);     }      function initControls() {          controls = new THREE.OrbitControls(camera, renderer.domElement);          // 如果使用animate方法时,将此函数删除         //controls.addEventListener( &#39;change', render );         // 使动画循环使用时阻尼或自转 意思是否有惯性         controls.enableDamping = true;         //动态阻尼系数 就是鼠标拖拽旋转灵敏度         //controls.dampingFactor = 0.25;         //是否可以缩放         controls.enableZoom = true;         //是否自动旋转         controls.autoRotate = false;         controls.autoRotateSpeed = 0.5;         //设置相机距离原点的最远距离         controls.minDistance = 1;         //设置相机距离原点的最远距离         controls.maxDistance = 2000;         //是否开启右键拖拽         controls.enablePan = true;     }      function render() {          animation && TWEEN.update();          controls.update();     }      //窗口变动触发的函数     function onWindowResize() {          camera.aspect = window.innerWidth / window.innerHeight;         camera.updatePRojectionMatrix();         renderer.setSize(window.innerWidth, window.innerHeight);      }      function animate() {         //更新控制器         render();          //更新性能插件         stats.update();          renderer.render(scene, camera);          requestAnimationFrame(animate);     }      function draw() {         //兼容性判断         if (!Detector.webgl) Detector.addGetWebGLMessage();          initGui();         initRender();         initScene();         initCamera();         initLight();         initModel();         initControls();         initStats();         initTween();          animate();         window.onresize = onWindowResize;     }   </script> </html>

简介

变形动画十分简洁。Three.js知道所有目标顶点的位置,实现变形动画所要做的就是将每一个顶点从一个位置变换到另一个位置。而骨骼和蒙皮则要复杂一些。当你使用骨骼创建动画时,你移动一下骨骼,Three.js需要决定如何响应地移动相应的皮肤(一系列顶点)。

实现案例

这次案例是导入了一只手的模型,并且模型上面带有骨骼点。我们要实现的是通过控制这些个骨骼点bones,来实现这只手模型有一个握的动作。

- 首先,正常导入模型。模型文件包含了顶点、面和骨骼的定义。在回调中,我们获得了模型的几何体geometry,我们通过模型的geometry来实例出一个SkinnedMesh对象。并且将模型所使用的material的skinning属性设置为true,否则骨头不会运动。

 loader.load("/lib/assets/models/hand-1.js", function (geometry) {      mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshLambertMaterial({         color:0xf4b397,         skinning: true     }));      mesh.rotation.x = 0.5 * Math.PI;     mesh.rotation.z = 0.7 * Math.PI;      mesh.scale.set(10, 10, 10);      scene.add(mesh); });

然后,我们使用TWEEN来创建补间动画,动态修改某些骨骼点的方向,来实现模拟手握的动作。

 tween = new TWEEN.Tween({pos: -1})     .to({pos: 0}, 3000)     .easing(TWEEN.Easing.Cubic.InOut) //动画曲线     .yoyo(true) //实现来回动画     .repeat(Infinity); //一直循环 tween.onUpdate(function () {         var pos = this.pos;         // 旋转手指的方向         mesh.skeleton.bones[5].rotation.set(0, 0, pos);         mesh.skeleton.bones[6].rotation.set(0, 0, pos);         mesh.skeleton.bones[10].rotation.set(0, 0, pos);         mesh.skeleton.bones[11].rotation.set(0, 0, pos);         mesh.skeleton.bones[15].rotation.set(0, 0, pos);         mesh.skeleton.bones[16].rotation.set(0, 0, pos);         mesh.skeleton.bones[20].rotation.set(0, 0, pos);         mesh.skeleton.bones[21].rotation.set(0, 0, pos);          // 旋转手腕         mesh.skeleton.bones[1].rotation.set(pos, 0, 0);     });

最后,为了方便我们理解骨骼点的位置,添加辅助SkeletonHelper来显示位置:

 skeletonHelper = new THREE.SkeletonHelper( mesh ); skeletonHelper.visible = false; scene.add( skeletonHelper );

在这个案例当中,我们只改变了骨骼的旋转方向,除此之外,我们还可以修改骨骼的位置和缩放比例。我们将在下一节中演示。

案例代码

 <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</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/91/three.min.js"></script> <script src="/lib/js/controls/OrbitControls.js"></script> <script src="https://cdn.bootcss.com/tween.js/r14/Tween.min.js"></script> <script src="https://cdn.bootcss.com/stats.js/r17/Stats.min.js"></script> <script src="https://cdn.bootcss.com/dat-gui/0.7.1/dat.gui.min.js"></script> <script src="/lib/js/Detector.js"></script>  <script>     var renderer, camera, scene, gui, light, stats, controls, mesh, skeletonHelper, tween, animation = true;     var clock = new THREE.Clock();      function initRender() {         renderer = new THREE.WebGLRenderer({antialias: true});         renderer.setPixelRatio(window.devicePixelRatio);         renderer.setSize(window.innerWidth, window.innerHeight);         renderer.setClearColor(0xeeeeee);         //告诉渲染器需要阴影效果         document.body.appendChild(renderer.domElement);     }      function initCamera() {         camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);         camera.position.set(0, 40, 50);     }      function initScene() {         scene = new THREE.Scene();     }      //初始化dat.GUI简化试验流程     function initGui() {         //声明一个保存需求修改的相关数据的对象         gui = {             animation: true,             helper: false         };         var datGui = new dat.GUI();         //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)         datGui.add(gui, "animation").onChange(function (e) {             animation = e;         });         datGui.add(gui, "helper").onChange(function (e) {             skeletonHelper.visible = e;         });     }      function initLight() {         scene.add(new THREE.AmbientLight(0x444444));          light = new THREE.PointLight(0xffffff);         light.position.set(0, 50, 0);          //告诉平行光需要开启阴影投射         light.castShadow = true;          scene.add(light);     }      function initModel() {          //辅助工具         var helper = new THREE.AxesHelper(50);         scene.add(helper);          //加载模型         var loader = new THREE.JSONLoader();         loader.load("/lib/assets/models/hand-1.js", function (geometry) {              mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshLambertMaterial({                 color:0xf4b397,                 skinning: true             }));              mesh.rotation.x = 0.5 * Math.PI;             mesh.rotation.z = 0.7 * Math.PI;              mesh.scale.set(10, 10, 10);              skeletonHelper = new THREE.SkeletonHelper( mesh );             skeletonHelper.visible = false;             scene.add( skeletonHelper );             console.log(mesh);              scene.add(mesh);              tween.start();         });     }      function initTween() {         tween = new TWEEN.Tween({pos: -1})             .to({pos: 0}, 3000)             .easing(TWEEN.Easing.Cubic.InOut)             .yoyo(true)             .repeat(Infinity); //一直循环         tween.onUpdate(function () {                 var pos = this.pos;                 // 旋转手指的方向                 mesh.skeleton.bones[5].rotation.set(0, 0, pos);                 mesh.skeleton.bones[6].rotation.set(0, 0, pos);                 mesh.skeleton.bones[10].rotation.set(0, 0, pos);                 mesh.skeleton.bones[11].rotation.set(0, 0, pos);                 mesh.skeleton.bones[15].rotation.set(0, 0, pos);                 mesh.skeleton.bones[16].rotation.set(0, 0, pos);                 mesh.skeleton.bones[20].rotation.set(0, 0, pos);                 mesh.skeleton.bones[21].rotation.set(0, 0, pos);                  // 旋转手腕                 mesh.skeleton.bones[1].rotation.set(pos, 0, 0);             });     }      //初始化性能插件     function initStats() {         stats = new Stats();         document.body.appendChild(stats.dom);     }      function initControls() {          controls = new THREE.OrbitControls(camera, renderer.domElement);          // 如果使用animate方法时,将此函数删除         //controls.addEventListener( 'change', render );         // 使动画循环使用时阻尼或自转 意思是否有惯性         controls.enableDamping = true;         //动态阻尼系数 就是鼠标拖拽旋转灵敏度         //controls.dampingFactor = 0.25;         //是否可以缩放         controls.enableZoom = true;         //是否自动旋转         controls.autoRotate = false;         controls.autoRotateSpeed = 0.5;         //设置相机距离原点的最远距离         controls.minDistance = 1;         //设置相机距离原点的最远距离         controls.maxDistance = 2000;         //是否开启右键拖拽         controls.enablePan = true;     }      function render() {          animation &amp;& TWEEN.update();          controls.update();     }      //窗口变动触发的函数     function onWindowResize() {          camera.aspect = window.innerWidth / window.innerHeight;         camera.updateProjectionMatrix();         renderer.setSize(window.innerWidth, window.innerHeight);      }      function animate() {         //更新控制器         render();          //更新性能插件         stats.update();          renderer.render(scene, camera);          requestAnimationFrame(animate);     }      function draw() {         //兼容性判断         if (!Detector.webgl) Detector.addGetWebGLMessage();          initGui();         initRender();         initScene();         initCamera();         initLight();         initModel();         initControls();         initStats();         initTween();          animate();         window.onresize = onWindowResize;     }   </script> </html>

觉得可用,就经常来吧!Javascript技巧 脚本宝典 欢迎评论哦! js技巧,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的js实例教程-Three.js通过SkinnedMesh来创建骨骼和蒙皮动画(代码实例)全部内容,希望文章能够帮你解决js实例教程-Three.js通过SkinnedMesh来创建骨骼和蒙皮动画(代码实例)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。