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

如何适配Three.js新版BufferGeometry实现平面与网格交点检测?

适配新版Three.js的几何体面相交检测方案

新版Three.js中BufferGeometry替代了旧版的Geometry,不再有faces和vertices属性,需要通过index和position属性来获取三角面与顶点数据,以下是修改后的代码:

// 提前声明复用的向量,避免频繁创建对象
const a = new THREE.Vector3();
const b = new THREE.Vector3();
const c = new THREE.Vector3();
const geometry = obj.geometry;
const positionAttr = geometry.getAttribute('position');
const indexArray = geometry.index ? geometry.index.array : null;

// 处理带索引的几何体(大部分复杂模型会用索引)
if (indexArray) {
  // 每3个索引对应一个三角面
  for (let i = 0; i < indexArray.length; i += 3) {
    // 获取当前三角面的三个顶点索引
    const idxA = indexArray[i];
    const idxB = indexArray[i + 1];
    const idxC = indexArray[i + 2];

    // 从position属性中读取顶点局部坐标
    a.set(positionAttr.getX(idxA), positionAttr.getY(idxA), positionAttr.getZ(idxA));
    b.set(positionAttr.getX(idxB), positionAttr.getY(idxB), positionAttr.getZ(idxB));
    c.set(positionAttr.getX(idxC), positionAttr.getY(idxC), positionAttr.getZ(idxC));

    // 转换为世界坐标
    obj.localToWorld(a);
    obj.localToWorld(b);
    obj.localToWorld(c);

    // 创建三条边(克隆向量避免后续循环覆盖值)
    const lineAB = new THREE.Line3(a.clone(), b.clone());
    const lineBC = new THREE.Line3(b.clone(), c.clone());
    const lineCA = new THREE.Line3(c.clone(), a.clone());

    // 调用交点检测方法,i/3对应原代码中的face索引
    setPointOfIntersection(lineAB, mathPlane, Math.floor(i / 3));
    setPointOfIntersection(lineBC, mathPlane, Math.floor(i / 3));
    setPointOfIntersection(lineCA, mathPlane, Math.floor(i / 3));
  }
} else {
  // 处理不带索引的几何体(简单几何体可能会用这种方式)
  const vertexCount = positionAttr.count;
  // 每3个顶点对应一个三角面
  for (let i = 0; i < vertexCount; i += 3) {
    // 读取三个顶点的局部坐标
    a.set(positionAttr.getX(i), positionAttr.getY(i), positionAttr.getZ(i));
    b.set(positionAttr.getX(i + 1), positionAttr.getY(i + 1), positionAttr.getZ(i + 1));
    c.set(positionAttr.getX(i + 2), positionAttr.getY(i + 2), positionAttr.getZ(i + 2));

    // 转换为世界坐标
    obj.localToWorld(a);
    obj.localToWorld(b);
    obj.localToWorld(c);

    // 创建三条边
    const lineAB = new THREE.Line3(a.clone(), b.clone());
    const lineBC = new THREE.Line3(b.clone(), c.clone());
    const lineCA = new THREE.Line3(c.clone(), a.clone());

    // 调用交点检测方法
    setPointOfIntersection(lineAB, mathPlane, Math.floor(i / 3));
    setPointOfIntersection(lineBC, mathPlane, Math.floor(i / 3));
    setPointOfIntersection(lineCA, mathPlane, Math.floor(i / 3));
  }
}

关键变化说明

  • 顶点数据获取:通过geometry.getAttribute('position')拿到顶点属性,用getX/Y/Z(index)方法读取指定顶点的坐标;也可以直接访问positionAttr.array(比如positionAttr.array[idxA * 3]取x值,idxA*3+1取y,idxA*3+2取z),两种方式效果一致。
  • 三角面索引:带索引的几何体通过geometry.index.array获取每个三角面的顶点索引,每3个元素对应一个面;无索引的几何体直接按顺序每3个顶点组成一个面。
  • 向量复用:提前声明a/b/c三个向量,避免在循环中频繁创建对象提升性能;创建Line3时克隆向量,防止后续循环修改原向量导致边的坐标被覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 10:01:24