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 形变动画。若你觉得某些部分需要补充,或是想尝试不同风格的教学,欢迎随时告诉我。

相关推荐
哆啦A梦158830 分钟前
商城后台管理系统 03 登录布局
javascript·vue.js·elementui
曼巴UE51 小时前
UE FString, FName ,FText 三者转换,再次学习,官方文档理解
服务器·前端·javascript
selt7911 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
行走的陀螺仪2 小时前
高级前端 Input 公共组件设计方案(Vue3 + TypeScript)
前端·javascript·typescript·vue·组件设计方案
一颗不甘坠落的流星2 小时前
【Antd】基于 Upload 组件,导入Json文件并转换为Json数据
前端·javascript·json
LYFlied2 小时前
Vue2 与 Vue3 虚拟DOM更新原理深度解析
前端·javascript·vue.js·虚拟dom
Lucky_Turtle2 小时前
【Node】npm install报错npm error Cannot read properties of null (reading ‘matches‘)
前端·npm·node.js
小飞侠在吗3 小时前
vue shallowRef 与 shallowReacitive
前端·javascript·vue.js
惜分飞3 小时前
sql server 事务日志备份异常恢复案例---惜分飞
前端·数据库·php