Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++, Grafika 3D] Dzielenie ścian na trójkąty - Face Triangulation

Ostatnio zmodyfikowano 2015-01-09 14:25
Autor Wiadomość
RazzorFlame
Temat założony przez niniejszego użytkownika
[C++, Grafika 3D] Dzielenie ścian na trójkąty - Face Triangulation
» 2015-01-08 22:59:24
Wiele szukałem artykułów o dzieleniu ścian z liczbą wierzchołków > 3 (bo przecież po co dzielić trójkąt na ten sam trójkąt :D). Niestety moje wysiłki nic nie dały, dlatego musiałem działaś na własną rękę.
Zaczynamy:

Dodatkowe potrzebne informacje:
Kurs STL | std::vector

Naszym celem będzie utworzenie trójkątnych face-ów z dajmy na to czterokątnych face-ów. Tutaj mamy wizualizację:
Wizualizacja
Z tej ściany utworzymy dwie ściany trójkątne. Początkowo indeksy naszej ściany będą wyglądały tak:
0 1 2 3
Oto wynik algorytmu, który zaraz opiszę:
Ściana 1:
0 1 2
Ściana 2:
0 2 3

Załóżmy, że wczytujemy plik z naszą geometrią czyli np. obiekt.obj Odczytujemy z niego indeksy czterokątnej ściany (0 1 2 3) do vectora. Oto algorytm:
C/C++
// Wejscie
std::vector < DWORD > faceIndices;

// Wyjscie
std::vector < DWORD > triangulatedFaceIndices;

// Petla ktora obiega kazdy wczytany indeks sciany
for( UINT i = 0; i < faceIndices.size(); i++ )
{
    // Pierwsze trzy indeksy i tworzymy z nich trojkat
    // Gdy odczytamy juz trzy indeksy to z kazdym nastepnym robimy to:
    if( i >= 3 )
    {
        triangulatedFaceIndices.push_back( faceIndices[ 0 ] );
        triangulatedFaceIndices.push_back( faceIndices[ i - 1 ] );
        triangulatedFaceIndices.push_back( faceIndices[ i ] );
    }
    else
         triangulatedFaceIndices.push_back( faceIndices[ i ] );
   
}
I oto mamy cały algorytm. Teraz trzeba go omówić ;)
Musimy przeiterować po każdym indeksie z wejścia, użyjemy do tego pętli for. Następnie wczytujemy pierwsze trzy indeksy (tworza one pierwszy trójkąt).
Kiedy już go wczytamy to przed każdy kolejny indeks dodajemy pierwszy indeks z wejścia oraz (i-1)-ty element wejścia.
Tym oto sposobem "strójkątujemy" nawet 45-ścian, oto przykład:
C/C++
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector < short > wejscie, wyjscie;
   
    for( int i = 0; i < 45; i++ )
         wejscie.push_back( i );
   
   
    // Petla ktora obiega kazdy wczytany indeks sciany
    for( int j = 0; j < wejscie.size(); j++ )
    {
        // Pierwsze trzy indeksy i tworzymy z nich trojkat
        // Gdy odczytamy juz trzy indeksy to z kazdym nastepnym robimy to:
        if( j >= 3 )
        {
            wyjscie.push_back( wejscie[ 0 ] );
            wyjscie.push_back( wejscie[ j - 1 ] );
            wyjscie.push_back( wejscie[ j ] );
        }
        else
             wyjscie.push_back( wejscie[ j ] );
       
    }
   
    cout << "Wejscie: ";
    for( int a = 0; a < wejscie.size(); a++ )
    {
        cout << wejscie[ a ] << "/";
    }
    cout << endl;
    cout << "Wyjscie: " << endl;
    for( int b = 0; b < wyjscie.size(); b++ )
    {
        cout << wyjscie[ b ] << " ";
       
        if(( b + 1 ) % 3 == 0 && b != 0 )
             cout << endl;
       
    }
   
    return 0;
}
Wyjscie:

Wejscie: 0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/
Wyjscie:
0 1 2
0 2 3
0 3 4
0 4 5
0 5 6
0 6 7
0 7 8
0 8 9
0 9 10
0 10 11
0 11 12
0 12 13
0 13 14
0 14 15
0 15 16
0 16 17
0 17 18
0 18 19
0 19 20
0 20 21
0 21 22
0 22 23
0 23 24
0 24 25
0 25 26
0 26 27
0 27 28
0 28 29
0 29 30
0 30 31
0 31 32
0 32 33
0 33 34
0 34 35
0 35 36
0 36 37
0 37 38
0 38 39
0 39 40
0 40 41
0 41 42
0 42 43
0 43 44
Możecie ten przykład znaleźć również tutaj:
http://ideone.com/BoXtkR
Z mojej strony to tyle, powodzenia!
P-124474
maly
» 2015-01-09 07:50:17
Przykład mógłbyś wrzucić tutaj.

Wydaje mi się że tak będzie "czyściej" :)
C/C++
for( std::size_t i = 1; i < faceIndices.size() - 1; ++i )
{
    triangulatedFaceIndices.push_back( faceIndices[ 0 ] );
    triangulatedFaceIndices.push_back( faceIndices[ i ] );
    triangulatedFaceIndices.push_back( faceIndices[ i + 1 ] );
}

Lepiej by było zamiast push_back ustawić potrzebną ilość miejsca w wyjściowym wektorze a potem tylko wypełnić.
C/C++
triangulatedFaceIndices.resize(( faceIndices.size() - 2 ) * 3 );

Wypadało by też wspomnieć że zadziała to tylko dla figur wypukłych.

Poza tym dziwię się że nie ma na forum działu właśnie dla takich "gotowców".
P-124480
DejaVu
» 2015-01-09 09:44:21
Można by się jeszcze pokusić o analizę kodu biblioteki libAssimp, ponieważ ona ma flagę, aby przy wczytywaniu modelu ewentualne wielokąty pozamieniać na trójkąty.
P-124482
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2015-01-09 14:25:38
Wypadało by też wspomnieć że zadziała to tylko dla figur wypukłych
Słusznie, już wczoraj o tym myślałem, jednak w ciągu paru dni zamierzam dopracować algorytm tak, żeby działał też na concave-ach. Postaram się też ogarnąć te libAssimp, jednak nie obiecuję, ponieważ pisząc w DirectX11 staram się sam zrobić większość rzeczy.
P-124487
« 1 »
  Strona 1 z 1