返回介绍

Three.js变形动画geometry.morphTargets

发布于 2021-07-10 20:14:16 字数 3015 浏览 1270 评论 0 收藏 0

关于变形动画,你可以理解为多组顶点数据,从一个状态变化到另一个状态,比如人的面部表情,哭的表情用一系列的顶点表示,笑的表情用一系列的顶点表示,从哭的表情过渡到笑的表情,就是表情对应的两组顶点之间的过渡,几何体的顶点的位置坐标发生变化,从一个状态过渡到另一个状态自然就产生了变形动画。

一般项目开发,变形动画和骨骼动画一样,由3D美术编辑好变形动画的模型数据,然后程序员通过Threejs相关的API解析渲染变形动画。

为了大家更好的理解变形动画,下面通过Threejs程序编写一个变形动画,然后再解析渲染出来。

下面的变形动画非常简单,给一个长方体网格模型对象Mesh设置两组顶点数据,然后从一组像另一组变化。

创建变形动画的顶点数据

先获取两个变形目标box1box2的顶点数据,然后通过几何体Geometry的变形目标属性.morphTargets设置好变形动画。

/**
 * 创建网格模型,并给模型的几何体设置多个变形目标
 */
// 创建一个几何体具有8个顶点
var geometry = new THREE.BoxGeometry(50, 50, 50); //立方体几何对象
console.log(geometry.vertices);
// 为geometry提供变形目标的数据
var box1 = new THREE.BoxGeometry(100, 5, 100); //为变形目标1提供数据
var box2 = new THREE.BoxGeometry(5, 200, 5); //为变形目标2提供数据
// 设置变形目标的数据
geometry.morphTargets[0] = {name: 'target1',vertices: box1.vertices};
geometry.morphTargets[1] = {name: 'target2',vertices: box2.vertices};
var material = new THREE.MeshLambertMaterial({
  morphTargets: true, //允许变形
  color: 0x0000ff
}); //材质对象
var mesh = new THREE.Mesh(geometry, material); //网格模型对象
scene.add(mesh); //网格模型添加到场景中

网格模型.morphTargetInfluences属性

通过上面代码把变形动画顶点数据设置好以后,如果想生成变形动画,首先要了解网格模型Mesh的.morphTargetInfluences属性。

你可以在上面代码中分别或同时插入下面代码进行测试,查看长方体网格模型mesh的外形变化。

//启用变形目标并设置变形目标影响权重,范围一般0~1
// 设置第一组顶点对几何体形状影响的变形系数
mesh.morphTargetInfluences[0] = 0.5;
// 设置第二组顶点对几何体形状影响的变形系数
mesh.morphTargetInfluences[1] = 1;

生成变形动画

通过上面的测试,你可以发现改变morphTargetInfluences属性的值可以改变网格模型的形状,那么回忆一下第11章讲解的帧动画,你只需要控制.morphTargetInfluences的属性值生成关键帧数据,就可以实现关键帧动画,然后播放关键帧动画即可实现变形动画。

第一步先利用关键帧KeyframeTrack、剪辑AnimationClip两个类创建好帧动画。

/**
 * 设置关键帧数据
 */
// 设置变形目标1对应权重随着时间的变化
var Track1 = new THREE.KeyframeTrack('.morphTargetInfluences[0]', [0,10,20], [0,1, 0]);
// 设置变形目标2对应权重随着时间的变化
var Track2 = new THREE.KeyframeTrack('.morphTargetInfluences[1]', [20,30, 40], [0, 1,0]);
// 创建一个剪辑clip对象,命名"default",持续时间40
var clip = new THREE.AnimationClip("default", 40, [Track1,Track2]);

第二步是使用混合器AnimationMixer播放设置好的关键帧动画。

/**
 * 播放编辑好的关键帧数据
 */
var mixer = new THREE.AnimationMixer(mesh); //创建混合器
var AnimationAction = mixer.clipAction(clip); //返回动画操作对象
AnimationAction.timeScale = 5; //默认1,可以调节播放速度
// AnimationAction.loop = THREE.LoopOnce; //不循环播放
// AnimationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
AnimationAction.play(); //开始播放
...
...
// 创建一个时钟对象Clock
var clock = new THREE.Clock();
// 渲染函数
function render() {
  renderer.render(scene, camera); //执行渲染操作
  requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
  //clock.getDelta()方法获得两帧的时间间隔
  // 更新混合器相关的时间
  mixer.update(clock.getDelta());
}
render();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文