ThreeJS 变形动画 geometry.morphTargets 详解

一、创建变形动画的目标数据

首先我们要理解什么变形动画,假设我们有一个50, 50, 50的立方体,将其形状变为5, 200, 5长方体的这个过程我们就叫变形动画。

那在ThreeJS中我们如果创建一个变形动画并且可以通过AnimationMixer控制其播放呢?接下来我们就一步一步实现这个过程。

我们首先创建一个正方体

js 复制代码
var geometry = new THREE.BoxGeometry(50, 50, 50); //立方体几何对象

再创建一个长方体,这个就是我们要变形的目标数据

js 复制代码
var box = new THREE.BoxGeometry(5, 200, 5); //为变形目标提供数据

二、设置变形动画的顶点数据

要想让我们正常显示的正方体可以变形成长方体,就需要通过geometry.morphAttributes.position属性去设置变形的数据(geometry.morphAttributes.position是一个数组,这样我们就可以设置多组变形数据生成多个变形动画)

js 复制代码
var geometry = new THREE.BoxGeometry(50, 50, 50); //立方体几何对象
var box = new THREE.BoxGeometry(5, 200, 5); //为变形目标提供数据
geometry.morphAttributes.position = [];
// 将长方体的位置数据赋值给geometry,这样geometry的各个顶点就能从原本的position变形到目标的position
geometry.morphAttributes.position[0] = box.attributes.position;

通过上步操作之后我们就可以通过权重去设置正方体的变形了,接下来是整个可变性的正方体完整代码

js 复制代码
var geometry = new THREE.BoxGeometry(50, 50, 50); //立方体几何对象
var box = new THREE.BoxGeometry(5, 200, 5); //为变形目标提供数据
geometry.morphAttributes.position = [];
// 将长方体的位置数据赋值给geometry,这样geometry的各个顶点就能从原本的position变形到目标的position
geometry.morphAttributes.position[0] = box.attributes.position;
var material = new THREE.MeshLambertMaterial({
  color: 0x0000ff,
  flatShading: true,
}); //材质对象
var mesh = new THREE.Mesh(geometry, material); //网格模型对象
scene.add(mesh); //网格模型添加到场景中

我们可以通过设置mesh.morphTargetInfluences0权重值去改变正方体的形状 mesh.morphTargetInfluences是一个数组,每个下标的权重值对应的geometry.morphAttributes.position中的变形动画的权重,权重值的范围一般是0~1,0代表的是未变形的状态,1代表的是正方体已经变形到目标形状(当然也可以大于1,只是变形超出的目标形状)

下面是权重设置为1的效果(你们自己试的时候可以尝试下其他值看看效果)

js 复制代码
mesh.morphTargetInfluences[0] = 1;

三、生成变形动画

通过KeyframeTrack去创建关键帧动画,通过控制每一帧的权重值来实现动画轨道效果。

js 复制代码
var track = new THREE.KeyframeTrack(".morphTargetInfluences[0]", [0, 10, 20], [0, 1, 0]);

new THREE.KeyframeTrack的三个参数分别代表的是:

  • .morphTargetInfluences[0]:需要用关键帧控制的属性;
  • [0, 10, 20]:时间轴,单位是秒
  • [0, 1, 0]:表示每个时间点被控制的属性的值

0秒的时候,权重为0,10秒的时候权重为1,20秒的时候权重为0

创建剪辑对象

js 复制代码
// 创建一个剪辑clip对象,命名"default",持续时间20秒
var clip = new THREE.AnimationClip("default", 20, [track]);

使用混合器AnimationMixer播放设置好的关键帧动画

js 复制代码
var mixer = new THREE.AnimationMixer(mesh); //创建混合器
var AnimationAction = mixer.clipAction(clip); //返回动画操作对象
AnimationAction.timeScale = 5; //默认1,可以调节播放速度
// AnimationAction.loop = THREE.LoopOnce; //不循环播放
// AnimationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
AnimationAction.play(); //开始播放

当然,对于动画的渲染少不了

js 复制代码
// 创建一个时钟对象Clock 
var clock = new THREE.Clock(); 
// 渲染函数 
function render() { 
  renderer.render(scene, camera); //执行渲染操作 
  requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧 
  
  //clock.getDelta()方法获得两帧的时间间隔 
  // 更新混合器相关的时间 
  mixer.update(clock.getDelta()); 
} 
render();

最终效果:

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端