5. 模型 (Models) 与加载器 (Loaders)


文档摘要

模型 (Models) 与加载器 (Loaders) Three.js 模型 (Models) 与加载器 (Loaders) 在 Three.js 中,模型是 3D 场景的核心组成部分,它们定义了场景中物体的形状和外观。然而,我们通常不会手动创建复杂的模型,而是使用建模软件(如 Blender、Maya、3ds Max)创建,然后将它们导入到 Three.js 场景中。这就需要用到加载器 (Loaders)。 5.1 模型 (Models) 概述 Three.js 提供了多种模型类,用于表示不同的 3D 几何体和结构: (已废弃): 这是 Three.js 中最基础的几何体类。它存储了顶点 (vertices) 和面 (faces) 的数据。虽然它仍然可用,但官方推荐使用 。

5. 模型 (Models) 与加载器 (Loaders)

5. Three.js 模型 (Models) 与加载器 (Loaders)

在 Three.js 中,模型是 3D 场景的核心组成部分,它们定义了场景中物体的形状和外观。然而,我们通常不会手动创建复杂的模型,而是使用建模软件(如 Blender、Maya、3ds Max)创建,然后将它们导入到 Three.js 场景中。这就需要用到加载器 (Loaders)。

5.1 模型 (Models) 概述

Three.js 提供了多种模型类,用于表示不同的 3D 几何体和结构:

  • THREE.Geometry (已废弃): 这是 Three.js 中最基础的几何体类。它存储了顶点 (vertices) 和面 (faces) 的数据。虽然它仍然可用,但官方推荐使用 THREE.BufferGeometry

  • THREE.BufferGeometry: BufferGeometry 是一种更高效的几何体表示方式,它将顶点数据存储在类型化数组 (Typed Arrays) 中,更适合 GPU 处理。它也是 Three.js 中推荐使用的几何体类型。

  • THREE.Mesh: Mesh 是由几何体 (GeometryBufferGeometry) 和材质 (Material) 组成的 3D 对象。它是场景中最常见的对象类型。

  • THREE.Group: Group 是一个容器,用于将多个 Object3D 对象(包括 MeshLightCamera 等)组合在一起。它可以方便地对一组对象进行统一的变换(如平移、旋转、缩放)。

  • THREE.Scene: Scene 是一个容器,用于存储场景中的所有对象。它是渲染的根节点。

5.2 加载器 (Loaders) 概述

加载器用于将外部 3D 模型文件(如 GLTF、OBJ、FBX 等)加载到 Three.js 场景中。Three.js 提供了多种加载器,每种加载器对应一种或多种模型格式。

常见的加载器包括:

  • THREE.GLTFLoader: 用于加载 GLTF (.gltf 或 .glb) 模型。GLTF 是一种流行的 3D 模型格式,它具有体积小、加载快、支持 PBR 材质等优点。

  • THREE.OBJLoader: 用于加载 OBJ (.obj) 模型。OBJ 是一种简单的文本格式,它只存储几何体数据,不包含材质和动画信息。

  • THREE.FBXLoader: 用于加载 FBX (.fbx) 模型。FBX 是一种常用的 3D 模型格式,它支持几何体、材质、动画等信息。

  • THREE.DRACOLoader: 用于加载 Draco 压缩的几何体。Draco 是一种 Google 开发的压缩算法,可以显著减小几何体的大小。

  • THREE.TextureLoader: 用于加载图像文件(如 JPG、PNG、GIF 等),并将其作为纹理应用于材质。

5.3 加载 GLTF 模型 (GLTFLoader) 的实践

GLTF (GL Transmission Format) 是一种开放标准的 3D 场景和模型格式。它旨在实现 3D 内容的高效传输和加载。

import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; // 创建场景、相机和渲染器 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); // 设置相机位置 camera.position.z = 5; // 创建 GLTFLoader 实例 const loader = new GLTFLoader(); // 加载 GLTF 模型 loader.load( 'path/to/your/model.gltf', // 模型文件路径 function (gltf) { // 模型加载成功后的回调函数 scene.add(gltf.scene); // 将模型添加到场景中 // 可选:处理动画 // gltf.animations.forEach(animation => { // const mixer = new THREE.AnimationMixer(gltf.scene); // const action = mixer.clipAction(animation); // action.play(); // }); }, function (xhr) { // 可选:加载进度回调函数 console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, function (error) { // 可选:加载错误回调函数 console.error('An error happened', error); } ); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();

代码详解:

  1. 导入模块: 导入 Three.js 核心库和 GLTFLoaderGLTFLoader 位于 three/examples/jsm/loaders/GLTFLoader,需要单独导入。

  2. 创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。

  3. 创建 GLTFLoader 实例: const loader = new GLTFLoader(); 创建一个新的 GLTFLoader 对象。

  4. 加载模型: loader.load() 方法用于加载 GLTF 模型。它接受四个参数:

    • 模型文件路径: GLTF 文件的 URL。

    • 加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 gltf 对象作为参数,该对象包含模型的场景、动画、材质等信息。

    • 加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。

    • 加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。

  5. 处理加载成功的模型: 在加载成功回调函数中,通常会将 gltf.scene 添加到场景中。gltf.scene 是一个 THREE.Group 对象,包含了模型的所有网格、材质和骨骼。

  6. 处理动画 (可选): 如果模型包含动画,可以通过 gltf.animations 访问动画剪辑。可以使用 THREE.AnimationMixer 来控制动画的播放。

  7. 渲染循环: animate() 函数是一个递归函数,它不断地更新场景并渲染。

5.4 加载 OBJ 模型 (OBJLoader) 的实践

OBJ 是一种简单的 3D 模型格式,它只存储几何体数据,不包含材质和动画信息。

import * as THREE from 'three'; import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'; import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'; // 创建场景、相机和渲染器 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); // 设置相机位置 camera.position.z = 5; // 创建 OBJLoader 和 MTLLoader 实例 const objLoader = new OBJLoader(); const mtlLoader = new MTLLoader(); // 加载 MTL 文件 (材质) mtlLoader.load('path/to/your/model.mtl', (materials) => { materials.preload(); //预加载材质 objLoader.setMaterials(materials); //设置材质 // 加载 OBJ 模型 objLoader.load( 'path/to/your/model.obj', function (object) { // 模型加载成功后的回调函数 scene.add(object); // 将模型添加到场景中 }, function (xhr) { // 可选:加载进度回调函数 console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, function (error) { // 可选:加载错误回调函数 console.error('An error happened', error); } ); }); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();

代码详解:

  1. 导入模块: 导入 Three.js 核心库、OBJLoaderMTLLoaderOBJLoaderMTLLoader 位于 three/examples/jsm/loaders/OBJLoaderthree/examples/jsm/loaders/MTLLoader,需要单独导入。

  2. 创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。

  3. 创建 OBJLoaderMTLLoader 实例: const objLoader = new OBJLoader();const mtlLoader = new MTLLoader(); 创建新的 OBJLoaderMTLLoader 对象。

  4. 加载 MTL 文件 (材质): mtlLoader.load() 方法用于加载 MTL 文件。它接受三个参数:

    • MTL 文件路径: MTL 文件的 URL。

    • 加载成功回调函数: 当 MTL 文件加载成功时,该函数会被调用。它接收一个 materials 对象作为参数,该对象包含了 MTL 文件中定义的材质。

    • 加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。

  5. 加载 OBJ 模型: objLoader.load() 方法用于加载 OBJ 模型。它接受四个参数:

    • OBJ 文件路径: OBJ 文件的 URL。

    • 加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 object 对象作为参数,该对象包含了模型的几何体数据。

    • 加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。

    • 加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。

  6. 处理加载成功的模型: 在加载成功回调函数中,通常会将 object 添加到场景中。

  7. 渲染循环: animate() 函数是一个递归函数,它不断地更新场景并渲染。

5.5 加载 FBX 模型 (FBXLoader) 的实践

FBX 是一种常用的 3D 模型格式,它支持几何体、材质、动画等信息。

import * as THREE from 'three'; import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'; // 创建场景、相机和渲染器 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); // 设置相机位置 camera.position.z = 5; // 创建 FBXLoader 实例 const loader = new FBXLoader(); // 加载 FBX 模型 loader.load( 'path/to/your/model.fbx', // 模型文件路径 function (object) { // 模型加载成功后的回调函数 scene.add(object); // 将模型添加到场景中 // 可选:处理动画 // object.animations.forEach(animation => { // const mixer = new THREE.AnimationMixer(object); // const action = mixer.clipAction(animation); // action.play(); // }); }, function (xhr) { // 可选:加载进度回调函数 console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, function (error) { // 可选:加载错误回调函数 console.error('An error happened', error); } ); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();

代码详解:

  1. 导入模块: 导入 Three.js 核心库和 FBXLoaderFBXLoader 位于 three/examples/jsm/loaders/FBXLoader,需要单独导入。

  2. 创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。

  3. 创建 FBXLoader 实例: const loader = new FBXLoader(); 创建一个新的 FBXLoader 对象。

  4. 加载模型: loader.load() 方法用于加载 FBX 模型。它接受四个参数:

    • 模型文件路径: FBX 文件的 URL。

    • 加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 object 对象作为参数,该对象包含模型的场景、动画、材质等信息。

    • 加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。

    • 加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。

  5. 处理加载成功的模型: 在加载成功回调函数中,通常会将 object 添加到场景中。

  6. 处理动画 (可选): 如果模型包含动画,可以通过 object.animations 访问动画剪辑。可以使用 THREE.AnimationMixer 来控制动画的播放。

  7. 渲染循环: animate() 函数是一个递归函数,它不断地更新场景并渲染。

5.6 加载器的选择

选择合适的加载器取决于模型的格式。以下是一些建议:

  • GLTF (.gltf 或 .glb): THREE.GLTFLoader (推荐,体积小,加载快,支持 PBR 材质)

  • OBJ (.obj): THREE.OBJLoader (简单,但不支持材质和动画,通常与 MTLLoader 配合使用)

  • FBX (.fbx): THREE.FBXLoader (支持几何体、材质、动画)

  • Draco 压缩的几何体: THREE.DRACOLoader (需要配合其他Loader使用,例如GLTFLoader,可以显著减小模型体积)

5.7 使用 DRACOLoader 压缩模型

Draco 是一种由 Google 开发的开源库,用于压缩和解压缩 3D 几何网格和点云。使用 Draco 可以显著减小模型文件的大小,从而加快加载速度并减少带宽消耗。

import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; // 创建场景、相机和渲染器 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); // 设置相机位置 camera.position.z = 5; // 创建 DRACOLoader 实例 const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath('/examples/jsm/libs/draco/'); // 设置解码器路径 (重要!) dracoLoader.setDecoderConfig({ type: 'js' }); // 选择解码器类型 // 创建 GLTFLoader 实例 const loader = new GLTFLoader(); loader.setDRACOLoader(dracoLoader); // 加载 GLTF 模型 loader.load( 'path/to/your/model.gltf', // 模型文件路径 function (gltf) { // 模型加载成功后的回调函数 scene.add(gltf.scene); // 将模型添加到场景中 }, function (xhr) { // 可选:加载进度回调函数 console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, function (error) { // 可选:加载错误回调函数 console.error('An error happened', error); } ); // 渲染循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();

代码详解:

  1. 导入模块: 导入 Three.js 核心库、GLTFLoaderDRACOLoader

  2. 创建 DRACOLoader 实例:

    • const dracoLoader = new DRACOLoader(); 创建一个新的 DRACOLoader 对象。

    • dracoLoader.setDecoderPath('/examples/jsm/libs/draco/'); (重要!) 设置解码器文件的路径。 Draco 解码器文件通常位于 three/examples/jsm/libs/draco/ 目录下。 必须正确设置此路径,否则无法加载 Draco 压缩的模型。

    • dracoLoader.setDecoderConfig({ type: 'js' }); 选择解码器类型,这里选择JavaScript解码器。

  3. DRACOLoader 传递给 GLTFLoader loader.setDRACOLoader(dracoLoader);DRACOLoader 实例传递给 GLTFLoader,以便 GLTFLoader 可以使用 Draco 解码器来加载 Draco 压缩的几何体。

  4. 加载 GLTF 模型: 使用 GLTFLoader 加载 GLTF 模型,过程与之前相同。

5.8 总结

模型和加载器是 Three.js 开发中不可或缺的部分。理解不同模型的类型和加载器的使用方法,可以帮助我们高效地将外部 3D 模型集成到 Three.js 场景中。通过选择合适的加载器和使用 Draco 压缩,可以优化模型的加载速度和性能,提升用户体验。

希望这篇文章对您有所帮助!


发布者: 作者: 转发
评论区 (0)
U