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

如何获取构成立方体单个面的三角形组?

获取Three.js BoxGeometry单个面三角形组的正确流程

问题背景

尝试获取Three.js中BoxGeometry构成立方体单个面的三角形组,具体尝试如下:

  • 假设BoxGeometry的groups数组(共6个元素)每个元素对应立方体的一个面,存储该面的构成数据
  • 使用以下代码获取第一个group的索引,通过mesh.getVertexPosition()获取顶点并渲染连线:
const topFaceTrgl = groups[0];
for (
  let i = topFaceTrgl.start;
  i < topFaceTrgl.start + topFaceTrgl.count;
  i += 3
) {
  const v1 = mesh.getVertexPosition(
    i,
    new THREE.Vector3()
  );
  const v2 = mesh.getVertexPosition(
    i + 1,
    new THREE.Vector3()
  );
  const v3 = mesh.getVertexPosition(
    i + 2,
    new THREE.Vector3()
  );

  const lineGeo = new THREE.BufferGeometry();
  const lineBufAtrb = new THREE.BufferAttribute(
    new Float32Array(4 * 3),
    3
  );
  lineBufAtrb.setXYZ(0, v1.x, v1.y, v1.z);
  lineBufAtrb.setXYZ(1, v2.x, v2.y, v2.z);
  lineBufAtrb.setXYZ(2, v3.x, v3.y, v3.z);
  lineBufAtrb.setXYZ(4, v1.x, v1.y, v1.z);
  lineGeo.setAttribute("position", lineBufAtrb);
  const lineMat = new THREE.LineBasicMaterial({
    color: "white",
    transparent: true,
  });
  const lineMesh = new THREE.Line(lineGeo, lineMat);
  scene.add(lineMesh);
}

实际渲染结果为杂乱的零散线条,预期是渲染出单个立方体面的矩形轮廓。

正确流程及代码

1. 核心错误分析

  • mesh.getVertexPosition(i)中的i是索引缓冲区(index buffer)的索引,而非顶点位置数组的直接索引。BoxGeometry会复用顶点,必须先通过index缓冲区拿到实际的顶点位置索引,再去position缓冲区获取坐标。
  • 绘制三角形轮廓时,顶点索引设置错误(代码中用了索引4,但数组长度仅支持0-3)。

2. 正确实现步骤

  • 从BoxGeometry中获取index和position属性
  • 遍历目标group的索引范围,逐个取出三角形的顶点索引
  • 通过顶点索引获取对应的三维坐标
  • 绘制三角形轮廓或填充三角形

3. 修正后的代码示例

const geometry = mesh.geometry;
const index = geometry.index;
const position = geometry.attributes.position;

// 取第一个面的group数据
const targetGroup = geometry.groups[0];

// 每个面由2个三角形组成,每个三角形占3个索引,所以count为6
for (let i = targetGroup.start; i < targetGroup.start + targetGroup.count; i += 3) {
  // 获取当前三角形的三个顶点索引
  const idx1 = index.getX(i);
  const idx2 = index.getX(i + 1);
  const idx3 = index.getX(i + 2);

  // 通过顶点索引获取坐标
  const v1 = new THREE.Vector3().fromBufferAttribute(position, idx1);
  const v2 = new THREE.Vector3().fromBufferAttribute(position, idx2);
  const v3 = new THREE.Vector3().fromBufferAttribute(position, idx3);

  // 创建三角形轮廓的几何体(v1->v2->v3->v1)
  const lineGeo = new THREE.BufferGeometry();
  const positions = new Float32Array([
    v1.x, v1.y, v1.z,
    v2.x, v2.y, v2.z,
    v3.x, v3.y, v3.z,
    v1.x, v1.y, v1.z
  ]);
  lineGeo.setAttribute('position', new THREE.BufferAttribute(positions, 3));

  const lineMat = new THREE.LineBasicMaterial({ color: 'white' });
  const lineMesh = new THREE.LineLoop(lineGeo, lineMat); // 使用LineLoop自动闭合轮廓
  scene.add(lineMesh);
}

4. 额外说明

  • 使用THREE.LineLoop可以自动实现轮廓闭合,无需手动重复第一个顶点
  • 如果需要获取面的所有顶点并去重(得到面的四个顶点),可以将每个三角形的顶点存入Set,再取出即可得到单个面的四个唯一顶点

内容的提问来源于stack exchange,提问作者MiguelG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:12:45