You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用three.js从GLB格式octet-stream响应提取顶点和面数组

GLB二进制响应提取顶点、面数据实现

首先修正原有代码的两处问题:

  1. responseType不属于HTTP请求头字段,是请求客户端的配置项,fetch场景下直接调用响应对象的arrayBuffer()方法拿到二进制数据即可
  2. 原逻辑直接拿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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:54:06