three.js进阶之动画系统

这篇具有很好参考价值的文章主要介绍了three.js进阶之动画系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我曾在three.js进阶之骨骼绑定文章中提到了AnimationMixer、AnimationAction等内容,其实这些应该属于Three.js的动画系统,本文就系统的介绍一下动画系统(Animation System)。

前言

一般情况下,我们很少会使用three.js的动画系统去手动创建动画——因为这真的很麻烦,更高效便捷的做法还是直接在建模软件如Blender中完成动画的制作,然后在three.js中进行播放。不过,学习了动画系统对我们还是会有帮助的,下面进入正文。

创建动画涉及三个概念:关键帧Keyframes,关键帧轨迹KeyframeTrack和动画剪辑AnimationClip

1 关键帧 Keyframes

在动画系统中最低级别的概念就是关键帧,每个关键帧由三个信息组成:时间、属性和值,举个栗子:

  • 在第0秒,position的取值为(0,0,0)
  • 在第3秒,scale的取值为(1,1,1)
  • 在第12秒,material.color为红色。

这三个关键帧分别描述特定时间的某些属性的值,不过关键帧并不指定任何特定对象。位置关键帧可用于为具有.location属性的任何对象设置动画,缩放关键帧可为具有.scale属性的任何对象设置动画,依此类推。但是,关键帧确实指定了数据类型。上面的positionscale关键帧指定矢量数据,而material.color关键帧指定颜色数据。目前,动画系统支持五种数据类型。
three.js进阶之动画系统
要创建动画,我们至少需要两个关键帧。最简单的例子是两个数字关键帧,例如,动画材质的不透明度(它的透明度/透视程度):

  • 在第0秒,material.opacity为0;
  • 在第3秒,material.opacity为1;

不透明度为0意味着完全不可见,不透明度为1意味着完全可见。当我们为某个对象设置了这两个关键帧后,它将会在3秒内逐渐出现。不管对象原本的透明度为多少,关键帧会覆盖其原本的值。

2 关键帧轨迹 KeyframeTrack

在Three.js中并没有表示单个关键帧的类,KeyframeTrack中包含两个数组——时间数组和取值数组,每一个关键帧就对应时间数组和取值数组中的一个值。另外,KeyframeTrack只是一个基类,不要直接使用KeyframeTrack,,针对前面提到的每种数据类型都有对应的子类,你需要根据取值的数据类型选择对应的子类:

  • BooleanKeyframeTrack
  • ColorKeyframeTrack
  • NumberKeyframeTrack
  • QuaternionKeyframeTrack
  • StringKeyframeTrack
  • VectorKeyframeTrack

2.1 NumberKeyframeTrack

使用前面的透明度关键帧的例子:

  • 在0秒时,material.opacity为0
  • 在1秒时,material.opacity为1
  • 在2秒时,material.opacity为0
  • 在3秒时,material.opacity为1
  • 在4秒时,material.opacity为0

由于透明度为数值型,因此可以使用NumberKeyframeTrack类来存储关键帧数据:

import { NumberKeyframeTrack } from "three";

const times = [0, 1, 2, 3, 4];
const values = [0, 1, 0, 1, 0];

const opacityKF = new NumberKeyframeTrack(".material.opacity", times, values);

说明:KeyframeTrack的构造函数为:

/**
 * KeyframeTrack构造函数
 * name: 关键帧轨道的名称
 * times: 关键帧时间数组,内部转换为Float32Array
 * values: 包含与时间数组相关的取值,内部转换为浮点32Array
 * interpolation: 要使用的插值类型,默认值为线性插值
 */
KeyframeTrack( name : String, times : Array, values : Array, interpolation : Constant )

2.2 VectorKeyframeTrack

由于NumberKeyframeTrack在每个时间点都只有一个数值类型的取值,因此times数组和values数组的长度是一样的,那么如果每一帧的数据是一个向量呢?应该如何构造values数组呢?我们使用下面的例子:

  • 在第0秒,position(0,0,0)
  • 在第3秒,position(2,2,2)
  • 在第6秒,position(0,0,0)
    这三个关键帧将使对象从场景的中心开始,在三秒内向右、向上和向前移动,然后反转方向并移动回中心。接下来,我们将使用这些关键帧创建矢量轨迹。
import { VectorKeyframeTrack } from "three";

const times = [0, 3, 6];
const values = [0, 0, 0, 2, 2, 2, 0, 0, 0];

const positionKF = new VectorKeyframeTrack(".position", times, values);

需要留意,由于每个时间点的position数据都是一个Vector3包含3个数值,而且这些数据是直接平铺开来的,因此values数组的长度是times数组的3倍,对应的映射关系为:

const times = [0, 3, 6];
const values = [
  0,
  0,
  0, // (x, y, z) at t = 0
  2,
  2,
  2, // (x, y, z) at t = 3
  0,
  0,
  0, // (x, y, z) at t = 6
];

3 动画剪辑 AnimationClip

如下图(动态效果可点击这里查看)中跳舞的模型动作非常复杂:双脚旋转,膝盖弯曲,手臂疯狂摆动,头部随着节拍点头。每个单独的动作都存储在一个单独的关键帧轨道中,因此有一个轨道控制舞者左脚的旋转,另一个轨道控制他的右脚的旋转,第三个轨道控制他的脖子的旋转,等等。
three.js进阶之动画系统

事实上,这个舞蹈动画是由53个关键帧轨道制成的,其中52个是控制舞者膝盖、肘部和脚踝等单个关节的四元数轨道。然后,有一个.location轨迹,可以在地板上来回移动图形。

这53个关键帧轨道结合在一起创建出的最终动画,我们称之为动画剪辑。因此,动画剪辑是附加到单个对象的任意数量关键帧的集合,表示剪辑的类是AnimationClip。动画剪辑可以循环播放,所以,虽然这个舞者的动画只有18秒长,但当它到达终点时,它开始下一轮的循环,因此看起来舞者似乎可以一直跳下去。

下面是AnimationClip的构造函数:

AnimationClip( name : String, duration : Number, tracks : Array )

从构造函数中能够看出动画剪辑存储三个信息:剪辑的名称、剪辑的长度和组成剪辑的轨道数组。如果我们将长度设置为-1,则轨道数组将用于计算长度。我们创建一个包含前面的单个位置轨迹的剪辑:

import { AnimationClip, VectorKeyframeTrack } from "three";

const times = [0, 3, 6];
const values = [0, 0, 0, 2, 2, 2, 0, 0, 0];

const positionKF = new VectorKeyframeTrack(".position", times, values);

// 当前只有一个关键帧轨道
const tracks = [positionKF];

// 将length设置为-1可以自动从tracks中计算长度,在本例中为6秒
const length = -1;

const clip = new AnimationClip("slowmove", length, tracks);

和关键帧一样,AnimationClip不会被附着到任何特定的对象上,那么应该如何将动画绑定到模型身上并且控制其进行播放呢?

4 动画混合器 AnimationMixer

为了让物体(如Mesh)接入动画系统并且能够动起来,我们需要将其和动画混合器AnimationMixer建立联系。场景中的每个动画对象都需要使用一个单独的混合器。混合器负责使模型按照动画剪辑的设定进行状态调整,如移动舞者的脚、手臂和臀部,或者是移动飞鸟的翅膀。

import { Mesh, AnimationMixer } from 'three';

// 创建一个静态的Mesh
const mesh = new Mesh();

// 通过将其连接到混合器,将其变为动画网格
const mixer = new AnimationMixer(mesh);

5 动画动作 AnimationAction

AnimationAction负责将动画对象连接到动画剪辑AnimationClip,同时也负责控制动画的暂停、播放、重置等操作。需要注意的是,我们不会直接创建action,而是借助AnimationMixer.clipAction()函数创建,这样能够有更好的性能,因为mixer会对action进行缓存。

看下面的例子:

import { AnimationClip, AnimationMixer } from "three";

const positionKF = new VectorKeyframeTrack(
  ".position",
  [0, 3, 6],
  [0, 0, 0, 2, 2, 2, 0, 0, 0]
);

const opacityKF = new NumberKeyframeTrack(
  ".material.opacity",
  [0, 1, 2, 3, 4, 5, 6],
  [0, 1, 0, 1, 0, 1, 0]
);

const moveBlinkClip = new AnimationClip("move-n-blink", -1, [
  positionKF,
  opacityKF,
]);

const mesh = new Mesh();

const mixer = new AnimationMixer(mesh);
const action = mixer.clipAction(moveBlinkClip);

5.1 多动作控制

假设我们有一个人的模型,并且这个模型可以走路、跑步和跳,每个动画都将在一个单独的剪辑中出现,每个剪辑必须连接到一个动作。因此,就像混合器和模型之间存在一对一的关系一样,动作和动画剪辑之间也存在一对一的关系:

const mixer = new AnimationMixer(humanModel);

const walkAction = mixer.clipAction(walkClip);
const runnAction = mixer.clipAction(runClip);
const jumpAction = mixer.clipAction(jumpClip);

下一步是选择要执行这些操作中的哪一个。你怎么做将取决于你正在建造什么样的场景。例如,如果是游戏,您将将这些操作连接到用户控件,这样当按下相应的按钮时,角色将行走、运行或跳跃。

参考资料

The three.js Animation System文章来源地址https://www.toymoban.com/news/detail-432439.html

到了这里,关于three.js进阶之动画系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • three.js 使用 tweenjs绘制相机运动动画

    效果: 代码:  

    2024年01月18日
    浏览(53)
  • Three.js之相机、渲染器、光源、动画、性能监测

    第一个3D案例—透视投影相机 第一个3D案例—渲染器 … Canvas画布布局和全屏 透视投影相机PerspectiveCamera WebGL渲染器WebGLRenderer 辅助观察坐标系AxesHelper 漫反射网格材质MeshLambertMaterial 点光源PointLight 点光源辅助观察PointLightHelper 环境光AmbientLight 平行光DirectionalLight 平行光辅助观

    2024年02月13日
    浏览(44)
  • 从three.js旋转动画,我了解了requestAnimationFrame

    前言  📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步!  🍅  个人主页: 南木元元 目录 three.js旋转动画 动画前置知识 屏幕刷新率与浏览器重绘次数 动画是如何形成的 实现动画的方式有哪些 什么是requestAnimationFrame setTimeoutsetInterval 结

    2024年02月03日
    浏览(42)
  • three.js 缓动算法.easing(渐入相机动画)

    效果:淡入,靠近物体 代码:

    2024年01月19日
    浏览(48)
  • vue3结合three.js实现3D带有交互的动画

    three.js引入 安装轨道控件插件: 安装渲染器插件: vue文件中引用: 在页面中创建场景 创建一个透视相机 初始化渲染器 初始动画混合器 参数:rootObject 混合器播放的动画所属的对象。就是包含动画模型的场景对象。 常用参数和属性: .time 全局的混合器时间。 .clipAction(Ani

    2024年02月04日
    浏览(55)
  • WEB 3D技术 three.js 3D贺卡(3) 点光源灯光动画效果

    经过 上文 WEB 3D技术 three.js 3D贺卡(2) 加入天空与水面效果 我们将水面 和 天空的效果搭建了一下 那么 我们将四周 点光源的效果做一下 首先 我们将 renderer.toneMappingExposure 的值 改为 0.1 让效果看着明显一点 这样 整个界面就会暗下来 然后 我们在任意位置 加入代码 创建一个点

    2024年01月19日
    浏览(58)
  • 【js&three.js】全景vr看房进阶版

    Scene场景 指包含了所有要渲染和呈现的三维对象、光源、相机以及其他相关元素的环境;场景可以被渲染引擎或图形库加载和处理,以生成最终的图像或动画 常见属性: 常见方法: Geometry  几何体 指的是表示和描述三维对象形状的数据, 描述了对象的形状 常用的Geometry(几

    2024年02月10日
    浏览(48)
  • Three.js指定路径漫游(站走切换、路径动画、展示路线、开始、暂停、继续、退出、镜头跟随)

    (由点生成曲线,npc沿曲线移动,相机跟随方式1)参考大佬: https://blog.csdn.net/weixin_40856652/article/details/125302355 (相机跟随方式2)参考大佬: https://lequ7.com/guan-yu-threejsthreejs-xi-lie-xie-yi-ge-di-yi-san-ren-cheng-shi-jiao-xiao-you-xi.html (模型站走切换)参考大佬: https://zhuanlan.zhihu.com/p

    2024年02月05日
    浏览(39)
  • Three.js 进阶之旅:页面平滑滚动-王国之泪 ?

    声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。 浏览网页时,常被一些基于鼠标滚轮控制的页面动画所惊艳到,比如greensock 官网这些 showcase 案例页面就非常优秀,它们大多数都是使用 Tw

    2024年02月02日
    浏览(51)
  • vue2+three.js实现宇宙(进阶版)

    2023.9.12今天我学习了vue2+three.js实现一个好看的动态效果: 首先是安装: npm install three 相关代码如下:

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包