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

在Three.js中计算立方体与平面的相交情况

THREE.js 平面与变换后立方体的相交判断及相交信息获取

一、判断是否相交

核心思路是将世界空间的平面转换到立方体局部坐标系,简化单位立方体的相交判断:

  1. 获取立方体的世界变换矩阵:若使用THREE.Mesh,取mesh.matrixWorld;若直接操作几何体,取geometry.matrix。
  2. 计算变换矩阵的逆矩阵:
    const inverseMatrix = new THREE.Matrix4().getInverse(mesh.matrixWorld);
    
  3. 将世界平面转换到立方体局部坐标系:
    const localPlane = plane.clone().applyMatrix4(inverseMatrix);
    
  4. 定义单位立方体的8个局部顶点(THREE.BoxGeometry(1,1,1)的顶点范围是±0.5):
    const localVertices = [
      new THREE.Vector3(-0.5, -0.5, -0.5),
      new THREE.Vector3(0.5, -0.5, -0.5),
      new THREE.Vector3(0.5, 0.5, -0.5),
      new THREE.Vector3(-0.5, 0.5, -0.5),
      new THREE.Vector3(-0.5, -0.5, 0.5),
      new THREE.Vector3(0.5, -0.5, 0.5),
      new THREE.Vector3(0.5, 0.5, 0.5),
      new THREE.Vector3(-0.5, 0.5, 0.5)
    ];
    
  5. 遍历顶点计算平面距离的符号:
    let hasPositive = false;
    let hasNegative = false;
    let hasZero = false;
    const eps = 1e-6;
    for (const v of localVertices) {
      const dist = localPlane.distanceToPoint(v);
      if (dist > eps) hasPositive = true;
      else if (dist < -eps) hasNegative = true;
      else hasZero = true;
    }
    
  6. 相交判定:
    • 若hasPositive && hasNegative:必然相交;
    • 若hasZero && !(hasPositive || hasNegative):平面包含立方体的部分顶点/棱/面,属于相交;
    • 其余情况:不相交。

二、确定相交形态

基于局部坐标系下的交点数量和连接关系判断:

  • 退化形态:
    • 点:仅1个交点(平面切中立方体顶点,其余顶点全在同侧);
    • 线段:仅2个交点(平面切过一条棱,或与两个平行面各交一条棱);
  • 非退化形态:
    • 三角形:3个交点,平面与立方体3个面相交;
    • 平行四边形:4个交点,平面与立方体4个两两平行的面相交;
    • 六边形:6个交点,平面与立方体6个面各交一条棱。

三、获取相交顶点坐标

2.1 立方体自身参考系(局部坐标系)坐标

  1. 定义立方体的12条棱:
    const edges = [
      [0,1], [1,2], [2,3], [3,0],
      [4,5], [5,6], [6,7], [7,4],
      [0,4], [1,5], [2,6], [3,7]
    ];
    
  2. 遍历棱计算交点:
    const localIntersects = [];
    const eps = 1e-6;
    for (const [i1, i2] of edges) {
      const v1 = localVertices[i1];
      const v2 = localVertices[i2];
      const d1 = localPlane.distanceToPoint(v1);
      const d2 = localPlane.distanceToPoint(v2);
    
      // 两点在平面两侧,计算交点
      if (d1 * d2 < -eps) {
        const t = Math.abs(d1) / (Math.abs(d1) + Math.abs(d2));
        const intersect = v1.clone().lerp(v2, t);
        localIntersects.push(intersect);
      }
      // 顶点在平面上,去重后加入
      else if (Math.abs(d1) <= eps) {
        if (!localIntersects.some(p => p.distanceToSquared(v1) <= eps * eps)) {
          localIntersects.push(v1.clone());
        }
      }
      else if (Math.abs(d2) <= eps) {
        if (!localIntersects.some(p => p.distanceToSquared(v2) <= eps * eps)) {
          localIntersects.push(v2.clone());
        }
      }
    }
    
  3. 对交点排序(可选,用于得到有序的截面轮廓):
    将交点投影到平面内的二维坐标系,按极角排序即可。

2.2 标准参考系(世界坐标系)坐标

将局部交点通过立方体的世界变换矩阵转换:

const worldIntersects = localIntersects.map(p => p.clone().applyMatrix4(mesh.matrixWorld));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:42:50