【问题标题】:Triangle - Triangle Intersection Test三角形 - 三角形相交测试
【发布时间】:2009-12-14 20:24:07
【问题描述】:

我想知道是否有一些教程或指南可以在 3D 环境中理解和实现三角形-三角形相交测试。 (我不需要知道确切的交叉点发生在哪里,只需要知道交叉点发生了)

我打算按照理论上的 pdf 来实现它,但我很卡在

  1. 计算三角形 2 的平面方程。
  2. 如果三角形 1 的所有点都在同一侧,则拒绝为微不足道。
  3. 计算三角形 1 的平面方程。
  4. 如果三角形 2 的所有点都在同一侧,则拒绝为微不足道。
  5. 计算相交线并投影到最大轴上。
  6. 计算每个三角形的间隔。
  7. 相交区间。

本指南的第 5 点。我真的不知道在问什么(所有 5,6 和 7)。呵呵

由于我的数学知识不高(嗯,我知道大学的几门考试给了我(我是一个原始程序员 XD)),请尽量简单我。 :D(我尝试在 google 上搜索,但大多数链接都指向一些 4-5 页的公式,其中充满了我不太想知道也不懂的公式。)

感谢您的帮助

【问题讨论】:

  • 这是 3D 还是 2D 的问题?
  • 一般原始程序员也需要理解数学:-P
  • 说真的,如果你不理解它就不要实现它。如果您选择实施它并且它稍后会中断(或者实际上从一开始就无法正常工作),那么您无法确定原因,甚至无法确定它是否已损坏。我并不是说不要实施它我是说不要跳过首先理解它所需的时间投资。
  • 嗯……它是 3D 的。我只知道简单的数学对不起。 XD
  • 我正在努力理解它,但是我在网上找到的所有理论信息只会让我用大量的公式等等......:(

标签: c# math physics collision-detection collision


【解决方案1】:

你说:

我想知道外面有没有 一些教程或指南来理解 并实现一个三角形-三角形 在 3D 环境中进行交叉测试。

然后你说:

大多数链接指向一些 4-5 充满公式的页面我真的不知道 想知道

我注意到这两个陈述完全相互矛盾。那么它是哪一个?您想了解三角形-三角形相交的工作原理,还是只是想要一个可行但您不理解的实现?

并不是所有这些网页都充满了不必要的数学。所有数学都是必要的,以了解交集算法的工作原理。从头开始,了解它是如何工作的。

一旦您知道这些词的含义,第 5 步、第 6 步和第 7 步就很容易理解。相交线是由两个平面相交形成的线。每个三角形位于一个平面内。分三种情况:

  • 平面平行且不相交。三角形显然不相交。
  • 这些位面是同一个位面。三角形可能会相遇,也可能不会。
  • 平面是在一条线上相交的两个不同平面。如果三角形相交,它们显然必须在这条线上相交。

假设我们处于第三种情况。计算包含在第一个三角形中的相交线段。计算第二个三角形中的相交线段。现在的问题是“这些部分是否重叠?”

您可以通过将线段投影到方便的轴上并查看该轴上的线段是否重叠来解决此问题。基本上,它的工作原理是这样的:想象你正在线段上照射一盏灯,这样它们的阴影就会落在一个轴上。如果轴上的阴影相交,则线段必须相交。如果轴上的阴影之间存在间隙,那么显然线段之间肯定存在间隙,因此三角形不会相交。

如果您想了解这是如何工作的,那么您将需要了解所有这些东西——所有计算平面如何相交和项目如何进行的代数,这是无法回避的事实到轴工作。这都是必要的。所有这些东西都是基本构建块,将构建更复杂的转换、投影等,因此如果您想走得更远,请彻底了解基础知识。

【讨论】:

  • 很好的解释。如果那些 pdf 以这种方式解释,我不会因为试图理解而窒息。 :D 问题解决了。
  • @feal87:这里的重要课程是学习如何从所提供的公式中提取洞察力。也就是说,既然已经向您解释了公式背后的见解,您是否可以通过公式并看到这些见解?将来您能否利用这些经验自行提取见解?
【解决方案2】:

我的答案很简单......这个问题在任意坐标系中都很难,所以将其更改为使问题变得简单的东西。 xna 中的 Matrix 类有一个 CreateLookAt 函数,可用于在所有顶点上创建有用的转换。

下面的例子没有优化,只是为了理解解决方案而写的。异常及其对应的 if 语句都可以删除,以及一些向量转换。

    public static bool CheckColision(Vector3 t1a, Vector3 t1b, Vector3 t1c, Vector3 t2a, Vector3 t2b, Vector3 t2c)
    {//rotates each edge of the first triangle to the Z axis and checks the second triangle against it then repeats with the second one against the first, and lastly checks to see if all points of the second triangle are on the same side as the first
        if(! CheckColisionLookAt(t1a, t1b, t1c, t2a, t2b, t2c))
            return false;
        if (!CheckColisionLookAt(t1b, t1c, t1a, t2a, t2b, t2c))
            return false;
        if (!CheckColisionLookAt(t1c, t1a, t1b, t2a, t2b, t2c))
            return false;

        if (!CheckColisionLookAt(t2a, t2b, t2c, t1a, t1b, t1c))
            return false;
        if (!CheckColisionLookAt(t2b, t2c, t2a, t1a, t1b, t1c))
            return false;
        if (!CheckColisionLookAt(t2c, t2a, t2b, t1a, t1b, t1c))
            return false;

        return CheckColisionAllOnOneSide(t1a, t1b, t1c, t2a, t2b, t2c);
    }

    public static bool CheckColisionAllOnOneSide(Vector3 t1a, Vector3 t1b, Vector3 t1c, Vector3 t2a, Vector3 t2b, Vector3 t2c)
    {//simply performs a transformation to check if all points on one triangle are on the same side of the other triangle
        Matrix m = Matrix.CreateLookAt(t1a, t1b, t1c - t1a);
        t2a = Vector3.Transform(t2a, m);
        t2b = Vector3.Transform(t2b, m);
        t2c = Vector3.Transform(t2c, m);
        if (t2a.X < 0 && t2b.X < 0 && t2c.X < 0)
            return false;
        if (0 < t2a.X && 0 < t2b.X && 0 < t2c.X)
            return false;
        return true;
    }

    public static bool CheckColisionLookAt(Vector3 t1a, Vector3 t1b, Vector3 t1c, Vector3 t2a, Vector3 t2b, Vector3 t2c)
    {//performs a transformation and checks if all points of the one triangle are under the other triangle after the transformation

        Matrix m = Matrix.CreateLookAt(t1a, t1b, t1c - t1a);
        t1a = Vector3.Transform(t1a, m);//  (0,     0,      0)
        if ( ZERRO < Math.Abs(t1a.X)|| ZERRO < Math.Abs(t1a.Y) || ZERRO < Math.Abs(t1a.Z))
            throw new Exception();
        t1b = Vector3.Transform(t1b, m);//  (0,     0,      maxZ)
        if (ZERRO < Math.Abs(t1a.X) || ZERRO < Math.Abs(t1a.Y))
            throw new Exception();
        t1c = Vector3.Transform(t1c, m);//  (0,     maxY,   someZ)
        if (ZERRO < Math.Abs(t1a.X))
            throw new Exception();
        t2a = Vector3.Transform(t2a, m);
        t2b = Vector3.Transform(t2b, m);
        t2c = Vector3.Transform(t2c, m);
        if (t2a.Y < 0 && t2b.Y < 0 && t2c.Y < 0)
            return false;
        return true;
    }

【讨论】:

    【解决方案3】:

    这是一个网站,其中包含对许多交叉点的引用:

    Real-Time Rendering Object/Object Intersection Page

    这是他们为 Tri/Tri 列出的内容:

    Möller jgt 2(2);
    Held jgt 2(4);
    GTweb;
    Möller;
    GPG p.393;
    GTCG p.539;
    TGS ;
    RTCD p.155,172;
    Shen jgt 8(1);
    Guigue jgt 8(1);
    SoftSurfer;
    实时渲染,第 2 版 p.590;
    实时渲染,第三版 p.757

    【讨论】:

    • 我正在查看此链接中的代码...希望我能理解它们。 XD
    【解决方案4】:

    我想你有三角形顶点的 x,y 坐标。 例如。
    对于三角形 A:
    1. A1面:xa1, ya1 2. A2面:xa2,ya2 3. A3面:xa3,ya3 对于三角形 B:
    1. B1面:xb1,yb1 2. B2面:xb2,yb2 3. B3面:xb3,yb3

    如果它们的线的任何组合相交,则三角形相交。表示 A1 是否与 B1 或 B2 或 B3 相交,或者 A2 是否与 B1 或 B2 或 B3 相交,或者 A3 是否与 B1 或 B2 或 B3 相交。

    因此,您需要检测两条线是否相交的算法。这是我找到的最简单的例子:http://www.mathopenref.com/coordintersection.html

    【讨论】:

    • 对不起,我的问题不是很准确。我在 3D 环境中谈论三角形。
    • 这不是一个正确的算法。如果一个三角形完全在另一个三角形内怎么办?然后它们的边都不相交,但三角形相交。
    • 在帕帕迪描述的检查之后,您可以计算两个三角形的面积。取较小的任意一点,通过将该点连接到较大三角形的每个点来创建 3 个新三角形。然后计算 3 个新三角形的面积。如果它与最大三角形的面积完全匹配,则较小的三角形在较大的三角形内。这不是最有效的方法,但如果您想让数学尽可能简单,这是很好的。
    【解决方案5】:

    您发布的方法看起来像是使用类似于this algorithm 的东西来检测凸多边形是否相交,基于分离轴定理。理解起来并不难。

    如果可以在两个多边形之间绘制一条称为分离轴的线,则它们不会相交。每个多边形的每条边都是一个候选分离轴。将多边形投影到垂直于该轴的矢量上,并测试一维范围是否重叠。如果没有一维重叠,则当前边是分离轴,两个多边形不相交。如果存在 1D 重叠,则在测试所有候选边之前,结果是不确定的,此时可以得出结论,这两个多边形确实相交。请注意,允许两个多边形共享一条边。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-08
      • 2015-11-21
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多