joken-前端工程师

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
  404 随笔 :: 39 文章 :: 8 评论 :: 20万 阅读

动画混合器介绍,用于加载模型动画,动画片段的控制

在 Three.js 中,THREE.AnimationMixer 是用于管理和播放模型动画的核心类。它允许你加载、控制和混合多个动画剪辑(Animation Clip),从而实现复杂的动画效果。以下是关于 AnimationMixer 的详细介绍,包括其功能、用法和相关 API。


结论

THREE.AnimationMixer 是一个动画管理器,用于播放和控制模型中的动画剪辑,支持单个或多个动画的混合与切换。


详细展开

1. 核心概念

  • Animation Mixer:动画混合器,负责管理模型的所有动画。
  • Animation Clip:动画片段,表示一段完整的动画数据(例如“走路”、“跑步”或“抓脸”)。
  • Animation Action:动画动作,是 AnimationMixer 播放动画的具体实例,可以通过它控制动画的播放状态、速度等。

2. 创建 Animation Mixer

每个 AnimationMixer 实例都绑定到一个特定的对象(通常是模型)。创建方法如下:

const mixer = new THREE.AnimationMixer(object);
  • object:绑定动画混合器的目标对象(通常是一个模型)。

3. 加载动画剪辑

通过 GLTFLoader 或其他加载器加载模型时,动画剪辑通常包含在模型文件中。以下是一个示例:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
    const model = gltf.scene;
    scene.add(model);

    // 获取动画剪辑数组
    const clips = gltf.animations;

    // 创建动画混合器
    const mixer = new THREE.AnimationMixer(model);

    // 获取第一个动画剪辑
    const clip = clips[0];

    // 创建动画动作并播放
    const action = mixer.clipAction(clip);
    action.play();
});

4. 播放动画

通过 clipAction 方法从动画剪辑创建一个动画动作,并调用 play() 方法开始播放。

// 创建动画动作
const action = mixer.clipAction(clip);

// 播放动画
action.play();

5. 控制动画

AnimationAction 提供了多种方法来控制动画的播放状态:

方法 描述
play() 开始播放动画。
stop() 停止播放动画。
reset() 重置动画的状态。
pause() 暂停动画。
crossFadeTo(targetAction, duration) 在当前动画和目标动画之间进行淡入淡出切换。
time 设置或获取动画的当前时间(以秒为单位)。
timeScale 设置动画的速度倍率(默认值为 1)。

6. 更新动画

动画混合器需要在每一帧中调用 update(delta) 方法,以确保动画正确播放。delta 表示自上次更新以来的时间间隔(以秒为单位)。

let clock = new THREE.Clock();

function animate() {
    requestAnimationFrame(animate);

    // 更新动画混合器
    if (mixer) mixer.update(clock.getDelta());

    renderer.render(scene, camera);
}
animate();

7. 混合多个动画

通过 THREE.AnimationMixer,你可以同时播放多个动画,并使用权重(weight)来控制它们的混合比例。

// 创建两个动画动作
const action1 = mixer.clipAction(clips[0]); // 动画1
const action2 = mixer.clipAction(clips[1]); // 动画2

// 设置权重
action1.setEffectiveWeight(0.7); // 动画1占70%
action2.setEffectiveWeight(0.3); // 动画2占30%

// 播放动画
action1.play();
action2.play();

8. 淡入淡出切换动画

使用 crossFadeTo 方法可以在两个动画之间进行平滑过渡。

// 创建两个动画动作
const action1 = mixer.clipAction(clips[0]); // 动画1
const action2 = mixer.clipAction(clips[1]); // 动画2

// 播放动画1
action1.play();

// 在2秒内淡入动画2
action1.crossFadeTo(action2, 2);
action2.play();

9. 循环模式

可以通过设置 loop 属性来控制动画的循环模式:

描述
THREE.LoopOnce 动画只播放一次。
THREE.LoopRepeat 动画无限循环(默认值)。
THREE.LoopPingPong 动画来回播放(即正向播放完后反向播放)。
action.loop = THREE.LoopPingPong; // 设置为来回播放
action.clampWhenFinished = true; // 如果是 LoopOnce,动画结束时保持最后一帧

10. 监听动画事件

可以通过 addEventListener 监听动画的生命周期事件,例如 startedfinished 等。

action.addEventListener('finished', () => {
    console.log('动画播放完毕');
});

完整示例代码

以下是一个完整的动画混合器示例:

// 创建场景
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);

// 引入 GLTFLoader
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

// 创建 GLTFLoader 实例
const loader = new GLTFLoader();

// 加载模型
loader.load('cat.glb', (gltf) => {
    const model = gltf.scene;
    scene.add(model);

    // 创建动画混合器
    const mixer = new THREE.AnimationMixer(model);

    // 获取动画剪辑
    const clips = gltf.animations;

    // 创建动画动作
    const action = mixer.clipAction(clips[0]);

    // 播放动画
    action.play();
}, undefined, (error) => {
    console.error('加载模型时出错:', error);
});

// 创建时钟
let clock = new THREE.Clock();

// 渲染循环
function animate() {
    requestAnimationFrame(animate);

    // 更新动画混合器
    if (mixer) mixer.update(clock.getDelta());

    renderer.render(scene, camera);
}
animate();

总结

THREE.AnimationMixer 是 Three.js 中管理动画的核心工具,支持单个或多个动画的播放、控制和混合。通过结合 AnimationActionAnimationClip,可以实现复杂的动画效果,例如淡入淡出切换、权重混合和循环模式控制等。

实现一只猫抓脸动作

在 Three.js 中实现一只猫抓脸的动画效果,可以通过以下步骤完成:加载一个 3D 模型(例如猫模型),并使用关键帧动画或骨骼动画来实现“抓脸”动作。以下是详细的实现方法和步骤。


结论

通过加载带有动画的 3D 模型(如 GLTF 格式),并使用 THREE.AnimationMixer 播放动画,可以实现一只猫抓脸的效果。


详细展开

1. 核心原理

  • 使用 GLTF 格式的 3D 模型文件,其中包含猫的几何体和动画数据。
  • 使用 THREE.GLTFLoader 加载模型。
  • 使用 THREE.AnimationMixer 播放模型中的动画。

2. 实现步骤

(1) 创建场景、相机和渲染器
// 创建场景
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);
(2) 加载猫模型

使用 THREE.GLTFLoader 加载带有动画的猫模型。

// 引入 GLTFLoader
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

// 创建 GLTFLoader 实例
const loader = new GLTFLoader();

// 加载猫模型
loader.load('cat.glb', (gltf) => { // 替换为你的猫模型路径
    const cat = gltf.scene; // 获取模型对象
    scene.add(cat); // 将模型添加到场景

    // 初始化动画混合器
    const mixer = new THREE.AnimationMixer(cat);

    // 获取模型中的动画剪辑
    const action = mixer.clipAction(gltf.animations[0]); // 假设第一个动画是“抓脸”

    // 播放动画
    action.play();
}, undefined, (error) => {
    console.error('加载模型时出错:', error);
});
(3) 添加相机控制器

使用 OrbitControls 实现用户视角的自由旋转。

// 引入 OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);

// 禁用缩放和平移,仅允许旋转
controls.enableZoom = false;
controls.enablePan = false;

// 设置初始视角
camera.position.set(2, 2, 2); // 相机位置
camera.lookAt(0, 0, 0); // 相机看向模型中心
(4) 渲染循环

创建一个渲染循环,并更新动画。

let clock = new THREE.Clock(); // 创建时钟用于动画更新

function animate() {
    requestAnimationFrame(animate);

    // 更新动画混合器
    if (mixer) mixer.update(clock.getDelta());

    renderer.render(scene, camera);
}
animate();
(5) 响应窗口大小变化

确保当窗口大小改变时,相机和渲染器能够正确调整。

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

完整示例代码

以下是一个完整的代码示例:

// 创建场景
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);

// 引入 GLTFLoader
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

// 创建 GLTFLoader 实例
const loader = new GLTFLoader();

// 加载猫模型
loader.load('cat.glb', (gltf) => { // 替换为你的猫模型路径
    const cat = gltf.scene; // 获取模型对象
    scene.add(cat); // 将模型添加到场景

    // 初始化动画混合器
    const mixer = new THREE.AnimationMixer(cat);

    // 获取模型中的动画剪辑
    const action = mixer.clipAction(gltf.animations[0]); // 假设第一个动画是“抓脸”

    // 播放动画
    action.play();
}, undefined, (error) => {
    console.error('加载模型时出错:', error);
});

// 引入 OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = false; // 禁用缩放
controls.enablePan = false;  // 禁用平移

// 设置初始视角
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);

// 创建时钟用于动画更新
let clock = new THREE.Clock();

// 渲染循环
function animate() {
    requestAnimationFrame(animate);

    // 更新动画混合器
    if (mixer) mixer.update(clock.getDelta());

    renderer.render(scene, camera);
}
animate();

// 响应窗口大小变化
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

相关延展

1. 自定义动画

如果模型没有预定义的“抓脸”动画,可以通过以下方式实现:

  • 使用 Blender 或其他建模软件为模型创建“抓脸”动画。
  • 导出带有动画的 GLTF 文件。

2. 控制动画播放

可以使用 THREE.AnimationAction 的方法控制动画播放:

  • action.play():播放动画。
  • action.stop():停止动画。
  • action.timeScale = value:设置动画速度。
  • action.crossFadeTo(otherAction):淡入淡出切换动画。

3. 添加背景

可以为场景添加背景(如全景图)以增强视觉效果。

// 加载全景图作为背景
const textureLoader = new THREE.TextureLoader();
const backgroundTexture = textureLoader.load('background.jpg'); // 替换为你的背景图路径
scene.background = backgroundTexture;

4. 优化性能

  • 使用高效的纹理格式(如 JPEG 或 WebP)减少加载时间。
  • 如果模型较大,可以使用简化版模型或分层级加载。

总结

通过加载带有动画的 3D 模型,并使用 THREE.AnimationMixer 播放动画,可以轻松实现一只猫抓脸的效果。Three.js 提供了强大的工具和灵活性,能够满足各种复杂需求,例如自定义动画和交互控制等。

posted on   joken1310  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示