5.1模型格式 Three.js 模型格式详解与加载实践 5.1 模型格式概览 Three.js 支持多种模型格式,每种格式都有其优缺点。选择合适的格式取决于项目的具体需求。以下是一些常见的模型格式: glTF (GL Transmission Format): 现代、开放、可扩展的格式,旨在成为 3D 内容的 JPEG。它支持动画、材质、PBR 渲染,并且可以高效传输。强烈推荐使用。 OBJ (Wavefront Object): 一种简单的文本格式,广泛支持,但文件通常较大,且材质和动画支持有限。 FBX (Filmbox): Autodesk 开发的专有格式,广泛用于游戏和动画行业。支持复杂的动画和材质,但文件通常较大,且需要 FBX Loader。
Three.js 支持多种模型格式,每种格式都有其优缺点。选择合适的格式取决于项目的具体需求。以下是一些常见的模型格式:
glTF (GL Transmission Format): 现代、开放、可扩展的格式,旨在成为 3D 内容的 JPEG。它支持动画、材质、PBR 渲染,并且可以高效传输。强烈推荐使用。
OBJ (Wavefront Object): 一种简单的文本格式,广泛支持,但文件通常较大,且材质和动画支持有限。
FBX (Filmbox): Autodesk 开发的专有格式,广泛用于游戏和动画行业。支持复杂的动画和材质,但文件通常较大,且需要 FBX Loader。
STL (Stereolithography): 用于 3D 打印的格式,仅包含几何信息,不支持材质或动画。
PLY (Polygon File Format): 存储多边形网格数据的格式,可以包含颜色、法线等信息。
Collada (DAE): 一种开放的交换格式,支持动画和材质,但逐渐被 glTF 取代。
Three.js JSON Format: Three.js 自有的 JSON 格式,已经过时,不推荐使用。
glTF 是现代 Web 3D 的首选格式。它旨在高效地传输和加载 3D 模型,并支持 PBR 材质、动画、蒙皮等高级特性。glTF 有两种变体:
glTF (.gltf): 基于 JSON 的格式,包含对外部资源(如纹理和二进制数据)的引用。
glTF Binary (.glb): 将所有数据(包括几何、纹理和动画)嵌入到单个二进制文件中,更易于传输和加载。
代码实践:
import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; 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); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); // soft white light scene.add(ambientLight); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); camera.position.z = 5; const loader = new GLTFLoader(); loader.load( 'models/scene.gltf', // 模型路径 function (gltf) { scene.add(gltf.scene); // 可选:访问模型的组件 gltf.animations; // Array<THREE.AnimationClip> gltf.scene; // THREE.Group gltf.scenes; // Array<THREE.Group> gltf.cameras; // Array<THREE.Camera> gltf.asset; // Object // 可选:调整模型位置和缩放 gltf.scene.scale.set(0.1, 0.1, 0.1); gltf.scene.position.set(0, -1, 0); renderer.render(scene, camera); }, 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();
详解:
引入 GLTFLoader: import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; 导入 glTF 加载器。
创建加载器实例: const loader = new GLTFLoader(); 创建 GLTFLoader 的实例。
加载模型: loader.load('models/scene.gltf', ...) 使用 load 方法加载 glTF 模型。load 方法接受四个参数:
模型路径: glTF 文件的路径。
加载成功回调: 在模型加载成功后执行的函数。该函数接收一个 gltf 对象,其中包含模型的场景、动画、相机等信息。
加载进度回调 (可选): 在模型加载过程中定期执行的函数,用于显示加载进度。
加载失败回调 (可选): 在模型加载失败时执行的函数。
添加到场景: scene.add(gltf.scene); 将加载的模型的场景添加到 Three.js 场景中。 gltf.scene 是一个 THREE.Group 对象,包含模型的所有网格、材质和子对象。
访问模型组件 (可选): gltf 对象包含模型的动画、场景、相机和资产信息。可以通过 gltf.animations、gltf.scene、gltf.cameras 和 gltf.asset 属性访问这些组件。
调整模型 (可选): 可以调整模型的位置、缩放和旋转,以适应场景的需求。
glTF 优势:
高效性: 压缩的二进制格式,减少文件大小和加载时间。
PBR 材质支持: 支持物理渲染材质,实现更逼真的视觉效果。
动画支持: 支持骨骼动画、变形动画等。
开放标准: 无需授权费用,易于集成到各种 3D 引擎和工具中。
OBJ 是一种简单的文本格式,广泛支持,但文件通常较大,且材质和动画支持有限。它主要包含几何信息(顶点、面)和材质引用。
代码实践:
import * as THREE from 'three'; import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'; import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'; 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); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); // soft white light scene.add(ambientLight); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); camera.position.z = 5; // 加载 MTL 材质文件 const mtlLoader = new MTLLoader(); mtlLoader.load('models/model.mtl', (materials) => { materials.preload(); // 加载 OBJ 模型文件 const objLoader = new OBJLoader(); objLoader.setMaterials(materials); // 设置材质 objLoader.load('models/model.obj', (object) => { scene.add(object); // 可选:调整模型位置和缩放 object.scale.set(0.1, 0.1, 0.1); object.position.set(0, -1, 0); renderer.render(scene, camera); }, function (xhr) { console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, (error) => { console.error('An error happened', error); }); }); function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
详解:
引入 OBJLoader 和 MTLLoader: import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'; 和 import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'; 导入 OBJ 和 MTL 加载器。OBJ 文件通常与 MTL (Material Template Library) 文件一起使用,MTL 文件定义了模型的材质。
创建加载器实例: const objLoader = new OBJLoader(); 和 const mtlLoader = new MTLLoader(); 创建 OBJLoader 和 MTLLoader 的实例。
加载 MTL 文件: mtlLoader.load('models/model.mtl', ...) 使用 load 方法加载 MTL 文件。
设置材质: objLoader.setMaterials(materials); 将加载的材质传递给 OBJLoader。
加载 OBJ 文件: objLoader.load('models/model.obj', ...) 使用 load 方法加载 OBJ 模型。
添加到场景: scene.add(object); 将加载的模型添加到 Three.js 场景中。
调整模型 (可选): 可以调整模型的位置、缩放和旋转,以适应场景的需求。
OBJ 优势:
简单易懂: 文本格式,易于阅读和编辑。
广泛支持: 几乎所有 3D 建模软件都支持导出 OBJ 格式。
OBJ 劣势:
文件较大: 文本格式,没有压缩,文件大小通常较大。
材质支持有限: MTL 文件仅支持简单的材质属性,不支持 PBR 渲染。
动画支持差: 不支持动画。
FBX 是 Autodesk 开发的专有格式,广泛用于游戏和动画行业。它支持复杂的动画和材质,但文件通常较大,且需要 FBX Loader。
代码实践:
import * as THREE from 'three'; import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'; 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); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); // soft white light scene.add(ambientLight); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); camera.position.z = 5; const loader = new FBXLoader(); loader.load( 'models/model.fbx', function (object) { scene.add(object); // 可选:调整模型位置和缩放 object.scale.set(0.1, 0.1, 0.1); object.position.set(0, -1, 0); // 可选:播放动画 if (object.animations && object.animations.length > 0) { const mixer = new THREE.AnimationMixer(object); const action = mixer.clipAction(object.animations[0]); action.play(); // 创建动画循环 function animate() { requestAnimationFrame(animate); mixer.update(0.01); // delta time renderer.render(scene, camera); } animate(); } else { renderer.render(scene, camera); // 没有动画则直接渲染 } }, 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(); // 只有有动画的时候才执行
详解:
引入 FBXLoader: import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'; 导入 FBX 加载器。
创建加载器实例: const loader = new FBXLoader(); 创建 FBXLoader 的实例。
加载模型: loader.load('models/model.fbx', ...) 使用 load 方法加载 FBX 模型。
添加到场景: scene.add(object); 将加载的模型添加到 Three.js 场景中。
调整模型 (可选): 可以调整模型的位置、缩放和旋转,以适应场景的需求。
播放动画 (可选): 如果模型包含动画,可以使用 THREE.AnimationMixer 来播放动画。
FBX 优势:
动画支持: 支持复杂的动画,包括骨骼动画和变形动画。
材质支持: 支持复杂的材质属性。
FBX 劣势:
文件较大: 文件大小通常较大。
专有格式: 由 Autodesk 开发,需要 FBX Loader。
STL 是一种用于 3D 打印的格式,仅包含几何信息(三角形网格),不支持材质或动画。
代码实践:
import * as THREE from 'three'; import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; 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); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); // soft white light scene.add(ambientLight); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); camera.position.z = 5; const loader = new STLLoader(); loader.load( 'models/model.stl', function ( geometry ) { const material = new THREE.MeshPhongMaterial( { color: 0xffffff } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); // 可选:调整模型位置和缩放 mesh.scale.set(0.1, 0.1, 0.1); mesh.position.set(0, -1, 0); renderer.render(scene, camera); } ); function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
详解:
引入 STLLoader: import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; 导入 STL 加载器。
创建加载器实例: const loader = new STLLoader(); 创建 STLLoader 的实例。
加载模型: loader.load('models/model.stl', ...) 使用 load 方法加载 STL 模型。
创建材质: 由于 STL 文件不包含材质信息,需要手动创建材质。 const material = new THREE.MeshPhongMaterial( { color: 0xffffff } );
创建网格: const mesh = new THREE.Mesh( geometry, material ); 使用加载的几何体和创建的材质创建网格。
添加到场景: scene.add(mesh); 将创建的网格添加到 Three.js 场景中。
调整模型 (可选): 可以调整模型的位置、缩放和旋转,以适应场景的需求。
STL 优势:
简单: 仅包含几何信息,易于生成和处理。
广泛支持: 几乎所有 3D 打印软件都支持导出 STL 格式。
STL 劣势:
不支持材质: 不包含材质信息,需要手动创建材质。
不支持动画: 不支持动画。
文件较大: 没有压缩,文件大小通常较大。
| 模型格式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| glTF | 高效、PBR 材质、动画支持、开放标准 | 复杂场景可能需要优化 | 现代 Web 3D 应用,需要高质量渲染和动画。 |
| OBJ | 简单易懂、广泛支持 | 文件较大、材质支持有限、动画支持差 | 简单的静态模型,不需要复杂的材质和动画。 |
| FBX | 动画支持、材质支持 | 文件较大、专有格式 | 游戏和动画行业,需要复杂的动画和材质。 |
| STL | 简单、广泛支持 | 不支持材质、不支持动画、文件较大 | 3D 打印,仅需要几何信息。 |
流程图:
选择合适的模型格式是 Three.js 开发的关键一步。glTF 是现代 Web 3D 的首选格式,因为它提供了高效的传输、PBR 材质支持和动画支持。对于简单的静态模型,OBJ 格式可能更合适。对于需要复杂动画和材质的场景,FBX 格式是一个不错的选择。STL 格式则适用于 3D 打印。了解各种模型格式的优缺点,可以帮助你做出明智的选择,优化 Three.js 应用的性能和视觉效果。
希望这篇文章能够帮助你更好地理解 Three.js 中的模型格式及其加载实践。