用于计算大量三角形的3D射线/三角形边缘交点的快速算法

时间:2017-02-12 14:54:43

标签: algorithm graphics 3d geometry computational-geometry

我在3D空间中有一个三角形ABC,并且在起点E(总是在三角形边缘内部或在三角形边缘上)和方向矢量d给出三角形平面内的光线。

顶点A,B和C以及E和d以3D坐标{x,y,z}给出。

我正在寻找一种算法来计算光线与三角形边缘P的交点。

我可以对三角形的3个边缘进行3次射线/线段交叉测试,但由于我必须为大量三角形做这个,我正在寻找更高效,更快的算法。

  1. 这样做的最佳方式是什么?
  2. 重心坐标有帮助吗?
  3. enter image description here

4 个答案:

答案 0 :(得分:1)

  1. 时间复杂度为O(1)
  2. 它可能会有所帮助。 如果我们谈论3D并且你的所有点都在一个平面上。在笛卡尔坐标系中,您需要求解三个线性系统以找到三条线的交点,然后确定交叉点是否位于边缘。 或者你需要在线找到两点的重心坐标。点A(a1,a2,a3)= E和B(b1,b2,b3)= E + d。线的方程是 enter image description here 现在你仍然需要解决三个线性系统(其中一个mu = 0,其他一个= 1)。但它将是2x2系统,更容易解决。然后检查找到根的信号,以确定发现的点是否位于边缘。

答案 1 :(得分:1)

  

重心坐标可以帮助吗?

可能。这取决于你的非重心代码有多高度优化,但我说使用重心坐标至少更容易编写既可维护又高效的代码。

据我所知,您的整个设置基本上是2d,E点和方向d都包含在A,B,C所跨越的平面内。你有

E = aE*A + bE*B + cE*C  with aE+bE+cE=1
d = ad*A + bd*B + cd*C  with ad+bd+cd=0

现在你有两个子问题:

  1. 如何有效地获得重心坐标
  2. 如何找到交叉点
  3. 让我们从后者开始吧。您只需将E的倍数添加到d,直到c坐标变为零。

    P = E - (cE/cd)*d
    

    根据您的设置,您可能也可以使用齐次坐标,在这种情况下,您可以将其写为P = cd*E - cE*d

    如何将x,y,zd的{​​{1}}坐标转换为重心E?那么,这只是一个线性方程组。您可以使用由向量a,b,c形成的矩阵的逆矩阵。同样,如果您正在处理齐次坐标,则可以使用adjunct而不是inverse。

    这是拼写出来的同质方法:

    A,B,C

    前三行将aE = (By*Cz-Bz*Cy)*Ex + (Bz*Cx-Bx*Cz)*Ey + (Bx*Cy-By*Cx)*Ez bE = (Cy*Az-Cz*Ay)*Ex + (Cz*Ax-Cx*Az)*Ey + (Cx*Ay-Cy*Ax)*Ez cE = (Ay*Bz-Az*By)*Ex + (Az*Bx-Ax*Bz)*Ey + (Ax*By-Ay*Bx)*Ez ad = (By*Cz-Bz*Cy)*dx + (Bz*Cx-Bx*Cz)*dy + (Bx*Cy-By*Cx)*dz bd = (Cy*Az-Cz*Ay)*dx + (Cz*Ax-Cx*Az)*dy + (Cx*Ay-Cy*Ax)*dz cd = (Ay*Bz-Az*By)*dx + (Az*Bx-Ax*Bz)*dy + (Ax*By-Ay*Bx)*dz aP = cd*aE - cE*ad bP = cd*bE - cE*bd Px = aP/(aP+bP)*Ax + bP/(aP+bP)*Bx Py = aP/(aP+bP)*Ay + bP/(aP+bP)*By Pz = aP/(aP+bP)*Az + bP/(aP+bP)*Bz 转换为重心坐标,接下来的三行E。然后我们计算d的重心坐标,并将它们转回笛卡尔坐标。在那一步中,我们也将它们去均匀化,即除以重心坐标的总和。

    总的来说,这里有相当多的代码。您可以通过将常用表达式移动到专用变量来减少操作数,特别是如果您的编译器没有为您执行此操作。一个好处是,除了最终的非均匀化,即除P之外,你不需要任何划分。如果你计算(a+b)一次,你可以用一个分区来做,这对性能有好处。

    上述代码的真正好处可能是您可以使用重心坐标做很多好事,而这些坐标对于其他坐标系统并不容易。例如,如果要检查光线是否到达线段上的线1/(a+b)或三角形外的某处,请检查是否AB

答案 2 :(得分:1)

暂时忽略d具有最小组件的轴,并处理生成的2D问题,就像我们在插图中看到的那样。

您可以预先计算光线支撑线的方程式,形式为ax + by + c = 0(假设z被忽略)。在此表达式中插入三个顶点的坐标,符号将告诉您顶点的哪一侧。

与线的两个交点出现在端点处具有不同符号的边缘上。

然后,为了确定哪个是右边缘,光线和第三个边缘之间的角度符号会做(如果我是对的);

当您知道哪条边时,您可以计算边的参数方程的参数,您可以从先前计算的符号中推导出该参数。例如,沿着边缘AB,t = Sb /(Sb-Sa)。同时计算1 - t;

最后,使用t值在端点之间进行插值,这次是3D。

计算成本

  • 评估Sa,Sb,Sc三个符号,取6 +和6 x;

  • 选择两个边缘候选者,进行两次或三次比较;

  • 选择单个候选者,采用2D交叉积,3 +和2 x并进行比较;

  • 计算插值参数,2 +,1 /;

  • 最终3D插值,3 +,6 x。

很难做得更短。

答案 3 :(得分:0)

见论文

  

Fast, minimum storage ray-triangle intersection,   作者:TomasMöller和Ben Trombone,   在   图形工具杂志,2(1):21-28,1997。

另见this page

作者说:

  

这种方法的一个优点是平面方程不需要在运行中计算也不需要存储,这可以节省三角网格的显着内存节省。由于我们发现我们的方法在速度上与以前的方法相当,我们认为它是没有预先计算平面方程的三角形中最快的光线 - 三角形交叉例程。