【问题标题】:How to correct winding of triangles to counter-clockwise direction of a 3D Mesh model?如何将三角形的缠绕校正为 3D Mesh 模型的逆时针方向?
【发布时间】:2013-06-06 21:09:15
【问题描述】:

首先让我清楚.. 我不是在询问 2D 网格,要确定 2D 网格的缠绕顺序很容易使用 normal-z 方向。

其次,我不问任何优化算法,我不担心时间或速度,我只想用我的网格来做。

当我使用贪心投影三角剖分算法对 3D 对象进行三角剖分时,会发生此问题。 检查附加的图像。

如果我使用“计算有符号面积”或“三角形的 AB 和 BC 向量的交叉产生”对该模型应用 2D 方法,它只能解决 2D 网格,但 3D 网格呢?

首先我们需要检查 3D 网格中哪些三角形的缠绕方向错误,然后我们只考虑这些三角形,那么问题是,我们如何检查 3D 中哪些三角形的缠绕方向错误?我们不能只使用我测试过但没有成功的 2D 方法。

例如,在球体的情况下,我们不能将 2D 方法应用于球体。 那么有什么办法可以解决这个问题吗?

谢谢。

更新 #1:

以下是检查哪条边具有相同绕组的算法。效果不好,不知道为什么。理论上它应该纠正所有的三角形,但它没有纠正。例如,在附图中进行球体检查的情况下。它有问题。

void GLReversedEdge(int i, int j, GLFace *temp)
{
    //i'th triangle
    int V1 = temp[i].v1;
    int V2 = temp[i].v2;
    int V3 = temp[i].v3;

    //i'th triangle edges
    int E1[] ={V1, V2};
    int E2[] ={V2, V3};
    int E3[] ={V3, V1};

    //adjacent triangle
    int jV1 = temp[j].v1;
    int jV2 = temp[j].v2;
    int jV3 = temp[j].v3;

    //adjacent edges
    int jE1[] ={jV1, jV2};
    int jE2[] ={jV2, jV3};
    int jE3[] ={jV3, jV1};

    // 1st edge of adjacent triangle is checking with all edges of ith triangle
    if((jE1[0] == E1[0] && jE1[1] == E1[1]) ||
       (jE1[0] == E2[0] && jE1[1] == E2[1]) ||
       (jE1[0] == E3[0] && jE1[1] == E3[1]))
    {
       temp[j].set(jV2, jV1, jV3);      // 1st edges orientation is same, so reverse/swap it
    }
    // 2nd edge of adjacent triangle is checking with all edges of ith triangle
    else if((jE2[0] == E1[0] && jE2[1] == E1[1]) ||
            (jE2[0] == E2[0] && jE2[1] == E2[1]) ||
            (jE2[0] == E3[0] && jE2[1] == E3[1]))
    {
            temp[j].set(jV1, jV3, jV2); // 2nd edges orientation is same, so reverse/swap it
    }
    // 3rd edge of adjacent triangle is checking with all edges of ith triangle
    else if((jE3[0] == E1[0] && jE3[1] == E1[1]) ||
            (jE3[0] == E2[0] && jE3[1] == E2[1]) ||
            (jE3[0] == E3[0] && jE3[1] == E3[1]))
    {
            temp[j].set(jV3, jV2, jV1); // 3rd edges orientation is same, so reverse/swap it
    }
}

void GetCorrectWindingOfMesh()
{
    for(int i=0; i<nbF; i++)
    {
        int j1 = AdjacentTriangleToEdgeV1V2;
        if(j1 >= 0) GLReversedEdge(i, j1, temp);

        int j2 = AdjacentTriangleToEdgeV2V3;
        if(j2 >= 0) GLReversedEdge(i, j2, temp);

        int j3 = AdjacentTriangleToEdgeV3V1;
        if(j3 >= 0) GLReversedEdge(i, j3, temp);
    }
}

【问题讨论】:

  • 要传播方向,您必须从要用于整个网格的三角形开始,然后将该方向传播到所有连接的三角形。使用哪个(图)遍历算法是相同的。上面的代码只向第一个邻居传播方向。
  • “仅向第一邻居传播方向”是什么意思?我认为一个三角形只有三个相邻的三角形,我正在检查所有三个相邻的三角形,如果发现一个错误的边然后交换那个边?好的,如果是一个球体,我通过检查它的法线向量到 z 方向来开始一个正确的三角形..但仍然没有得到正确的结果..你能否再解释一下..我一直在解决这个问题这么多天以来的问题.. :)
  • 从一个好的定向三角形开始,而不是对其邻居应用相同的方向,而不是应用到邻居的邻居,...这称为graph traversal,因为三角形连接可以看作是一个图形。
  • 谢谢安特,我真的很感谢你的努力。我以前不知道图遍历,但现在我知道了,我尝试学习它,但仍然对如何实现它感到困惑。你能帮我写一个简短的伪代码吗?我有一个数组中的所有边缘信息,那么如何创建一个循环来检查每个带边缘的三角形?它令人困惑。我真的很努力.. :)

标签: algorithm computational-geometry mesh triangulation normals


【解决方案1】:

要检索相邻信息,假设我们有一个方法可以返回给定边 neighbor_on_egde( next_tria, edge ) 上三角形的邻居。

该方法可以通过使用三角形的每个顶点的信息来实现。那是将顶点索引映射到三角形索引列表的字典结构。它很容易通过传递三角形列表并在右字典元素中设置三角形的每个三角形顶点索引来创建。

遍历是通过存储要检查方向的三角形以及已经检查过的三角形来完成的。虽然有三角形要检查,但要检查它并添加它的邻居,如果它们没有被检查。伪代码如下:

to_process = set of pairs triangle and orientation edge
             initial state is one good oriented triangle with any edge on it
processed = set of processed triangles; initial empty

while to_process is not empty:
    next_tria, orientation_edge = to_process.pop()
    add next_tria in processed
    if next_tria is not opposite oriented than orientation_edge:
        change next_tria (ABC) orientation  (B<->C)
  for each edge (AB) in next_tria:
      neighbor_tria = neighbor_on_egde( next_tria, edge )
      if neighbor_tria exists and neighbor_tria not in processed:
          to_process add (neighbor_tria, edge opposite oriented (BA))

【讨论】:

  • 非常感谢。我会在实施后通知您。我想我明白了。让我执行。 :)
【解决方案2】:

您的网格是否包含边缘邻接信息?即每个三角形 T 包含三个顶点 A、B、C 和三个边 AB、BC 和 CA,其中 AB 是三角形 T1 的链接,它共享公共顶点 A、B 并包含一个新顶点 D。类似于

struct Vertex 
{
 double x,y,z;
};

struct Triangle
{
   int vertices[3],edges[3];
};


struct TriangleMesh
{
   Vertex Vertices[];
   Triangle Triangles[];
};

如果是这种情况,对于任何三角形 T = {{VA,VB,VC},{TAB,TBC,TCA}},在边 AB 处相邻的 TE = &TAB,A 和 B 必须以相反的顺序出现T 和 TE 具有相同的绕组。例如TAB = {{VB,VA,VD},{TBA,TAD,TDA}} 其中 TBA = &T。这可用于为所有三角形提供相同的绕组。

【讨论】:

  • 谢谢谢恩。是的,我有相邻的三角形和边缘。我想我能理解你的意思。你能告诉我如何检查边缘的缠绕吗?意味着我怎么知道边缘是相同的还是相反的?与法线向量?我试图理解,但我认为它看起来很复杂.. 如果(AB BC CA)正确的三角形和(BC CD DB)是错误的,那么你在这里所说的。我是否需要检查是否有任何边缘共享相同的顶点,如果他们这样做,那么我应该使三反转?你能写一些小的伪代码吗?非常感谢。
  • @furqan,您有两个具有不同绕组的相邻三角形,要使绕组相同,只需更改相邻边上的顶点顺序,例如T={{VA,VB,VC},{TAB,TBC,TCA}} 变为 T={{VB,VA,VC},{TAB,TBC,TCA}} 假设在检查边缘 AB 后进行更改。请注意,邻接关系保持不变。这需要检查 TIN 中的每个三角形,并在进行时标记已修正和检查的三角形。
  • 请检查我的更新。我已经更新了我的算法结果。我认为算法没问题,因为它试图纠正,但我认为我应该检查更多案例。为什么它没有纠正球体三角形的缠绕。请检查我的算法并立即指导我。我哪里做错了?谢谢。
猜你喜欢
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
相关资源
最近更新 更多