如何计算三角射线交点的坐标?

How do I calculate the coordinates of a triangle-ray intersection?

提问人:rbw 提问时间:11/13/2023 最后编辑:rbw 更新时间:11/13/2023 访问量:48

问:

所以我正在编写自己的游戏引擎,我最近写了一个三角射线跨扇区(我写的意思是从本教程中批发复制而来的)。截至目前,只有当光线和三角形相交时,它才会贯穿整个函数,虽然这很有帮助,但我想知道如何获得相交点的确切坐标。那么,您认为最好的方法是什么?

为了便于实验,我准备了一个最小可重复的例子:

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);

我目前的假设是,解决这个问题的最好方法是从检查光线是否在三角形边界内时返回的值来解释它,我一直在尝试通过点之间的线性插值来让它工作,边界计算返回的值为 t 值。我还没有让它工作,但如果它工作,我会告诉你。

JavaScript 数学 游戏引擎

评论

1赞 Gabriele Petrioli 11/13/2023
您已经在 中拥有交点(与平面)。随后的代码是检查该点是否位于三角形内。如果它确实位于三角形中,那么它就是您想要的点。ii
0赞 rbw 11/13/2023
是的,这奏效了。谢谢!有时我倾向于把最简单的事情复杂化。
0赞 Giorgio Tempesta 11/13/2023
@GabrielePetrioli可以发布它作为答案吗?所以它可以被接受并帮助其他人。

答: 暂无答案