You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从GLTF文件中提取动画并生成独立动画文件?

从GLTF/GLB中提取动画生成独立文件的方案

推荐工具库

有两个成熟的库可以帮你高效完成动画提取:

  • glTF Transform:专门针对glTF格式的编辑工具,API简洁直观,支持Node.js和浏览器环境,适合批量处理或精细编辑glTF结构。
  • Three.js:通用3D库,自带GLTFLoader可以解析glTF,提取动画后再构建新的glTF文件,适合已经在使用Three.js的项目。

具体实现示例(glTF Transform)

以你的现有代码为基础,用glTF Transform修改动画提取部分:

首先安装依赖:

npm install @gltf-transform/core @gltf-transform/functions

然后修改代码中的动画处理逻辑:

import { Document, NodeIO } from '@gltf-transform/core';
import { prune } from '@gltf-transform/functions';

// ... 你的现有代码 ...

// 创建仅包含动画的glb文件
const io = new NodeIO();
const document = await io.read(`temp/${assetData.file?.filename}`);

// 定位目标动画
const targetAnimation = document.getAnimation(animation.name);
if (!targetAnimation) {
    return reject(new Error(`Animation ${animation.name} not found`));
}

// 移除其他无关动画
document.listAnimations().forEach(anim => {
    if (anim !== targetAnimation) anim.dispose();
});

// 修剪掉动画未引用的冗余资源(网格、材质等)
await document.transform(prune({ keepMeshes: false, keepMaterials: false }));

// 导出为GLB文件
const glbBuffer = await io.writeBinary(document);
fsExtra.writeFileSync(`${animation.name}.glb`, glbBuffer);

// 更新文件元数据
const stats = fsExtra.statSync(`${animation.name}.glb`);
assetData.file = {
    filename: `${animation.name}.glb`,
    size: stats.size,
    hash: assetData.file?.hash,
};

// ... 后续的数据库操作 ...

关键说明

  • 动画依赖节点层级结构,prune工具会自动保留动画引用的节点(即使没有网格),确保导出的动画文件能正确绑定到目标模型(目标模型需要有匹配的节点名称/层级)。
  • 如果需要提取所有动画并分别导出,只需循环处理每个动画即可。

备选方案(Three.js)

如果你的项目已经依赖Three.js,可以用以下方式实现:

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';

// ... 你的现有代码 ...

const loader = new GLTFLoader();
const gltf = await loader.loadAsync(`temp/${assetData.file?.filename}`);

// 过滤出目标动画
const targetClip = gltf.animations.find(clip => clip.name === animation.name);
if (!targetClip) {
    return reject(new Error(`Animation ${animation.name} not found`));
}

// 创建仅包含动画关联节点的场景
const scene = new THREE.Scene();
const cloneAnimatedNodes = (node: THREE.Object3D) => {
    const clone = node.clone(false); // 不复制网格、材质
    scene.add(clone);
    node.children.forEach(child => cloneAnimatedNodes(child));
};

// 遍历原场景,复制被动画引用的节点
gltf.scene.traverse(node => {
    const isAnimated = targetClip.tracks.some(track => {
        const targetName = track.name.split('.')[0];
        return node.name === targetName;
    });
    if (isAnimated) cloneAnimatedNodes(node);
});

// 导出为GLB
const exporter = new GLTFExporter();
const glbBuffer = await exporter.parseAsync(scene, {
    animations: [targetClip],
    binary: true
});
fsExtra.writeFileSync(`${animation.name}.glb`, glbBuffer);

// ... 更新文件元数据 ...

内容的提问来源于stack exchange,提问作者jomaup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:21:56