模型 (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) 的数据。虽然它仍然可用,但官方推荐使用 。
在 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 是由几何体 (Geometry 或 BufferGeometry) 和材质 (Material) 组成的 3D 对象。它是场景中最常见的对象类型。
THREE.Group: Group 是一个容器,用于将多个 Object3D 对象(包括 Mesh、Light、Camera 等)组合在一起。它可以方便地对一组对象进行统一的变换(如平移、旋转、缩放)。
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();
代码详解:
导入模块: 导入 Three.js 核心库和 GLTFLoader。GLTFLoader 位于 three/examples/jsm/loaders/GLTFLoader,需要单独导入。
创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。
创建 GLTFLoader 实例: const loader = new GLTFLoader(); 创建一个新的 GLTFLoader 对象。
加载模型: loader.load() 方法用于加载 GLTF 模型。它接受四个参数:
模型文件路径: GLTF 文件的 URL。
加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 gltf 对象作为参数,该对象包含模型的场景、动画、材质等信息。
加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。
加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。
处理加载成功的模型: 在加载成功回调函数中,通常会将 gltf.scene 添加到场景中。gltf.scene 是一个 THREE.Group 对象,包含了模型的所有网格、材质和骨骼。
处理动画 (可选): 如果模型包含动画,可以通过 gltf.animations 访问动画剪辑。可以使用 THREE.AnimationMixer 来控制动画的播放。
渲染循环: 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();
代码详解:
导入模块: 导入 Three.js 核心库、OBJLoader 和 MTLLoader。 OBJLoader 和 MTLLoader 位于 three/examples/jsm/loaders/OBJLoader 和 three/examples/jsm/loaders/MTLLoader,需要单独导入。
创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。
创建 OBJLoader 和 MTLLoader 实例: const objLoader = new OBJLoader(); 和 const mtlLoader = new MTLLoader(); 创建新的 OBJLoader 和 MTLLoader 对象。
加载 MTL 文件 (材质): mtlLoader.load() 方法用于加载 MTL 文件。它接受三个参数:
MTL 文件路径: MTL 文件的 URL。
加载成功回调函数: 当 MTL 文件加载成功时,该函数会被调用。它接收一个 materials 对象作为参数,该对象包含了 MTL 文件中定义的材质。
加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。
加载 OBJ 模型: objLoader.load() 方法用于加载 OBJ 模型。它接受四个参数:
OBJ 文件路径: OBJ 文件的 URL。
加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 object 对象作为参数,该对象包含了模型的几何体数据。
加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。
加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。
处理加载成功的模型: 在加载成功回调函数中,通常会将 object 添加到场景中。
渲染循环: 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();
代码详解:
导入模块: 导入 Three.js 核心库和 FBXLoader。FBXLoader 位于 three/examples/jsm/loaders/FBXLoader,需要单独导入。
创建场景、相机和渲染器: 这是 Three.js 应用程序的标准初始化步骤。
创建 FBXLoader 实例: const loader = new FBXLoader(); 创建一个新的 FBXLoader 对象。
加载模型: loader.load() 方法用于加载 FBX 模型。它接受四个参数:
模型文件路径: FBX 文件的 URL。
加载成功回调函数: 当模型加载成功时,该函数会被调用。它接收一个 object 对象作为参数,该对象包含模型的场景、动画、材质等信息。
加载进度回调函数 (可选): 在加载过程中,该函数会被周期性地调用,可以用于显示加载进度。
加载错误回调函数 (可选): 当加载发生错误时,该函数会被调用。
处理加载成功的模型: 在加载成功回调函数中,通常会将 object 添加到场景中。
处理动画 (可选): 如果模型包含动画,可以通过 object.animations 访问动画剪辑。可以使用 THREE.AnimationMixer 来控制动画的播放。
渲染循环: 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();
代码详解:
导入模块: 导入 Three.js 核心库、GLTFLoader 和 DRACOLoader。
创建 DRACOLoader 实例:
const dracoLoader = new DRACOLoader(); 创建一个新的 DRACOLoader 对象。
dracoLoader.setDecoderPath('/examples/jsm/libs/draco/'); (重要!) 设置解码器文件的路径。 Draco 解码器文件通常位于 three/examples/jsm/libs/draco/ 目录下。 必须正确设置此路径,否则无法加载 Draco 压缩的模型。
dracoLoader.setDecoderConfig({ type: 'js' }); 选择解码器类型,这里选择JavaScript解码器。
将 DRACOLoader 传递给 GLTFLoader: loader.setDRACOLoader(dracoLoader); 将 DRACOLoader 实例传递给 GLTFLoader,以便 GLTFLoader 可以使用 Draco 解码器来加载 Draco 压缩的几何体。
加载 GLTF 模型: 使用 GLTFLoader 加载 GLTF 模型,过程与之前相同。
5.8 总结
模型和加载器是 Three.js 开发中不可或缺的部分。理解不同模型的类型和加载器的使用方法,可以帮助我们高效地将外部 3D 模型集成到 Three.js 场景中。通过选择合适的加载器和使用 Draco 压缩,可以优化模型的加载速度和性能,提升用户体验。
希望这篇文章对您有所帮助!