Как исправить наматывание треугольников против часовой стрелки модели 3D Mesh?

Прежде всего, позвольте мне прояснить. Я не спрашиваю о 2D-сетке, определить порядок намотки 2D-сетки очень просто с направлением нормали-z.

Во-вторых, я не прошу никакого оптимизированного алгоритма, я не беспокоюсь о времени или скорости, я просто хочу сделать это со своей сеткой.

Когда я триангулирую трехмерный объект, используя алгоритм триангуляции жадной проекции, возникает эта проблема. проверьте прикрепленные изображения.

Если я применяю 2D-подходы к этой модели, используя «Рассчитать площадь со знаком» или «Перекрестное производство векторов AB и BC треугольника», он решает только 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);
    }
}

введите здесь описание изображения


person maxpayne    schedule 11.06.2013    source источник
comment
Чтобы распространить ориентацию, вы должны начать с треугольника, ориентацию которого вы хотите использовать для всей сетки, а затем распространить эту ориентацию на все соединенные треугольники. Это то же самое, какой алгоритм обхода (графа) использовать. Код выше распространяет ориентацию только на первых соседей.   -  person Ante    schedule 13.06.2013
comment
Что вы подразумеваете под распространением ориентации только на первых соседей? Я думаю, что у треугольника есть только три соседних треугольника, и я проверяю все три соседних треугольника, и если нахожу неправильное ребро, то меняю это ребро? ОК. В случае со сферой я начинаю треугольник, который является правильным, проверяя его вектор нормали к направлению z... но все еще не получая правильного результата.. Не могли бы вы объяснить мне немного больше.. Я решал эту проблему вопрос так много дней .. :)   -  person maxpayne    schedule 14.06.2013
comment
Начните с хорошего ориентированного треугольника, затем примените ту же ориентацию к его соседям, чем примените к соседям соседей, ... Это называется обход графа, поскольку связность треугольника можно рассматривать как граф.   -  person Ante    schedule 14.06.2013
comment
Спасибо, Анте, я очень ценю ваши усилия. Раньше я не знал об обходе графа, но теперь я знаю, я пытался его изучить, но все еще не понимаю, как его реализовать. Не могли бы вы написать мне короткий псевдокод? У меня есть вся информация о ребрах в массиве, так как же сделать цикл для проверки каждого треугольника с ребрами? Это сбивает с толку. Я очень старалась.. :)   -  person maxpayne    schedule 17.06.2013


Ответы (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))
person Ante    schedule 17.06.2013
comment
Большое спасибо. Сообщу после реализации. Думаю, я понял идею. Позвольте мне реализовать. :) - person maxpayne; 18.06.2013

Включает ли ваша сетка информацию о смежности ребер? т. е. каждый треугольник 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 = &TAB на ребре AB A и B должны стоять в обратном порядке для T и TE иметь одинаковую обмотку. например TAB = {{VB,VA,VD},{TBA,TAD,TDA}}, где TBA = &T. Это можно использовать, чтобы дать всем треугольникам одинаковую обмотку.

person SmacL    schedule 11.06.2013
comment
Спасибо, Шейн. Да, у меня есть смежные треугольники и ребра. Думаю, я могу понять, что вы имеете в виду. Подскажите, пожалуйста, как проверить намотку кромок? означает, как я могу узнать, что края находятся в том же или в обратном направлении? с нормальным вектором? Я пытался понять, но я думаю, что это выглядит сложно.. если (AB BC CA) правильный треугольник и (BC CD DB) неправильный, то то, что вы здесь говорите. Нужно ли мне проверять, имеют ли какие-либо ребра одни и те же вершины, если они имеют, то я должен сделать это три обратным? Не могли бы вы написать небольшой псевдокод. Большое спасибо. - person maxpayne; 11.06.2013
comment
@furqan, где у вас есть два соседних треугольника с разными обмотками, чтобы сделать обмотку одинаковой, просто измените порядок вершин на соседнем ребре, например. T={{VA,VB,VC},{TAB,TBC,TCA}} становится T={{VB,VA,VC},{TAB,TBC,TCA}} при условии, что изменение выполняется после проверки ребра AB. Обратите внимание, что смежности остаются прежними. Это необходимо проверять для каждого треугольника в TIN, отмечая исправленные и проверенные треугольники по ходу дела. - person SmacL; 12.06.2013
comment
пожалуйста, проверьте мое обновление. Я обновил результаты своего алгоритма. Я думаю, что алгоритм в порядке, потому что он пытается исправить, но я думаю, что я должен проверить еще несколько случаев. Почему он не исправляет намотку треугольников сферы.. Пожалуйста, проверьте мой алгоритм и помогите мне сейчас. где я сделал не так? Спасибо. - person maxpayne; 12.06.2013