在 Three.js 中,骨骼动画为模型赋予了生动的动态效果,使场景更加鲜活。本文假定读者已经具备 Three.js 的基础知识,将直接深入骨骼动画的核心内容。
骨骼动画基础概念回顾
骨骼动画基于骨骼系统,模型的顶点通过蒙皮与骨骼相连。当骨骼移动、旋转或缩放时,与之关联的顶点也会相应地产生变形,从而实现逼真的动画效果。在 Three.js 中,骨骼动画主要涉及到Skeleton(骨骼结构)和SkinnedMesh(蒙皮网格)这两个关键概念。
加载带骨骼动画的模型
在开始使用骨骼动画前,我们需要加载一个带有骨骼动画信息的模型。通常,我们会使用GLTFLoader来加载常见的.gltf或.glb格式模型,这些格式能够很好地保存骨骼动画数据。
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load('yourModel.glb', (gltf) => {
const skinnedMesh = gltf.scene.getObjectByName('SkinnedMeshName');
// 这里SkinnedMeshName是模型中包含骨骼动画的网格名称,需根据实际模型调整
scene.add(skinnedMesh);
const animationMixer = new THREE.AnimationMixer(skinnedMesh);
const clip = gltf.animations[0];
const action = animationMixer.clipAction(clip);
action.play();
}, undefined, (error) => {
console.error('Error loading model:', error);
});
在这段代码中,我们首先创建了一个GLTFLoader实例来加载模型。加载成功后,我们从场景中获取到带有骨骼动画的SkinnedMesh。接着,创建一个AnimationMixer,它负责管理模型的动画状态。然后获取模型自带的动画剪辑clip,并通过clipAction方法创建一个动画动作action,最后调用action.play()来播放动画。
控制动画播放
- 播放、暂停与停止
-
- 播放动画:如上述代码中action.play()即可启动动画播放。
-
- 暂停动画:使用action.paused = true;来暂停当前动画。
-
- 停止动画:虽然 Three.js 没有直接的停止方法,但可以通过将动画时间重置到开始位置并暂停来实现类似效果,如action.time = 0; action.paused = true;。
- 动画混合与过渡
在复杂的动画场景中,我们可能需要在不同的动画之间进行混合过渡,以实现更自然的效果。例如,从走路动画平滑过渡到跑步动画。
const walkClip = gltf.animations[0];
const runClip = gltf.animations[1];
const walkAction = animationMixer.clipAction(walkClip);
const runAction = animationMixer.clipAction(runClip);
// 从走路动画过渡到跑步动画,过渡时间为0.5秒
walkAction.crossFadeTo(runAction, 0.5);
这里,我们获取了两个不同的动画剪辑(走路和跑步),分别创建对应的动画动作。然后使用crossFadeTo方法实现从走路动画到跑步动画的平滑过渡,过渡时间设置为 0.5 秒。
自定义骨骼动画
除了加载现成的模型动画,我们还可以自定义骨骼动画。这需要我们手动创建骨骼结构和蒙皮网格,并为骨骼添加动画关键帧。
- 创建骨骼结构
const bone1 = new THREE.Bone();
const bone2 = new THREE.Bone();
bone1.add(bone2);
const skeleton = new THREE.Skeleton([bone1, bone2], []);
在这段代码中,我们创建了两个骨骼bone1和bone2,并将bone2作为bone1的子骨骼。然后通过这两个骨骼创建了一个Skeleton实例。
- 创建蒙皮网格
const geometry = new THREE.BufferGeometry();
// 假设已经设置好顶点数据等几何信息
const material = new THREE.MeshStandardMaterial({ color: 0xffffff });
const skinnedMesh = new THREE.SkinnedMesh(geometry, material);
skinnedMesh.bind(skeleton);
这里,我们创建了一个BufferGeometry作为网格的几何形状,并设置了材质。然后创建SkinnedMesh,并通过bind方法将其与之前创建的骨骼结构绑定。
- 添加动画关键帧
const keyframeTracks = [];
const times = [0, 1];
const values1 = [0, Math.PI / 2];
const values2 = [0, Math.PI / 4];
const rotationTrack1 = new THREE.NumberKeyframeTrack(
'.bones[0].rotation.y',
times,
values1
);
const rotationTrack2 = new THREE.NumberKeyframeTrack(
'.bones[1].rotation.y',
times,
values2
);
keyframeTracks.push(rotationTrack1, rotationTrack2);
const clip = new THREE.AnimationClip('customClip', 1, keyframeTracks);
const animationMixer = new THREE.AnimationMixer(skinnedMesh);
const action = animationMixer.clipAction(clip);
action.play();
在这个示例中,我们定义了两个骨骼在不同时间点的旋转关键帧。通过NumberKeyframeTrack创建关键帧轨道,分别描述了bone1和bone2在时间为 0 和 1 时绕 Y 轴的旋转角度。然后将这些关键帧轨道组合成一个动画剪辑clip,并通过AnimationMixer和clipAction来播放自定义的骨骼动画。
通过以上对 Three.js 中骨骼动画的深入介绍,包括加载模型动画、控制动画播放以及自定义骨骼动画,相信你已经对如何在项目中运用骨骼动画有了更清晰的认识。在实际应用中,不断探索和尝试,结合具体需求,你将能够创造出更加精彩的动画效果。