如何纠正三角形到三维网格模型逆时针方向的缠绕?

时间:2013-06-11 05:21:05

标签: algorithm computational-geometry mesh triangulation normals

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

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

当我使用Greedy Projection Triangulation算法对3D对象进行三角测量时,会出现此问题。 检查附图。

如果我使用“计算签名区域”或“三角形的AB和BC矢量的交叉生成”将2D方法应用于此模型,它只能解决2D网格但3D网格怎么样?

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

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

感谢。

enter image description here enter image description here

更新#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);
    }
}

enter image description here

2 个答案:

答案 0 :(得分: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}},邻居TE =&amp; TAB在AB边缘,A和B必须出现在反向为了使T和TE具有相同的绕组。例如TAB = {{ VB,VA ,VD},{TBA,TAD,TDA}},其中TBA =&amp; T。这可用于为所有三角形提供相同的绕组。

答案 1 :(得分:2)

要检索邻近信息,我们假设我们有在给定边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))