[C++, Grafika 3D] Dzielenie ścian na trójkąty - Face Triangulation
Ostatnio zmodyfikowano 2015-01-09 14:25
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::vectorNaszym celem będzie utworzenie trójkątnych face-ów z dajmy na to czterokątnych face-ów. Tutaj mamy wizualizację: 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: std::vector < DWORD > faceIndices;
std::vector < DWORD > triangulatedFaceIndices;
for( UINT i = 0; i < faceIndices.size(); i++ ) { 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: #include <iostream> #include <vector> using namespace std;
int main() { vector < short > wejscie, wyjscie; for( int i = 0; i < 45; i++ ) wejscie.push_back( i ); for( int j = 0; j < wejscie.size(); j++ ) { 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/BoXtkRZ mojej strony to tyle, powodzenia! |
|
maly |
» 2015-01-09 07:50:17 Przykład mógłbyś wrzucić tutaj. Wydaje mi się że tak będzie "czyściej" :) 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ć. 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". |
|
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. |
|
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. |
|
« 1 » |