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

游戏引擎开发:如何计算射线与三角形的交点坐标?

射线-三角形相交检测获取交点坐标的最佳实现方式

我自研一款游戏引擎,此前完整实现了射线-三角形相交检测功能,目前仅能判断两者是否相交,我想获取交点的精确坐标,请问最佳实现方式是什么?

我准备了用于测试的最小可复现代码:

var cube = {
  "positions": [-1.0, -1.0, -1.0,
    1.0, -1.0, -1.0, -1.0, 1.0, -1.0,
    1.0, 1.0, -1.0, -1.0, -1.0, 1.0,
    1.0, -1.0, 1.0, -1.0, 1.0, 1.0,
    1.0, 1.0, 1.0

  ],
  "indices": [
    0, 3, 2,
    1, 3, 0,

    3, 1, 7,
    1, 5, 7,

    0, 4, 5,
    5, 1, 0,

    6, 2, 7,
    2, 3, 7,

    5, 4, 7,
    7, 4, 6,

    0, 6, 4,
    0, 2, 6

  ],
  "uv": [
    0.0, 0.0, 1.0, 1.0, 0.0, 1.0,
    1.0, 0.0, 1.0, 1.0, 0.0, 0.0,

    0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 0.0, 1.0, 1.0,

    0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 0.0, 0.0, 0.0,

    0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 0.0, 1.0, 1.0,

    0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
    0.0, 1.0, 1.0, 0.0, 1.0, 1.0,

    1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 1.0, 1.0, 0.0, 1.0
  ]
}

var camPos = [0, 0, -10];
var camRot = [0, 0, 0];

setInterval(() => {
  for (var j = 0; j < cube.indices.length; j += 3) {

    var startPos = [camPos[0], camPos[1], camPos[2]];
    var rotation = [-camRot[0], camRot[1], camRot[2]];
    var len = 1000000;

    var endPos = [
      startPos[0] + (len * Math.sin(rotation[1])),
      startPos[1] + (len * Math.tan(rotation[0])),
      startPos[2] + (len * Math.cos(rotation[1]))
    ];


    var dir = [
      endPos[0] - startPos[0],
      endPos[1] - startPos[1],
      endPos[2] - startPos[2],
    ];

    var v1 = [
      cube.positions[cube.indices[j] * 3],
      cube.positions[cube.indices[j] * 3 + 1],
      cube.positions[cube.indices[j] * 3 + 2]
    ];
    var v2 = [
      cube.positions[cube.indices[j + 1] * 3],
      cube.positions[cube.indices[j + 1] * 3 + 1],
      cube.positions[cube.indices[j + 1] * 3 + 2]
    ];
    var v3 = [
      cube.positions[cube.indices[j + 2] * 3],
      cube.positions[cube.indices[j + 2] * 3 + 1],
      cube.positions[cube.indices[j + 2] * 3 + 2]
    ];

    var u = [
      v2[0] - v1[0],
      v2[1] - v1[1],
      v2[2] - v1[2]
    ];

    var v = [
      v3[0] - v1[0],
      v3[1] - v1[1],
      v3[2] - v1[2]
    ];

    var n = [
      u[1] * v[2] - u[2] * v[1],
      u[2] * v[0] - u[0] * v[2],
      u[0] * v[1] - u[1] * v[0]
    ];

    var w0 = [
      startPos[0] - v1[0],
      startPos[1] - v1[1],
      startPos[2] - v1[2]
    ];

    var a = -(n[0] * w0[0] + n[1] * w0[1] + n[2] * w0[2]);
    var b = (n[0] * dir[0] + n[1] * dir[1] + n[2] * dir[2]);

    if (b < 0) {
      continue;
    }

    /*if(Math.abs(b) < 0.00001){
        if(a==0){
            //console.log("parallel");
            continue;}
        else{
            //console.log("not intersecting");
            continue;}
    }*/

    var r = a / b;

    //console.log(r);

    if (r <= 0 || r >= 1) {
      //console.log("not intersecting");
      continue;
    }

    var rd = [
      dir[0] * r,
      dir[1] * r,
      dir[2] * r
    ];

    var ii = [
      startPos[0] + rd[0],
      startPos[1] + rd[1],
      startPos[2] + rd[2]
    ];

    var uu = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
    var uv = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
    var vv = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];

    var w = [
      ii[0] - v1[0],
      ii[1] - v1[1],
      ii[2] - v1[2]
    ];

    var wu = w[0] * u[0] + w[1] * u[1] + w[2] * u[2];
    var wv = w[0] * v[0] + w[1] * v[1] + w[2] * v[2];

    var d = uv * uv - uu * vv;

    var s = (uv * wv - vv * wu) / d;
    if (s <= 0 || s > 1) {
      //console.log("not intersecting");
      continue;
    }
    var t = (uv * wu - uu * wv) / d;

    if (t <= 0 || (s + t) > 1) {
      //console.log("not intersecting");
      continue;
    }

    // use these values to find the point of intersection somehow??
    console.log(s + "," + t + "," + (s + t));
  }
  camRot[1] = Math.sin(Date.now() / 1000) * .1;
}, 10);

我的假设是利用边界检查返回的值,通过线性插值计算交点,但目前尚未成功,后续会反馈进展。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:45:04