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

如何获取两个相交网格的全部交点?已知mesh.intersectsMesh仅返回布尔值

获取两个网格碰撞的全部交点方法(以Three.js为例)

mesh.intersectsMesh()仅返回布尔值,无法直接获取交点,要拿到所有交点可以通过以下两种方式实现:

方法1:手动遍历三角面+射线检测

核心逻辑是遍历两个网格的三角面/边,通过射线与三角形的相交检测逐个获取交点:

  • 先更新两个网格的世界矩阵,确保坐标转换准确:
    mesh.updateMatrixWorld(true);
    anotherMesh.updateMatrixWorld(true);
    
  • 提取两个网格的三角面数据:如果使用BufferGeometry,需先转成三角面格式;如果是旧版Geometry,直接取faces数组即可。
  • 遍历第一个网格的每个三角面,转换为世界空间下的三角形:
    const meshGeometry = mesh.geometry;
    const triangle = new THREE.Triangle();
    const intersectionPoint = new THREE.Vector3();
    const intersections = [];
    
    for (let i = 0; i < meshGeometry.faces.length; i++) {
      const face = meshGeometry.faces[i];
      const v1 = meshGeometry.vertices[face.a].clone().applyMatrix4(mesh.matrixWorld);
      const v2 = meshGeometry.vertices[face.b].clone().applyMatrix4(mesh.matrixWorld);
      const v3 = meshGeometry.vertices[face.c].clone().applyMatrix4(mesh.matrixWorld);
      triangle.set(v1, v2, v3);
    
  • 遍历第二个网格的每条边,生成射线并检测与当前三角形的交点:
    const anotherGeo = anotherMesh.geometry;
      for (let j = 0; j < anotherGeo.faces.length; j++) {
        const anotherFace = anotherGeo.faces[j];
        // 遍历当前面的三条边
        const edges = [
          [anotherGeo.vertices[anotherFace.a], anotherGeo.vertices[anotherFace.b]],
          [anotherGeo.vertices[anotherFace.b], anotherGeo.vertices[anotherFace.c]],
          [anotherGeo.vertices[anotherFace.c], anotherGeo.vertices[anotherFace.a]]
        ];
        for (const [start, end] of edges) {
          const worldStart = start.clone().applyMatrix4(anotherMesh.matrixWorld);
          const worldEnd = end.clone().applyMatrix4(anotherMesh.matrixWorld);
          const ray = new THREE.Ray(worldStart, worldEnd.clone().sub(worldStart).normalize());
          if (ray.intersectTriangle(v1, v2, v3, false, intersectionPoint)) {
            intersections.push(intersectionPoint.clone());
          }
        }
      }
    }
    
  • 最后对结果去重:通过判断点之间的距离(比如小于0.001),剔除重复交点。

方法2:使用空间分割树或专用相交库

如果网格面数较多,手动遍历性能太差,可以用空间分割树(BSPTree)加速检测:

  • 为两个网格构建BSP树:
    const bsp1 = new THREE.BSPTree().fromGeometry(mesh.geometry, mesh.matrixWorld);
    const bsp2 = new THREE.BSPTree().fromGeometry(anotherMesh.geometry, anotherMesh.matrixWorld);
    
  • 调用树的相交方法获取所有相交片段,从中提取交点:
    const intersectResults = bsp1.intersectTree(bsp2);
    const intersections = intersectResults.map(res => res.point);
    

也可以使用专门的几何相交库(如实现了三角面两两相交算法的工具),这类库会优化遍历逻辑,提升检测效率。

关键注意事项

  • 先调用mesh.intersectsMesh(anotherMesh)判断是否相交,再执行交点检测,避免无意义计算。
  • 所有检测必须在同一坐标空间(如世界空间)进行,务必提前更新矩阵。
  • 处理浮点数精度问题,对检测到的交点做适当的精度修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:21:38