三角形 - 三角交叉测试

时间:2009-12-14 20:24:08

标签: c# math physics collision-detection collision

我想知道是否有一些教程或指南来理解和实现3D环境中的三角形 - 三角形交叉测试。 (我不需要知道交叉点发生的确切位置,但只知道交叉点已经发生)

我打算按照理论上的pdf来实现它,但我非常坚持

  1. 三角形的计算平面方程2.
  2. 如果三角形1的所有点都在同一侧,则拒绝为琐碎。
  3. 三角形的计算平面方程1.
  4. 如果三角形2的所有点都在同一侧,则拒绝为琐碎。
  5. 计算交叉线并将项目计算到最大轴上。
  6. 计算每个三角形的间隔。
  7. 相互间隔。
  8. 本指南的第5点。我真的不知道要问的是什么(全部是5,6和7)。 XD

    由于我对数学知之甚少(嗯,我知道大学的几门考试给了我(我是一名原始程序员XD)),请尽可能简单我。 :D(我试图在谷歌搜索,但大多数链接指向大约4-5页的公式,我真的不在乎知道,我不明白。)

    感谢您的帮助

5 个答案:

答案 0 :(得分:12)

你说:

  

我想知道是否有   一些教程或指南来理解   并实现三角形三角形   3D环境中的交叉点测试。

然后你说:

  

大多数链接指向4-5   充满公式的页面我并不是真的   关心

我注意到这两个陈述完全相互矛盾。那是哪个呢?您想了解三角形 - 三角形交叉点的工作原理,还是只想要一个有效但无法理解的实现?

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

一旦你知道单词的含义,就可以直接理解步骤5,6和7。交叉线是两个平面的交点所形成的线。每个三角形都在一个平面上。有三种情况:

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

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

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

如果你想了解它是如何工作的那么你就不需要了解你需要理解所有这个东西的事实 - 解决了飞机如何相交的所有代数以及项目的方式在轴上工作。这一切都是必要的。所有这些东西都是基本的构建块,其中将构建更复杂的转换,投影等,因此如果您想要更进一步,请彻底了解基础知识。

答案 1 :(得分: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;
    }

答案 2 :(得分:1)

这是一个包含许多交叉点参考的网站:

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;
实时渲染,第3版p.757

答案 3 :(得分:1)

我想你有三角形顶点的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

答案 4 :(得分:1)

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

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