ďťż

bmetoda

Lemur zaprasza

Drzewo BSP (Binary Space
Partitioning)
Drzewo BSP to nic innego jak zwykłe drzewo
binarne. Najciekawszy jest sposób jego generowania.
Cała lokacja dzielona jest w taki sposób że
w końcowym etapie tworzy zamknięte bryły. Do podziału lokacji wykorzystywane są płaszczyzny na
których leżą poligony. Cała
lokacja rozdzielana jest na zbiory poligonów leżących przed i za płaszczyzną
podziału. Poligony które
przecinają płaszczyznę podziału są dzielone tak aby jedna cześć leżała za a
druga przed płaszczyzną.
Poligony które leżą na płaszczyźnie podziału
jeżeli mają taką samą orientację jak płaszczyzna podziału dodawane są do
poligonów leżących przed tą płaszczyzną jeżeli maja przeciwną orientację
dodawane są do zbioru z tyłu płaszczyzny. Warunkiem kończącym dzielenie jest utworzenie przez poligony
bryły zamkniętej czyli sektora.
Przechodząc całe drzewo otrzymujemy kompletną
lokację a dodatkowo kolejne sektory są posortowane względem
odległości. Drzewo BSP ma
wszystkie cechy algorytmu malarskiego a dodatkowo zapewnia połączenie
przenikających się powierzchni.
Struktura elementu drzewa
BSP:

Definicja sektora: Sektor to zbiór takich poligonów że
dla każdego poligonu z tego zbioru są spełnione następujące dwa warunki:
1.Dla płaszczyzny zawierającej dany poligon nie znajdziemy żadnego
poligonu ze zbioru poligonów sektora który byłby przez nią przecinany.
2.Pozostałe poligony sektora leżą zawsze po jednej stronie płaszczyzny
zawierającej ten poligon.
Przykłady sektorów i zbiorów które nie są sektorami:


Definicje węzłów drzewa: 1. Sektor jest węzłem dla
którego wskaźniki przód,  tył, płaszczyzna podziału wynoszą NULL natomiast
wskaźnik sektora jest różny od NULL. 2. Węzeł drzewa ma wskaźniki
przód, tył, płaszczyzna podziału  różne od NULL natomiast wskaźnik sektora
jest równy NULL.
Definicja kryterium wyboru płaszczyzny rozdzielającej: W
najprostszym przypadku jest to płaszczyzna zawierająca  poligon dla której
zachodzi warunek że liczba poligonów leżących przed i za tą płaszczyzną jest w
przybliżeniu równa.
Prosty przykład generowania drzewa BSP: Mamy prostą
lokację składającą się z 12 ścian. Lokacja zawiera tylko ściany
pionowe oznaczone numerami od 1do 12. Wektory normalne tych ścian
oznaczyłem kolorem czerwonym. Wektor normalny ściany wyznacza jej
orientację.
Budując drzewo będziemy wykorzystywali dwa wskaźniki: przód i
tył gdzie:
-przód to odpowiednik prawo w drzewie binarnym i wskazuje zbór ścian
leżących po stronie zgodnej z kierunkiem wektora normalnego płaszczyzny
rozdzielającej. -tył to odpowiednik lewo w drzewie binarnym i
wskazuje zbiór ścian leżących po stronie przeciwnej do kierunku wektora
normalnego płaszczyzny rozdzielającej.
Zwrot wektora normalnego płaszczyzny rozdzielającej jest taki sam jak
zwrot wektora normalnego wybranej ściany leżącej na tej płaszczyźnie.

Korzeń drzewa wynosi NULL. Wybieramy ścianę numer 4 i
względem płaszczyzny tej ściany rozdzielamy lokację na dwa zbiory.
Dlaczego wybieramy ścianę numer 4 ? Wynika to przyjętego
kryterium wyboru płaszczyzny rozdzielającej (patrz definicja tego kryterium)

Jak wyznaczamy ściany według tego kryterium ? sumujemy wagi
przypisane ścianom i sprawdzamy która waga jest najbliższa zeru. Wagi
przypisujemy dla zbioru ścian który aktualnie przetwarzamy i wynoszą one:
1 dla ściany z przodu potencjalnej płaszczyzny rozdzielającej
-1 dla ściany z tyłu potencjalnej płaszczyzny rozdzielającej 0
dla ściany leżącej na potencjalnej płaszczyźnie rozdzielającej do
sumowania pomijamy ściany przecinane przez potencjalną płaszczyznę
rozdzielającą.  
Zgodnie z tym kryterium ściany 4 i 10 mają najmniejszą (najbliższą 0) sumę
wag wynoszącą 1. Do podziału wybrałem ścianę 4 (równie dobrze mogłem
wybrać ścianę 10) Zgodnie z tym kryterium będę wybierał wszystkie
następne płaszczyzny rozdzielające.

Ściany numer  1 i 7 ulegają podziałowi. Sprawdzamy czy
zbiory ścian po rozdzieleniu lokacji płaszczyzną P4 tworzą sektory.( brak
sektora  -> patrz definicja sektora) Korzeń wskazuje na węzeł
zawierający płaszczyznę P4. Wskaźniki przód i tył dla węzła P4
wynoszą NULL tzn. nie wskazują na żaden sektor.

Wybieramy ścianę numer 3 i względem płaszczyzny tej ściany rozdzielamy
zbiór leżący z tyłu płaszczyzny P4 na dwa zbiory. Ściany 3 i 5 mają
najmniejszą (najbliższą 0) sumę wag która wynosi -1. Do podziału
wybrałem ścianę 3 (równie dobrze mogłem wybrać 5)

Sprawdzamy czy zbiory ścian po rozdzieleniu lokacji płaszczyzną P3 tworzą
sektory.( oba nowe zbiory tworzą sektory -> patrz definicja sektora)
Wskaźnik tył dla węzła zawierającego P4 wskazuje na węzeł zawierający
płaszczyznę P3. Wskaźniki przód i tył węzła P3 wskazują odpowiednio
na sektory S1 i S2.

Wybieramy ścianę numer 11 i względem płaszczyzny tej ściany rozdzielamy
zbiór leżący z przodu płaszczyzny P4 na dwa zbiory. Ściany numer
11,9,10 mają taką samą najmniejszą sumę wag (najbliższą 0) wynoszącą -3.
Do podziału wybrałem ścianę 11 (równie dobrze mogłem wybrać 9 lub
10).  

Sprawdzamy czy zbiory ścian po rozdzieleniu lokacji płaszczyzną P11 tworzą
sektory.( zbiór z przodu P11 tworzy sektor -> patrz definicja sektora)
Wskaźnik przód dla węzła zawierającego P4 wskazuje na węzeł zawierający
P11. Wskaźnik przód dla węzła zawierającego P11 wskazuje na sektory
S3. Wskaźnik tył dla tego węzła wynosi NULL.

Wybieramy ścianę numer 9 i względem płaszczyzny tej ściany rozdzielamy
zbiór leżący z tyłu płaszczyzny P11 na dwa zbiory. Ściana 9 ma jako
jedyna idealną sumę wag równą 0.

Sprawdzamy czy zbiory ścian po rozdzieleniu lokacji płaszczyzną P9 tworzą
sektory.( zbiory z przodu i z tyłu P9 tworzą sektory -> patrz definicja
sektora) Wskaźnik tył dla węzła zawierającego P11 wskazuje na węzeł
zawierający płaszczyznę P9. Wskaźnik tył dla węzła zawierającego P9
wskazuje na sektor S4. Wskaźnik przód dla tego węzła wskazuje na
sektor S5.

W ten sposób utworzyliśmy drzewo BSP dla przykładowej lokacji.
Uwagi końcowe: Procedura budująca drzewo BSP powinna być
rekurencyjna Oto szkielet takiej procedury w pseudokodzie:
Procedura generacji drzewa BSP ( zbiór ścian ,wskaźnik węzła
początkowego) {     krok 1
    Utwórz nowy węzeł i nakieruj na niego wskaźnik węzła
początkowego     Czy zbiór ścian jest sektorem ( zbiór
ścian )     {
       Jeżeli jest to  zapisz sektor i
zakończ        Jeżeli nie jest to idź
do kroku 2     }
   krok 2     Wybierz
płaszczyznę dzielącą ( zbiór ścian)     {
        wyznacz z kryterium wyboru
płaszczyzny podziału        
płaszczyznę dzielącą oraz zapisz węzeł drzewa    
}
    krok 3     Rozdziel
zbiór zbór ścian ( zbór ścian , płaszczyzna dzieląca )
    {
        podziel zbór ścian na dwa
zbiory: zbiór ścian 1 i zbiór ścian 2
        względem płaszczyzny
dzielącej     }
   krok 4     Procedura
generacji drzewa BSP ( zbiór ścian 1 ,wskaźnik przód nowego węzła)
    Procedura generacji drzewa BSP ( zbiór ścian 2
,wskaźnik tył nowego węzła) }
Procedura renderująca poprzez drzewo BSP powinna być rekurencyjna.
Oto szkielet takiej procedury w pseudokodzie:
Renderuj drzewo BSP ( pozycja gracza, wskaźnik na węzeł początkowy)
{     krok 1
    Czy węzeł początkowy jest sektorem ( węzeł
początkowy)     {
        jeżeli jest to wyświetl
wszystkie ściany sektora i zakończ
        jeżeli nie jest to idź do
kroku 2     }
    krok 2     Wyznacz z
której strony płaszczyzny dzielącej węzła jest gracz
    ( pozycja gracza, płaszczyzna dzieląca węzła)
    {
        jeżeli jest z przodu to:
           
Renderuj drzewo BSP ( pozycja gracza, wskaźnik przód węzła początkowego)
           
Renderuj drzewo BSP ( pozycja gracza, wskaźnik tył węzła początkowego)
       jeżeli jest z tyłu to:
           
Renderuj drzewo BSP ( pozycja gracza, wskaźnik tył węzła początkowego)
           
Renderuj drzewo BSP ( pozycja gracza, wskaźnik przód węzła początkowego)
    } }
Procedury zapisu i odczytu drzewa BSP powinny być również
rekurencyjne. Oto szkielet procedury zapisu w
pseudokodzie:
Zapisz drzewo BSP ( wskaźnik na węzeł początkowy ) {
    krok 1     Czy węzeł
początkowy jest sektorem ( węzeł początkowy)     {
        jeżeli jest to zapisz znacznik
węzła, wszystkie ściany sektora i zakończ
        jeżeli nie jest to 
zapisz znacznik węzła i płaszczyznę węzła oraz idź do kroku 2
    }
    krok 2
           
Zapisz drzewo BSP ( wskaźnik przód węzła początkowego)
            Zapisz
drzewo BSP ( wskaźnik tył węzła początkowego)   }
}
Znacznik węzła pozwala na odróżnienie sektora od zwykłego węzła.
Oto szkielet procedury odczytu w pseudokodzie:
Odczytaj drzewo BSP ( wskaźnik na węzeł początkowy) {
    krok 1     Utwórz
nowy węzeł i nakieruj na niego wskaźnik na węzeł początkowy
    Czy odczytujemy sektor ( odczytany znacznik węzła)
    {
        jeżeli tak to odczytaj 
wszystkie ściany sektora i zakończ
        jeżeli nie to odczytaj
płaszczyznę węzła i idź do kroku 2     }
    krok 2
           
Odczytaj drzewo BSP ( wskaźnik przód nowego węzła)
           
Odczytaj drzewo BSP ( wskaźnik tył nowego węzła)   }
}
Dokładny opis algorytmów generowania i odczytu drzewa
BSP należy szukać w Internecie. Polecam zapoznanie się z
książką Wojciecha Jawora 'Principia
silnika' gdzie można
znaleźć gotowe programy do generacji drzewa BSP 3D oraz prosty silnik do gier
3D.
Zalety: 1. Wyświetlana
grafika jest od razu posortowana we właściwej kolejności np. od najdalszych
poligonów do najbliższych. 2.
Zapis grafiki do drzewa BSP powoduje że przenikające się powierzchnie są
automatycznie łączone. Na
przenikających się powierzchniach wykonywana jest operacja sumowania.

Wady: 1. Chcąc wyświetlić
lokację zapisaną w drzewie BSP musimy przejść całe drzewo zaczynając od
korzenia. 2. Standardowe drzewo
BSP uniemożliwia proste wykrywanie widoczności postaci.
Uwagi: Wady drzewa BSP praktycznie
uniemożliwiają jego zastosowanie w grach SPP i FPP z rozbudowanymi poziomami i
dużą ilością postaci. Jedynym rozwiązaniem jest
przełączanie się pomiędzy wieloma małymi drzewami BSP lub przejście na drzewa
PVS i portale.        
 
Autor: Mirosław Kozioł
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • teen-mushing.xlx.pl
  • Wątki
    Powered by wordpress | Theme: simpletex | © Lemur zaprasza