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

如何从GLTFLoader加载的glTF场景中获取顶点与三角面数组

从glTF加载场景提取顶点与三角面数组实现方法

GLTFLoader解析完成后返回的场景对象是Three.js的Group实例,所有模型网格以Mesh子节点的形式挂载在组下,网格的BufferGeometry属性里存储了完整的顶点、拓扑数据,直接遍历提取即可,不需要额外依赖。

核心数据说明

  • 顶点坐标列表:存储在网格几何体的attributes.position属性中,类型为Float32BufferAttribute,访问.array可得到原始Float32Array数组,数组每3个连续元素对应1个顶点的X、Y、Z三维坐标
  • 三角面索引列表:分两种场景
    • 索引几何体(绝大多数glTF模型采用):数据存储在几何体的index属性中,访问.array可得到Uint16Array或Uint32Array数组,每3个连续元素对应1个三角面的三个顶点在顶点列表中的下标
    • 非索引几何体:无独立索引数组,顶点列表按顺序每3个连续顶点组成1个三角面

修改后完整代码

原代码存在Promise链式调用未返回值、加载完成后未遍历提取几何数据的问题,修正后代码如下:

return from(
  fetch(targetUrl.toString(), {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  .then(response => {
    // 补全return,保证外层Promise链能拿到解析后的数据
    return response.arrayBuffer()
  })
  .then(data => {
    return new Promise((resolve) => {
      const loader = new GLTFLoader();
      // 如果使用了Draco/Meshopt压缩,在此处注册对应解码器扩展即可
      loader.parse(data, "", (gltf) => {
        const allMeshes = [];
        const allVertexData = [];
        const allTriangleIndexData = [];

        // 遍历场景下所有节点,筛选出网格类型
        gltf.scene.traverse((node) => {
          if (node.isMesh && node.geometry) {
            const geometry = node.geometry;
            // 提取顶点坐标数组
            const positionAttr = geometry.getAttribute('position');
            const vertexArray = positionAttr.array; // Float32Array类型,即需要的顶点列表
            // 提取三角面索引数组
            let triangleIndexArray = null;
            if (geometry.index) {
              triangleIndexArray = geometry.index.array; // Uint16Array/Uint32Array类型,即需要的三角面索引列表
            } else {
              // 非索引几何体,生成顺序索引
              triangleIndexArray = new Uint32Array(vertexArray.length / 3);
              for (let i = 0; i < triangleIndexArray.length; i++) {
                triangleIndexArray[i] = i;
              }
            }

            // 按需求存储数据
            const meshData = {
              mesh: node,
              vertices: vertexArray,
              triangleIndices: triangleIndexArray
            };
            allMeshes.push(meshData);
            allVertexData.push(vertexArray);
            allTriangleIndexData.push(triangleIndexArray);

            // 把网格加入场景
            this.scene.add(node);
          }
        });

        // 返回提取好的几何数据供后续pipe流程使用
        resolve({
          gltfScene: gltf.scene,
          meshes: allMeshes,
          allVertices: allVertexData,
          allTriangleIndices: allTriangleIndexData
        });
      })
    })
  })
).pipe(
  map((loadResult) => {
    // 此处可以直接拿到所有顶点、三角面数组
    this.surfaceMeshes.set(surfaceMeshKey, loadResult);
    return loadResult;
  })
)

注意事项

  • 如果glTF模型做了几何压缩(Draco、Meshopt等),需要先给GLTFLoader注册对应的解码扩展,否则提取到的几何数据为空
  • 拿到的TypedArray是几何体内部引用的原始数据,如果需要修改请先做克隆,避免直接修改原始缓冲导致渲染异常
  • 如果模型带蒙皮、变形器,上述方法拿到的是初始绑定姿态的顶点数据,如需获取动画运行中的实时顶点位置,需要用SkinnedMesh的boneTransform方法逐顶点计算,或调用几何体对应更新方法后再读取

内容的提问来源于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 16:28:03