3

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

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

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

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

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

谢谢您的帮助

4

5 回答 5

12

你说:

我想知道是否有一些教程或指南可以在 3D 环境中理解和实现三角形-三角形相交测试。

然后你说:

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

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

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

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

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

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

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

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

于 2009-12-14T21:51:53.337 回答
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;
    }
于 2011-02-03T20:51:57.770 回答
1

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

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

于 2009-12-14T22:03:49.970 回答
1

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

实时渲染对象/对象交叉页面

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

穆勒 jgt 2(2) ;
举行 jgt 2(4) ;
万维网
穆勒
GPG 第 393 页;
GTCG 第 539 页;
TGS ;
RTCD 第 155,172 页;
沉 jgt 8(1) ;
Guigue jgt 8(1) ;
软冲浪者
实时渲染,第 2 版,第 590 页;
实时渲染,第三版 p.757

于 2009-12-14T20:32:52.623 回答
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

于 2009-12-14T20:42:31.730 回答