Autor Wątek: CSG SUBSTRACT  (Przeczytany 2344 razy)

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 20, 2007, 19:35:36
Post odwołuje się do artykyłu na gamedev.pl

http://www.warsztat.gd/articles.php?x=view&id=95


      // Pętelka wykonująca właściwe CSG
2.    for( loop = nr_wielokata; loop < bryla_csg.IloscWielokatow; loop ++ )
{
      // Sprawdzamy czy dany wielokąt tnie bryłę
2a.           if( bryla_cieta.CzyJestIntersekcjaZWielokatem( bryla_csg.wielokaty[loop] ) )
{
   // Tnie. Dzielimy bryłkę płaszczyzną tego wielokąta
2b.            bryla_cieta.PrzetnijWielokatem( bryla_csg.wielokaty[loop],
                                   &prawa_brylka, &lewa_brylka );

   // Dodajemy prawą bryłkę do listy wyjściowej
2c.              solids_list[nastepny_element] = prawa_brylka;

   // Budujemy dalej : wchodzimy rekurencyjnie
2d.             CSG_Substract( lewa_brylka, nr_wielokata + 1, bryla_csg, false );

   // BARDZO WA¯NE: Przerywamy iterację, ponieważ następne wielokąty
   // zostały już obsłużone przez wywołanie rekurencyjne

   return true;
}
}

     // Wyjście tędy z funkcji oznacza już brak operacji cięcia
     return true;
}


Jak się tnie jakiś polygon płaszczyzną? jak to wyliczyć?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 20, 2007, 23:03:32
Zakładamy, że wielokąt jest wypukły. Przechodzimy kolejno wierzchołki w jego obwodzie i sprawdzamy, po której stronie płaszczyzny one są. W ten sposób znajdujemy krawędzie, które przecina płaszczyzna. Nalezy także uwzględnić szczególny przypadek, gdy płaszczyzna przechodzi przez któryś z wierzchołków albo oba (uwaga na niedokładności FPU). :)

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 20, 2007, 23:34:54
nie czaje jak mam znalezc nowa krawedz wielokata jak dziele jedna plasczyzna quada i np. jak podziele to mam 2 po jednej stronie i dwa po drugiej to teraz musze jakos wyliczyc nowe dwa punkty powstale po podziale co nie? tylko jak

RageX

  • Gość
# Lipiec 20, 2007, 23:49:00
rzutując na normalną płaszczyzny.
Oba punkty rzutujesz na normalną... w ten sposób masz odcinek "od A do P" i odcinek "od P do B".
(AP) + (PB) = AB

gdzie P to punkt przecięcia.

A tu metoda ode mnie... ciekawe czy skumasz o co biega...

http://rafb.net/p/hjy1zv83.html

Edit: A tu prowizorka rysunku...

« Ostatnia zmiana: Lipiec 21, 2007, 00:18:09 wysłana przez RageX »

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 21, 2007, 01:04:44
Oba punkty rzutujesz na normalną... w ten sposób masz odcinek "od A do P" i odcinek "od P do B".
Czyli po prostu możesz sprawdzić ich odległość od płaszczyzny. :)

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 21, 2007, 01:16:05
yy rzucam promień np. od A do B i sprawdzam czy przecina płaszczyznę jak tak to spoko :) swoja droga co robi tamten kod bo z tego co widze to chyba nie jest to o czym ja tutaj pisze bo tam nawet nie ma zwrotu puinktu ale ok to jest nie wazne :x

moze mnie ktoś jeszcze nakierować w jaki sposób oddzielić FRONT od BACK przy podziale polygona przez płaszczyznę, w sumie to pewnie do tego dojde po czasie ale miłobybyło żeby mi ktoś pomógł...
« Ostatnia zmiana: Lipiec 21, 2007, 02:00:54 wysłana przez ziomber »

RageX

  • Gość
# Lipiec 21, 2007, 01:24:01
Jak się tnie jakiś polygon płaszczyzną? jak to wyliczyć?

A czytałeś cały artykuł ???. Rozdział 7 - łopatologicznie wyjaśnione, bez trików optymalizacyjnych, tak aby każdy zrozumiał.

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 21, 2007, 02:02:58
szczerze mówiąc to dopiero teraz ten kod się pojawił wczeniej nie bylo rozdziału 7 ani wczesniejszych tylko  przykładowy kod ten co podałem w pierwszym poście i już dalej nic nie było! Z tym dzieleniem to sobie względnie poradziłem bo już wymyśliłem sposób trzeba po prostu znależć pary punktów, które są połączone ze sobą i znajdują sie po różnych stronach tzw. SPLIT PLANE, a teraz niech ktoś mnie poprawi, w zależności z której strony SPLIT PLANE chcemy mieć punkty to: robimy tak, ze jak chcemy z przodu (i mamy odpowiednio punkty)
1: A z przodu B z tyłu to
Punkt przeciecia tego odcinka z płaszczyzną to nowe B
2: mamy nowe B ale dalej operujemy na (starym B) bryle którą chcemy pociąc  (polygonie nie bryle) i teraz punkt B jest dalej z tyłu a C jest z przodu sprawdzamy w którym punkcie płaszczyzna tnie odcinek BC i to jest nasz nowy punkt, który łączy się z B i C

To obrazuje rysunek nizej czy takich przypadków (innych) jest wiecej pewnie jest bo cos mi swita ale czy musze je wszystkie obsłużyć na warunkach if czy jest jakaś inna metoda UNIWERSALNA


Cholera nie lubie w ciemno kodzic :/



O i znalazłem przykładowy kod

bool PodzielWielokatPlaszczyzna( CPolygon wielokat, vect3D Nplaszczyzny, float Dplaszczyzny,

                                 CPolygon out lewy_wielokat, CPolygon out prawy_wielokat  )
{

    // wierzchołki pomocnicze
    vect3D v1, v2, hit_point;

    ilosc_wierzcholkow = wielokat.PodajIloscWierzcholkow();

    for( loop = 0; loop < ilosc_wierzcholkow; loop ++ )
    {
        v1 = wielokat.wierzcholki[loop];
        v2 = loop < ilosc_wierzcholkow -1 ? wielokat.wierzcholki[loop+1] : wielokat.wierzcholki[0];

        v_side1 = v1.GetSide( Nplaszczyzny, Dplaszczyzny );
        v_side2 = v2.GetSide( Nplaszczyzny, Dplaszczyzny );

        // Testujemy
        if( v_side1 == VS_ONPLANE )
        {
            // Dodajemy do lewego i prawego kanału
            lewy_wielokat.DodajWierzcholek( v1 );
            prawy_wielokat DodajWierzcholek( v1 );
            continue;
        }

        // Dodajemy do odpowiedniego wielokąta:
        switch( v_side1 )
        {
            case VS_LEFT  : lewy_wielokat.DodajWierzcholek( v1 ); break;
            case VS_RIGHT : prawy_wielokat.DodajWierzcholek( v1 ); break;
        }

        // Elegancko :). Nie kończymy bo musimy sprawdzić czy odcinek [loop,loop+1] przecina płaszczyznę
        if( v_side1 == v_side2 || v_side2 == VS_ONPLANE )continue; // Teraz możemy :-))))

        // OK. dzielimy odcinek na dwie części i punk przecięcia dodajemy zarówno do lewego
        // jak i prawegej tablicy:
        TCalcHitPoint( v1 - v2, v1, Nplaszczyzny, Dplaszczyzny, hit_point );

        // Dodajemy do lewego i prawego kanału
        lewy_wielokat.DodajWierzcholek( hit_point );
        prawy_wielokat.DodajWierzcholek( hit_point );
   }
   return true;
}


Nie namoci to mi jak stworze sobie dwie tablice z wierzchołkami i bede dodawał wszystko co jest z porzdu do tablicy lewy_wielokat, a to co z tyłu do tablicy prawy_wielokat? i dodatkowo kazdy punkt przeciecia dodam do tych dwoch tablic bo tak zrozumialem z kodu i co robi instrukcja switch w c? :P I jak ma sie taki podział do rysowania polygonów w opengl bo tutaj widze jakis chyba nieposortowany polygon :X
« Ostatnia zmiana: Lipiec 21, 2007, 02:23:58 wysłana przez ziomber »

RageX

  • Gość
# Lipiec 21, 2007, 02:19:06
szczerze mówiąc to dopiero teraz ten kod się pojawił wczeniej nie bylo rozdziału 7 ani wczesniejszych tylko  przykładowy kod ten co podałem w pierwszym poście i już dalej nic nie było!

Co Ty za głupotki piszesz ??. Pełny artykuł napisałem w 2002 roku i w takiej postaci jak jest teraz istnieje na warsztacie (dawniej GDPL) od ponad 5-ciu lat :)
« Ostatnia zmiana: Lipiec 21, 2007, 02:22:33 wysłana przez st3tc »

RageX

  • Gość
# Lipiec 21, 2007, 12:54:14
yy rzucam promień np. od A do B i sprawdzam czy przecina płaszczyznę jak tak to spoko :) swoja droga co robi tamten kod bo z tego co widze to chyba nie jest to o czym ja tutaj pisze bo tam nawet nie ma zwrotu puinktu ale ok to jest nie wazne :x

Mój kod to wstęp do mojego raytriangle test. W każdym razie robi prawie że dokładnie to, co potrzeba. Zwraca stosunek długości promienia AP do AB. Poza metodą wystarczy przemnożyć AB przez te ratio.

To już wiesz jak lineSegmentToPlaneIntersection powinno działać?

Poza tym proponuje zacząć od prostych trójkątów ciętych płaszczyznami...
Co do rysowania czegoś takiego...hmm wiem że w xna i chiba directx, należało by to rysować drawPrimitives, niźli "stawiać" na device-ie. W końcu chodzi o efekt realtime.

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 22, 2007, 11:54:28
Jeżeli chodzi o rekurencje to jestem troche tępy z tego :0

bool CSG_Substract( CSolid bryla_cieta, DWORD nr_wielokata,

                    CSolid  bryla_csg,   CSolid solids_list[],
                    bool pierwsze_wywolanie )
{

      // Zmienne lokalne istotne dla pseudokodu
      CSolid   prawa_brylka, lewa_brylka;

      // Sprawdzamy czy bryła cięta znajduje się wewnątrz bryły, która
      // wykonuje operację CSG. UWAGA: Wywołanie tego testu ma sens jedynie
      // przy pierwszym wejściu do funkcji
1.     if( bryla_cieta.IsInsideSolid( bryla_csg )  &&  pierwsze_wywolanie == true )
      {
           // bryłka na ktrej mają być wykonane operacje znajduje się wewnątrz
           // bryłki robiącej CSG.
           // To specyficzna sytuacja. Ponieważ "bryla_cieta" jest wewnątrz
           // "bryla_csg" to tak naprawdę ta bryłka znika. Pozostawiamy pustą listę
           // brył wyjściowych ( "solids_list" ).

           return SKASUJ_BRYLE_CIETA;
      }

      // Pętelka wykonująca właściwe CSG
2.    for( loop = nr_wielokata; loop < bryla_csg.IloscWielokatow; loop ++ )
{
      // Sprawdzamy czy dany wielokąt tnie bryłę
2a.           if( bryla_cieta.CzyJestIntersekcjaZWielokatem( bryla_csg.wielokaty[loop] ) )
{
   // Tnie. Dzielimy bryłkę płaszczyzną tego wielokąta
2b.            bryla_cieta.PrzetnijWielokatem( bryla_csg.wielokaty[loop],
                                   &prawa_brylka, &lewa_brylka );

   // Dodajemy prawą bryłkę do listy wyjściowej
2c.              solids_list[nastepny_element] = prawa_brylka;

   // Budujemy dalej : wchodzimy rekurencyjnie
2d.             CSG_Substract( lewa_brylka, nr_wielokata + 1, bryla_csg, false );

   // BARDZO WA¯NE: Przerywamy iterację, ponieważ następne wielokąty
   // zostały już obsłużone przez wywołanie rekurencyjne

   return true;
}
}

     // Wyjście tędy z funkcji oznacza już brak operacji cięcia
     return true;
}


Moze mi ktoś pomóc wyjaśnić gdzie jest przechowywana bryła, która zostaje scięta i na jakiej dokładnei bryle sie operuje po następnym wywołaniu funkcji bo ja tego nie czaje w ogole :P