图形化开发(七)03-Three.js之动画——区别-变形动画(精度要求高-人物表情) 骨骼动画(精度要求低-人物走动)

本文主要是介绍图形化开发(七)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的架构。接下来我们了解一下这套动画系统的主要组件以及它们时如何协同工作。

  1. 在模型加载成功以后,我们首先将模型创建出来,并将材质的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);
  2. 然后我们创建了一个针对于该模型的混合器:

    mixer = new THREE.AnimationMixer(mesh);
    
  3. 接着使用变形目标数据创建一个动画片段:

    var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('gallop', geometry.morphTargets, 30);
    
  4. 使用混合器和动画片段创建一个动画播放器来播放:

    var action = mixer.clipAction(clip); //创建动画播放器
    action.setDuration(1); //设置当前动画一秒为一个周期
    action.play(); //设置当前动画播放
    
  5. 最后,我们还需要在重新绘制循环中更新混合器,进行动作更新:

    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之动画——区别-变形动画(精度要求高-人物表情) 骨骼动画(精度要求低-人物走动)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/435748

相关文章

Python38个游戏开发库整理汇总

《Python38个游戏开发库整理汇总》文章介绍了多种Python游戏开发库,涵盖2D/3D游戏开发、多人游戏框架及视觉小说引擎,适合不同需求的开发者入门,强调跨平台支持与易用性,并鼓励读者交流反馈以... 目录PyGameCocos2dPySoyPyOgrepygletPanda3DBlenderFife

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期