如何获取两个相交网格的全部交点?已知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
相关产品推荐
相关产品推荐

