Three.js 形变动画(Morph Target Animation):让 3D 模型跳起变形之舞

在 Three.js 的 3D 数字王国里,每一个模型都是一位独特的居民。它们或静默伫立,或轻盈旋转,而今天,我们要赋予这些模型一种神奇的能力 ------ 形变动画(Morph Target Animation),让它们能够像拥有魔法一般,在瞬间变换形态,上演一场场精彩绝伦的变形秀。

一、Three.js 与形变动画的初次邂逅

Three.js 就像是这个 3D 王国的魔法工坊,为我们提供了各种神奇的工具,帮助我们创造出令人惊叹的 3D 世界。而形变动画,就是其中一种充满魅力的魔法技艺。

在现实世界中,物体的变形可能需要借助复杂的物理手段,但在 Three.js 的虚拟世界里,我们可以通过编程,轻松实现模型从一种形态到另一种形态的转变。这种转变的核心,在于模型的顶点数据。想象一下,模型就像是由无数个微小的点组成的,通过改变这些点的位置,我们就能改变模型的整体形状,这就是形变动画的底层奥秘。

二、搭建魔法舞台:准备工作

在开始这场变形魔法表演之前,我们需要先搭建好舞台,准备好所需的道具。

1. 引入 Three.js 库

首先,我们要把 Three.js 这个强大的魔法工具引入到我们的项目中。就像魔法师需要先准备好魔法杖一样,我们在 HTML 文件中通过

xml 复制代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

这一步就像是打开了通往魔法世界的大门,让我们能够使用 Three.js 提供的各种魔法能力。

2. 创建场景、相机和渲染器

接下来,我们要创建 3D 世界的基本要素:场景(Scene)、相机(Camera)和渲染器(Renderer)。场景是模型们表演的舞台,相机决定了我们从哪个角度观看这场表演,而渲染器则负责将这个 3D 世界呈现在我们的屏幕上。

用 JavaScript 代码创建它们就像在召唤三位得力助手:

javascript 复制代码
// 创建场景
const scene = new THREE.Scene();
// 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

有了这三位得力助手,我们的 3D 世界就初具雏形了。

三、创造变形主角:加载或创建带形变目标的模型

现在,我们需要一位能够施展变形魔法的主角 ------ 一个带有形变目标的 3D 模型。我们可以通过两种方式获得这样的模型:从外部文件加载,或者在代码中直接创建。

1. 从外部文件加载模型

很多时候,我们会使用专业的 3D 建模软件(如 Blender)创建带有形变目标的模型,然后将其导出为 Three.js 可以识别的格式,比如.obj或.gltf格式。以加载.gltf格式模型为例,我们需要借助GLTFLoader这个加载魔法道具:

javascript 复制代码
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load(
    // 模型文件路径
    'yourModel.gltf',
    // 加载成功回调函数
    function (gltf) {
        scene.add(gltf.scene);
    },
    // 加载进度回调函数
    function (xhr) {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
    },
    // 加载错误回调函数
    function (error) {
        console.log('An error happened');
    }
);

当模型成功加载到场景中后,我们就拥有了一个潜在的变形大师。

2. 在代码中创建简单模型

如果我们想要快速创建一个简单的带有形变目标的模型,也可以在代码中实现。以创建一个正方体并让它变形为例:

php 复制代码
// 创建基础几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建形变目标几何体
const morphGeometry1 = new THREE.BoxGeometry(1.2, 1.2, 1.2);
const morphGeometry2 = new THREE.BoxGeometry(0.8, 0.8, 0.8);
// 将形变目标添加到基础几何体
geometry.morphTargets.push(
    { name: 'big', vertices: morphGeometry1.vertices },
    { name:'small', vertices: morphGeometry2.vertices }
);
// 创建材质
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00, morphTargets: true });
// 创建网格模型
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

通过这种方式,我们亲手打造了一个可以变形的正方体模型。

四、施放变形魔法:实现形变动画

现在,主角已经就位,是时候为它注入变形的魔力了。在 Three.js 中,我们通过控制模型的morphTargetInfluences属性来实现形变动画。这个属性就像是一个魔法开关,控制着每个形变目标对模型最终形态的影响程度。

假设我们有一个加载好的模型,并且它有两个形变目标,我们可以通过以下代码让它在两种形态之间平滑过渡:

scss 复制代码
function animate() {
    requestAnimationFrame(animate);
    // 控制第一个形变目标的影响程度,从0到1平滑变化
    mesh.morphTargetInfluences[0] = Math.sin(Date.now() * 0.001) * 0.5 + 0.5;
    // 控制第二个形变目标的影响程度,与第一个形变目标的影响程度互补
    mesh.morphTargetInfluences[1] = 1 - mesh.morphTargetInfluences[0];
    renderer.render(scene, camera);
}
animate();

在这段代码中,我们使用requestAnimationFrame函数创建了一个动画循环。在每次循环中,我们通过Math.sin函数让第一个形变目标的影响程度在 0 到 1 之间平滑变化,而第二个形变目标的影响程度则与之互补。这样,模型就会在两种形态之间优雅地变换,仿佛在跳一支变形之舞。

五、进阶魔法:更复杂的形变动画

掌握了基本的形变动画技巧后,我们还可以尝试一些更复杂、更炫酷的变形效果。

1. 多阶段变形

**

我们可以为模型设置多个形变目标,并按照一定的顺序和节奏让它们依次生效。比如,让一个模型先从圆形变成方形,再从方形变成三角形:

ini 复制代码
function multiStageAnimate() {
    requestAnimationFrame(multiStageAnimate);
    const time = Date.now() * 0.001;
    // 控制第一个形变目标,在0到1秒内从0到1变化
    if (time < 1) {
        mesh.morphTargetInfluences[0] = time;
        mesh.morphTargetInfluences[1] = 0;
        mesh.morphTargetInfluences[2] = 0;
    }
    // 控制第二个形变目标,在1到2秒内从0到1变化
    else if (time < 2) {
        mesh.morphTargetInfluences[0] = 2 - time;
        mesh.morphTargetInfluences[1] = time - 1;
        mesh.morphTargetInfluences[2] = 0;
    }
    // 控制第三个形变目标,在2到3秒内从0到1变化
    else {
        mesh.morphTargetInfluences[0] = 0;
        mesh.morphTargetInfluences[1] = 3 - time;
        mesh.morphTargetInfluences[2] = time - 2;
    }
    renderer.render(scene, camera);
}
multiStageAnimate();

通过这种方式,我们可以创造出更加丰富多样的变形效果。

2. 与其他动画结合

形变动画还可以与其他类型的动画(如位置动画、旋转动画)相结合,创造出更加复杂和精彩的动画场景。例如,让一个变形的模型同时在场景中移动和旋转:

scss 复制代码
function combinedAnimate() {
    requestAnimationFrame(combinedAnimate);
    // 控制形变动画
    mesh.morphTargetInfluences[0] = Math.sin(Date.now() * 0.001) * 0.5 + 0.5;
    mesh.morphTargetInfluences[1] = 1 - mesh.morphTargetInfluences[0];
    // 控制位置动画,让模型在x轴和z轴上做周期性运动
    mesh.position.x = Math.sin(Date.now() * 0.001) * 5;
    mesh.position.z = Math.cos(Date.now() * 0.001) * 5;
    // 控制旋转动画,让模型绕y轴旋转
    mesh.rotation.y += 0.01;
    renderer.render(scene, camera);
}
combinedAnimate();

这样,模型就会在变形的同时,在场景中展现出更加灵动的姿态。

六、魔法小贴士:优化与注意事项

在施展形变动画的魔法时,还有一些小贴士可以帮助我们让魔法效果更加完美:

1. 性能优化

过多的形变目标和复杂的顶点变化可能会对性能产生影响。尽量减少不必要的形变目标,合理控制顶点的变化范围。同时,可以使用 LOD(Level of Detail,细节层次)技术,在模型远离相机时降低形变的精度,提高性能。

2. 模型兼容性

确保你的模型在导出和导入过程中,形变目标的数据没有丢失或损坏。不同的 3D 建模软件和文件格式在处理形变目标时可能会有一些差异,需要仔细检查和调试。

3. 动画节奏把控

合理设置动画的速度和节奏,让变形效果看起来自然流畅。可以通过调整时间参数和影响程度的变化曲线,来达到理想的动画效果。

现在,你已经掌握了 Three.js 形变动画的魔法秘籍,可以在 3D 数字王国中尽情创造属于自己的变形奇迹了!让模型们跳出独特的变形之舞,为你的 3D 世界增添无限的魅力和惊喜吧!

以上文章系统讲解了 Three.js 形变动画。若你觉得某些部分需要补充,或是想尝试不同风格的教学,欢迎随时告诉我。

相关推荐
中微子9 分钟前
React状态管理最佳实践
前端
烛阴19 分钟前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子25 分钟前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...34 分钟前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts
初遇你时动了情36 分钟前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图
dssxyz40 分钟前
uniapp打包微信小程序主包过大问题_uniapp 微信小程序时主包太大和vendor.js过大
javascript·微信小程序·uni-app
天天扭码1 小时前
《很全面的前端面试题》——HTML篇
前端·面试·html
xw51 小时前
我犯了错,我于是为我的uni-app项目引入环境标志
前端·uni-app
!win !1 小时前
被老板怼后,我为uni-app项目引入环境标志
前端·小程序·uni-app
Burt1 小时前
tsdown vs tsup, 豆包回答一坨屎,还是google AI厉害
前端