如何使用three.js从GLB格式octet-stream响应提取顶点和面数组
GLB二进制响应提取顶点、面数据实现
首先修正原有代码的两处问题:
responseType不属于HTTP请求头字段,是请求客户端的配置项,fetch场景下直接调用响应对象的arrayBuffer()方法拿到二进制数据即可- 原逻辑直接拿fetch返回的Response对象做存储,没有做二进制解析,无法拿到几何数据
直接替换原有请求逻辑即可,代码适配你当前使用的RxJS写法,返回结构和之前JSON格式完全对齐:
// 引入依赖,路径根据本地three版本调整 import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { from, switchMap } from 'rxjs'; import { map } from 'rxjs/operators'; // 初始化加载器,建议提为类成员变量复用,不要每次请求新建实例 private gltfLoader = new GLTFLoader(); // 替换你原来的return逻辑 return from( fetch(targetUrl.toString(), { method: 'GET', headers: { 'Accept': 'application/octet-stream' } }).then(res => { if (!res.ok) throw new Error(`请求失败,状态码:${res.status}`); return res.arrayBuffer(); }) ).pipe( switchMap((glbBuffer) => { return new Promise((resolve, reject) => { // 直接解析内存中的GLB二进制数据,不需要走网络请求加载 this.gltfLoader.parse( glbBuffer, '', (gltfScene) => { const vertices: number[] = []; const faces: number[] = []; let vertexOffset = 0; // 遍历场景下所有节点,提取网格几何数据 gltfScene.scene.traverse((node) => { const mesh = node as THREE.Mesh; if (!mesh.isMesh) return; const position = mesh.geometry.getAttribute('position'); const index = mesh.geometry.getIndex(); // 按x/y/z顺序写入顶点数组 for (let i = 0; i < position.count; i++) { vertices.push(position.getX(i), position.getY(i), position.getZ(i)); } // 写入三角面索引,多网格场景下加偏移量保证索引连续 if (index) { for (let i = 0; i < index.count; i++) { faces.push(index.getX(i) + vertexOffset); } } else { // 兼容无索引的几何体,自动生成连续三角面索引 for (let i = 0; i < position.count; i++) { faces.push(i + vertexOffset); } } vertexOffset += position.count; }); resolve({ vertices, faces, n_faces: faces.length / 3 }); }, (parseErr) => reject(parseErr) ); }); }), map((parsedMesh) => { this.surfaceMeshes.set(surfaceMeshKey, parsedMesh); return parsedMesh; }) );
适配说明
- 代码自动处理GLB包含多个网格的场景,合并后的顶点、面数组和你之前单几何体JSON结构完全一致,不需要修改下游使用逻辑
- 如果原有JSON数据做过坐标轴翻转(比如Y/Z轴互换),在提取顶点坐标时调整
getX/getY/getZ的取值顺序即可 - 解析逻辑会自动跳过场景内的灯光、相机、空节点等非网格对象,只提取三角面几何数据
- GLTFLoader实例建议提为类成员变量复用,避免每次请求重复初始化
内容的提问来源于stack exchange,提问作者user13856337
相关产品推荐
相关产品推荐

