​ 目前,3D模型的格式有成千上万种可供选择,但每一种格式都具有不同的目的、用途以及复杂性。 虽然three.js已经提供了多种导入工具, 但是选择正确的文件格式以及工作流程将可以节省很多时间,以及避免遭受很多挫折。某些格式难以使用,或者实时体验效率低下,或者目前尚未得到完全支持。

ThreeJS支持的模型格式

​ 推荐使用glTF(gl传输格式)。.GLB和.GLTF是这种格式的这两种不同版本, 都可以被很好地支持。由于glTF这种格式是专注于在程序运行时呈现三维物体的,所以它的传输效率非常高,且加载速度非常快。 功能方面则包括了网格、材质、纹理、皮肤、骨骼、变形目标、动画、灯光和摄像机。

​ 当glTF不可用的时候,诸如FBX、OBJ或者COLLADA等等其它广受欢迎的格式在Three.js中也是可以使用、并且定期维护的。

glTF加载器

​ GLTFLoader用于载入glTF 2.0资源的加载器。

glTF简介

​ glTF(gl传输格式)是一种开放格式的规范 (open format specification), 用于更高效地传输、加载3D内容。该类文件以JSON(.gltf)格式或二进制(.glb)格式提供, 外部文件存储贴图(.jpg、.png)和额外的二进制数据(.bin)。一个glTF组件可传输一个或多个场景, 包括网格、材质、贴图、蒙皮、骨架、变形目标、动画、灯光以及摄像机。

glTF模型加载器

​ ThreeJS内置了GLTF模型加载器,用于加载GLTF模型资源。

GLTFLoader uses ImageBitmapLoader whenever possible. Be advised that image bitmaps are not automatically GC-collected when they are no longer referenced, and they require special handling during the disposal process. More information in the How to dispose of objects guide.

DRACOLoader模型解压器

​ 用于加载经过Draco压缩的图形库。
​ Draco是一个开源的库,主要用于压缩和解压缩三维模型及点云。 以客户端上解压缩为代价,显著减少压缩的图形。

​ 独立的Draco文件后缀为.drc,其中包含顶点坐标,法线,颜色和其他的属性, Draco文件包含材质,纹理,动画和节点结构-为了能使用这些特征,需要将Draco图形 嵌入到GLTF文件中。使用glTF-Pipeline可以将一个普通的GLTF文件转化为经过Draco压缩的GLTF文件。 当使用Draco压缩的GLTF模型时,GLTFLoader内部会调用DRACOLoader。

​ 推荐创建一个DRACOLoader实例并重用,可以有效避免重复创建加载多个解压器实例。

ThreeJS加载GLTF模型

​ 以下,使用GLTFLoader加载官网提供的模型数据,核心代码段如下,

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; //GLTF加载器
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

//TODO:添加光源
const light = new THREE.PointLight(0xffffff, 1000, 1000);
light.position.set(15, 15, 15);
scene.add(light);
scene.background = new THREE.Color(0xbfe3dd);

//TODO:加载模型
const modelPath = "models/LittlestTokyo.glb";
const gltfLoader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("draco/");
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.load(modelPath, function (gltfData) {
  console.log("onload::", gltfData);
    
  //TODO:加载glb模型到场景中
  const model = gltfData.scene;
  model.position.set(1, 1, 0);
  model.scale.set(0.01, 0.01, 0.01);
  scene.add(model);
});

模型动画

​ 在上述案例中,注意到该模型数据携带有一个动画,那么如何在Web3D页面中播放这个动画呢?

AnimationMixer模型动画混合器

​ ThreeJS提供了AnimationMixer模型动画混合器,是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。

​ 通过clipAction方法,可以传入预定义的模型动画参数,并可以获取到一个AnimationAction实例。

AnimationAction动画调度器

​ AnimationAction实例,用于调度存储在AnimationClips中的动画,通过调用其play()方法,可以主动唤起混合器激活动画。

ThreeJS播放模型动画

​ 修改上述加载GLTF模型的代码如下,即可播放模型动画,

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; //GLTF加载器
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

//TODO:创建时钟
const clock = new THREE.Clock();

//TODO:添加光源
const light = new THREE.PointLight(0xffffff, 1000, 1000);
light.position.set(15, 15, 15);
scene.add(light);
scene.background = new THREE.Color(0xbfe3dd);

//TODO:声明动画混合器
let mixer = null;

//TODO:加载模型
const modelPath = "models/LittlestTokyo.glb";
const gltfLoader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("draco/");
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.load(modelPath, function (gltfData) {
  console.log("onload::", gltfData);

  //TODO:加载glb模型到场景中
  const model = gltfData.scene;
  model.position.set(1, 1, 0);
  model.scale.set(0.01, 0.01, 0.01);
  scene.add(model);

  //TODO:激活动画
  mixer = new THREE.AnimationMixer( model );
  mixer.clipAction( gltfData.animations[ 0 ] ).play();
  animate()
});

//TODO:修改animate渲染函数逻辑如下
//TODO:渲染函数
function animate() {
  requestAnimationFrame(animate);

  //TODO:更新轨道控制器
  orbitControls.update();

  //TODO:更新模型动画
  if(mixer){
    const delta = clock.getDelta();
    mixer.update(delta);
  }

  //TODO:渲染
  renderer.render(scene, camera);
}