好了我们到目前为止已经把 Three.js 的基础摸了一遍,大概没漏什么了吧…… 但,是!像 这种 屌爆了的动画,难道所有模型都是用一行行的程序画出来 的吗?怎么可能 ╮( ̄. ̄)╭ ……

准备工作

这次我们会直接使用现成的模型: 这台BF-109许可协议 )。模型是 .3ds 格式,而且不带任何动画数据,所以我们需要:

  1. 将模型转换为 Three.js 能处理的格式;
  2. 给这台小灰机加入骨骼动画。

Three.js 有其特有的 模型数据格式 ,但说白了其实就是 JSON . 貌似这个 东西最近开发速度很快所以经常有变动,这里以旧的 3.x 格式为准。

将其他格式转换为 Three.js 格式最方(pian)便(yi)的方法是用 Blender , 因为 Three.js 源码里就提供了导出模型的 Blender 插件 。而且 Blender 本身 是个强大的 3D 建模和动画工具,我们可以顺便用它加入骨骼动画。

鉴于我们的重点是 Three.js 而不是 Blender ,我在这里直接放上已经加入骨骼 动画的 .blend 文件 和转换后的 JSON 模型

需要注意的是,这里使用的 Three.js 版本是 r70 ,但是 Blender 插件用的 是 r69 版本,因为 r70 的 Blender 插件变化非常大,而且导出的动画在 r70 版本的 Three.js 中播放不正常,我这还没找到解决方法……另外使用 Blender 插件 导出模型的时候, 一定要 选择 “Bones”、“Skinning”、“Skeleton animation” 这三个选项,否则骨骼动画不会被导出。

JSONLoader

Three.js 提供的 JSONLoader 可以以异步方式载入 3D 模型的所有数据,包括几 何结构、材质和贴图等,当然还有动画数据,并且提供了简单的载入进度管理。

以前面的模型为例,最简单的载入过程是这样的:

1
2
3
4
5
var loader = new THREE.JSONLoader();
loader.load('bf109e/bf109e.json', function (geometry, materials) {
    model = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
    scene.add(model);
});

可见载入过程得到的结果是一个几何结构和一组材质,我们需要做的只是将它们组合为 一个 Mesh 对象。

执行结果如下(模型和贴图挺大,载入可能会比较慢):

播放动画

既然模型已经 load 进来了,我们就来播放动画吧~这步其实很简单:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var animation = new THREE.Animation(model, model.geometry.animations[0]);
animation.play();

var clock = new THREE.Clock();
function render() {
    requestAnimationFrame(render);
    // ....
    var delta = clock.getDelta();
    THREE.AnimationHandler.update(delta);
    // ....
}
render();

这里的 “animation.play()” 仅仅是将这个 Animation 对象标记为“播放中”,并没有 处理动画数据——具体的动画表现是由 AnimationHandler 完成的。需要注意的是到目 前为止 Three.js 的文档对 Animation 类的构造函数描述与实际代码都是 不一致 的:第二个参数是具体的动画数据,而不是动画数据的名称。这大概是因为 Three.js 中 处理动画的代码跟模型数据格式一样,最近更新很频繁,所以不久之后很可能又大不一样 了……

所有东西放在一起

为了让场景看起来更完整,我添加了简单的天空贴图和粒子效果: