SlideShare a Scribd company logo
1 of 60
Download to read offline
P O L I T E C H N I K A S Z C Z E C I Ń S K A
Wydział Informatyki
PRACA DYPLOMOWA
Wybrane zagadnienia wizualizacji
wirtualnego środowiska za pomocą biblioteki
OpenGL
Autor:
Łukasz Szczepański
Opiekun pracy:
dr inż. Radosław Mantiuk
Szczecin, 2004/2005
Spis treści
1 Wstęp 3
1.1 Pojęcia istotne dla zrozumienia zagadnienia pracy . . . . . . . . . . . . . 4
1.2 Schemat podziału pracy . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Przegląd wybranych, istniejących implementacji wirtualnego środowiska 6
2.1 Schemat podziału współczesnych środowisk wirtualnych . . . . . . . . . . 6
2.1.1 MMORPG: World of Warcraft . . . . . . . . . . . . . . . . . . . . 7
2.1.2 FPP: Half Life 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.3 Wizualizacja Inżynierska : WalkInside . . . . . . . . . . . . . . . . 10
3 Implementacja wirtualnego środowiska za pomocą biblioteki OpenGL 16
3.1 Wizualizacja geometrii . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2 Vertex Buffering - Vertex Buffer Objects . . . . . . . . . . . . . . . . . . 18
3.2.1 Tworzenie Obiektów VBO . . . . . . . . . . . . . . . . . . . . . . 18
3.3 Teksturowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.1 Politeksturing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.2 Light Mapping jako szczególny przypadek multiteksturingu . . . . 21
3.3.3 Tekstury przejść . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4 Symulacja mgły . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.5 Poruszanie się po środowisku . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.5.1 Ogólny algorytm pracy kamery . . . . . . . . . . . . . . . . . . . 25
3.5.2 Implementacja ruchu kamery . . . . . . . . . . . . . . . . . . . . . 26
3.5.3 Ruch poprzeczny . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.5.4 Obrót kamery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.6 Detekcja kolizji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.6.1 Pojęcia istotne dla zrozumienia zagadnienia detekcji kolizji . . . . 28
3.6.2 Algorytm detekcji kolizji . . . . . . . . . . . . . . . . . . . . . . . 29
3.6.3 Charakterystyka struktur danych użytych do rozwiązania problemu
detekcji kolizji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.6.4 Test przecięcia sfery i bryły AABB . . . . . . . . . . . . . . . . . 31
3.6.5 Algorytm budowy drzewa binarnego AABB . . . . . . . . . . . . 31
3.6.6 Wizualizacja drzewa AABB . . . . . . . . . . . . . . . . . . . . . 34
3.6.7 Algorytm ukrywania powierzchni niewidocznych oparty o bryły
AABB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1
4 Rezultaty i wnioski 37
4.1 Opis procedury testowej . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2 Analiza wyników przeprowadzonych testów . . . . . . . . . . . . . . . . . 38
4.2.1 Wpływ rozdzielczości oraz trybu płótna OpenGL na wydajność śro-
dowiska . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.2.2 Wpływ optymalizacji Frustum Culling na wydajność systemu . . 40
4.2.3 Wpływ detekcji kolizji akcelerowanej metodą drzew AABB na pręd-
kość działania systemu . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.4 Wpływ ilości geometrii na prędkość działania systemu . . . . . . . 41
4.2.5 Poprawność wizualizacji środowiska . . . . . . . . . . . . . . . . . 41
4.3 Prezentacja uzyskanych wyników, rysunki . . . . . . . . . . . . . . . . . . 41
5 Podsumowanie i wnioski 51
5.1 Dalsze prace związane z rozwojem wirtualnych środowisk . . . . . . . . . 53
5.1.1 Wielowątkowość . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5.1.2 Inne modele hierarchii sceny . . . . . . . . . . . . . . . . . . . . . 53
5.1.3 Metody optymalizacji ilości renderowanej geometrii . . . . . . . . 54
5.1.4 Efekty specjalne, Pixel Shading . . . . . . . . . . . . . . . . . . . 54
5.1.5 Wirtualny realizm - CAVE i dźwięk . . . . . . . . . . . . . . . . . 55
A Dodatek 57
A.1 Specyfikacja formatu plikow .n3d. . . . . . . . . . . . . . . . . . . . . . . 57
A.2 Obsługa środowiska nGine . . . . . . . . . . . . . . . . . . . . . . . . . . 57
B Dodatek 59
B.1 Zawartość dołączonej płyty CD . . . . . . . . . . . . . . . . . . . . . . . 59
2
Rozdział 1
Wstęp
Wirtualne środowiska stanowią bardzo ważną część rynku oprogramowania kompute-
rowego i są jedną z najprężniej rozwijających się dziedzin. Spotkać je można na każdym
kroku, w grach, w symulacji, w inżynierii, wszędzie tam gdzie potrzeba zaprezentować
użytkownikowi efekty jego pracy zanim zostaną one przekształcone w formę ostateczną.
Wirtualne środowiska, określane często mianem rzeczywistości wirtualnej (ang. Vir-
tual Reality, VR) podlegają ciągłej ewolucji. Każego roku producenci sprzętu kompu-
terowego, a zwłaszcza podzespołów graficznych prześcigają się w tworzeniu coraz to
lepszych, wydajniejszych układów oferujących coraz to nowsze metody wizualizacyjne.
W tym samym czasie producenci oprogramowania tworzą nowe, bardziej konkurencyjne
wersje środowisk wirtualnych. Stopień skomplikowania najnowszych aplikacji wymaga za-
trudniania całych sztabów inżynierów potrafiących złożyć kompletne i spójne środowisko
w całość ze wszystkich dostępnych elementów.
Większość aktualnie powstających środowisk przeznaczonych dla systemu Windows
opiera się o bibliotekę Direct3D firmy Microsoft. Biblioteka ta, podlegająca ciągłej ewolucji
napędzanej przez Microsoft oferuje programiście szereg ułatwień i narzędzi. Direct3D
daje programiście zestaw funkcji realizujących pewne elementy wizualizacji środowiska
bez zewnętrznej ingerencji. Użytkownik nie musi znać ani specyfiki ani sposobu działa-
nia tych elementów, ponieważ funkcje biblioteczne ukrywają całą mechanikę działania.
Daje to znaczny wzrost efektywności oraz przyspiesza proces implementacji danego śro-
dowiska, ale z drugiej strony nie pozwala programiście ingerować w proces wizualizacji
tych elementów zmniejszając elastyczność całego procesu. Należy pamiętać że Direct3D
dostępny jest jedynie w środowisku Windows oraz o tym że podczas ewolucji tej bib-
lioteki, jej twórcy nie raz zmieniali interfejs programisty często zmuszając użytkowników
do ponownej nauki jej działania.
Drugą z popularnych bibliotek używanych do tworzenia rzeczywistości wirtualnej jest
OpenGL (Open Graphics Library). Jest to tak zwany standard przemysłowy (ang. In-
dustry Standard) stworzony przez firmę Silicon Graphics. OpenGL jest darmową bib-
lioteką przenośną, działającą tak samo pod kontrolą różnych systemów operacyjnych, co
czyni ją bardzo elastyczną. Biblioteka tworzona jest przez grupę zwaną jako Architec-
ture Review Board (ARB) składjącą się z przedstawicieli firm tworzących sprzęt i opro-
gramowanie komputerowe. Dzięki temu OpenGL stał się solidną biblioteką o rozszerza-
jących się możliwościach i stałym interfejsie. W przeciwieństwie do Direct3D, OpenGL
nie oferuje gotowych funkcji realizujących elementy wizualizacji, ale daje użytkownikowi
narzędzia dzięki którym możliwe jest zaimplementowanie dowolnej metody w pełni kon-
trolowany, autorski sposób.
Celem niniejszej pracy jest opracowanie autorskiego wirtualnego środowiska wyko-
rzystującego wybrane elementy wizualizacji przy pomocy biblioteki OpenGL. Zaimple-
mentowane środowisko powinno obsłgiwać detekcję kolizji oraz dowolny ruch kamery oraz
poprzeć tezę pracy brzmiącą : ”Przy użyciu biblioteki OpenGL możliwa jest implemen-
tacja fizycznie poprawnego i wydajnego wirtualnego środowiska”.
W celu zrealizowania postawionych pracy celów, stworzono autorskie środowisko o
nazwie nGine. W środowisku tym zaimplementowane zostały następujące elementy wi-
zualizacji wirtualnego środowiska :
1. Oświetlenie i cieniowanie za pomocą map oświetlenia,
2. Detekcja kolizji oparta na drzewach binarnych AABB,
3. Optymalizacja prędkości wyświetlania poprzez Vertex Buffering,
4. Optymalizacja zbioru wyświetlanej geometrii poprzez Frustum Culling,
5. Implementacja binarnego formatu danych geometrycznych,
6. System politeksturingu,
7. Kamera o pełnej swobodzie poruszania,
8. Projekt wnętrza wirtualnego środowiska.
1.1 Pojęcia istotne dla zrozumienia zagadnienia pracy
Środowisko - Środowiskiem nazywamy wszelkie zewnetrzne czynniki oddziałujące na
rozpatrywany układ.
Środowisko Wirtualne - Środowiskiem takim, nazywamy pewien zestaw cech i obiek-
tów, który jest wizualizowany przez specjalne oprogramowanie. Zestawem cech najczę-
sciej są podstawowe elementy fizyki takie jak grawitacja czy też zderzenia sprężyste i
niesprężyste. Podstawowymi obiektami w środowisku wirtualnym są obiekty opisujące
głównie wygląd przestrzeni wirtualnej. Podstawowym obiektem jest tzw. mapa, czyli
obiekt składający sie z tysiecy trójkątów imitujący wygląd wybranego środowiska rzeczy-
wistego takiego jak jaskinia czy też wnętrze budynku. Innymi obiektami najczęściej są
przedmioty, których położenie może ulegac interaktywnej modyfikacji poprzez odpowied-
nie procedury modułu fizyki, mogą to także byc obiekty zmieniające stopien swobody
poruszania sie po danym środowisku, takimi obiektami są na przyklad drabina, winda
4
czy też schody.
W skrócie, wirtualne środowisko jest ograniczoną imitacją dowolnie wybranego śro-
dowiska rzeczywistego, o ścisle dobranych parametrach i obowiazujących zasadach fizyki.
Wizualizacja - Wizualizacją nazywamy graficzną reprezentację pewnego zbioru danych.
W kontekście środowisk wirtualnych, będzie to połączona reprezentacja obrazów dwuwy-
miarowych (tekstur) oraz zestawu danych trójwymiarowych odpowiadających za wygląd
środowiska. Zadaniem wizualizacji jest jak najwierniejsze oddanie wyglądu obiektów
rzeczywistych za pomocą przygotowanych wczesniej danych.
Detekcja Kolizji - Detekcja kolizji używana jest w środowiskach wirtualnych do bada-
nia relatywnych położeń obiektów zawartych w tym środowisku. Jeśli program nadzoru-
jący zachowanie środowiska zauwazy iż dwa obiekty są wystarczająco blisko siebie, to
zachodzi zdarzenie kolizji. Wynikiem tego zdarzenia jest zazwyczaj zmiana kierunku
poruszających sie obiektów, tak aby ich scianki nie nachodzily na siebie. W środowiskach
symulujacych zdarzenia rzeczywiste, część energii kinetycznej obiektu poruszającego sie
jest przenoszona na obiekt z którym następuje kolizja.
1.2 Schemat podziału pracy
Niniejsza praca została podzielona na następujące części :
1. Wstęp, w rozdziale tym przedstawiono ogólne założenia pracy a także wyjaśniono
najważniejsze pojęcia związane z pracą.
2. Przeglad wybranych, istniejacych implementacji wirtualnego srodowiska,
w tej części pracy omówiono najbardziej charakterystyczne, istniejące implementacje
wirtualnego środowiska oraz zdefiniowano schemat podziału współczesnych środowisk
wirutalnych.
3. Implementacja wirtualnego srodowiska za pomoca biblioteki OpenGL, w
rozdziale tym przedstawiono teoretyczne jak i implementacyjne aspekty każdego z uży-
tych w pracy elementów wizualizacji, oraz zdefiniowano schemat przepływu danych w
zaimplementowanym środowisku i przedstawiono jego ogólny sposób działania.
4. Rezultaty i wnioski, w części tej znajduje się opis procedury testowej zaimple-
mentowanego środowiska, jak i wyniki przeprowadzonych testów wydajnościowych oraz
porównanie tych wyników z implementacjami znanymi wcześniej.
5. Podsumowanie, w rozdziale tym podsumowane zostały osiągnięcia uzyskane pod-
czas implementacji środowiska oraz przeprowadzona została dyskusja nad dalszymi as-
pektami rozwoju wirtualnych środowisk.
5
Rozdział 2
Przegląd wybranych, istniejących
implementacji wirtualnego
środowiska
Wirtualne środowiska zdobywają coraz większą popularność w życiu codziennym i
nauce. Znajdują szerokie zastosowanie w symulacji, projektowaniu i wizualizacji oraz
w interaktywnej rozrywce. Są one jednym z najprężniej rozwijających się sektorów infor-
matyki użytkowej. Wraz z rozwojem wirtualnych środowisk, rośnie także ich specjalizacja,
co obrazuje rysunek 2.1
2.1 Schemat podziału współczesnych środowisk
wirtualnych
Środowiska Wirtualne
Środowiska
Rozrywkowe, gry
Środowiska
Wizualizacyjne
Gry MMORPG
(ang. Massive Multiplayer
Online Game )
Gry FPP
(ang. First Person
Perspective)
Wizualizacja
Inżynierska
Wizualizacja
Architektoniczna
Rysunek 2.1: Schemat podziału współczesnych środowisk wirtualnych.
• Środowiska o charakterze rozrywkowym
– Gry Massive Multiplayer Online Role Playing Game (MMORPG).
W środowiskach tego typu, tysiące graczy egzystuje wspólnie w jednym świecie
przeżywając wspólnie przygody i realizując wspólnie różne cele. Cechą charak-
terystyczną tych środowisk jest bardzo rozległy obszar na którym prowadzona
jest rozgrywka oraz obecność wielu avatarów w jednym miejscu, a także pewne
uproszczenie środowiska pod względem dokładności geometrii.
– Gry First Person Perspective (FPP), oraz podobne.
W grach tego typu gracz wciela się zazwyczaj w postać bohatera ratującego
świat lub własną skórę przed różnymi rodzajami szeroko pojętego zła. Cha-
rakterystyczną cechą tych środowisk jest to iż implementowane w nich są za-
zwyczaj wszystkie nowinki techniczne dostępne w czasie wydania danego ty-
tułu. Środowiska te są w pewnym stopniu testem (ang. benchmark) wydajności
dostepnych komputerów jak też i testem możliwości najnowszych algorytmów
i efektów specjalnych.
• Środowiska o charakterze naukowym i badawczym
– Środowiska wizualizacyjne i symulacyjne.
Środowiska te służą zazwyczaj symulacji działających systemów, lub też wizu-
alizacji. Głównym zastosowaniem tych środowisk jest wizualizacja inżynierska
i architektoniczna, pomagające w doborze odpowiednich parametrów wizuali-
zowanego środowiska, lub też wizualizacja symulacji - np. wizualizacja symu-
latora lotniczego. Charakterystyczną cechą tych środowisk jest to iż prezen-
towana grafika posiada najdrobniejsze detale, a ilość przetwarzanych danych
często mierzona jest w gigabajtach. Środowiska symulacyjne posiadają bardzo
skomplikowane matematycznie procedury przetwarzania symulacji, a część wi-
zualizacyjna jest często prowizoryczna.
2.1.1 MMORPG: World of Warcraft
World of Warcraft (WoW) jest grą komputerową typu Massive Multiplayer Online
Role Playing Game wydaną przez firmę Blizzard Entertainment w listopadzie 2004 roku.
W grze tej tysiące graczy przeżywa wspólnie przygody w jednym świecie (wirtualnym
środowisku). World of Warcraft oferuje użytkownikowi najróżniejsze rodzaje wirtualnych
środowisk, począwszy od piaszczystych pustyń, poprzez gęste lasy, bagna oraz podziemne
lochy i jaskinie wszelkiego rodzaju, aż po zabudowę miejską stylizowaną na średniowieczne
grody warowne.
Wizualizacja w WoW jest możliwa zarówno za pomocą biblioteki Direct3D jak i
OpenGL. Podstawowym atutem World of Warcraft w stosunku do innych środowisk tego
typu jest to iż nie istnieją tutaj przestoje związane z wczytywaniem dużych ilosci danych,
7
oraz nie istnieją linie podziału stref świata gdzie takie przestoje miały by miejsce (tzw.
zoning). System pobiera dane dotyczące geometrii świata w sposób zupełnie przezroczysty
dla użytkownika, oferując niczym nie zakłóconą i wciągającą rozrywkę.
Geometria świata jest określana jako low-poly, geometria ta nie opisuje detali na
postaciach lub budynkach, a tworzy jedynie jakby zarys elementu docelowego, definiu-
jąc jedynie najwazniejsze jego elementy. Mimo oszczędnej geometrii World of Warcraft
jest środowiskiem, które posiada największą liczbę detali wśrod programów swojej klasy.
Detale te osiągane są poprzez bardzo szczegółowe, recznie rysowane tekstury nałożone
precyzyjnie na każdy obiekt.
Rzeźba terenu w WoW jest poddawana optymalizacji Level of Detail w czasie rzeczy-
wistym. Wraz ze zbliżaniem sie do danego obszaru staje się on coraz bardziej szczegółowy.
Teksturowanie terenu oparte jest na specjalnych shaderach. Shadery te teksturują teren w
sposób bardzo realistyczny i szczegółowy - dla przykładu : szczyt pagórka jest porośniety
trawą, zaś razem ze wzrostem nachylenia zbocza pagórka trawa przechodzi w piaszczysty
podkład lub skałę, bruk porasta mchem i trawą tym bardziej im dalej dany punkt jest
położony od środka drogi.
Specjalną rolę w World of Warcraft odgrywają systemy cząsteczek dzieki którym two-
rzone są różne efekty specjalne, od wodospadów (rysunek 2.7) i fontann, aż po różne
efekty umiejętności specjalnych oraz ogień. Ciekawym rozwiązaniem są wodospady, które
obrazują główny nurt wody poprzez statyczną geometrię, na którą nałożona jest ani-
mowana tekstura z kanałem alpha. System cząsteczek odpowiada tutaj za cząsteczki
wody, które wyrywają się losowo z głównego nurtu i tworzą ”mgiełkę”wokół głównego
nurtu.
Na szczególną uwagę zasługuje shader bloom nazwany przez producenta Full Screen
Glow. Shader ten imituje efekty osiągane przy użyciu oświetlenia opartego o HDR,
tworząc swietlistą poświatę wokół obszarów silnie odbijających światło.
World of Warcraft jest na dzien dzisiejszy najwiekszą i najbardziej rozbudowaną grą
gatunku MMORPG, zarówno pod względem ilości użytkowników jak i rozmiarów świata,
którego powierzchnia sięga 70-100km2
. Ilość detali świata i postaci jest o wiele większa niż
we wcześniejszych tytułach tej klasy. Nie jest to jednak szczyt możliwości technicznych
dzisiejszych komputerów, a uproszczenie wizualizacji środowiska jest wymuszone poprzez
fakt iż jest to gra online i niesiona przez sieć ilość informacji nie może byc zbyt duża.
2.1.2 FPP: Half Life 2
Half Life 2 (HL2) jest grą komputerową typu First Person Perspective wydana przez
Valve Software [Cor04] pod koniec 2004 roku, opartą na autorskim silniku o nazwieSource.
Gracz wciela się rolę naukowca, Dr Freemana, który został uwikłany w spisek przeciw
rodzajowi ludzkiemu i musi utorować sobie, oraz ludzkośći drogę do wolnosci łomem oraz
całym arsenałem współczesnej broni.
8
Pierwszą zauważalną rzeczą w grze jest oświetlenie scen przy użyciu HDR. Ekspozy-
cja regulowana jest automatycznie poprzez system wizualizacji, dając wrażenie oślepienia
oraz powidoku podczas nagłych zmian w natężeniu oświetlenia. System potrafi także
obliczać oświetlenie metodą energetyczna (radiosity) w czasie rzeczywistym.
Kolejnym przełomowym elementem wizualizacji zaimplementowanym w HL2 jest sys-
tem materiałów. Materiał w ujeciu silnika Source jest zbiorem danych w pełni opisują-
cym wszystkie właściwości fizyczne danego tworzywa. Materiały mają przypisane funkcje
zmieniające wygląd tekstury wraz ze stopniem jej zniszczenia, posiadają specjalne kanały
tekstur dzieki którym uzyskuje sie efekty odbic lustrzanych lub też chropowatości. Każdy
materiał ma przypisaną gęstość oraz ciężar. Materiały opisują także odgłosy wydawane
przez obiekty podczas uderzenia lub przesunięcia. Większość użytych tekstur jest au-
torskimi shaderami napisanymi w języku High Level Shading Language (HLSL). Na
szczególną uwagę zasługuje tutaj woda w której zaimplementowano efekt refrakcji oraz
efekt Fresnela polegający na wzroście ilości światła odbitego do oka wraz ze wzrostem
kąta nachylenia kamery do powierzchni.
Tym co odróżnia Half Life 2 od innych gier komputerowych na przełomie lat 2004/2005
jest system fizyki. System Source wprowadza pełną gamę oddziaływań fizycznych miedzy
obiektami w scenie. Podczas gry, gracz napotyka wiele zagadek związanych z podsta-
wowymi prawami fizyki, równowagą, inercją, wypornością, i tym podobnymi. W więk-
szosci pozycji, które zostały wydane przed HL2, interakcja między obiektami jest za-
zwyczaj prekalkulowana i stała. W silniku Source oddziaływania między obiektami symu-
lowane sa w czasie rzeczywistym. Jednym z przykładów może być etap gry, gdzie gracz
musi obciażyć jedną ze stron równoważni cegłami aby przejsc po kładce na wyższy poziom.
Cegły układane są na szerszym końcu kładki, jeżeli zostaną upuszczone na siebie zbyt
gwałtownie, lub w złym miejscu, obsuwaja się oraz rozbijają juz ułożony szyk. Jeśli gracz
nie obciąży dostatecznie kładki, to podczas wchodzenia w górę przeważy ułożone cegły
i opadnie na doł, a cegly obsuną się wzdłuż deski oraz rozsypią na boki. Source defini-
uje także system tzw. kukiełek (ang. Rag Doll Model), dzięki któremu postaci oraz ele-
menty ich ciała oddziałowują poprawnie na interakcje z obiektami oraz przyłożonymi doń
siłami. W HL2 zaimplementowano także uproszczoną fizykę pojazdów. Zmiennymi opisu-
jącymi pojazd są : moc silnika, maksymalna prędkość, prędkość skrzyni biegów, materiał
z którego wykonane są opony, oraz twardość zawieszenia. Pojazdy podlegają wszystkim
prawom fizyki, wpadają w poślizgi, tracą przyczepność, pochylają się na bok podczas
dynamicznych zakrętów, a w skrajnych przypadkach przewracają się na bok.
Wizualizowana geometria poddawana jest optymalizacjom Level Of Detail w czasie
rzeczywistym. Geometria świata w Half Life 2 jest w pełni deformowalna, pociski wybijają
dziury w murach, a ładunki wybuchowe pozostawiają głębokie kratery w ziemi. Całość
środowiska zamknięta jest w tzw. sky box’ach, które są sześciennymi mapami nieba, nada-
jącymi scenie realizmu oraz głębi.
Half Life 2 redefiniuje pojęcie realizmu w dziedzinie gier komputerowych (rysunek
2.8). Przedstawione środowiska, stylizowane na wschodnią europę przełomu lat 80/90
wyglądają prawdziwie. System sztucznej inteligencji czesto zaskakuje gracza swoimi po-
9
sunięciami, a system fizyki przyciąga na długie godziny. Całość tworzy kamień milowy w
dziedzinie interaktywnej rozrywki, oraz wyznacza trend którym bedą podążali wydawcy
w kolejnych latach.
2.1.3 Wizualizacja Inżynierska : WalkInside
Walkinside firmy VRcontext jest aplikacją wizualizacyjną, umożliwiającą użytkowni-
kowi poruszanie się po środowiskach zaprojektowanych w programach CAD takich jak
Microstation czy Autocad.
Głównym atutem Walkinside [Inc05] jest fakt iż system ten nie posiada ograniczeń
co do wielkości wyświetlanego modelu. Oprogramowanie nie podlega ograniczeniom roz-
miarów plików, ani rozciągłości terenu, możliwa jest wizualizacja środowisk o rozciągłości
ponad 10km [Inc05].
Wizualizacja w Walkinside możliwa jest z perspektywy pierwszej lub trzeciej osoby
(FPP,TPP, rys. 2.6). Użytkownik może poruszać się po zaprojektowanych modelach,
zachowując proporcje oraz możliwości przeciętnego człowieka. Opatentowany system de-
tekcji kolizji umożliwia realistyczne poruszanie się w przestrzeni i dokładną reakcję na
zachodzące zdarzenia. System wizualizacji w walkinside pozwala także na używanie spec-
jalnego hełmu z systemem śledzenia ruchów głowy, dzięki czemu użytkownik może w pełni
skoncentrować się na wizualizowanym przekazie.
System wizualizacji Walkinside opiera się na dynamicznej teselacji zakrzywionych
powierzchni oraz na mechanizmie szybkiego odrzucania zbędnych elementów dla obiek-
tów, które znajdują się zbyt daleko aby mogły być wizualizowane.
System oświetlenia aplikacji korzysta ze zwykłych świateł bibliotecznych OpenGL (gl-
Light). W aplikacji tego typu realistyczne oświetlenie światłem HDR lub też za pomocą
metody energetycznej jest zupełnie zbędne i zaszkodziłoby wydajności całej aplikacji.
Walkinside posiada moduł symulacyjny oraz sieciowy, dzięki którym możliwe są treningi
personelu w wirtualnej rzeczywistości (rysunki 2.2,2.3). Użytkownicy widzą avatary in-
nych użytkowników, dzięki czemu w łatwy i intuicyjny sposób mogą ze sobą współpra-
cować. Systemy detekcji kolizji oraz cząsteczek dodają symulacji dodatkowego realizmu i
pozwalają przeprowadzić ćwiczenia w iście prawdziwy sposób. System symulacji pozwala
użytkownikowi zaprojektować długie scenariusze podczas których inni użytkownicy bedą
odbywać swoje szkolenie.
Walkinside jest aplikacją niespotykaną i przełomową, nigdy do tej pory nie było
możliwe wizualizowanie modeli inżynierskich takich jak platforma wiertnicza (rysunek
2.4), czy też wnętrze reaktora jądrowego na domowym komputerze klasy PC. Dzięki sys-
temowi detekcji kolizji, użytkownik może chodzic po schodach, czy też wspinać sie po
drabinie, a dzięki unikalnemu silnikowi wyświetlającemu możliwa jest wizualizacja tak
ogromnych ilości danych. Poprzednie systemy tego typu nie radziły sobie z wyświetlaniem
tak dużych porcji danych bez poświęcenia detali wizualizowanego środowiska. Walkinside
jest w stanie wizualizować sceny siegające kilku milionów wielokątów oraz posiadające
10
bardzo wiele zakrzywionych powierzchni (curved surfaces, np. NURBS, rysunek 2.5).
Dzięki natywnemu wsparciu systemu dla formatu zapisu plików Microstation (.dwg),
użytkownik może w prosty sposób wymodelować całe środowisko razem z teksturami i
wyeksportować je prosto do silnika wizualizacyjnego, pomijając wszystkie konwersje oraz
obliczenia wstępne jakie spotykało się w aplikacjach tego typu.
Walkinside firmy VRcontext jest w tej chwili liderem wśród środowisk swojej klasy,
a dzięki wielu tak istotnym możliwosciom jak import danych z laserowego skanera oraz
wsparcie dla Microstation v8 z pewnościa nim pozostanie.
Rysunek 2.2: Walkinside, symulacja pożaru na platformie wiertniczej w której uczesniczy
wielu użytkowników.
Rysunek 2.3: Walkinside, symulacja wypadku drogowego, dokładna detekcja kolizji, sys-
tem cząsteczek (dym).
11
Rysunek 2.4: Walkinside, wizualizacja plaformy wiertniczej posiadającej ponad 800 000
rur.
Rysunek 2.5: Walkinside, turbina o bardzo złożonej geometrii oraz ogromnej ilości detali.
12
Rysunek 2.6: Walkinside, widok z perspektywy trzeciej osoby, wizualizacja wnętrz.
13
Rysunek 2.7: World Of Warcraft. Wodospady tworzone są poprzez geometrię z animowaną
teksturą, oraz dodatkowy system cząsteczek (widoczne przy ujściu wody u góry).
14
Rysunek 2.8: Half-Life 2. Niespotykany dotąd realizm sceny, woda z realistycznymi odbi-
ciami i zakłóceniami, po prawej w pełni symulowany fizycznie pojazd.
15
Rozdział 3
Implementacja wirtualnego
środowiska za pomocą biblioteki
OpenGL
W rozdziale tym, opisane są wybrane metody wizualizacji wirtualnego środowiska.
Przedstawione zostały zarówno teoretyczne jak i implementacyjne aspekty każdej z metod.
W celu zaprezentowania owych metod został stworzony silnik graficzny (ang. graphic en-
gine,game engine) o nazwie nGine, w którym zaimplementowano opisywane metody. Sil-
nik ten jest zbiorem bibliotek, w których zahermetyzowane zostały odpowiednie metody
wizualizacji oraz renderingu sceny. Zbiór ten można w prosty sposób rozbudować i wyko-
rzystać do tworzenia gier lub bardziej zaawansowanych systemów wizualizacyjnych.
Poniższy schemat (rys. 3.1) obrazuje mechanizm działania oraz przepływ danych w
zaimplementowanym programie.
Pierwszym etapem konstrukcji sceny jest zaprojektowanie geometrii w programie 3D
Studio Max za pomocą narzędzi edycji poligonalnej oraz bezposrednich przekształceń
wierzchołków siatki. Następnie obiekt eksportowany jest za pomocą autorskiego skryptu
nBinExport do binarnego pliku .n3d.
Kolejnym etapem jest wczytanie pliku .n3d przez klasę nMesh, która zajmuje się
przechowywaniem oraz obróbką danych wejsciowych. Z danych tych budowane sa obiekty
VBO a następnie przekazywane do głównej funkcji rysującej. W tym samym czasie przez
klase nGine ładowane są odpowiednie tekstury i przekazywane razem z geometrią do
funkcji rysującej oraz budowane jest drzewo AABB zawarte w danym obiekcie. Funkcja ry-
sująca RenderScene() w każdej klatce animacji uaktualnia pozycję kamery, oraz sprawdza
czy drzewa AABB mają byc wizualizowane. Klasa kamery nCamera odpowiedzialna jest
za interakcje użytkownika ze środowiskiem, oraz badanie pozycji kamery względem innych
obiektów przy pomocy procedur detekcji kolizji zawartych w klasie nAABBTree.
3.1 Wizualizacja geometrii
Geometria we współczesnych środowiskach wirtualnych składa się głównie z
trójkątów, które sa najprostszymi prymitywami przestrzennymi bedącymi w stanie
Plik .n3D
Przetwarzanie pliku
Oraz
Budowanie Obiektu VBO
3D Studio Max
Zarządzanie zasobami sceny
Klasa nMesh Klasa nGine
Pik Tekstury
Plik Mapy
Oświetlenia
Tworzenie drzewa AABB
Detekcja kolizji w drzewie
Operacje pomocnicze
Klasa nAABB Tree
Poruszanie się kamerą
Oraz
Funkcje Pomiarowe
Klasa nCamera
Płótno OpenGL
GL_TEXTURE0_ARB
GL_TEXTURE1_ARB
GL_COMBINE_RGB_EXT
+
GL_MODULATE
RenderScene()
Rysunek 3.1: Schemat działania silnika nGine.
opisać pewną powierzchnie. Producenci podzespołów komputerowych odpowiedzialnych
za wyświetlanie grafiki trójwymiarowej optymalizują swoje rozwiązania pod kątem
operacji na trójkątach, dodając odpowiednie typy danych oraz funkcje bezpośrednio w
konstrukcji układów scalonych.
Innym typem geometrii, która jest jeszcze dosyć nieśmiało wykorzystywana w grafice
czasu rzeczywistego są powierzchnie parametryczne takie jak NURBS (Non-Uniform Ra-
tional B-Spline) lub NURMS (Non-Uniform Rational MeshSmooth). Powierzchnie NURBS
zdefiniowane są poprzez zestaw punktów kontrolnych z przypisanymi wagami, kolejność
krzywych oraz wektor węzła. NURBS sa uogólnieniem zarówno krzywych B-sklejanych
jak też i krzywych Beziera, główną rożnicą są ważone punkty kontrolne dzięki którym
stają się wymierne (niewymierne B-krzywe są szczególnym przypadkiem wymiernych B-
krzywych, w praktyce wiekszość powierzchni NURBS jest niewymierna). Krzywe NURMS
są pochodną krzywych NURBS. Główną różnicą pomiedzy nimi jest to iż wagi wierz-
17
chołków kontrolnych NURMS mogą być różne dla każdego wierzchołka, oraz możliwa jest
kontrola wyglądu obiektu poprzez zmianę wag krawędzi.
W zaimplementowanym w pracy silniku wizualizacji, wykorzystano jedynie siatki
trójkątów ponieważ uznano iż stopień realizmu osiągany tą techniką jest wystarczający.
3.2 Vertex Buffering - Vertex Buffer Objects
Obiekty Vertex Buffer Object, w skrócie VBO są rozszerzeniem biblioteki OpenGL o
nazwie GL ARB vertex buffer object. Rozszerzenie to definiuje interfejs, który umożli-
wia przechowywanie różnych typów danych w bardzo wydajnej pamięci karty graficznej,
zwiększając tym samym prędkość przekazywania danych.
Zbiory danych zamykane są w tzw. obiekty buforowe (buffer objects), które w założe-
niu nie są niczym innym jak tablicą wypełnioną danymi. Interfejs programisty (API)
pozwala użytkownikowi korzystać z VBO poprzez funkcje biblioteki OpenGL lub też
poprzez bezpośredni dostęp do wskaźnika.
Drugą z technik, która zawarta jest w rozszerzeniu jest ”mapowanie buforów”. Gdy ap-
likacja mapuje bufor, system przydziela jej wskaźnik do pamięci. Gdy aplikacja zakończy
pobieranie i zapisywanie do bufora, musi ódmapować”bufor, aby móc z niego skorzystać
ponownie. Mapowanie pozwala na pozbycie się dodatkowej kopii danych, ponieważ dane
zostały zapisane w pamięci karty graficznej i przechowywanie ich w pamięci konwencjon-
alnej komputera jest zbędne, można dzięki temu zaobserwować wzrost wydajności.
Podstawową korzyścią z wykorzystania obiektów VBO jest to iż droga pomiędzy pamię-
cią a procesorem graficznym zostaje znacznie skrócona, oraz to iż do rysowania geometrii
potrzeba jedynie kilku wywołań. W podejsciu klasycznym, narysowanie jednego trójkąta
wymagało trzykrotnego wywołania funkcji glVertex3f, trzykrotnego wywołania funkcji
glNormal3f oraz trzykrotnego wywołania funkcji glTexCoord3f. Każde wywołanie funkcji
wymaga zapisania danych, odłożenia ich na stos i przejścia do kolejnej funkcji. Dzięki uży-
ciu rozszerzenia GL ARB vertex buffer object możliwe jest narysowanie dowolnej liczby
trójkątów wraz z przypisanymi im wektorami normalnymi oraz wspołrzędnymi mapowa-
nia za pomocą wywołania jednej funkcji - glDrawElements lub glDrawArrays.
3.2.1 Tworzenie Obiektów VBO
Pierwszym etapem tworzenia buforów jest wczytanie pliku .n3d przez klasę nMesh.
Po wczytaniu danych wejsciowych do buforów tymczasowych, następuje przekształce-
nie indeksów z formatu MaxScript (1..n) na format indeksowania C++ (0..n). Następ-
nie tablica indeksów ścianek FaceTable sortowana jest metodą qsort wedle materiału
przypisanego do każdej ze ścianek. Po operacji tej otrzymywane sa posortowane tablice
indeksów ścianek oraz identyfikatorów materiałów oraz otrzymywana jest tablica długości
materiałów, w której zapisana jest ilość trójkątów przynależących do danego identyfika-
tora materiału.
18
Następnie tablice wierzchołków oraz dwie tablice wierzchołków mapowania tekstur
konsolidowane są z posortowaną tablicą indeksów, tworząc trzy tablice wierzchołków o
rozmiarze nFaces*3.
Następnym krokiem jest wywołanie funkcji BuildVBO(), której zadaniem jest zbu-
dowanie obiektów zawartych w buforze geometrii (Vertex Buffer Object,VBO).
Funkcja BuildVBO iniciuje wskaźnik do pamięci gdzie zawarte bedą dane bufora, a
następnie wypełnia go, kopiując wskazane dane z pamięci RAM komputera do pamięci
VRAM karty graficznej. Poniższy kod prezentuje proces tworzenia bufora.
// Generowanie i przypinanie bufora
glGenBuffersARB( 1, &nVBOVerts ); // Pobierz wlasciwa nazwe
glBindBufferARB( GL_ARRAY_BUFFER_ARB, nVBOVerts ); // Przypnij bufor
// Zaladuj dane
glBufferDataARB(GL_ARRAY_BUFFER_ARB,nFaces*3*sizeof(nVertex), /
VertexTable,GL_STATIC_DRAW_ARB );
Następnie funkcja usuwa obiekty dynamiczne z których zostały stworzone obiekty
VBO, ponieważ nie są już potrzebne.
Poniższy kod obrazuje sposób wykorzystania buforów VBO do rysowania geometrii.
Na wstępie włączane jest wsparcie dla Vertex Buffer Object’ow po stronie klienta (ap-
likacji), a następnie bufory są odpowiednio łączone z odpowiadającym im funkcjom. Os-
tatnia linia pokazuje przykładowe wywołanie funkcji glDrawElements do narysowania
zestawu danych zawartych w buforach.
// wlaczamy obsluge dla kolejnych buforow danych :
// wierzcholkow, wektorow normalnych, koordynatow mapowania
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// przypinamy bufor geometrii
glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOVerts);
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );
// wektorow normalnych
glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBONormals );
glNormalPointer( GL_FLOAT, 0, (char *) NULL );
// koordynatow tekstur
glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan1);
glTexCoordPointer( 3, GL_FLOAT, 0, (char *) NULL);
// rysujemy element korzystajac z przypietych buforow
glDrawElements(GL_TRIANGLES,engine.Objects[i]->MatLen[j]*3, /
GL_UNSIGNED_INT,&engine.Objects[i]->SortedFaceTable[stride]);
Przy zakończeniu aplikacji należy odmapować bufory danych znajdujące się w pamięci.
Zadanie to wykonywane jest przez destruktor klasy nMesh, obrazuje je poniższy kod.
Tworzona jest tablica wskaźników do buforów, a nastepnie bufory te są usuwane przez
funkcje glDeleteBuffersARB
unsigned int nBuffers[4] = { nVBOVerts, nVBOTVChan1, nVBOTVChan3, nVBONormals};
glDeleteBuffersARB( 4, nBuffers );
19
3.3 Teksturowanie
Teksturowanie jest jedną z podstawowych technik wizualizacyjnych. Dzięki odpowied-
niemu oteksturowaniu obiektów można uzyskać wiele ciekawych efektów, a także nadać
projektowanej scenie realizmu. W ninejszej pracy zaimplementowane zostały następujące
techniki teksturowania :
– Politeksturing
– Light Mapping (Multiteksturing)
– Tekstury Przejść (Metoda Artystyczna)
Dzięki technikom tym możliwe jest uzyskanie sceny o wysokiej jakości, a także uzyskanie
statycznego oświetlenia obliczanego metodą Global Illumination.
3.3.1 Politeksturing
Politeksturing jest techniką zaimplementowaną w celu zwiększenia wyrazistości sceny
z jednoczesnym zmniejszeniem ilości pamięci potrzebnej na przechowanie tekstur. Po-
liteksturing pozwala użytkownikowi na nałożenie osobnych tekstur na każdy z trójkątów
bedących częścią jednego obiektu. Dzięki temu możliwe jest zastosowanie tekstur o śred-
niej rozdzielczości, a geometria będzie w stanie ponownie wykorzystać piksele zapisane w
danej teksturze.
Jak wspomniano wcześniej, podejście klasyczne korzystające z pętli zawierających
instrukcje glVertex jest zbyt mało wydajne. Dzięki wykorzystaniu VBO możliwe jest
podniesienie wydajności o ponad 300%, jednak wiąże się to z pewnymi ograniczeniami
związanymi z wykorzystywanymi funkcjami rysującymi. Funkcja glDrawArrays jest w
stanie narysować cały obiekt VBO przy użyciu jednego wywołania funkcji, niestety rozsz-
erzenie Vertex Buffer Objects nie przewiduje osobnego bufora dedykowanego dla in-
deksowania materiałów. Stąd obiekty rysowane poprzez glDrawArrays mogą posiadać
nałożoną tylko jedną teksturę. Wiąże się to z pewnymi komplikacjami. Głównym prob-
lemem jest tutaj konieczność renderowania (bakingu) kompletnych, oświetlonych tekstur
dla całego obiektu, w bardzo wysokiej rozdzielczości sięgającej ponad 2000px2
. Mimo
zastosowania tak olbrzymiej rozdzielczości, rezultaty osiągane tą metodą są niezadowala-
jące, ponieważ rozmiary tekseli rozpraszają użytkownika i dają wrażenie rozmycia sceny
co obrazuje rysunek 4.4.
Odpowiedzią na ten problem jest zaimplementowana metoda zwana Politeksturingiem.
Struktura danych pliku wejściowego została rozszerzona o dodatkowy kanał koordynatów
UV, z którego korzystać bedą tekstury map oświetlenia, a kanał tekstur (diffuse) został
wzbogacony o identyfikatory materiału dla każdej ze ścianek. Dzięki temu możliwe jest
normalne oteksturowanie środowiska wewnątrz programu służącego do projektowania
(np. oteksturowanie jednego obiektu, jedną, powtarzalną teksturą), a następnie wyeks-
portowanie go na potrzeby systemu czasu rzeczywistego. Metoda ta umożliwia znaczne
oszczędności pamięci, ponieważ jeden piksel tekstury odpowiada wielu tekselom w scenie,
podczas gdy w podejściu poprzednim (glDrawArrays) jeden piksel odpowiadał jednemu
20
tekselowi, i wymagał znacznie dłuższej obróbki wstępnej. Problem ten nie dotyczy map
oświetlenia, ponieważ są one wypiekane w średniej rozdzielczości, a łagodne przejścia
pomiędzy obszarami o różnej intensywności oświetlenia dają wrażenie ciągłości i maskują
wszelkie niedociągnięcia, co obrazuje rysunek 4.5.
Do implementacji Politeksturingu wykorzystano funkcję OpenGL’a glDrawElements.
Pobiera ona następujace parametry : tryb rysowania, ilość obiektów zależna od trybu, typ
danych w tablicy indeksów oraz wskaźnik na tablicę indeksów. Aby wykorzystać możli-
wości tej funkcji, należało wstępnie przygotowac dane, co zostało opisane w sekcji 3.2,
należy tu dodać iż konsolidacja musiała zostać przeprowadzona dla wszystkich buforów
danego obiektu, ponieważ funkcja zakłada zalezności 1:1 dla kolejnych pól danych.
Poniższy fragment kodu obrazuje rysowanie obiektów z wykorzystaniem mechanizmu
politeksturingu. Funkcja wykonywana jest w pętli dla wszystkich materiałów danego
obiektu, zagnieżdżonej w pętli iterującej wszystkie obiekty danej sceny. W wewnętrznej
części przypinana jest tekstura wskazywana przez identyfikator bieżącego materiału, a
następnie jest rysowany fragment obiektu odpowiadający temu materiałowi. Do funkcji
przekazywana jest długość danego materiału w wierzchołkach, oraz wskaźnik uwzględnia-
jący przesunięcie względem poprzednich materiałów do miejsca w tablicy indeksów gdzie
zaczyna się indeksowanie bierzącego fragmentu.
for (int i=0; i<engine.WorldObjects ; i++)
{
int stride=0;
for (int j=0; j<engine.Objects[i]->nTextures;j++)
{
glBindTexture(GL_TEXTURE_2D, engine.Objects[i]->FaceMatTable[stride].matID);
glDrawElements(GL_TRIANGLES, engine.Objects[i]->MatLen[j]*3, GL_UNSIGNED_INT, /
&engine.Objects[i]->SortedFaceTable[stride]);
stride += engine.Objects[i]->MatLen[j]; // wskaznik przesuniecia
}
}
3.3.2 Light Mapping jako szczególny przypadek multiteks-
turingu
Multiteksturowanie jest rozszerzeniem biblioteki OpenGL, a od wersji OpenGL 1.2
wzwyż jest wbudowaną funkcją biblioteki. Rozszerzenie to umożliwia nakładanie na jedną
powierzchnie do ośmiu tekstur oraz zapewnia funkcje łączenia nakładanych tekstur takie
jak mnożenie, odejmowanie oraz inne funkcje logiczne.
Light Mapping, czyli mapowanie oświetlenia opiera się o mnożenie dwóch tekstur za
pomocą parametru GL MODULATE. Do dwóch jednostek teksturujących ładowane są osobne
bitmapy, które stworzą teksturę wyjściową gdzie każdy piksel jest wynikiem mnożenia
odpowiadających sobie pikseli z aktywnych jednostek teksturujących. Proces ten oraz
proces odejmowania od siebie dwóch tekstur obrazuje rysunek 3.2.
Pliki map oświetlenia (tzw. Light Mapy) są zwykłymi teksturami wypiekanymi (ang.
texture baking) za pomocą oprogramowania do syntezy obrazu takiego jak np. Mental Ray.
21
X =
- =
Rysunek 3.2: Multiteksturowanie, złożenie ze sobą dwóch tekstur. U góry iloczyn, u dołu
różnica dwóch obrazów.
Oprogramowanie to oblicza oświetlenie dla całego obiektu, po czym odwija mapę oświet-
lenia z geometrii, technika ta nazywana jest unwrappingiem. Mapa taka zapisywana jest
jako tekstura, a koordynaty mapowania UV zapisywane są w strukturze danych obiektu
w osobnym kanale mapowania, przeznaczonym do tego celu.
W implementacji silnika nGine użyto map oświetlenia w celu pominięcia obliczeń
wykonywanych przez bibliotekę OpenGL związanych z oświetleniem, cieniowaniem i rzu-
caniem cieni. A także w celu uzyskania realistycznego oświetlenia przy użyciu map oświet-
lenia obliczanych metoda Global Illumination. Implementacja takiego modelu oświetlenia,
tak aby możliwa była w czasie rzeczywistym wykracza poza umiejętności autora i możli-
wości dostępnego mu sprzętu komputerowego. Największym minusem jaki ciągnie za sobą
wykorzystanie Light Mappingu do oświetlenia sceny jest to iż sceny te są w pełni sta-
tyczne.
Poniższy kod przedstawia zastosowaną implementację Light Mappingu. W pętli iteru-
jącej wszystkie obiekty sceny uaktywniana jest jednostka teksturująca nr.1 a następnie
ładowana jest mapa oświetlenia odpowiadająca temu obiektowi do wybranej jednostki
teksturującej (Texture Unit,TU). W wewnętrznej pętli iterującej materiały w bieżącym
obiekcie definiowany jest sposób mieszania tekstur nakładanych na obiekt. Następnie
rysowany jest obiekt.
// petla : dla wszystkich obiektow
// wlacz TU1
glActiveTextureARB(GL_TEXTURE1_ARB);
22
// wlacz TU1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
// wlacz obsluge tekstur na TU1
glEnable(GL_TEXTURE_2D);
// przypnij bufor koordynatow light mapy
glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan3); // LM CHAN
// wskaznik do bufora
glTexCoordPointer( 3, GL_FLOAT, 0,(char *) NULL);
// ustawienie flagi bufora
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// przypiecie tekstury z UV pobranymi z bufora
glBindTexture(GL_TEXTURE_2D, engine.WorldTextures + i+1); // przypiecie LM
// petla : dla wszystkich materialow w obiekcie
// przypnij bufor geometrii
glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan1);
// wlacz TU0
glActiveTextureARB(GL_TEXTURE0_ARB);
// wlacz TU0
glClientActiveTextureARB(GL_TEXTURE0_ARB);
// wlacz teksturowanie na TU0
glEnable(GL_TEXTURE_2D);
// wskaznik do bufora UV
glTexCoordPointer( 3, GL_FLOAT, 0, (char *) NULL);
// ustawienie flagi dla bufora
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// funkcja przejscia tekstur W = A*B
// GL_COMBINE - polaczenie 2 tekstur
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT);
// MODULATE - mnozenie ich
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
// zrodlo 0 - tekstura i kolor kazdego piksela
// zrodlo 0 tekstura
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_TEXTURE);
// zrodlo 0 , kolor tekstury
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_EXT,GL_SRC_COLOR);
// zrodlo 1 - tekstura i jej kanal alfa
// zrodlo 1 tekstura
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT,GL_TEXTURE);
// zrodlo 1 kanal alpha tekstury
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_EXT,GL_SRC_ALPHA);
// przypnij teksture diffuse (TU0)
glBindTexture(GL_TEXTURE_2D, engine.Objects[i]->FaceMatTable[stride].matID);
// narysuj calosc
glDrawElements(...);
3.3.3 Tekstury przejść
Bardzo prostą techniką stosowaną przez artystów w celu ujednolicenia sceny jest
tworzenie tekstur przejścia (ang. Transition Textures). Technika ta polega na tworzeniu
tekstury łączącej dwa obszary o różniacych sie teksturach. Mapa ta tworzona jest jest ze
złączenia dwóch tekstur za pomocą liniowej funkcji przejścia. Proces ten obrazuje rysunek
3.3. Uzyskany efekt nadaje scenom ciągłości i nie powoduje nieprzyjemnych przeskoków
pomiędzy obszarami o różnych teksturach.
23
Rysunek 3.3: 3D Studio Max - Ujęcie jednego z korytarzy jaskini zaprojektowanej na
potrzeby systemu nGine. U dołu widoczna tekstura przejścia pomiędzy piaszczystą ścieżką
a kamienną posadzką.
3.4 Symulacja mgły
Efekt mgły jest powszechnie wykorzystywany w wizualizacji środowisk aby nadać im
głębi. W implementacji mgły posłużono się funkcjami bibliotecznymi OpenGL’a. Mgła
może być generowana przez bibliotekę na podstawie trzech funkcji : liniowej, wykładniczej
oraz wykładniczej drugiego stopnia. Metoda ta polega na polega na mieszaniu koloru
piksela geometrii z kolorem mgły w funkcji gęstości mgły oraz odległości punktu od ob-
serwatora. Ostateczna barwa wyznaczana jest poprzez kombinację liniową barwy mgły
oraz barwy obiektu [JDF01]. W zależności od wyboru parametru GL FOG MODE wartość
współczynnika łączenia może mieć postac :
GL LINEAR wspolczynnik = koniec−z
koniec−poczatek
GL EXP wspolczynnik = e(−gestosc·glebokosc)
GL EXP2 wspolczynnik = e(−gestosc·glebokosc)2
Poniższy kod źródłowy przedstawia implementację mgły w opisywanym środowisku.
24
float fogColor[4] = {0.7f,0.7f,0.5f,1.0f}; // kolor mgly
glFogi(GL_FOG_MODE, GL_EXP2); // tryb doboru wspolczynnika
glFogfv(GL_FOG_COLOR, fogColor); // przypisanie koloru mgly
glFogf(GL_FOG_DENSITY, 0.002f); // gestosc mgly
glEnable(GL_FOG); // wlaczenie mgly w maszynie stanu
Powyższe parametry mgły zostały dobrane empirycznie na podstawie zmysłu estety-
cznego autora.
Inną metodą implementacji mgły jest stworzenie tzw. mgły objętościowej (ang. Vol-
umetric Fog), która oparta jest na geometrii. Geometrie mgły objęctościowej stanowią
zazwyczaj obiekty pomocnicze (prymitywy) takie jak kule czy też systemy cząstek. Za-
stosowanie tych technik jest jednak skomplikowane obliczeniowo, co rzutuje negatywnie
na wydajność systemu wizualizacyjnego. Dltego też zrezygnowano z implementacji mgły
objętościowej na rzecz prostej mgły oferowanej przez bibliotekę OpenGL.
3.5 Poruszanie się po środowisku
Poruszanie się oraz interakcja użytkownika ze środowiskiem jest realizowana za po-
mocą klasy nCamera. Klasa ta implementuje także metody pomiaru wydajności, oraz jest
punktem wyprowadzenia mechanizmów detekcji i reakcji na kolizję.
Zaimplementowana kamera jest kamerą widoku z pierwszej osoby (ang. First Person
View, FPP) i składa się z następujących elementów :
– Pozycji kamery
– Wektora kierunku
– Wektora orientacji pionowej
– Wektora ruchu poprzecznego (Strafe)
– Prędkości przemieszczenia
Pozycja kamery modyfikowana jest przez użytkownika za pomocą klawiszy odpowiedzial-
nych za ruch w wyznaczonym kierunku, a kąt skierowania modyfikowany jest poprzez
ruch myszką.
3.5.1 Ogólny algorytm pracy kamery
Przedstawiona poniżej sekwencja czynności powtarzana jest w każdej, kolejnej klatce
animacji.
Pierwszym krokiem jest odświeżenie kamery za pomoca funkcji nCamera.Update().
Funkcja ta pobiera parametr odpowiadający za włączenie lub wyłączenie funkcji detekcji
kolizji, następnie oblicza wektor ruchu poprzecznego (ang. Strafe Vector) wyliczając
iloczyn wektorowy pomiędzy wektorem kierunku a wektorem orientacji pionowej (ang. Up
Vector). Następnie wywoływana jest funkcja SetViewByMouse() odpowiedzialna za obrót
25
kamery za pomocą myszki. Kolejną wywoływaną funkcją jest CheckForMovement(),
która sprawdza stany klawiszy na klawiaturze i modyfikuje prędkość kamery. Ostatnim
krokiem jest wywołanie funkcji calculateFrameRate(), która odpowiedzialna jest za
zliczanie ilości klatek rysowanych w ciągu sekundy.
Po opuszczeniu funkcji nCamera.Update program wywołuje główną funkcję rysującą
(RenderScene()), która wywołuje funkcję nCamera.Look(), odpowiadającą za przekaza-
nie parametrów pozycji kamery do funkcji gluLookAt().
3.5.2 Implementacja ruchu kamery
Poruszanie się kamery realizowane jest przez parę funkcji składowych klasy nCamera,
CheckForMovement() oraz MoveCamera(). Zadaniem pierwszej z nich jest wyskalowanie
prędkości (stałej przesunięcia) względem prędkości rysowania poprzedniej klatki animacji
poprzez iloczyn tych dwóch wartości, a następnie wywołanie funkcji MoveCamera() z
odpowiednim parametrem, w zależności od wciśniętego przez użytkownika klawisza.
Funkcja MoveCamera() tworzy pomocniczy wektor ruchu (vVector) poprzez odjęcie od
wektora kierunku (m vView) wektora pozycji (m vPosition) a nastepnie normalizuje go.
Kolejnym krokiem jest dodanie to wektorów pozycji oraz kierunku iloczynu wektora ruchu
i kamery, co obrazuje poniższy kod:
m_vPosition.x += vVector.x * speed; // dodajemy przyspieszenie do skladowej X pozycji
m_vPosition.y += vVector.y * speed; // dodajemy przyspieszenie do skladowej Y pozycji
m_vPosition.z += vVector.z * speed; // dodajemy przyspieszenie do skladowej Z pozycji
m_vView.x += vVector.x * speed; // dodajemy przyspieszenie do skladowej X widoku
m_vView.y += vVector.y * speed; // dodajemy przyspieszenie do skladowej Y widoku
m_vView.z += vVector.z * speed; // dodajemy przyspieszenie do skladowej Z widoku
W funkcję tą wbudowany jest także algorytm reakcji na kolizję kamery z otoczeniem.
Algorytm bada w którym z sektorów znajduje się kamera, a następnie wykonuje testy
przecięcia z bryłami okalającymi dla tego sektora. Jeżeli zostanie wykryta kolizja z jednym
z liści drzewa, to zamiast inkrementacji wektorów pozycji i widoku o iloczyn wektora
kierunku i zmiennej prędkości z powyższego kodu, następuje dekrementacja, co owocuje
odrzuceniem kamery w kierunku przeciwnym do kierunku poruszania się, uniemożliwiając
przejście przez geometrię sceny.
3.5.3 Ruch poprzeczny
Implementacja ruchu poprzecznego jest praktycznie identyczna jak implementacja
ruchu kamery, z tą różnicą, iż w obliczeniach pomijana jest oś Y. Poniższy kod prezentuje
metodę zawartą w funkcji StrafeCamera() wywoływaną przez funkcję CheckForMove-
ment().
// Inkrementacja pozycji w ruchu poprzecznym
m_vPosition.x += m_vStrafe.x * speed;
m_vPosition.z += m_vStrafe.z * speed;
// Inkrementacja wektora widoku
m_vView.x += m_vStrafe.x * speed;
m_vView.z += m_vStrafe.z * speed;
26
3.5.4 Obrót kamery
Klasa nCamera daje użytkownikowi możliwość w okół wektora orientacji pionowej oraz
wektora ruchu poprzecznego. Funkcja ta implementowana jest przez funkcję SetViewBy-
Mouse() oraz RotateView().
Kąt obrotu kamery uzyskiwany jest poprzez badanie wychylenia pionowego i poziomego
wskaźnika myszy od środka ekranu. Funkcja SetViewByMouse() pobiera współrzędne
ekranowe wskaźnika i sprawdza czy są one równe połowie wysokości i szerokości ekranu,
jeżeli są, funkcja kończy dzialanie, jeżeli nie to przechodzi do kolejnego kroku. Kolejnym
krokiem jest odjęcie od wartości połowy rozdzielczości ekranu aktualnej pozycji wskaźnika
w osiach X i Y dla kątów odpowiednio Y i Z. Następnie badane jest wychylenie kamery
w pionie, jeżeli kąt obrotu wynosi więcej niż jeden radian, to skracany jest on do wartości
jednego radiana aby zapobiec pełnemu obrotowi w pionie. Następnie wyliczany i nor-
malizowany jest iloczyn wektorowy wektora orientacji pionowej oraz wektora widoku i
przekazywany z kątem obrotu osi Z do funkcji RotateView(). W kolejnym kroku kamera
jest obracana o kąt Z w osi Y.
Po wykonaniu powyższej procedury należy przywrócić wskaźnik do pozycji środkowej
aby uniknąć akumulacji obrotu w kolejnych klatkach animacji.
Funkcja SetViewByMouse() przekazuje do funkcji RotateView() kąt oraz osie obrotu
kamery. Zadaniem funkcji RotateView() jest modyfikacja wektora widoku kamery. W
tym celu tworzone są dwa nowe wektory pomocnicze, nowy wektor widoku (vNewView)
oraz bierzący wektor widoku (vView) bedący różnicą pomiędzy wektorem widoku kamery
oraz jej pozycją.
Obrót kamery realizowany jest za pomocą poniższego kodu :
// Dla oszczednosci obliczen wyliczamy kąty tylko raz
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);
// Znajdujemy nowa pozycje wspolrzednej X
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
// Znajdujemy nowa pozycje wspolrzednej Y
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
// Znajdujemy nowa pozycje wspolrzednej Z
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
// Dodajemy uzyskany wektor obrotu do pozycji kamery
// aby uzyskac nowy, obrocony wektor widoku
m_vView = m_vPosition + vNewView;
Metoda ta wykorzystuje wzory na obrót wektora według zadanej osi [Wei99] aby
27
obliczyc nowe współrzędne wektora widoku, który kontroluje kierunek kamery.
3.6 Detekcja kolizji
Systemy detekcji kolizji (Collision Detection,CD) składają się zazwyczaj z dwóch
części :
• Detekcja kolizji (CD)
• Reakcja na kolizję (CR)
System detekcji kolizji w środowisku wirtualnym bada relatywne położenia obiektów
zawartych w tym środowisku. Jeśli zauwazy on iż dwa obiekty są wystarczająco blisko
siebie, lub też w następnej jednostce czasu zajdzie zjawisko przecięcia lub też przeniknię-
cia to zachodzi zdarzenie kolizji, które przekazywane jest z odpowiednimi parametrami
do systemu reakcji na kolizję.
Zdarzenie kolizji przekazywane jest do systemu reakcji na kolizję. W zdarzeniu tym
przekazywane są dane takie jak pozycje obu obiektów z klatki bieżącej oraz następnej,
wektor przesunięcia, dane obiektów takie jak masa, czy też materiał z którego zostały
wykonane, modyfikujący właściwości fizyczne. Następnym krokiem systemu reakcji na
kolizję jest przekazanie tych danych po wstępnej obróbce do systemu symulacji fizyki,
lub też w przypadku jego braku zastosowanie procedur zapobiegania kolizji - w najprost-
szym przypadku jest to wyzerowanie wektora prędkości, dzięki czemu obiekt pozostaje
na pozycji z klatki biezącej. Innym, bardziej dokładnym rozwiązaniem jest wyliczenie
dokładnego miejsca kolizji lub przecięcia między obiektami i przesunięcie obiektu kolidu-
jącego wzdłuż wektora prędkości w to miejsce.
3.6.1 Pojęcia istotne dla zrozumienia zagadnienia detekcji kolizji
Kolider (Collider) - Jest to dynamiczny obiekt kolidujący ze statycznym środowiskiem.
Bounding Volume (BV) - Jest to najczęściej primityw geometryczny okalający zbiór
geometrii w celu uproszczenia obliczeń związanych z interakcją z obiektami zawartymi w
jego wnętrzu (rysunek 3.4).
Axis Aligned Bounding Box (AABB) - Jest to prostopadłościan opisujący dany zbiór
geometrii. AABB tworzony jest poprzez wyznaczenie wektorów miedzy punktami mini-
malnymi i maksymalnymi w kazdej z trzech osi. AABB ułożone są wzdłuż osi układu
współrzednych.
Drzewo AABB - Jest to drzewo binarne posiadające bryły AABB w swych węzłach,
tworzone jest w celu hierarchicznego podziału przestrzeni. Dzięki drzewom tym możliwe
jest szybkie przeszukiwanie hierarchii w celu przyspieszenia obliczeń. Słabą stroną tej
metody jest to iż dla każdego obiektu należy przygotować osobne drzewo, oraz przebu-
dowywać je jeśli zajdzie zmiana położenia. Dlatego też metoda ta sprawdza się optymalnie
jedynie w środowiskach statycznych lub środowiskach nie określanych mianem środowisk
28
Rysunek 3.4: Bryły okalające, sześcian (bounding box) oraz sfera (bounding sphere).
czasu rzeczywistego.
3.6.2 Algorytm detekcji kolizji
Zaimplementowany algorytm detekcji kolizji opiera się o założenie, iż w scenie nie
występują żadne kolizje poza kolizją sfery otaczającej ( Bounding Sphere) kamery ze
środowiskiem, którego elementy reprezentowane są poprzez liście drzewa binarnego AABB.
Ponizszy algorytm (rysunek 3.5) wykonywany jest w każdej kolejnej jednostce czasu
(klatce animacji). Algorytm ten w klatce i-tej sprawdza położenie kolidera kamery wzglę-
dem środowiska dla klatki i+1-szej. Aby dokonać tego testu, kolider przesuwany jest
wzdłuż wektora prędkości z klatki i-tej.
Pierwszym krokiem algorytmu jest sprawdzenie w którym (lub w których) z sektorów
znajduje się obiekt kamery. Jest to realizowane przez test przecięcia się kolidera kamery z
pierwszymi poziomami hierarchii dla każdego z sektorów. W ten sposób wyznaczany lub
wyznaczane są sektory aktywne dla których bedą wykonywane dalsze obliczenia.
Kolejnym krokiem algorytmu jest testowanie przecięcia (kolizji) sfery otaczającej
kamery z drzewem hierarchii obiektu aktywnego. Dla każdej gałęzi na bierzącym poziomie
drzewa wykonywany jest test przecięcia z koliderem kamery. Jeżeli da on wynik pozytywny
to wykonywane są rekurencyjnie testy dla potomków bierzącej gałęzi aż do osiągnięcia
liści drzewa, w których znajduje się maksymalnie jeden trójkąt geometrii, lub też do osią-
gnięcia wystarczająco małej objętości bryły okalającej AABB.
Osiągnięcie liści drzewa lub też gałęzi w której zapisana jest bryła okalająca o objętości
mniejszej niż progowa nazywane jest kolizją i przekazywane do systemu reakcji na kolizję.
29
Sprawdź kolizję dla
tej gałęzi
Czy jest to liść lub gałąź
o wystarczająco małym
rozmiarze?
Wywołaj rekurencję
dla prawej gałęzi
Wywołaj rekurencję
dla lewej gałęzi
Zgłoś kolizję
Nie
Tak
Tak
Zakończ
Nie
START
Rysunek 3.5: Algorytm detekcji kolizji dla drzewa AABB.
3.6.3 Charakterystyka struktur danych użytych do rozwiązania
problemu detekcji kolizji
Trzonem całego systemu jest niezbalansowane drzewo binarne, charakteryzującye się
różną długością głównych gałęzi drzewa, oraz długim czasem przeszukiwania dla przy-
padków pesymistycznych. Problemu tego można uniknąć dzięki zastosowaniu heurestyki
podziału przestrzeni płaszczyzną prostopadłą do najdłuższej osi umieszczoną na środku
jej długości. Dzięki zastosowaniu tej metody otrzymywane są zbalansowane lub pół-
zbalansowane drzewa (gdzie większa część jest co najwyżej dwukrotnie większa od części
mniejszej) gdzie nakładanie się na siebie brył otaczających jest minimalne [vdB98]. Główną
zaletą drzew AABB nad drzewami OBB ( Oriented Bounding Box) jest znacznie większa
prędkość konstrukcji oraz niewiele mniejsza precyzja. Kolejnym atutem drzew AABB jest
także to iż zapisanie ich wymaga znacznie mniej (o połowę) mniej miejsca niż zapisanie
drzew AABB [vdB98].
Sześciany okalające AABB definiowane są przez dwa punkty w przestrzeni utworzone
na podstawie maksymalnych i minimalnych wartości punktów modelu w każdej z osi. W
strukturze zawarta jest także objętość danego sześcianu, używana jako parametr precyzji
detekcji kolizji.
Geometria z której tworzone są bryły AABB jest zdefiniowana przez zbiór ścianek
(faces) opisanych przez trójki punktów w przestrzeni. Strukura niesie ze sobą także środek
ciężkości każdego z trójkątów, używany jako parametr determinujący przynależność danego
30
prymitywu jako część lewą lub prawą podczas podpodziałów przestrzeni.
3.6.4 Test przecięcia sfery i bryły AABB
Algorytm testowania przecięć pomiędzy sferą a sześcianem okalającym AABB został
po raz pierwszy zaprezentowany przez Arvo [Jam90, TAM02] i jest zadziwiająco prosty.
Trzonem tego algorytmu jest znalezienie punktu na AABB, który jest najbliżej środka
sfery c. Używane do tego są testy jednowymiarowe, po jednym na każdą z osi AABB.
Środek sfery porównywany jest z punktami granicznymi bryły okalającej. Jeśli znajduje
się poza bryłą, obliczana jest odległość między bryłą a środkiem sfery (wzory 3.2 i 3.1)
na bieżącej osi, a nastepnie podnoszona do kwadratu. Czynność ta wykonywana jest dla
wszystkich trzech osiach, suma tych kwadratów porównywana jest z kwadratem promienia
sfery, r2
. Jeśli suma jest mniejsza niż kwadrat promienia to nabliższy punkt bryły AABB
znajduje się wewnątrz sfery i zachodzi przecięcie.
∀i ∈ {x, y, z} d = d + (ci − amin
i )2
(3.1)
∀i ∈ {x, y, z} d = d + (ci − amax
i )2
(3.2)
gdzie :
– ci to kolejne współrzędne środka sfery,
– d to obliczana suma,
– amin
i i amax
i to kolejne współrzędne punktów granicznych bryły AABB, odpowiednio
minimalnego i maksymalnego.
Algorytm ten obrazuje poniższy pseudokod.
d=0;
for each i in {x,y,z}
if(c[i] < a_min[i]) // jesli dana skladowa jest mniejsza od minimalnej
d=d+(c[i] - a_min[i])^2 // wykonaj obliczenie
else if (c[i] > a_max[i]) // jesli jest wieksza od maksymalnej
d=d+(c[i] - a_max[i])^2 // wykonaj obliczenia
if (d > r^2) // jesli odleglosc jest wieksza od kwadratu promienia
return(BRAK_KOLIZJI) // zwroc brak kolizji
return(KOLIZJA) // w innym wypadku zwroc kolizje
3.6.5 Algorytm budowy drzewa binarnego AABB
Przedstawiony poniżej algorytm (rysunek 3.6) jest wykonywany rekurencyjnie do mo-
mentu osiągnięcia progu, którym jest zamkniecie nie wiecej jak jednego trójkąta we
wnętrzu bryły AABB. Zadanie to wykonywane jest przez klasę nAABBTree.
Pierwszym krokiem algorytmu jest odnalezienie wartości minimalnych i maksymal-
nych w każdej z trzech osi (lx, ly, lz, ux, uy, uz), region taki opisany jest przez rownanie 3.3
i nazywany bedzie bryłą okalającą AABB. Procedury tworzące brylę AABB zawarte są
w klasie nAABB.
31
Stwórz AABB dla
podanej geometrii
Czy wewnątrz znajduje
się wiecej jak jeden
trójkąt?
Podziel przestrzeń
płaszczyzną na
dwie części
Wywołaj rekurencję
dla prawej gałęzi
Wywołaj rekurencję
dla lewej gałęzi
Utwórz liść.
Zakończ
rekurencje.
Tak
Nie
START
Rysunek 3.6: Algorytm konstrukcji drzewa AABB.
32
R = {(x, y, z) | lx ≤ x ≤ ux, ly ≤ y ≤ uy, lz ≤ z ≤ uz} (3.3)
Następnie tworzony jest wektor v(x, y, z) wg. wzoru 3.4.
v = l − u. (3.4)
Z wektora v(x, y, z) obliczana jest objętość danej bryły AABB, wg. wzoru 3.5. Jeśli
we wnętrzu bryły okalającej znajduje się wiecej jak jeden obiekt (trójkąt) to algorytm
wykonywany jest dalej, w przeciwnym wypadku tworzony jest liść drzewa i rekurencja
jest kończona.
VAABB = x · y · z. (3.5)
Kolejnym krokiem jest dokonanie podziału przestrzeni płaszczyzną ( slicing plane).
Płaszczyzna ta dzieli zbiory geometrii sub-optymalnie [vdB98] jeśli jej wektor normalny
n jest równoległy do najdłuższej osi bryły AABB w bieżącym węźle, a płaszczyzna (rów-
nanie 3.6) przechodzi przez punkt p0 znajdujący się na środku długości najdłuższej osi.
Ax + By + Cz + D = 0. (3.6)
gdzie:
– A, B, C są współrzędnymi odpowiednio x,y,z wektora normalnego do płaszczyny n
– x, y, z to wspolrzędne punktu p0
– D to odległość płaszczyzny od początku układu współrzędnych.
Kolejnym etapem podziału przestrzeni jest segregowanie prymitywów na części lewą i
prawą. Jeśli wynik równania 3.7 będzie większy lub równy zero, to trójkąt, którego środka
ciężkości (równanie 3.8) użyliśmy do rozwiązania tego równania zaklasyfikowany będzie
jako część prawa, w przeciwnym wypadku będzie on zaklasyfikowany jako część lewa.
Implementacja tego kroku w klasie nAABBTree zawiera się w funkcji CreateNode() i
wykorzystuje klasę pomocniczą nTriSort, która pozwala na zapisanie w swym wnętrzu
środka ciężkości każdego z trójkątów oraz jego przynależności do części prawej lub lewej.
Na wstępie tworzony jest obiekt dynamiczny klasy nTriSort or rozmiarze geometrysize,
czyli ilości scianek w danym obiekcie. Dla każdej ze ścianek w bierzącym obiekcie obliczany
jest środek ciężkości, który następnie porównywany jest z płaszczyzną przecięcia. W za-
leżności od wyniku porównania, bierząca ścianka klasyfikowana jest jako lewa lub prawa
oraz inkrementowane sa odpowiednie wartości numLeft oraz numRight odpowiadające
za rozmiar obiektów dynamicznych, przechowujących geometrię dla lewego oraz prawego
rozgałęzienia.
Na tym etapie algorytm przeprowadza jeszcze jeden test. Dla niektórych, bardzo
ekstremalnych przypadków zdarzyc się moze iż wszystkie scianki danego rozgałęzienia
zostaną zaklasyfikowane jako część lewa lub prawa. Prowadzi to nieskończonego zapętlenia
rekurencji (tzw. deadloop), co prowadzi do szybkiego wyczerpania zasobów pamięci oraz
błędu ochrony pamięci. W przypadku takim, algorytm dzieli bierzący zestaw geometrii
33
(subset) na dwie równe części, nadpisując wykonane wcześniej sortowanie. Przypadki takie
mają miejsce zazwyczaj gdy bierzący zestaw składa się z bardzo małej ilości prymitywów.
D =
ax0 + by0 + cz0 + d
√
a2 + b2 + c2
(3.7)
gdzie:
– (a, b, c) to współrzędne wektora normalnego do płaszczyzny n
– x0, y0, z0 to współrzędne badanego punktu
– d to odległość płaszczyzny od środka układu współrzędnych
Równanie to daje wynik dodatni jeśli badany punkt znajduje się po tej samej stronie
płaszczyzny co wektor normalny n, oraz wynik ujemny w przypadku przeciwnym.
Jeśli S = (xs, ys, zs) jest środkiem trójkąta ABC to:
xs =
xa + xb + xc
3
, ys =
ya + yb + yc
3
, zs =
za + zb + zc
3
. (3.8)
Końcowym etapem jest wykonanie rekurencji algorytmu dla części prawej oraz lewej.
Wynikiem działania tego algorytmu jest półzbalansowane drzewo binarne, posiadające
bryły AABB w swych gałęziach oraz bryły AABB okalające pojedyńcze primitywy w
swych liściach [vdB98]. Wizualizację drzewa przedstawia rysunek 3.7
Na etapie tym klasa nAABBTree tworzy dwa nowe obiekty swej klasy, podając do
konstruktora klasy zestawy geometrii zaklasyfikowane wcześniej jako prawy i lewy. Kon-
struktor klasy nAABBTree zeruje wskaźniki na liście prawy i lewy, które zostana nadpisane
podczas tworzenia kolejnych obiektów, lub też pozostaną wyzerowane, oznaczając bieżący
punkt jako liść drzewa. Następnie wywoływana jest funkcja BuildNode, która tworzy ko-
lejne gałęzie drzewa.
3.6.6 Wizualizacja drzewa AABB
W silniku nGine zaimplementowano prosty system wizualizacji drzew AABB dla
wszystkich obiektów. Funkcja rysująca daną bryłę AABB zawarta jest wewnątrz klasy
nAABBTree i może być wywolywana rekurencyjnie dla wszystkich potomków danej gałęzi,
dając w rezultacie obraz wybranej części drzewa (rysunek 3.7). Metoda ta została zaim-
plementowana w celach badawczych i testowych, pozwala ona projektantowi na analizę
wybranego modelu, i takie optymalizacje aby objętości wybranych węzłów drzewa były
jak najmniejsze.
Funkcja rysująca bryły AABB rysuje pary wierzchołków między którymi rysowane
są linie za pomocą funkcji glBegin(GL LINES). W parze glBegin(), glEnd() zawarte
jest 12 par definiujących wszystkie linie sześcianu. Współrzędne punktów wyliczane sa
na postawie punktu minimalnego bryły AABB oraz wektora v stworzonego między pun-
ktami minimalnym i maksymalnym.
34
Rysunek 3.7: nGine - Wizualizacja drzewa AABB opisującego sferę.
Bardzo waznym elementem porównawczym jest tutaj sposób rysowania brył okala-
jących. Każdorazowe wywołanie funkcji DrawBV() pociąga za sobą wywołanie funkcji
glVertex3f aż 24 razy. Przy każdorazwym wywołaniu należy także wyłączyć obie akty-
wne jednostki teksturujące, oraz włączyć je po wizualizacji drzewa. Wykonanie tej pro-
cedury rekurencyjnie dla całego drzewa owocuje spadkiem wydajności (ilości klatek na
sekundę, FPS) aplikacji o ponad 50%. Gdyby wierzchołki brył AABB zapisać w obiekcie
VBO, spadek wydajności niebyłby tak znaczny.
3.6.7 Algorytm ukrywania powierzchni niewidocznych oparty o
bryły AABB
Jednym z zastosowań brył okalających (ang. bounding volumes) jest szybkie wyłączanie
dużych ilości danych z obliczeń. Dzieki tej metodzie możliwe jest pomijanie dużych ilości
geometrii podczas rysowania sceny, co owocuje znacznym zwiększeniem wydajności.
W ujęciu typowym, stosuje się testowanie przecięcia bryły okalającej z bryłą widzenia
(frustum). Jeśli bryły te nie przecinają się to są one pomijane przy wyświetlaniu, pro-
ces ten nazywany jest ukrywaniem obiektów niewidocznych, lub też selekcją za pomocą
bryły widzenia (frustum culling). W ujęciu implementowanego środowiska, podejście za-
proponowane w [TAM02], opierające się na testowaniu bryły AABB i sześciu płaszczyzn
uznano za słuszne i rozbudowano je o dodatkowy stopień dokładności, jakim jest punkt
środkowy bryły AABB.
35
AABB Top
Back
Right
Bottom
Left
Front
Rysunek 3.8: Bryła widzenia oraz obiekt otoczony przez bryłę AABB.
W każdej klatce animacji z bryły widzenia izolowane są płaszczyzny budujące tą bryłę.
Następnie wykonywany jest test położenia punktu względęm płaszczyzny dla wszystkich
wierzchołków bryły AABB oraz dla jej punktu środkowego. Test ten opiera się o rów-
nanie 3.7. Jesli odległość między badanym punktem a płaszczyzną jest większa od zera
to punkt klasyfikowany jest jako leżący w dodatniej półprzestrzeni wyznaczonej przez
tą płaszczyznę, w przeciwnym wypadku bryła klasyfikowana jest jako niewidoczna. Jeśli
punkt leży w dodatniej półprzestrzeni wszystkich sześciu płaszczyzn to bryła do której
należy klasyfikowana jest jako widoczna.
W pracy zmodyfikowano oryginalny algorytm frustum cullingu [TAM02] dodając
dodatkowy test punktu środkowego, w celu zwiększenia dokładności testowania. Przed
wprowadzeniem tej modyfikacji, dla ekstremalnych przypadków, w których bryła okala-
jąca była większa niz bryła widzenia, obiekty były klasyfikowane jako niewidoczne, mimo
iż znajdowały się dokładnie na wprost kamery. Dodanie punktu środkowego zwiększa
dokładność testowania ośmiokrotnie, ponieważ przez punkt środkowy można przeprowadzic
trzy płaszczyzny równoległe do osi szcześcianu, rozdzielające bryłę AABB na osiem części.
Modyfikacja ta z powodzeniem wyeliminowała wszelkie występujące anomalia.
36
Rozdział 4
Rezultaty i wnioski
W rozdziale tym znajdują się wyniki testów wydajnościowych środowiska nGine.
Zadaniem tych testów jest ocena wydajności aplikacji przy różnych parametrach wej-
ściowych - głównie przy zwiększającej się ilości geometrii.
4.1 Opis procedury testowej
Klasy środowiska nGine zostały wyposażone w specjalne moduły do badania i rapor-
towania wydajności aplikacji.
Głównym testem wydajnościowym jest liczba generowanych klatek animacji w ciągu
sekundy (ang. Frames Per Second, FPS). W celu pomiaru FPS klasa nCamera została wy-
posażona w funkcję calculateFramerate(), której zadaniem jest pomiar liczby klatek
animacji rysowanych w ciągu sekundy, oraz obliczanie liczb średnich, maksymalnych i
minimalnych.
Funkcja RenderScene() odpowiedzialna jest za rysowanie kolejnych klatek animacji
oraz odświeżanie widoku kamery. W każdej kolejnej klatce animacji wywołuje ona funkcję
nCamera.Look() odpowiedzialną za odświeżenie parametrów kamery oraz wywołanie
funkcji calculateFramerate(). Podczas każdego wywołania funkcja ta pobiera aktu-
alny czas oraz inkrementuje liczbę narysowanych klatek. Jeżeli czas jaki upłynął pomiędzy
kolejnymi wywołaniami jest większy od jednej sekundy to wartość FPS jest zapisywana
i wyświetlana, a parametry pomiarowe zostają wyzerowane.
Klasa nCamera jest sprzężona z funkcją calculateFramerate(), dzięki czemu możliwa
jest regulacja prędkości kamery w zależności od prędkości komputera, na jakim aplikacja
jest uruchamiana. Zmiana prędkości jest iloczynem ilości klatek narysowanych w ciągu
ostatniej sekundy oraz stałej kSpeed. Dzięki zastosowaniu tej procedury kamera prze-
będzie tą samą drogę w tym samym czasie, niezależnie od prędkości systemu, na którym
działa aplikacja.
Procedura testowa opiera się na mierzeniu wydajności środowiska poprzez wskaźnik,
jakim jest liczba generowanych klatek animacji w ciągu sekundy przy następujących para-
metrach :
• Rozdzielczość płótna OpenGL.
• Tryb okienkowy oraz pełnoekranowy.
• Zastosowanie optymalizacji Frustum Culling.
• Detekcja kolizji.
• Ilość geometrii w scenie.
• Poprawność środowiska.
Wynikiem przeprowadzonych testów jest uzyskanie wartości średnich, maksymalnych
i minimalnych dla ilości generowanych klatek animacji w ciągu sekundy dla złożeń wyżej
wymienionych parametrów. Każdorazowy pomiar odbywał się podczas trzykrotnego prze-
lotu kamery wewnątrz specjalnie zaprojektowanej jaskini, podczas którego zebrano około
100 próbek.
Wszystkie testy zostały przeprowadzone na komputerze PC o następującej konfigu-
racji :
– Procesor : Intel Pentium IV 3.06 GHz HT.
– GPU : Ati Radeon 9600XT (Sterowniki Omega 2.6.05a).
– Pamięć : 1024 MB Dual Channel DDR CL 2.5, taktowane magistralą 200MHz.
– Płyta Główna : Abit IS-7, taktowana magistralą 200MHz.
System nGine pracuje w technologii jednowątkowej i nie wykorzystuje możliwości
drugiego potoku procesora HT.
4.2 Analiza wyników przeprowadzonych testów
4.2.1 Wpływ rozdzielczości oraz trybu płótna OpenGL na wyda-
jność środowiska
Wpływ przyrostu rozdzielczości rysowanego płótna OpenGL na prędkość generowanego
obrazu przedstawia wykres 4.1. Prezentowane dane pochodzą ze sceny testowej o złożoności
siatki 9500 trójkątów oraz posiadającej 14 MB tekstur. W celu uniknięcia błędów pomia-
rowych, oraz aby zapewnić stałą liczbę rysowanej geometrii wyłączono optymalizacje
Frustum Culling.
Jak łatwo zauważyc, spadek rozdzielczości powoduje wzrost liczby generowanych klatek
o około 30%. Spowodowane jest to faktem, iż procesor graficzny musi wypełnić mniejszą
liczbę pikseli w ciągu sekundy.
Wykres 4.2 obrazuje wpływ przejścia aplikacji w tryb pełno ekranowy wraz ze zmianą
rozdzielczości.
38
Rysunek 4.1: Wpływ rozdzielczości oraz Frustum Culling’u na średnią prędkość generowa-
nia animacji w trybie okienkowym.
Rysunek 4.2: Wpływ rozdzielczości oraz Frustum Culling’u na średnią prędkość generowa-
nia animacji w trybie pełnoekranowym.
39
Rysunek 4.3: Wpływ ilości geometrii i Frustum Cullingu na ilość generowanych klatek
animacji.
Można zaobserwować tutaj wzrost wydajności systemu o kolejne 10−20% w stosunku
do trybu okienkowego (wykres 4.1) związany z bezpośrednim dostępem do pamięci ekranu
oraz brakiem rysowania elementów, które nie należą do systemu wizualizacyjnego nGine.
4.2.2 Wpływ optymalizacji Frustum Culling na wydajność sys-
temu
Wykresy 4.1, 4.2, 4.3 obrazują przyrost prędkości generowanej sceny przy zastosowa-
niu optymalizacji Frustum Culling.
Dzięki zastosowaniu tej optymalizacji uzyskano przyrost wydajności między 90% a
150%. Tak olbrzymi przyrost spowodowany jest faktem, iż większość geometrii znajdu-
jącej poza bryłą widzenia jest usuwana z potoku renderującego, wobec czego procesor
graficzny nie zajmuje się jej przetwarzaniem. Ma to szczególne znaczenie dla scen z dużą
(150 000 trójkątów) ilością geometrii (wykres 4.3), ponieważ spadek ilości generowanych
klatek poniżej 40-60 FPS jest zauważalny dla użytkownika i może powodować dyskomfort.
4.2.3 Wpływ detekcji kolizji akcelerowanej metodą drzew
AABB na prędkość działania systemu
Podczas przeprowadzonych testów nie zauważono wpływu włączenia mechanizmu
detekcji kolizji na prędkość generowanej sceny przekraczającego założony błąd pomi-
arowy ±5FPS. Fakt ten został potwierdzony dla obydwu scen testowych, różniących
się ilością geometrii w stosunku 1:15,7. Brak wpływu na prędkość generowania animacji
spowodowany jest faktem, iż algorytm detekcji kolizji kończy swoją pracę po zaledwie
40
kilku krokach, ponieważ kolider kamery nie przecina brył okalających wewnętrznych części
drzewa. Wynik ten można uznać za dobry w porównaniu z wynikami uzyskanymi w
[Kos04], gdzie zagęszczenie geometrii z 1000 trójkątów do 10 000 trójkątów owocowało
spadkiem wydajności o ponad 50% a detekcja kolizji została zaimplementowana za po-
mocą sferycznej metody śledzenia promieni.
4.2.4 Wpływ ilości geometrii na prędkość działania systemu
Wykres 4.3 obrazuje spadek wydajności systemu dla sceny o wysokiej złożoności
(Hi-Poly) w stosunku do sceny Low-Poly z wykresu 4.1. Można zaobserwować tutaj
znaczny spadek wydajności systemu, sięgający od 50% do 75% związany z przyrostem
przetwarzanej geometrii o około 1570%. Mimo tak ogromnej różnicy w ilości geometrii, nie
uzyskano nigdy średniej ilości FPS mniejszej niż 40 FPS, co jest znacznym osiągnięciem
w stosunku do wcześniej prezentowanych metod [Kos04]. Różnicę wydajności można zm-
niejszyć dzięki zastosowaniu optymalizacji Frustum Culling, co obrazuje wykres 4.3. Dal-
szy przyrost wydajności możliwy jest dzięki zastosowaniu cullingu o większej dokładności,
np. działającego w odniesieniu do pojedyńczych liści drzewa, a nie tylko w odniesieniu
do jego korzenia.
4.2.5 Poprawność wizualizacji środowiska
Testowane wirtualne środowisko jest fizycznie poprawne. Wizualizowana geometria nie
posiada prześwitów ani żadnych braków. Wszystkie koordynaty geometryczne, współrzę-
dne mapowania, wektory normalne nie zmieniły się w wyniku działania środowiska i są
odbiciem tego, co zostało zaprojektowane w programie graficznym.
Detekcja kolizji i reakcja na kolizje są poprawne, nie występują obszary z niewidzial-
nymi bryłami kolidującymi, nie istnieją także miejsca gdzie użytkownik mógłby przejść
przez ścianę lub inny obiekt w scenie.
4.3 Prezentacja uzyskanych wyników, rysunki
W sekcji tej zaprezentowane są wyniki działania programu. Dołączone rysunki są
niemodyfikowanymi zrzutami ekranu z działającego środowiska nGine.
Rysunek 4.5 obrazuje zwiększenie jakości wyświetlanego środowiska poprzez użycie
politeksturingu w stosunku do środowiska opisanego przez pojedyńcze tekstury na ry-
sunku 4.4.
Rysunek 4.6 prezentuje cieniowanie oraz efekty świetlne, takie jak pozorne świecenie.
Rysunek 4.7 dokładniej obrazuje jakość uzyskanych cieni.
Rysunek 4.8 obrazuje porównanie jakości wyświetlania sceny w środowisku nGine
(OpenGL) oraz tej samej sceny wyrenderowanej w 3D Studio Max za pomocą programu
Mental Ray. Klatka animacji w środowisku nGine została stworzona w czasie około 1/300
41
sekundy, obraz z Mental Ray był przetwarzany przez około 3 minuty.
Rysunek 4.9 obrazuje efekt pozornego świecenia obiektów, uzyskany dzięki zastosowa-
niu light mappingu. Dzięki tej technice możliwe jest częściowe wyeliminowanie Pixel
Shadingu dla prostych środowisk.
Rysunki 4.10 oraz 4.11 obrazują ogólny widok na zaprojektowane środowisko. Specy-
fiką tego projektu jest to, iż normalne ścian jaskini odwrócone są do wewnątrz, dzięki
czemu po „wyjściu” z jaskini możliwe jest obejrzenie całości środowiska, ponieważ ścianki
z wektorami normalnymi równoległymi do kamery nie są rysowane. W zaprojektowanym
środowisku wyróżniono trzy tematycznie różne strefy : ruiny z otwartym sklepieniem
(rysunek 4.10), tunel jaskini (rysunki 4.5, 4.10) oraz zasypaną starożytną komnatę (ry-
sunki 4.7, 4.11, 4.12). Strefy te połączone są w sposób płynny, prezentując użytkownikowi
ciekawe i zróżnicowane środowisko.
Rysunek 4.4: nGine - Single Texturing oparty o glDrawArrays, widoczny znaczny rozmiar
tekseli. Powierzchnie sceny dają wrażenie rozmytych.
42
Rysunek 4.5: nGine - Politeksturing, znaczna poprawa jakości wyświetlanego obrazu
43
Rysunek 4.6: nGine - Lightmapping, cienie i efekty świetlne
44
Rysunek 4.7: nGine - Lightmapping, cienie
45
Rysunek 4.8: nGine - Porównanie jakości wyświetlania
46
Rysunek 4.9: nGine - Wejście do jaskini, widoczne świecące kryształy
47
Rysunek 4.10: nGine - Widok ogólny na część południową
48
Rysunek 4.11: nGine - Widok ogólny na część północną
49
Rysunek 4.12: nGine - Wejście do północnej komnaty
50
Rozdział 5
Podsumowanie i wnioski
Osiągnięte podczas implementacji środowiska nGine rezultaty są pozytywne. Osią-
gnięto zadowalający stopień realizmu oraz zrealizowano założenia postawione pracy. Teza
pracy brzmiąca „Przy użyciu biblioteki OpenGL możliwa jest implementacja fizycznie
poprawnego i wydajnego wirtualnego środowiska” została więc udowodniona.
Wszystkie wybrane elementy wizualizacji zostały zaimplementowane od postaw dzięki
użyciu biblioteki OpenGL i działają zgodnie z definicją. Wydajność wszystkich elementów
wizualizacyjnych jest wysoka i spełnia wszelkie standardy komfortu pracy ze środowiskiem.
Przy maksymalnym testowanym obciążeniu, prędkość animacji nie była niższa niż 39-41
klatek na sekundę, co jest rezultatem dość dobrym, zważając na stopień profesjonalizmu
oraz ilość osób zaangażowanych w implementacje systemu nGine w stosunku do aplikacji
komercyjnych.
Zgodnie z założeniami pracy, opracowano w pełni funkcjonalne, poprawne fizycznie
wirtualne środowisko obsługujące dowolony ruch kamery w przestrzeni środowiska, oraz
detekcję kolizji kamery ze środowiskiem, uniemożliwiającą jej przenikanie przez elementy
środowiska. W środowisku zaimplementowano także wybrane elementy wizualizacji pod-
noszące relatywny stopień realizmu sceny, elementami tymi są :
1. Detekcja kolizji akcelerowana drzewem binarnym AABB. Metoda ta opiera się na
zbudowaniu drzewa binarnego zawierającego w swych węzłach i liściach bryły okala-
jące AABB. Drzewo jest hierarchiczną reprezentacją geometrii danego obiektu, dla-
tego też możliwe jest szybkie przeszukanie go w celu odnalezienia szukanego ele-
mentu oraz szybkie zakończenie przeszukiwania drzewa na wczesnych etapach jeżeli
kolider nie znajduje się w pobliżu geometrii z którą może kolidować. Implementacja
tej metody wymaga każdorazowego przebudowania drzewa podczas uruchamiania
aplikacji, co wydłuża czas uruchomienia. Przeciwwagą jest fakt, iż przeszukiwanie
drzewa nie wpływa w sposób widoczny na wydajność aplikacji.
2. Implementacja oświetlenia i cieniowania sceny za pomocą map oświetlenia. Metoda
ta, oparta na multiteksturingu pozwala na uzyskanie realistycznych efektów świet-
lnych w statycznym środowisku. Oświetlenie sceny obliczane jest wstępnie metodą
oświetlenia globalnego (ang. Global Illumination, GI) a następnie zapisywane do
tekstur oświetlenia. Kolejnym krokiem jest przemnożenie wartości pikseli mapy oś-
wietlenia z odpowiadającym im fragmentom sceny uzyskując realistyczne efekty
świetlne.
3. Implementacja wyświetlania geometrii za pomocą buforów pamięci karty graficznej.
Zastosowanie tej metody skraca znacznie drogę jaką wyświetlane dane muszą po-
konać, co owocuje wzrostem wydajności aplikacji o ponad 300%. Kolejnym plusem
tej metody jest rysowanie całego przygotowanego zestawu funkcji za pomocą jednej
funkcji, co znacznie zmniejsza czas jaki potrzebuje CPU na przygotowanie zestawu
geometrii do wyświetlenia.
4. Opracowanie autorskiego, binarnego formatu eksportu grafiki o nazwie „n3D”. Dzięki
temu formatowi zapisu danych, możliwe jest wyeksportowanie geometrii z programu
3D Studio Max i odczytanie jej za pomocą silnika nGine po bardzo niewielu ope-
racjach wstępnych. Format ten został zoptymalizowany pod kątem współpracy z
buforami pamięci karty graficznej. Podczas eksportowania danych nietracone są
żadne informacje a scena zaimportowana do wirtualnego środowiska wygląda do-
kładnie tak jak została zaprojektowana w programie graficznym. Dzięki temu, oraz
przejrzystej strukturze formatu, możliwe jest rozgraniczenie funkcji programisty i
grafika, co pozwala na zatrudnienie wyspecjalizowanej kadry dla każdej z osobnych
dziedzin.
5. Opracowanie systemu politeksturingu. System ten pozwala na rysowanie i tekstur-
owanie geometrii dokładnie tak jak została zaprojektowana w programie graficznym.
Dzięki politeksturingowi możliwe jest nałożenie wielu tekstur na jeden obiekt, oraz
użycie powtarzalnych tekstur w całej scenie, co owocuje znacznym zmniejszeniem
zapotrzebowania na pamięć. Politeksturing współpracuje także z systemem mapowa-
nia oświetlenia dając grafikom potężne narzędzie do projektowania wirtualnych
środowisk.
6. Implementacja kamery. Zastosowana metoda implementacji kamery pozwala użyt-
kownikowi na poruszanie się we wszystkich kierunkach, pozwala na ruch poprzeczny
oraz blokuje możliwość pełnego obrotu pionowego, powodującego dezorientujący
efekt. Klasa kamery posiada także skalowanie prędkości przemieszczania się kamery
w locie, dzięki czemu wraz z rozwojem architektury komputerów animacja nigdy
nie będzie zbyt szybka, powodując trudności w używaniu środowiska.
7. Zbudowanie w programie 3D Studio Max wirtualnego środowiska jaskini połączo-
nej z elementami starożytnych ruin w celach prezentacji możliwości zaimplemen-
towanego wirtualnego środowiska, oraz wersji o dużej ilości szczegółów w celach
testowych. Zaprojektowane środowisko obrazuje przejścia pomiędzy różnymi tema-
tycznie obszarami oraz pokazuje spektrum tematyczne środowisk jakie mogą być
współcześnie wizualizowane.
8. Tekstury przejść. Metoda ta pomogła w połączeniu w sposób płynny dwóch ob-
szarów o diametralnie różnej charakterystyce wystroju, tworząc spójną całość.
52
5.1 Dalsze prace związane z rozwojem wirtualnych
środowisk
5.1.1 Wielowątkowość
Testy wydajnościowe środowiska nGine zostały przeprowadzone na sprzęcie klasy PC
wyposażonym w procesor opierający się na technologii Hyper Threading. Technologia ta
opiera się o dwa potoki przetwarzające oraz jedną jednostkę wykonawczą, dzięki czemu
możliwe jest uzyskanie wydajności zbliżonej do maszyn dwuprocesorowych.
Środowisko nGine nie zostało jednak wyposażone w technologię wielowątkową, dlatego
też korzysta jedynie z jednego potoku przetwarzającego. Implementacja wielowątkowości
skróciłaby czas potrzebny na budowanie drzewa AABB oraz umożliwiła stworzenie osob-
nych wątków dla mechanizmu detekcji kolizji i obsługi sceny oraz dla głównej funkcji
renderującej, co znacznie zwiększyłoby wydajność środowiska.
5.1.2 Inne modele hierarchii sceny
Zastosowane w systemie nGine drzewo binarne opierające się o bryły AABB jest
metodą stosunkowo prostą w implementacji oraz w miarę wydajną, lecz może się nie
sprawdzić dla bardzo dużych scen (powyzej miliona trójkątów), oraz jest metodą je-
dynie dostatecznie dokładną, ponieważ sześciany okalające ułożone są wzdłuż osi układu
współrzędnych, przez co zawierają bardzo dużo pustej przestrzeni.
Alternatywnymi metodami reprezentacji hierarchii geometrii są drzewa binarne OBB,
drzewa ósemkowe, oraz drzewa binarne BSP.
Drzewa OBB (ang. Oriented Bounding Box) są podobne do drzew AABB z tą różnicą
że sześciany okalające ułożone są naokoło opisywanej geometrii tak, aby zminimalizować
ich objętość i zmniejszyć ilość pustej przestrzeni w ich wnętrzu (ang. Tight-fit). Metoda
ta nie została zaimplementowana ze względu na skomplikowanie obliczeń oraz znacznie
większe zapotrzebowanie na pamięć w stosunku do brył AABB.
Drzewa ósemkowe (ang. Octrees) są regularnym odpowiednikiem drzew AABB. Drzewo
ósemkowe tworzone jest przez rekurencyjny podział przestrzeni poprzez rozcięcie jej
płaszczyznami we wszystkich trzech osiach posiadających punkt wspólny będący środ-
kiem bryły okalającej. Metoda ta jest szybsza dla niektórych zapytań, ale wiąże się także
z redundancją danych w przypadku, gdy obiekt leży w dwóch sektorach naraz [TAM02].
Zapobiec temu zjawisku można poprzez tworzenie geometrii w miejscu przecięcia, ale to
wiąże się ze zwiększeniem zapotrzebowania na pamięć, dlatego też metoda ta nie została
zaimplementowana.
Drzewa BSP oparte o sortowanie poligonalne są odpowiednikiem zastosowanego drzewa
BSP opierającego się o bryły okalające AABB. Podział przestrzeni w poligonalnym drzewie
BSP opiera się o ułożenie płaszczyzny wzdłuż jednego z poligonów obranego według
autorskiej heurestyki. Problemem tej metody, jak i opisywanej wyżej metody drzew
53
ósemkowych jest rozdzielanie prymitywów na dwie części w miejscu przecięcia z pła-
szczyzną podziału, powodując zwiększenie ilości geometrii w scenie. Kryterium to zade-
cydowało o odrzuceniu tej metody.
5.1.3 Metody optymalizacji ilości renderowanej geometrii
W systemie nGine zastosowano dwie metody akceleracji wyświetlania. Pierwszą z
nich jest Frustum Culling opierający się o odrzucanie elementów sceny, których korze-
nie (ang. root-node) nie znajdują się wewnątrz bryły widzenia. Drugą z użytych metod
jest biblioteczna optymalizacja glEnable(GL CULL FACE), która odrzuca z potoku ren-
derowania ścianki, których wektory normalne są równoległe do wektora widoku kamery.
Z przeprowadzonych badań wynika, iż zastosowanie tych metod daje wzrost wydajności
rzędu 50 − 150% (wykres 4.3), co jest wynikiem zadowalającym.
W celu zwiększenia wydajności aplikacji na tym polu zastosować można dokładniejszą
metodę Frustum Culling’u, opierającą się o wybór poszczególnych prymitywów z drzewa
hierarchii oraz metodę odrzucania obszarów zasłoniętych (ang. Occulsion Culling).
Metoda Occulsion Culling polega na odrzucaniu z potoku renderującego geometrii,
która zasłonięta jest przez obiekty znajdujące się bliżej kamery. Jednakże określenie
dokładnego obszaru zasłanianego przez obiekty jest bardzo skomplikowane zarówno ob-
liczeniowo jak i algorytmicznie i dlatego metoda ta została pominięta w implementacji.
Inną popularną metodą zmniejszania ilości geometrii będącej w potoku renderowania
jest optymalizacja Level Of Detail, opierająca się o podstawianie geometrii danego obiektu
o różnym stopniu skomplikowania w zależności od odległości od obserwatora. Metoda
ta wymaga jednak przygotowania kilku wersji danej sceny przez grafika i podmienianie
ich w czasie rzeczywistym, co zwiększa znacznie ilość czasu jaką należy przeznaczyć na
przygotowanie danych oraz ilość pamięci potrzebnej na przechowanie geometrii, dlatego
też metoda ta została zarzucona.
5.1.4 Efekty specjalne, Pixel Shading
Realizm sceny można podnieść znacznie za pomocą zastosowania technik związanych
z użyciem jednostek Pixel i Vertex Shader. Dzięki użyciu tych programowalnych i auto-
nomicznych jednostek, projektanci są w stanie tworzyć filtry obejmujące swym działaniem
całą wizualizowaną scenę. Możliwymi zastosowaniami tej techniki jest oświetlanie sceny za
pomocą map HDR, tworzenie efektów imitujących niedoskonałości ludzkiego oka jak cho-
ciażby brak umiejętności postrzegania obszarów o znacznej dynamice jasności obrazujący
się świeceniem obszarów o wysokiej dynamice na małej przestrzeni. Innym zastosowaniem
jest automatyczne tworzenie tekstur przejścia ze zdefiniowanych wcześniej zestawów tek-
stur w zależności od przyjętych kryteriów przejścia, jak chociażby wysokość danego ob-
szaru.
54
5.1.5 Wirtualny realizm - CAVE i dźwięk
Kolejnym krokiem rozwoju środowiska powino być zaimplementowanie dźwięku prze-
strzennego oraz punktowych i kierunkowych źródeł dźwięku. Zastosowanie dźwięku sur-
round ma kluczowe znaczenie dla podniesienia realizmu wizualizowanej sceny. Użytkownik
jest w stanie uwierzyć, iż znajduje się wewnątrz prezentowanego środowiska. Udźwięko-
wione środowiska dostępne są na rynku od kilku lat, głównie w formie gier komputerowych
i zdobywają coraz większą popularność.
Ostatnim, najbardziej rozwojowym krokiem wizualizacji i tworzenia wirtualnego śro-
dowiska jest przeniesienie go w rzeczywistość wirtualną. Zabiegu tego można dokonać
poprzez wyposażenie go w specjalny hełm z wyświetlaczem ciekłokrystalicznym oraz
czujnikiem ruchu, lub też poprzez wejście do systemu CAVE. System CAVE używany
w labolatorium SARA w Holandii oraz na uniwersytecie w Helsinkach, jak i w innych
placówkach naukowych jest pomieszczeniem, w którym obraz rysowany jest na trzech
ścianach i podłodze. Użytkownik wyposażony w specjalne okulary oraz manipulator może
poruszać się w tym środowisku w sposób dowolny. Podstawę oprogramowania systemu
CAVE stanowi biblioteka OpenGL. System ten wyposażony jest także w system dźwięku
przestrzennego podnoszącego znacznie stopień realizmu prezentowanego środowiska.
55
Bibliografia
[Cor04] Valve Corporation. Valve Source Engine Features. Valve Corporation, 2004.
http://www.valvesoftware.com/sourcelicense/enginefeatures.htm.
[Inc05] VRcontext Inc. Walkinside Product Features Page, 2005.
http://www.walkinside.com/walkinside/virtual reality windows.htm.
[Jam90] Arvo James. A simple method for box-sphere intersection testing. In Andrew S.
Glassner, editor, Graphic Gems. Academic Press, 1990.
[JDF01] Andries van Dam James D. Foley. Wprowadzenie do grafiki komputerowej.,
chapter Dązenie do wizualnego realizmu, pages 530,531. Wydawnictwo
Naukowo Techniczne, 2001.
[Kos04] Krystian Kostecki. Implementacja gier rpg z wykorzystaniem biblioteki gl4java.
Master’s thesis, Wydział Informatyki Politechniki Szczecińskiej, 2004.
[TAM02] Eric Haines Thomas Akenine-Moller. Real-Time Rendering. A.K Peters, second
edition, 2002.
[vdB98] Gino van den Bergen. Efficient collision detection of complex deformable models
using aabb trees. Technical report, Department of Mathematics and Computing
Science Eindhoven University of Technology, November 1998.
[Wei99] Eric W. Weisstein. Rotation formula. Technical report, Mathworld, 1999.
http://mathworld.wolfram.com/RotationFormula.html.
56
Dodatek A
Dodatek
A.1 Specyfikacja formatu plikow .n3d.
Ponizej zaprezentowana jest struktura autorskiego formatu n3d, pozwalającego na za-
pis geometrii wraz z dwoma kanałami mapowania UV oraz wektorami normalnymi.
float nVerts; // (4 bajty) liczba wierzchołków
float nFaces; // (4 bajty) liczba scianek bryły
float nTVChan3; // (4 bajty) liczba wierzchołków kanału mapowania UV dla LightMappingu
float nTFChan3; // (4 bajty) liczba ścianek kanału mapowania UV dla LightMappingu
float nTVChan3; // (4 bajty) liczba wierzchołków kanału mapowania UV dla tekstur
float nTFChan3; // (4 bajty) liczba ścianek kanału mapowania UV dla tekstur
nVertex VertexTable; // (4*3*nVerts bajtów) tablica wierzchołków geometrii
nVertex FaceTable; // (4*3*nFaces bajtów) tablica ścianek geometrii
nVertex TVChan3; // (4*3*nTVChan3 bajtów) tablica wierzchołków dla kanału UV Lightmapy
nVertex TFChan3; // (4*3*nTFChan3 bajtów) indeksu wierzchołków dla UV Lightmapy
nVertex TVChan3; // (4*3*nTVChan3 bajtów) tablica wierzchołków dla kanału UV tekstur
nVertex TFChan3; // (4*3*nTFChan3 bajtów) indeksy wierzchołków dla UV tekstur
nVertex NormalTable // (4*3*nFaces*3 bajtów) tablica wektorów normalnych
short int MatIdTable // (2*nFaces bajtów) tablica indeksów materiałów
A.2 Obsługa środowiska nGine
W celu uruchomienia środowiska nGine należy uruchomic program nGine.exe zna-
jdujący się w katalogu „/nGine/bin/nGine.exe” dołączonej płyty CD. Zaleca się aby
skopiować całość katalogu „/nGine” do katalogu tymczasowego na dysku twardym i
przeprowadzić procedurę uruchomienia z tego miejsca aby uniknąć możliwych przesto-
jów związanych ze specyfiką napędów optycznych.
Opis klawiszy kontrolujących zachowanie środowiska
W - ruch kamery do przodu
S - ruch kamery do tylu
57
A - ruch kamery w lewo
D - ruch kamery w prawo
F2 - Tryb wyświetlania liści drzewa AABB
F3 - Włączenie/Wyłączenie detekcji kolizji
F4 - Włączenie/Wyłączenie mgły
58
Dodatek B
Dodatek
B.1 Zawartość dołączonej płyty CD
Do pracy została dołączona płyta CD zawierająca niezbędne materiały, o następującej
strukturze katalogów :
• /nGine - katalog zawierający środowisko nGine
– /bin/ - katalog zawierający plik uruchomieniowy
– /world/ - katalog zawierający dane geometryczne i tekstury
• /source code/ - katalog zawierający kod źródłowy pracy
• /reports/ - katalog zawierający zrzuty ekranowe z kolejnych etapów pracy
• /latex - katalog zawierający źrodło pracy w języku LATEX
– /rys/ - katalog zawierający rysunki użyte w pracy w formacie .eps
– /temp/ - katalog zawierający źródła użytych rysunków w formacie .ai
• /docs/ - katalog zawierający część użytych w pracy materiałów
W katalogu głównym umieszczono tekst pracy w formacie PDF w pliku o nazwie
„pd.pdf” oraz plik tekstowy „ZawartoscPlyty.txt” zawierający opis zawartości dołączonej
plyty CD.
59

More Related Content

What's hot

Fotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIFotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIWydawnictwo Helion
 
Fotografia cyfrowa. Leksykon kieszonkowy
Fotografia cyfrowa. Leksykon kieszonkowyFotografia cyfrowa. Leksykon kieszonkowy
Fotografia cyfrowa. Leksykon kieszonkowyWydawnictwo Helion
 
Anatomia PC. Kompendium. Wydanie IV
Anatomia PC. Kompendium. Wydanie IVAnatomia PC. Kompendium. Wydanie IV
Anatomia PC. Kompendium. Wydanie IVWydawnictwo Helion
 
3ds max 5. Ćwiczenia praktyczne
3ds max 5. Ćwiczenia praktyczne3ds max 5. Ćwiczenia praktyczne
3ds max 5. Ćwiczenia praktyczneWydawnictwo Helion
 
3ds max 8. Ćwiczenia praktyczne
3ds max 8. Ćwiczenia praktyczne3ds max 8. Ćwiczenia praktyczne
3ds max 8. Ćwiczenia praktyczneWydawnictwo Helion
 
ABC sam naprawiam komputer. Wydanie II
ABC sam naprawiam komputer. Wydanie IIABC sam naprawiam komputer. Wydanie II
ABC sam naprawiam komputer. Wydanie IIWydawnictwo Helion
 
3ds max 6. Skuteczne rozwiązania
3ds max 6. Skuteczne rozwiązania3ds max 6. Skuteczne rozwiązania
3ds max 6. Skuteczne rozwiązaniaWydawnictwo Helion
 
Photoshop Elements 2. Szybki start
Photoshop Elements 2. Szybki startPhotoshop Elements 2. Szybki start
Photoshop Elements 2. Szybki startWydawnictwo Helion
 
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...Wydawnictwo Helion
 
Windows Movie Maker 2. Od zera do bohatera
Windows Movie Maker 2. Od zera do bohateraWindows Movie Maker 2. Od zera do bohatera
Windows Movie Maker 2. Od zera do bohateraWydawnictwo Helion
 
Blender. Ćwiczenia praktyczne
Blender. Ćwiczenia praktyczneBlender. Ćwiczenia praktyczne
Blender. Ćwiczenia praktyczneWydawnictwo Helion
 
Fotografia cyfrowa. Kurs. Wydanie II
Fotografia cyfrowa. Kurs. Wydanie IIFotografia cyfrowa. Kurs. Wydanie II
Fotografia cyfrowa. Kurs. Wydanie IIWydawnictwo Helion
 
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówFotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówWydawnictwo Helion
 

What's hot (17)

Instrukcia
InstrukciaInstrukcia
Instrukcia
 
Fotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIFotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie II
 
Fotografia cyfrowa. Leksykon kieszonkowy
Fotografia cyfrowa. Leksykon kieszonkowyFotografia cyfrowa. Leksykon kieszonkowy
Fotografia cyfrowa. Leksykon kieszonkowy
 
Anatomia PC. Kompendium. Wydanie IV
Anatomia PC. Kompendium. Wydanie IVAnatomia PC. Kompendium. Wydanie IV
Anatomia PC. Kompendium. Wydanie IV
 
3ds max 5. Ćwiczenia praktyczne
3ds max 5. Ćwiczenia praktyczne3ds max 5. Ćwiczenia praktyczne
3ds max 5. Ćwiczenia praktyczne
 
3ds max 8. Ćwiczenia praktyczne
3ds max 8. Ćwiczenia praktyczne3ds max 8. Ćwiczenia praktyczne
3ds max 8. Ćwiczenia praktyczne
 
ABC sam naprawiam komputer. Wydanie II
ABC sam naprawiam komputer. Wydanie IIABC sam naprawiam komputer. Wydanie II
ABC sam naprawiam komputer. Wydanie II
 
3ds max 6. Skuteczne rozwiązania
3ds max 6. Skuteczne rozwiązania3ds max 6. Skuteczne rozwiązania
3ds max 6. Skuteczne rozwiązania
 
Photoshop Elements 2. Szybki start
Photoshop Elements 2. Szybki startPhotoshop Elements 2. Szybki start
Photoshop Elements 2. Szybki start
 
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...
Sekrety cyfrowej ciemni Scotta Kelbyego. Edycja i obróbka zdjęć w programie A...
 
Windows Movie Maker 2. Od zera do bohatera
Windows Movie Maker 2. Od zera do bohateraWindows Movie Maker 2. Od zera do bohatera
Windows Movie Maker 2. Od zera do bohatera
 
ABC sam składam komputer
ABC sam składam komputerABC sam składam komputer
ABC sam składam komputer
 
OpenGL. Programowanie gier
OpenGL. Programowanie gierOpenGL. Programowanie gier
OpenGL. Programowanie gier
 
Blender. Ćwiczenia praktyczne
Blender. Ćwiczenia praktyczneBlender. Ćwiczenia praktyczne
Blender. Ćwiczenia praktyczne
 
Fotografia cyfrowa. Kurs. Wydanie II
Fotografia cyfrowa. Kurs. Wydanie IIFotografia cyfrowa. Kurs. Wydanie II
Fotografia cyfrowa. Kurs. Wydanie II
 
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówFotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
 
3ds Max 8. Biblia
3ds Max 8. Biblia3ds Max 8. Biblia
3ds Max 8. Biblia
 

Similar to Wybrane zagadnienia wizualizacji wirtualnego środowiska za pomocą biblioteki OpenGL

Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Adam Skołuda
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemniceWydawnictwo Helion
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawWydawnictwo Helion
 
Flash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceFlash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceWydawnictwo Helion
 
Triangledigger Thesis
Triangledigger ThesisTriangledigger Thesis
Triangledigger Thesisguest7d27f2
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Wydawnictwo Helion
 
C++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweC++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweWydawnictwo Helion
 
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IICore Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IIWydawnictwo Helion
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceWydawnictwo Helion
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanieWydawnictwo Helion
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIWydawnictwo Helion
 
Projektowanie i analiza algorytmów
Projektowanie i analiza algorytmówProjektowanie i analiza algorytmów
Projektowanie i analiza algorytmówWydawnictwo Helion
 
Visual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyVisual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyWydawnictwo Helion
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerWydawnictwo Helion
 

Similar to Wybrane zagadnienia wizualizacji wirtualnego środowiska za pomocą biblioteki OpenGL (20)

Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...
 
mgr
mgrmgr
mgr
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstaw
 
Flash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatceFlash CS3 Professional PL. Klatka po klatce
Flash CS3 Professional PL. Klatka po klatce
 
Triangledigger Thesis
Triangledigger ThesisTriangledigger Thesis
Triangledigger Thesis
 
Linux. Kurs. Wydanie II
Linux. Kurs. Wydanie IILinux. Kurs. Wydanie II
Linux. Kurs. Wydanie II
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 
Solid Edge 17. Podstawy
Solid Edge 17. PodstawySolid Edge 17. Podstawy
Solid Edge 17. Podstawy
 
C++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweC++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputerowe
 
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IICore Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie II
 
Projektowanie i analiza algorytmów
Projektowanie i analiza algorytmówProjektowanie i analiza algorytmów
Projektowanie i analiza algorytmów
 
Visual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programistyVisual Basic 2008. Warsztat programisty
Visual Basic 2008. Warsztat programisty
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputer
 

Wybrane zagadnienia wizualizacji wirtualnego środowiska za pomocą biblioteki OpenGL

  • 1. P O L I T E C H N I K A S Z C Z E C I Ń S K A Wydział Informatyki PRACA DYPLOMOWA Wybrane zagadnienia wizualizacji wirtualnego środowiska za pomocą biblioteki OpenGL Autor: Łukasz Szczepański Opiekun pracy: dr inż. Radosław Mantiuk Szczecin, 2004/2005
  • 2. Spis treści 1 Wstęp 3 1.1 Pojęcia istotne dla zrozumienia zagadnienia pracy . . . . . . . . . . . . . 4 1.2 Schemat podziału pracy . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2 Przegląd wybranych, istniejących implementacji wirtualnego środowiska 6 2.1 Schemat podziału współczesnych środowisk wirtualnych . . . . . . . . . . 6 2.1.1 MMORPG: World of Warcraft . . . . . . . . . . . . . . . . . . . . 7 2.1.2 FPP: Half Life 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.1.3 Wizualizacja Inżynierska : WalkInside . . . . . . . . . . . . . . . . 10 3 Implementacja wirtualnego środowiska za pomocą biblioteki OpenGL 16 3.1 Wizualizacja geometrii . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2 Vertex Buffering - Vertex Buffer Objects . . . . . . . . . . . . . . . . . . 18 3.2.1 Tworzenie Obiektów VBO . . . . . . . . . . . . . . . . . . . . . . 18 3.3 Teksturowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.3.1 Politeksturing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.3.2 Light Mapping jako szczególny przypadek multiteksturingu . . . . 21 3.3.3 Tekstury przejść . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.4 Symulacja mgły . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3.5 Poruszanie się po środowisku . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.5.1 Ogólny algorytm pracy kamery . . . . . . . . . . . . . . . . . . . 25 3.5.2 Implementacja ruchu kamery . . . . . . . . . . . . . . . . . . . . . 26 3.5.3 Ruch poprzeczny . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.5.4 Obrót kamery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.6 Detekcja kolizji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.6.1 Pojęcia istotne dla zrozumienia zagadnienia detekcji kolizji . . . . 28 3.6.2 Algorytm detekcji kolizji . . . . . . . . . . . . . . . . . . . . . . . 29 3.6.3 Charakterystyka struktur danych użytych do rozwiązania problemu detekcji kolizji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.6.4 Test przecięcia sfery i bryły AABB . . . . . . . . . . . . . . . . . 31 3.6.5 Algorytm budowy drzewa binarnego AABB . . . . . . . . . . . . 31 3.6.6 Wizualizacja drzewa AABB . . . . . . . . . . . . . . . . . . . . . 34 3.6.7 Algorytm ukrywania powierzchni niewidocznych oparty o bryły AABB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1
  • 3. 4 Rezultaty i wnioski 37 4.1 Opis procedury testowej . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.2 Analiza wyników przeprowadzonych testów . . . . . . . . . . . . . . . . . 38 4.2.1 Wpływ rozdzielczości oraz trybu płótna OpenGL na wydajność śro- dowiska . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4.2.2 Wpływ optymalizacji Frustum Culling na wydajność systemu . . 40 4.2.3 Wpływ detekcji kolizji akcelerowanej metodą drzew AABB na pręd- kość działania systemu . . . . . . . . . . . . . . . . . . . . . . . . 40 4.2.4 Wpływ ilości geometrii na prędkość działania systemu . . . . . . . 41 4.2.5 Poprawność wizualizacji środowiska . . . . . . . . . . . . . . . . . 41 4.3 Prezentacja uzyskanych wyników, rysunki . . . . . . . . . . . . . . . . . . 41 5 Podsumowanie i wnioski 51 5.1 Dalsze prace związane z rozwojem wirtualnych środowisk . . . . . . . . . 53 5.1.1 Wielowątkowość . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 5.1.2 Inne modele hierarchii sceny . . . . . . . . . . . . . . . . . . . . . 53 5.1.3 Metody optymalizacji ilości renderowanej geometrii . . . . . . . . 54 5.1.4 Efekty specjalne, Pixel Shading . . . . . . . . . . . . . . . . . . . 54 5.1.5 Wirtualny realizm - CAVE i dźwięk . . . . . . . . . . . . . . . . . 55 A Dodatek 57 A.1 Specyfikacja formatu plikow .n3d. . . . . . . . . . . . . . . . . . . . . . . 57 A.2 Obsługa środowiska nGine . . . . . . . . . . . . . . . . . . . . . . . . . . 57 B Dodatek 59 B.1 Zawartość dołączonej płyty CD . . . . . . . . . . . . . . . . . . . . . . . 59 2
  • 4. Rozdział 1 Wstęp Wirtualne środowiska stanowią bardzo ważną część rynku oprogramowania kompute- rowego i są jedną z najprężniej rozwijających się dziedzin. Spotkać je można na każdym kroku, w grach, w symulacji, w inżynierii, wszędzie tam gdzie potrzeba zaprezentować użytkownikowi efekty jego pracy zanim zostaną one przekształcone w formę ostateczną. Wirtualne środowiska, określane często mianem rzeczywistości wirtualnej (ang. Vir- tual Reality, VR) podlegają ciągłej ewolucji. Każego roku producenci sprzętu kompu- terowego, a zwłaszcza podzespołów graficznych prześcigają się w tworzeniu coraz to lepszych, wydajniejszych układów oferujących coraz to nowsze metody wizualizacyjne. W tym samym czasie producenci oprogramowania tworzą nowe, bardziej konkurencyjne wersje środowisk wirtualnych. Stopień skomplikowania najnowszych aplikacji wymaga za- trudniania całych sztabów inżynierów potrafiących złożyć kompletne i spójne środowisko w całość ze wszystkich dostępnych elementów. Większość aktualnie powstających środowisk przeznaczonych dla systemu Windows opiera się o bibliotekę Direct3D firmy Microsoft. Biblioteka ta, podlegająca ciągłej ewolucji napędzanej przez Microsoft oferuje programiście szereg ułatwień i narzędzi. Direct3D daje programiście zestaw funkcji realizujących pewne elementy wizualizacji środowiska bez zewnętrznej ingerencji. Użytkownik nie musi znać ani specyfiki ani sposobu działa- nia tych elementów, ponieważ funkcje biblioteczne ukrywają całą mechanikę działania. Daje to znaczny wzrost efektywności oraz przyspiesza proces implementacji danego śro- dowiska, ale z drugiej strony nie pozwala programiście ingerować w proces wizualizacji tych elementów zmniejszając elastyczność całego procesu. Należy pamiętać że Direct3D dostępny jest jedynie w środowisku Windows oraz o tym że podczas ewolucji tej bib- lioteki, jej twórcy nie raz zmieniali interfejs programisty często zmuszając użytkowników do ponownej nauki jej działania. Drugą z popularnych bibliotek używanych do tworzenia rzeczywistości wirtualnej jest OpenGL (Open Graphics Library). Jest to tak zwany standard przemysłowy (ang. In- dustry Standard) stworzony przez firmę Silicon Graphics. OpenGL jest darmową bib- lioteką przenośną, działającą tak samo pod kontrolą różnych systemów operacyjnych, co czyni ją bardzo elastyczną. Biblioteka tworzona jest przez grupę zwaną jako Architec- ture Review Board (ARB) składjącą się z przedstawicieli firm tworzących sprzęt i opro-
  • 5. gramowanie komputerowe. Dzięki temu OpenGL stał się solidną biblioteką o rozszerza- jących się możliwościach i stałym interfejsie. W przeciwieństwie do Direct3D, OpenGL nie oferuje gotowych funkcji realizujących elementy wizualizacji, ale daje użytkownikowi narzędzia dzięki którym możliwe jest zaimplementowanie dowolnej metody w pełni kon- trolowany, autorski sposób. Celem niniejszej pracy jest opracowanie autorskiego wirtualnego środowiska wyko- rzystującego wybrane elementy wizualizacji przy pomocy biblioteki OpenGL. Zaimple- mentowane środowisko powinno obsłgiwać detekcję kolizji oraz dowolny ruch kamery oraz poprzeć tezę pracy brzmiącą : ”Przy użyciu biblioteki OpenGL możliwa jest implemen- tacja fizycznie poprawnego i wydajnego wirtualnego środowiska”. W celu zrealizowania postawionych pracy celów, stworzono autorskie środowisko o nazwie nGine. W środowisku tym zaimplementowane zostały następujące elementy wi- zualizacji wirtualnego środowiska : 1. Oświetlenie i cieniowanie za pomocą map oświetlenia, 2. Detekcja kolizji oparta na drzewach binarnych AABB, 3. Optymalizacja prędkości wyświetlania poprzez Vertex Buffering, 4. Optymalizacja zbioru wyświetlanej geometrii poprzez Frustum Culling, 5. Implementacja binarnego formatu danych geometrycznych, 6. System politeksturingu, 7. Kamera o pełnej swobodzie poruszania, 8. Projekt wnętrza wirtualnego środowiska. 1.1 Pojęcia istotne dla zrozumienia zagadnienia pracy Środowisko - Środowiskiem nazywamy wszelkie zewnetrzne czynniki oddziałujące na rozpatrywany układ. Środowisko Wirtualne - Środowiskiem takim, nazywamy pewien zestaw cech i obiek- tów, który jest wizualizowany przez specjalne oprogramowanie. Zestawem cech najczę- sciej są podstawowe elementy fizyki takie jak grawitacja czy też zderzenia sprężyste i niesprężyste. Podstawowymi obiektami w środowisku wirtualnym są obiekty opisujące głównie wygląd przestrzeni wirtualnej. Podstawowym obiektem jest tzw. mapa, czyli obiekt składający sie z tysiecy trójkątów imitujący wygląd wybranego środowiska rzeczy- wistego takiego jak jaskinia czy też wnętrze budynku. Innymi obiektami najczęściej są przedmioty, których położenie może ulegac interaktywnej modyfikacji poprzez odpowied- nie procedury modułu fizyki, mogą to także byc obiekty zmieniające stopien swobody poruszania sie po danym środowisku, takimi obiektami są na przyklad drabina, winda 4
  • 6. czy też schody. W skrócie, wirtualne środowisko jest ograniczoną imitacją dowolnie wybranego śro- dowiska rzeczywistego, o ścisle dobranych parametrach i obowiazujących zasadach fizyki. Wizualizacja - Wizualizacją nazywamy graficzną reprezentację pewnego zbioru danych. W kontekście środowisk wirtualnych, będzie to połączona reprezentacja obrazów dwuwy- miarowych (tekstur) oraz zestawu danych trójwymiarowych odpowiadających za wygląd środowiska. Zadaniem wizualizacji jest jak najwierniejsze oddanie wyglądu obiektów rzeczywistych za pomocą przygotowanych wczesniej danych. Detekcja Kolizji - Detekcja kolizji używana jest w środowiskach wirtualnych do bada- nia relatywnych położeń obiektów zawartych w tym środowisku. Jeśli program nadzoru- jący zachowanie środowiska zauwazy iż dwa obiekty są wystarczająco blisko siebie, to zachodzi zdarzenie kolizji. Wynikiem tego zdarzenia jest zazwyczaj zmiana kierunku poruszających sie obiektów, tak aby ich scianki nie nachodzily na siebie. W środowiskach symulujacych zdarzenia rzeczywiste, część energii kinetycznej obiektu poruszającego sie jest przenoszona na obiekt z którym następuje kolizja. 1.2 Schemat podziału pracy Niniejsza praca została podzielona na następujące części : 1. Wstęp, w rozdziale tym przedstawiono ogólne założenia pracy a także wyjaśniono najważniejsze pojęcia związane z pracą. 2. Przeglad wybranych, istniejacych implementacji wirtualnego srodowiska, w tej części pracy omówiono najbardziej charakterystyczne, istniejące implementacje wirtualnego środowiska oraz zdefiniowano schemat podziału współczesnych środowisk wirutalnych. 3. Implementacja wirtualnego srodowiska za pomoca biblioteki OpenGL, w rozdziale tym przedstawiono teoretyczne jak i implementacyjne aspekty każdego z uży- tych w pracy elementów wizualizacji, oraz zdefiniowano schemat przepływu danych w zaimplementowanym środowisku i przedstawiono jego ogólny sposób działania. 4. Rezultaty i wnioski, w części tej znajduje się opis procedury testowej zaimple- mentowanego środowiska, jak i wyniki przeprowadzonych testów wydajnościowych oraz porównanie tych wyników z implementacjami znanymi wcześniej. 5. Podsumowanie, w rozdziale tym podsumowane zostały osiągnięcia uzyskane pod- czas implementacji środowiska oraz przeprowadzona została dyskusja nad dalszymi as- pektami rozwoju wirtualnych środowisk. 5
  • 7. Rozdział 2 Przegląd wybranych, istniejących implementacji wirtualnego środowiska Wirtualne środowiska zdobywają coraz większą popularność w życiu codziennym i nauce. Znajdują szerokie zastosowanie w symulacji, projektowaniu i wizualizacji oraz w interaktywnej rozrywce. Są one jednym z najprężniej rozwijających się sektorów infor- matyki użytkowej. Wraz z rozwojem wirtualnych środowisk, rośnie także ich specjalizacja, co obrazuje rysunek 2.1 2.1 Schemat podziału współczesnych środowisk wirtualnych Środowiska Wirtualne Środowiska Rozrywkowe, gry Środowiska Wizualizacyjne Gry MMORPG (ang. Massive Multiplayer Online Game ) Gry FPP (ang. First Person Perspective) Wizualizacja Inżynierska Wizualizacja Architektoniczna Rysunek 2.1: Schemat podziału współczesnych środowisk wirtualnych.
  • 8. • Środowiska o charakterze rozrywkowym – Gry Massive Multiplayer Online Role Playing Game (MMORPG). W środowiskach tego typu, tysiące graczy egzystuje wspólnie w jednym świecie przeżywając wspólnie przygody i realizując wspólnie różne cele. Cechą charak- terystyczną tych środowisk jest bardzo rozległy obszar na którym prowadzona jest rozgrywka oraz obecność wielu avatarów w jednym miejscu, a także pewne uproszczenie środowiska pod względem dokładności geometrii. – Gry First Person Perspective (FPP), oraz podobne. W grach tego typu gracz wciela się zazwyczaj w postać bohatera ratującego świat lub własną skórę przed różnymi rodzajami szeroko pojętego zła. Cha- rakterystyczną cechą tych środowisk jest to iż implementowane w nich są za- zwyczaj wszystkie nowinki techniczne dostępne w czasie wydania danego ty- tułu. Środowiska te są w pewnym stopniu testem (ang. benchmark) wydajności dostepnych komputerów jak też i testem możliwości najnowszych algorytmów i efektów specjalnych. • Środowiska o charakterze naukowym i badawczym – Środowiska wizualizacyjne i symulacyjne. Środowiska te służą zazwyczaj symulacji działających systemów, lub też wizu- alizacji. Głównym zastosowaniem tych środowisk jest wizualizacja inżynierska i architektoniczna, pomagające w doborze odpowiednich parametrów wizuali- zowanego środowiska, lub też wizualizacja symulacji - np. wizualizacja symu- latora lotniczego. Charakterystyczną cechą tych środowisk jest to iż prezen- towana grafika posiada najdrobniejsze detale, a ilość przetwarzanych danych często mierzona jest w gigabajtach. Środowiska symulacyjne posiadają bardzo skomplikowane matematycznie procedury przetwarzania symulacji, a część wi- zualizacyjna jest często prowizoryczna. 2.1.1 MMORPG: World of Warcraft World of Warcraft (WoW) jest grą komputerową typu Massive Multiplayer Online Role Playing Game wydaną przez firmę Blizzard Entertainment w listopadzie 2004 roku. W grze tej tysiące graczy przeżywa wspólnie przygody w jednym świecie (wirtualnym środowisku). World of Warcraft oferuje użytkownikowi najróżniejsze rodzaje wirtualnych środowisk, począwszy od piaszczystych pustyń, poprzez gęste lasy, bagna oraz podziemne lochy i jaskinie wszelkiego rodzaju, aż po zabudowę miejską stylizowaną na średniowieczne grody warowne. Wizualizacja w WoW jest możliwa zarówno za pomocą biblioteki Direct3D jak i OpenGL. Podstawowym atutem World of Warcraft w stosunku do innych środowisk tego typu jest to iż nie istnieją tutaj przestoje związane z wczytywaniem dużych ilosci danych, 7
  • 9. oraz nie istnieją linie podziału stref świata gdzie takie przestoje miały by miejsce (tzw. zoning). System pobiera dane dotyczące geometrii świata w sposób zupełnie przezroczysty dla użytkownika, oferując niczym nie zakłóconą i wciągającą rozrywkę. Geometria świata jest określana jako low-poly, geometria ta nie opisuje detali na postaciach lub budynkach, a tworzy jedynie jakby zarys elementu docelowego, definiu- jąc jedynie najwazniejsze jego elementy. Mimo oszczędnej geometrii World of Warcraft jest środowiskiem, które posiada największą liczbę detali wśrod programów swojej klasy. Detale te osiągane są poprzez bardzo szczegółowe, recznie rysowane tekstury nałożone precyzyjnie na każdy obiekt. Rzeźba terenu w WoW jest poddawana optymalizacji Level of Detail w czasie rzeczy- wistym. Wraz ze zbliżaniem sie do danego obszaru staje się on coraz bardziej szczegółowy. Teksturowanie terenu oparte jest na specjalnych shaderach. Shadery te teksturują teren w sposób bardzo realistyczny i szczegółowy - dla przykładu : szczyt pagórka jest porośniety trawą, zaś razem ze wzrostem nachylenia zbocza pagórka trawa przechodzi w piaszczysty podkład lub skałę, bruk porasta mchem i trawą tym bardziej im dalej dany punkt jest położony od środka drogi. Specjalną rolę w World of Warcraft odgrywają systemy cząsteczek dzieki którym two- rzone są różne efekty specjalne, od wodospadów (rysunek 2.7) i fontann, aż po różne efekty umiejętności specjalnych oraz ogień. Ciekawym rozwiązaniem są wodospady, które obrazują główny nurt wody poprzez statyczną geometrię, na którą nałożona jest ani- mowana tekstura z kanałem alpha. System cząsteczek odpowiada tutaj za cząsteczki wody, które wyrywają się losowo z głównego nurtu i tworzą ”mgiełkę”wokół głównego nurtu. Na szczególną uwagę zasługuje shader bloom nazwany przez producenta Full Screen Glow. Shader ten imituje efekty osiągane przy użyciu oświetlenia opartego o HDR, tworząc swietlistą poświatę wokół obszarów silnie odbijających światło. World of Warcraft jest na dzien dzisiejszy najwiekszą i najbardziej rozbudowaną grą gatunku MMORPG, zarówno pod względem ilości użytkowników jak i rozmiarów świata, którego powierzchnia sięga 70-100km2 . Ilość detali świata i postaci jest o wiele większa niż we wcześniejszych tytułach tej klasy. Nie jest to jednak szczyt możliwości technicznych dzisiejszych komputerów, a uproszczenie wizualizacji środowiska jest wymuszone poprzez fakt iż jest to gra online i niesiona przez sieć ilość informacji nie może byc zbyt duża. 2.1.2 FPP: Half Life 2 Half Life 2 (HL2) jest grą komputerową typu First Person Perspective wydana przez Valve Software [Cor04] pod koniec 2004 roku, opartą na autorskim silniku o nazwieSource. Gracz wciela się rolę naukowca, Dr Freemana, który został uwikłany w spisek przeciw rodzajowi ludzkiemu i musi utorować sobie, oraz ludzkośći drogę do wolnosci łomem oraz całym arsenałem współczesnej broni. 8
  • 10. Pierwszą zauważalną rzeczą w grze jest oświetlenie scen przy użyciu HDR. Ekspozy- cja regulowana jest automatycznie poprzez system wizualizacji, dając wrażenie oślepienia oraz powidoku podczas nagłych zmian w natężeniu oświetlenia. System potrafi także obliczać oświetlenie metodą energetyczna (radiosity) w czasie rzeczywistym. Kolejnym przełomowym elementem wizualizacji zaimplementowanym w HL2 jest sys- tem materiałów. Materiał w ujeciu silnika Source jest zbiorem danych w pełni opisują- cym wszystkie właściwości fizyczne danego tworzywa. Materiały mają przypisane funkcje zmieniające wygląd tekstury wraz ze stopniem jej zniszczenia, posiadają specjalne kanały tekstur dzieki którym uzyskuje sie efekty odbic lustrzanych lub też chropowatości. Każdy materiał ma przypisaną gęstość oraz ciężar. Materiały opisują także odgłosy wydawane przez obiekty podczas uderzenia lub przesunięcia. Większość użytych tekstur jest au- torskimi shaderami napisanymi w języku High Level Shading Language (HLSL). Na szczególną uwagę zasługuje tutaj woda w której zaimplementowano efekt refrakcji oraz efekt Fresnela polegający na wzroście ilości światła odbitego do oka wraz ze wzrostem kąta nachylenia kamery do powierzchni. Tym co odróżnia Half Life 2 od innych gier komputerowych na przełomie lat 2004/2005 jest system fizyki. System Source wprowadza pełną gamę oddziaływań fizycznych miedzy obiektami w scenie. Podczas gry, gracz napotyka wiele zagadek związanych z podsta- wowymi prawami fizyki, równowagą, inercją, wypornością, i tym podobnymi. W więk- szosci pozycji, które zostały wydane przed HL2, interakcja między obiektami jest za- zwyczaj prekalkulowana i stała. W silniku Source oddziaływania między obiektami symu- lowane sa w czasie rzeczywistym. Jednym z przykładów może być etap gry, gdzie gracz musi obciażyć jedną ze stron równoważni cegłami aby przejsc po kładce na wyższy poziom. Cegły układane są na szerszym końcu kładki, jeżeli zostaną upuszczone na siebie zbyt gwałtownie, lub w złym miejscu, obsuwaja się oraz rozbijają juz ułożony szyk. Jeśli gracz nie obciąży dostatecznie kładki, to podczas wchodzenia w górę przeważy ułożone cegły i opadnie na doł, a cegly obsuną się wzdłuż deski oraz rozsypią na boki. Source defini- uje także system tzw. kukiełek (ang. Rag Doll Model), dzięki któremu postaci oraz ele- menty ich ciała oddziałowują poprawnie na interakcje z obiektami oraz przyłożonymi doń siłami. W HL2 zaimplementowano także uproszczoną fizykę pojazdów. Zmiennymi opisu- jącymi pojazd są : moc silnika, maksymalna prędkość, prędkość skrzyni biegów, materiał z którego wykonane są opony, oraz twardość zawieszenia. Pojazdy podlegają wszystkim prawom fizyki, wpadają w poślizgi, tracą przyczepność, pochylają się na bok podczas dynamicznych zakrętów, a w skrajnych przypadkach przewracają się na bok. Wizualizowana geometria poddawana jest optymalizacjom Level Of Detail w czasie rzeczywistym. Geometria świata w Half Life 2 jest w pełni deformowalna, pociski wybijają dziury w murach, a ładunki wybuchowe pozostawiają głębokie kratery w ziemi. Całość środowiska zamknięta jest w tzw. sky box’ach, które są sześciennymi mapami nieba, nada- jącymi scenie realizmu oraz głębi. Half Life 2 redefiniuje pojęcie realizmu w dziedzinie gier komputerowych (rysunek 2.8). Przedstawione środowiska, stylizowane na wschodnią europę przełomu lat 80/90 wyglądają prawdziwie. System sztucznej inteligencji czesto zaskakuje gracza swoimi po- 9
  • 11. sunięciami, a system fizyki przyciąga na długie godziny. Całość tworzy kamień milowy w dziedzinie interaktywnej rozrywki, oraz wyznacza trend którym bedą podążali wydawcy w kolejnych latach. 2.1.3 Wizualizacja Inżynierska : WalkInside Walkinside firmy VRcontext jest aplikacją wizualizacyjną, umożliwiającą użytkowni- kowi poruszanie się po środowiskach zaprojektowanych w programach CAD takich jak Microstation czy Autocad. Głównym atutem Walkinside [Inc05] jest fakt iż system ten nie posiada ograniczeń co do wielkości wyświetlanego modelu. Oprogramowanie nie podlega ograniczeniom roz- miarów plików, ani rozciągłości terenu, możliwa jest wizualizacja środowisk o rozciągłości ponad 10km [Inc05]. Wizualizacja w Walkinside możliwa jest z perspektywy pierwszej lub trzeciej osoby (FPP,TPP, rys. 2.6). Użytkownik może poruszać się po zaprojektowanych modelach, zachowując proporcje oraz możliwości przeciętnego człowieka. Opatentowany system de- tekcji kolizji umożliwia realistyczne poruszanie się w przestrzeni i dokładną reakcję na zachodzące zdarzenia. System wizualizacji w walkinside pozwala także na używanie spec- jalnego hełmu z systemem śledzenia ruchów głowy, dzięki czemu użytkownik może w pełni skoncentrować się na wizualizowanym przekazie. System wizualizacji Walkinside opiera się na dynamicznej teselacji zakrzywionych powierzchni oraz na mechanizmie szybkiego odrzucania zbędnych elementów dla obiek- tów, które znajdują się zbyt daleko aby mogły być wizualizowane. System oświetlenia aplikacji korzysta ze zwykłych świateł bibliotecznych OpenGL (gl- Light). W aplikacji tego typu realistyczne oświetlenie światłem HDR lub też za pomocą metody energetycznej jest zupełnie zbędne i zaszkodziłoby wydajności całej aplikacji. Walkinside posiada moduł symulacyjny oraz sieciowy, dzięki którym możliwe są treningi personelu w wirtualnej rzeczywistości (rysunki 2.2,2.3). Użytkownicy widzą avatary in- nych użytkowników, dzięki czemu w łatwy i intuicyjny sposób mogą ze sobą współpra- cować. Systemy detekcji kolizji oraz cząsteczek dodają symulacji dodatkowego realizmu i pozwalają przeprowadzić ćwiczenia w iście prawdziwy sposób. System symulacji pozwala użytkownikowi zaprojektować długie scenariusze podczas których inni użytkownicy bedą odbywać swoje szkolenie. Walkinside jest aplikacją niespotykaną i przełomową, nigdy do tej pory nie było możliwe wizualizowanie modeli inżynierskich takich jak platforma wiertnicza (rysunek 2.4), czy też wnętrze reaktora jądrowego na domowym komputerze klasy PC. Dzięki sys- temowi detekcji kolizji, użytkownik może chodzic po schodach, czy też wspinać sie po drabinie, a dzięki unikalnemu silnikowi wyświetlającemu możliwa jest wizualizacja tak ogromnych ilości danych. Poprzednie systemy tego typu nie radziły sobie z wyświetlaniem tak dużych porcji danych bez poświęcenia detali wizualizowanego środowiska. Walkinside jest w stanie wizualizować sceny siegające kilku milionów wielokątów oraz posiadające 10
  • 12. bardzo wiele zakrzywionych powierzchni (curved surfaces, np. NURBS, rysunek 2.5). Dzięki natywnemu wsparciu systemu dla formatu zapisu plików Microstation (.dwg), użytkownik może w prosty sposób wymodelować całe środowisko razem z teksturami i wyeksportować je prosto do silnika wizualizacyjnego, pomijając wszystkie konwersje oraz obliczenia wstępne jakie spotykało się w aplikacjach tego typu. Walkinside firmy VRcontext jest w tej chwili liderem wśród środowisk swojej klasy, a dzięki wielu tak istotnym możliwosciom jak import danych z laserowego skanera oraz wsparcie dla Microstation v8 z pewnościa nim pozostanie. Rysunek 2.2: Walkinside, symulacja pożaru na platformie wiertniczej w której uczesniczy wielu użytkowników. Rysunek 2.3: Walkinside, symulacja wypadku drogowego, dokładna detekcja kolizji, sys- tem cząsteczek (dym). 11
  • 13. Rysunek 2.4: Walkinside, wizualizacja plaformy wiertniczej posiadającej ponad 800 000 rur. Rysunek 2.5: Walkinside, turbina o bardzo złożonej geometrii oraz ogromnej ilości detali. 12
  • 14. Rysunek 2.6: Walkinside, widok z perspektywy trzeciej osoby, wizualizacja wnętrz. 13
  • 15. Rysunek 2.7: World Of Warcraft. Wodospady tworzone są poprzez geometrię z animowaną teksturą, oraz dodatkowy system cząsteczek (widoczne przy ujściu wody u góry). 14
  • 16. Rysunek 2.8: Half-Life 2. Niespotykany dotąd realizm sceny, woda z realistycznymi odbi- ciami i zakłóceniami, po prawej w pełni symulowany fizycznie pojazd. 15
  • 17. Rozdział 3 Implementacja wirtualnego środowiska za pomocą biblioteki OpenGL W rozdziale tym, opisane są wybrane metody wizualizacji wirtualnego środowiska. Przedstawione zostały zarówno teoretyczne jak i implementacyjne aspekty każdej z metod. W celu zaprezentowania owych metod został stworzony silnik graficzny (ang. graphic en- gine,game engine) o nazwie nGine, w którym zaimplementowano opisywane metody. Sil- nik ten jest zbiorem bibliotek, w których zahermetyzowane zostały odpowiednie metody wizualizacji oraz renderingu sceny. Zbiór ten można w prosty sposób rozbudować i wyko- rzystać do tworzenia gier lub bardziej zaawansowanych systemów wizualizacyjnych. Poniższy schemat (rys. 3.1) obrazuje mechanizm działania oraz przepływ danych w zaimplementowanym programie. Pierwszym etapem konstrukcji sceny jest zaprojektowanie geometrii w programie 3D Studio Max za pomocą narzędzi edycji poligonalnej oraz bezposrednich przekształceń wierzchołków siatki. Następnie obiekt eksportowany jest za pomocą autorskiego skryptu nBinExport do binarnego pliku .n3d. Kolejnym etapem jest wczytanie pliku .n3d przez klasę nMesh, która zajmuje się przechowywaniem oraz obróbką danych wejsciowych. Z danych tych budowane sa obiekty VBO a następnie przekazywane do głównej funkcji rysującej. W tym samym czasie przez klase nGine ładowane są odpowiednie tekstury i przekazywane razem z geometrią do funkcji rysującej oraz budowane jest drzewo AABB zawarte w danym obiekcie. Funkcja ry- sująca RenderScene() w każdej klatce animacji uaktualnia pozycję kamery, oraz sprawdza czy drzewa AABB mają byc wizualizowane. Klasa kamery nCamera odpowiedzialna jest za interakcje użytkownika ze środowiskiem, oraz badanie pozycji kamery względem innych obiektów przy pomocy procedur detekcji kolizji zawartych w klasie nAABBTree. 3.1 Wizualizacja geometrii Geometria we współczesnych środowiskach wirtualnych składa się głównie z trójkątów, które sa najprostszymi prymitywami przestrzennymi bedącymi w stanie
  • 18. Plik .n3D Przetwarzanie pliku Oraz Budowanie Obiektu VBO 3D Studio Max Zarządzanie zasobami sceny Klasa nMesh Klasa nGine Pik Tekstury Plik Mapy Oświetlenia Tworzenie drzewa AABB Detekcja kolizji w drzewie Operacje pomocnicze Klasa nAABB Tree Poruszanie się kamerą Oraz Funkcje Pomiarowe Klasa nCamera Płótno OpenGL GL_TEXTURE0_ARB GL_TEXTURE1_ARB GL_COMBINE_RGB_EXT + GL_MODULATE RenderScene() Rysunek 3.1: Schemat działania silnika nGine. opisać pewną powierzchnie. Producenci podzespołów komputerowych odpowiedzialnych za wyświetlanie grafiki trójwymiarowej optymalizują swoje rozwiązania pod kątem operacji na trójkątach, dodając odpowiednie typy danych oraz funkcje bezpośrednio w konstrukcji układów scalonych. Innym typem geometrii, która jest jeszcze dosyć nieśmiało wykorzystywana w grafice czasu rzeczywistego są powierzchnie parametryczne takie jak NURBS (Non-Uniform Ra- tional B-Spline) lub NURMS (Non-Uniform Rational MeshSmooth). Powierzchnie NURBS zdefiniowane są poprzez zestaw punktów kontrolnych z przypisanymi wagami, kolejność krzywych oraz wektor węzła. NURBS sa uogólnieniem zarówno krzywych B-sklejanych jak też i krzywych Beziera, główną rożnicą są ważone punkty kontrolne dzięki którym stają się wymierne (niewymierne B-krzywe są szczególnym przypadkiem wymiernych B- krzywych, w praktyce wiekszość powierzchni NURBS jest niewymierna). Krzywe NURMS są pochodną krzywych NURBS. Główną różnicą pomiedzy nimi jest to iż wagi wierz- 17
  • 19. chołków kontrolnych NURMS mogą być różne dla każdego wierzchołka, oraz możliwa jest kontrola wyglądu obiektu poprzez zmianę wag krawędzi. W zaimplementowanym w pracy silniku wizualizacji, wykorzystano jedynie siatki trójkątów ponieważ uznano iż stopień realizmu osiągany tą techniką jest wystarczający. 3.2 Vertex Buffering - Vertex Buffer Objects Obiekty Vertex Buffer Object, w skrócie VBO są rozszerzeniem biblioteki OpenGL o nazwie GL ARB vertex buffer object. Rozszerzenie to definiuje interfejs, który umożli- wia przechowywanie różnych typów danych w bardzo wydajnej pamięci karty graficznej, zwiększając tym samym prędkość przekazywania danych. Zbiory danych zamykane są w tzw. obiekty buforowe (buffer objects), które w założe- niu nie są niczym innym jak tablicą wypełnioną danymi. Interfejs programisty (API) pozwala użytkownikowi korzystać z VBO poprzez funkcje biblioteki OpenGL lub też poprzez bezpośredni dostęp do wskaźnika. Drugą z technik, która zawarta jest w rozszerzeniu jest ”mapowanie buforów”. Gdy ap- likacja mapuje bufor, system przydziela jej wskaźnik do pamięci. Gdy aplikacja zakończy pobieranie i zapisywanie do bufora, musi ódmapować”bufor, aby móc z niego skorzystać ponownie. Mapowanie pozwala na pozbycie się dodatkowej kopii danych, ponieważ dane zostały zapisane w pamięci karty graficznej i przechowywanie ich w pamięci konwencjon- alnej komputera jest zbędne, można dzięki temu zaobserwować wzrost wydajności. Podstawową korzyścią z wykorzystania obiektów VBO jest to iż droga pomiędzy pamię- cią a procesorem graficznym zostaje znacznie skrócona, oraz to iż do rysowania geometrii potrzeba jedynie kilku wywołań. W podejsciu klasycznym, narysowanie jednego trójkąta wymagało trzykrotnego wywołania funkcji glVertex3f, trzykrotnego wywołania funkcji glNormal3f oraz trzykrotnego wywołania funkcji glTexCoord3f. Każde wywołanie funkcji wymaga zapisania danych, odłożenia ich na stos i przejścia do kolejnej funkcji. Dzięki uży- ciu rozszerzenia GL ARB vertex buffer object możliwe jest narysowanie dowolnej liczby trójkątów wraz z przypisanymi im wektorami normalnymi oraz wspołrzędnymi mapowa- nia za pomocą wywołania jednej funkcji - glDrawElements lub glDrawArrays. 3.2.1 Tworzenie Obiektów VBO Pierwszym etapem tworzenia buforów jest wczytanie pliku .n3d przez klasę nMesh. Po wczytaniu danych wejsciowych do buforów tymczasowych, następuje przekształce- nie indeksów z formatu MaxScript (1..n) na format indeksowania C++ (0..n). Następ- nie tablica indeksów ścianek FaceTable sortowana jest metodą qsort wedle materiału przypisanego do każdej ze ścianek. Po operacji tej otrzymywane sa posortowane tablice indeksów ścianek oraz identyfikatorów materiałów oraz otrzymywana jest tablica długości materiałów, w której zapisana jest ilość trójkątów przynależących do danego identyfika- tora materiału. 18
  • 20. Następnie tablice wierzchołków oraz dwie tablice wierzchołków mapowania tekstur konsolidowane są z posortowaną tablicą indeksów, tworząc trzy tablice wierzchołków o rozmiarze nFaces*3. Następnym krokiem jest wywołanie funkcji BuildVBO(), której zadaniem jest zbu- dowanie obiektów zawartych w buforze geometrii (Vertex Buffer Object,VBO). Funkcja BuildVBO iniciuje wskaźnik do pamięci gdzie zawarte bedą dane bufora, a następnie wypełnia go, kopiując wskazane dane z pamięci RAM komputera do pamięci VRAM karty graficznej. Poniższy kod prezentuje proces tworzenia bufora. // Generowanie i przypinanie bufora glGenBuffersARB( 1, &nVBOVerts ); // Pobierz wlasciwa nazwe glBindBufferARB( GL_ARRAY_BUFFER_ARB, nVBOVerts ); // Przypnij bufor // Zaladuj dane glBufferDataARB(GL_ARRAY_BUFFER_ARB,nFaces*3*sizeof(nVertex), / VertexTable,GL_STATIC_DRAW_ARB ); Następnie funkcja usuwa obiekty dynamiczne z których zostały stworzone obiekty VBO, ponieważ nie są już potrzebne. Poniższy kod obrazuje sposób wykorzystania buforów VBO do rysowania geometrii. Na wstępie włączane jest wsparcie dla Vertex Buffer Object’ow po stronie klienta (ap- likacji), a następnie bufory są odpowiednio łączone z odpowiadającym im funkcjom. Os- tatnia linia pokazuje przykładowe wywołanie funkcji glDrawElements do narysowania zestawu danych zawartych w buforach. // wlaczamy obsluge dla kolejnych buforow danych : // wierzcholkow, wektorow normalnych, koordynatow mapowania glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // przypinamy bufor geometrii glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOVerts); glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL ); // wektorow normalnych glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBONormals ); glNormalPointer( GL_FLOAT, 0, (char *) NULL ); // koordynatow tekstur glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan1); glTexCoordPointer( 3, GL_FLOAT, 0, (char *) NULL); // rysujemy element korzystajac z przypietych buforow glDrawElements(GL_TRIANGLES,engine.Objects[i]->MatLen[j]*3, / GL_UNSIGNED_INT,&engine.Objects[i]->SortedFaceTable[stride]); Przy zakończeniu aplikacji należy odmapować bufory danych znajdujące się w pamięci. Zadanie to wykonywane jest przez destruktor klasy nMesh, obrazuje je poniższy kod. Tworzona jest tablica wskaźników do buforów, a nastepnie bufory te są usuwane przez funkcje glDeleteBuffersARB unsigned int nBuffers[4] = { nVBOVerts, nVBOTVChan1, nVBOTVChan3, nVBONormals}; glDeleteBuffersARB( 4, nBuffers ); 19
  • 21. 3.3 Teksturowanie Teksturowanie jest jedną z podstawowych technik wizualizacyjnych. Dzięki odpowied- niemu oteksturowaniu obiektów można uzyskać wiele ciekawych efektów, a także nadać projektowanej scenie realizmu. W ninejszej pracy zaimplementowane zostały następujące techniki teksturowania : – Politeksturing – Light Mapping (Multiteksturing) – Tekstury Przejść (Metoda Artystyczna) Dzięki technikom tym możliwe jest uzyskanie sceny o wysokiej jakości, a także uzyskanie statycznego oświetlenia obliczanego metodą Global Illumination. 3.3.1 Politeksturing Politeksturing jest techniką zaimplementowaną w celu zwiększenia wyrazistości sceny z jednoczesnym zmniejszeniem ilości pamięci potrzebnej na przechowanie tekstur. Po- liteksturing pozwala użytkownikowi na nałożenie osobnych tekstur na każdy z trójkątów bedących częścią jednego obiektu. Dzięki temu możliwe jest zastosowanie tekstur o śred- niej rozdzielczości, a geometria będzie w stanie ponownie wykorzystać piksele zapisane w danej teksturze. Jak wspomniano wcześniej, podejście klasyczne korzystające z pętli zawierających instrukcje glVertex jest zbyt mało wydajne. Dzięki wykorzystaniu VBO możliwe jest podniesienie wydajności o ponad 300%, jednak wiąże się to z pewnymi ograniczeniami związanymi z wykorzystywanymi funkcjami rysującymi. Funkcja glDrawArrays jest w stanie narysować cały obiekt VBO przy użyciu jednego wywołania funkcji, niestety rozsz- erzenie Vertex Buffer Objects nie przewiduje osobnego bufora dedykowanego dla in- deksowania materiałów. Stąd obiekty rysowane poprzez glDrawArrays mogą posiadać nałożoną tylko jedną teksturę. Wiąże się to z pewnymi komplikacjami. Głównym prob- lemem jest tutaj konieczność renderowania (bakingu) kompletnych, oświetlonych tekstur dla całego obiektu, w bardzo wysokiej rozdzielczości sięgającej ponad 2000px2 . Mimo zastosowania tak olbrzymiej rozdzielczości, rezultaty osiągane tą metodą są niezadowala- jące, ponieważ rozmiary tekseli rozpraszają użytkownika i dają wrażenie rozmycia sceny co obrazuje rysunek 4.4. Odpowiedzią na ten problem jest zaimplementowana metoda zwana Politeksturingiem. Struktura danych pliku wejściowego została rozszerzona o dodatkowy kanał koordynatów UV, z którego korzystać bedą tekstury map oświetlenia, a kanał tekstur (diffuse) został wzbogacony o identyfikatory materiału dla każdej ze ścianek. Dzięki temu możliwe jest normalne oteksturowanie środowiska wewnątrz programu służącego do projektowania (np. oteksturowanie jednego obiektu, jedną, powtarzalną teksturą), a następnie wyeks- portowanie go na potrzeby systemu czasu rzeczywistego. Metoda ta umożliwia znaczne oszczędności pamięci, ponieważ jeden piksel tekstury odpowiada wielu tekselom w scenie, podczas gdy w podejściu poprzednim (glDrawArrays) jeden piksel odpowiadał jednemu 20
  • 22. tekselowi, i wymagał znacznie dłuższej obróbki wstępnej. Problem ten nie dotyczy map oświetlenia, ponieważ są one wypiekane w średniej rozdzielczości, a łagodne przejścia pomiędzy obszarami o różnej intensywności oświetlenia dają wrażenie ciągłości i maskują wszelkie niedociągnięcia, co obrazuje rysunek 4.5. Do implementacji Politeksturingu wykorzystano funkcję OpenGL’a glDrawElements. Pobiera ona następujace parametry : tryb rysowania, ilość obiektów zależna od trybu, typ danych w tablicy indeksów oraz wskaźnik na tablicę indeksów. Aby wykorzystać możli- wości tej funkcji, należało wstępnie przygotowac dane, co zostało opisane w sekcji 3.2, należy tu dodać iż konsolidacja musiała zostać przeprowadzona dla wszystkich buforów danego obiektu, ponieważ funkcja zakłada zalezności 1:1 dla kolejnych pól danych. Poniższy fragment kodu obrazuje rysowanie obiektów z wykorzystaniem mechanizmu politeksturingu. Funkcja wykonywana jest w pętli dla wszystkich materiałów danego obiektu, zagnieżdżonej w pętli iterującej wszystkie obiekty danej sceny. W wewnętrznej części przypinana jest tekstura wskazywana przez identyfikator bieżącego materiału, a następnie jest rysowany fragment obiektu odpowiadający temu materiałowi. Do funkcji przekazywana jest długość danego materiału w wierzchołkach, oraz wskaźnik uwzględnia- jący przesunięcie względem poprzednich materiałów do miejsca w tablicy indeksów gdzie zaczyna się indeksowanie bierzącego fragmentu. for (int i=0; i<engine.WorldObjects ; i++) { int stride=0; for (int j=0; j<engine.Objects[i]->nTextures;j++) { glBindTexture(GL_TEXTURE_2D, engine.Objects[i]->FaceMatTable[stride].matID); glDrawElements(GL_TRIANGLES, engine.Objects[i]->MatLen[j]*3, GL_UNSIGNED_INT, / &engine.Objects[i]->SortedFaceTable[stride]); stride += engine.Objects[i]->MatLen[j]; // wskaznik przesuniecia } } 3.3.2 Light Mapping jako szczególny przypadek multiteks- turingu Multiteksturowanie jest rozszerzeniem biblioteki OpenGL, a od wersji OpenGL 1.2 wzwyż jest wbudowaną funkcją biblioteki. Rozszerzenie to umożliwia nakładanie na jedną powierzchnie do ośmiu tekstur oraz zapewnia funkcje łączenia nakładanych tekstur takie jak mnożenie, odejmowanie oraz inne funkcje logiczne. Light Mapping, czyli mapowanie oświetlenia opiera się o mnożenie dwóch tekstur za pomocą parametru GL MODULATE. Do dwóch jednostek teksturujących ładowane są osobne bitmapy, które stworzą teksturę wyjściową gdzie każdy piksel jest wynikiem mnożenia odpowiadających sobie pikseli z aktywnych jednostek teksturujących. Proces ten oraz proces odejmowania od siebie dwóch tekstur obrazuje rysunek 3.2. Pliki map oświetlenia (tzw. Light Mapy) są zwykłymi teksturami wypiekanymi (ang. texture baking) za pomocą oprogramowania do syntezy obrazu takiego jak np. Mental Ray. 21
  • 23. X = - = Rysunek 3.2: Multiteksturowanie, złożenie ze sobą dwóch tekstur. U góry iloczyn, u dołu różnica dwóch obrazów. Oprogramowanie to oblicza oświetlenie dla całego obiektu, po czym odwija mapę oświet- lenia z geometrii, technika ta nazywana jest unwrappingiem. Mapa taka zapisywana jest jako tekstura, a koordynaty mapowania UV zapisywane są w strukturze danych obiektu w osobnym kanale mapowania, przeznaczonym do tego celu. W implementacji silnika nGine użyto map oświetlenia w celu pominięcia obliczeń wykonywanych przez bibliotekę OpenGL związanych z oświetleniem, cieniowaniem i rzu- caniem cieni. A także w celu uzyskania realistycznego oświetlenia przy użyciu map oświet- lenia obliczanych metoda Global Illumination. Implementacja takiego modelu oświetlenia, tak aby możliwa była w czasie rzeczywistym wykracza poza umiejętności autora i możli- wości dostępnego mu sprzętu komputerowego. Największym minusem jaki ciągnie za sobą wykorzystanie Light Mappingu do oświetlenia sceny jest to iż sceny te są w pełni sta- tyczne. Poniższy kod przedstawia zastosowaną implementację Light Mappingu. W pętli iteru- jącej wszystkie obiekty sceny uaktywniana jest jednostka teksturująca nr.1 a następnie ładowana jest mapa oświetlenia odpowiadająca temu obiektowi do wybranej jednostki teksturującej (Texture Unit,TU). W wewnętrznej pętli iterującej materiały w bieżącym obiekcie definiowany jest sposób mieszania tekstur nakładanych na obiekt. Następnie rysowany jest obiekt. // petla : dla wszystkich obiektow // wlacz TU1 glActiveTextureARB(GL_TEXTURE1_ARB); 22
  • 24. // wlacz TU1 glClientActiveTextureARB(GL_TEXTURE1_ARB); // wlacz obsluge tekstur na TU1 glEnable(GL_TEXTURE_2D); // przypnij bufor koordynatow light mapy glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan3); // LM CHAN // wskaznik do bufora glTexCoordPointer( 3, GL_FLOAT, 0,(char *) NULL); // ustawienie flagi bufora glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // przypiecie tekstury z UV pobranymi z bufora glBindTexture(GL_TEXTURE_2D, engine.WorldTextures + i+1); // przypiecie LM // petla : dla wszystkich materialow w obiekcie // przypnij bufor geometrii glBindBufferARB( GL_ARRAY_BUFFER_ARB, engine.Objects[i]->nVBOTVChan1); // wlacz TU0 glActiveTextureARB(GL_TEXTURE0_ARB); // wlacz TU0 glClientActiveTextureARB(GL_TEXTURE0_ARB); // wlacz teksturowanie na TU0 glEnable(GL_TEXTURE_2D); // wskaznik do bufora UV glTexCoordPointer( 3, GL_FLOAT, 0, (char *) NULL); // ustawienie flagi dla bufora glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // funkcja przejscia tekstur W = A*B // GL_COMBINE - polaczenie 2 tekstur glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT); // MODULATE - mnozenie ich glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE); // zrodlo 0 - tekstura i kolor kazdego piksela // zrodlo 0 tekstura glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_TEXTURE); // zrodlo 0 , kolor tekstury glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_EXT,GL_SRC_COLOR); // zrodlo 1 - tekstura i jej kanal alfa // zrodlo 1 tekstura glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT,GL_TEXTURE); // zrodlo 1 kanal alpha tekstury glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_EXT,GL_SRC_ALPHA); // przypnij teksture diffuse (TU0) glBindTexture(GL_TEXTURE_2D, engine.Objects[i]->FaceMatTable[stride].matID); // narysuj calosc glDrawElements(...); 3.3.3 Tekstury przejść Bardzo prostą techniką stosowaną przez artystów w celu ujednolicenia sceny jest tworzenie tekstur przejścia (ang. Transition Textures). Technika ta polega na tworzeniu tekstury łączącej dwa obszary o różniacych sie teksturach. Mapa ta tworzona jest jest ze złączenia dwóch tekstur za pomocą liniowej funkcji przejścia. Proces ten obrazuje rysunek 3.3. Uzyskany efekt nadaje scenom ciągłości i nie powoduje nieprzyjemnych przeskoków pomiędzy obszarami o różnych teksturach. 23
  • 25. Rysunek 3.3: 3D Studio Max - Ujęcie jednego z korytarzy jaskini zaprojektowanej na potrzeby systemu nGine. U dołu widoczna tekstura przejścia pomiędzy piaszczystą ścieżką a kamienną posadzką. 3.4 Symulacja mgły Efekt mgły jest powszechnie wykorzystywany w wizualizacji środowisk aby nadać im głębi. W implementacji mgły posłużono się funkcjami bibliotecznymi OpenGL’a. Mgła może być generowana przez bibliotekę na podstawie trzech funkcji : liniowej, wykładniczej oraz wykładniczej drugiego stopnia. Metoda ta polega na polega na mieszaniu koloru piksela geometrii z kolorem mgły w funkcji gęstości mgły oraz odległości punktu od ob- serwatora. Ostateczna barwa wyznaczana jest poprzez kombinację liniową barwy mgły oraz barwy obiektu [JDF01]. W zależności od wyboru parametru GL FOG MODE wartość współczynnika łączenia może mieć postac : GL LINEAR wspolczynnik = koniec−z koniec−poczatek GL EXP wspolczynnik = e(−gestosc·glebokosc) GL EXP2 wspolczynnik = e(−gestosc·glebokosc)2 Poniższy kod źródłowy przedstawia implementację mgły w opisywanym środowisku. 24
  • 26. float fogColor[4] = {0.7f,0.7f,0.5f,1.0f}; // kolor mgly glFogi(GL_FOG_MODE, GL_EXP2); // tryb doboru wspolczynnika glFogfv(GL_FOG_COLOR, fogColor); // przypisanie koloru mgly glFogf(GL_FOG_DENSITY, 0.002f); // gestosc mgly glEnable(GL_FOG); // wlaczenie mgly w maszynie stanu Powyższe parametry mgły zostały dobrane empirycznie na podstawie zmysłu estety- cznego autora. Inną metodą implementacji mgły jest stworzenie tzw. mgły objętościowej (ang. Vol- umetric Fog), która oparta jest na geometrii. Geometrie mgły objęctościowej stanowią zazwyczaj obiekty pomocnicze (prymitywy) takie jak kule czy też systemy cząstek. Za- stosowanie tych technik jest jednak skomplikowane obliczeniowo, co rzutuje negatywnie na wydajność systemu wizualizacyjnego. Dltego też zrezygnowano z implementacji mgły objętościowej na rzecz prostej mgły oferowanej przez bibliotekę OpenGL. 3.5 Poruszanie się po środowisku Poruszanie się oraz interakcja użytkownika ze środowiskiem jest realizowana za po- mocą klasy nCamera. Klasa ta implementuje także metody pomiaru wydajności, oraz jest punktem wyprowadzenia mechanizmów detekcji i reakcji na kolizję. Zaimplementowana kamera jest kamerą widoku z pierwszej osoby (ang. First Person View, FPP) i składa się z następujących elementów : – Pozycji kamery – Wektora kierunku – Wektora orientacji pionowej – Wektora ruchu poprzecznego (Strafe) – Prędkości przemieszczenia Pozycja kamery modyfikowana jest przez użytkownika za pomocą klawiszy odpowiedzial- nych za ruch w wyznaczonym kierunku, a kąt skierowania modyfikowany jest poprzez ruch myszką. 3.5.1 Ogólny algorytm pracy kamery Przedstawiona poniżej sekwencja czynności powtarzana jest w każdej, kolejnej klatce animacji. Pierwszym krokiem jest odświeżenie kamery za pomoca funkcji nCamera.Update(). Funkcja ta pobiera parametr odpowiadający za włączenie lub wyłączenie funkcji detekcji kolizji, następnie oblicza wektor ruchu poprzecznego (ang. Strafe Vector) wyliczając iloczyn wektorowy pomiędzy wektorem kierunku a wektorem orientacji pionowej (ang. Up Vector). Następnie wywoływana jest funkcja SetViewByMouse() odpowiedzialna za obrót 25
  • 27. kamery za pomocą myszki. Kolejną wywoływaną funkcją jest CheckForMovement(), która sprawdza stany klawiszy na klawiaturze i modyfikuje prędkość kamery. Ostatnim krokiem jest wywołanie funkcji calculateFrameRate(), która odpowiedzialna jest za zliczanie ilości klatek rysowanych w ciągu sekundy. Po opuszczeniu funkcji nCamera.Update program wywołuje główną funkcję rysującą (RenderScene()), która wywołuje funkcję nCamera.Look(), odpowiadającą za przekaza- nie parametrów pozycji kamery do funkcji gluLookAt(). 3.5.2 Implementacja ruchu kamery Poruszanie się kamery realizowane jest przez parę funkcji składowych klasy nCamera, CheckForMovement() oraz MoveCamera(). Zadaniem pierwszej z nich jest wyskalowanie prędkości (stałej przesunięcia) względem prędkości rysowania poprzedniej klatki animacji poprzez iloczyn tych dwóch wartości, a następnie wywołanie funkcji MoveCamera() z odpowiednim parametrem, w zależności od wciśniętego przez użytkownika klawisza. Funkcja MoveCamera() tworzy pomocniczy wektor ruchu (vVector) poprzez odjęcie od wektora kierunku (m vView) wektora pozycji (m vPosition) a nastepnie normalizuje go. Kolejnym krokiem jest dodanie to wektorów pozycji oraz kierunku iloczynu wektora ruchu i kamery, co obrazuje poniższy kod: m_vPosition.x += vVector.x * speed; // dodajemy przyspieszenie do skladowej X pozycji m_vPosition.y += vVector.y * speed; // dodajemy przyspieszenie do skladowej Y pozycji m_vPosition.z += vVector.z * speed; // dodajemy przyspieszenie do skladowej Z pozycji m_vView.x += vVector.x * speed; // dodajemy przyspieszenie do skladowej X widoku m_vView.y += vVector.y * speed; // dodajemy przyspieszenie do skladowej Y widoku m_vView.z += vVector.z * speed; // dodajemy przyspieszenie do skladowej Z widoku W funkcję tą wbudowany jest także algorytm reakcji na kolizję kamery z otoczeniem. Algorytm bada w którym z sektorów znajduje się kamera, a następnie wykonuje testy przecięcia z bryłami okalającymi dla tego sektora. Jeżeli zostanie wykryta kolizja z jednym z liści drzewa, to zamiast inkrementacji wektorów pozycji i widoku o iloczyn wektora kierunku i zmiennej prędkości z powyższego kodu, następuje dekrementacja, co owocuje odrzuceniem kamery w kierunku przeciwnym do kierunku poruszania się, uniemożliwiając przejście przez geometrię sceny. 3.5.3 Ruch poprzeczny Implementacja ruchu poprzecznego jest praktycznie identyczna jak implementacja ruchu kamery, z tą różnicą, iż w obliczeniach pomijana jest oś Y. Poniższy kod prezentuje metodę zawartą w funkcji StrafeCamera() wywoływaną przez funkcję CheckForMove- ment(). // Inkrementacja pozycji w ruchu poprzecznym m_vPosition.x += m_vStrafe.x * speed; m_vPosition.z += m_vStrafe.z * speed; // Inkrementacja wektora widoku m_vView.x += m_vStrafe.x * speed; m_vView.z += m_vStrafe.z * speed; 26
  • 28. 3.5.4 Obrót kamery Klasa nCamera daje użytkownikowi możliwość w okół wektora orientacji pionowej oraz wektora ruchu poprzecznego. Funkcja ta implementowana jest przez funkcję SetViewBy- Mouse() oraz RotateView(). Kąt obrotu kamery uzyskiwany jest poprzez badanie wychylenia pionowego i poziomego wskaźnika myszy od środka ekranu. Funkcja SetViewByMouse() pobiera współrzędne ekranowe wskaźnika i sprawdza czy są one równe połowie wysokości i szerokości ekranu, jeżeli są, funkcja kończy dzialanie, jeżeli nie to przechodzi do kolejnego kroku. Kolejnym krokiem jest odjęcie od wartości połowy rozdzielczości ekranu aktualnej pozycji wskaźnika w osiach X i Y dla kątów odpowiednio Y i Z. Następnie badane jest wychylenie kamery w pionie, jeżeli kąt obrotu wynosi więcej niż jeden radian, to skracany jest on do wartości jednego radiana aby zapobiec pełnemu obrotowi w pionie. Następnie wyliczany i nor- malizowany jest iloczyn wektorowy wektora orientacji pionowej oraz wektora widoku i przekazywany z kątem obrotu osi Z do funkcji RotateView(). W kolejnym kroku kamera jest obracana o kąt Z w osi Y. Po wykonaniu powyższej procedury należy przywrócić wskaźnik do pozycji środkowej aby uniknąć akumulacji obrotu w kolejnych klatkach animacji. Funkcja SetViewByMouse() przekazuje do funkcji RotateView() kąt oraz osie obrotu kamery. Zadaniem funkcji RotateView() jest modyfikacja wektora widoku kamery. W tym celu tworzone są dwa nowe wektory pomocnicze, nowy wektor widoku (vNewView) oraz bierzący wektor widoku (vView) bedący różnicą pomiędzy wektorem widoku kamery oraz jej pozycją. Obrót kamery realizowany jest za pomocą poniższego kodu : // Dla oszczednosci obliczen wyliczamy kąty tylko raz float cosTheta = (float)cos(angle); float sinTheta = (float)sin(angle); // Znajdujemy nowa pozycje wspolrzednej X vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x; vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y; vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z; // Znajdujemy nowa pozycje wspolrzednej Y vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x; vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y; vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z; // Znajdujemy nowa pozycje wspolrzednej Z vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x; vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y; vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z; // Dodajemy uzyskany wektor obrotu do pozycji kamery // aby uzyskac nowy, obrocony wektor widoku m_vView = m_vPosition + vNewView; Metoda ta wykorzystuje wzory na obrót wektora według zadanej osi [Wei99] aby 27
  • 29. obliczyc nowe współrzędne wektora widoku, który kontroluje kierunek kamery. 3.6 Detekcja kolizji Systemy detekcji kolizji (Collision Detection,CD) składają się zazwyczaj z dwóch części : • Detekcja kolizji (CD) • Reakcja na kolizję (CR) System detekcji kolizji w środowisku wirtualnym bada relatywne położenia obiektów zawartych w tym środowisku. Jeśli zauwazy on iż dwa obiekty są wystarczająco blisko siebie, lub też w następnej jednostce czasu zajdzie zjawisko przecięcia lub też przeniknię- cia to zachodzi zdarzenie kolizji, które przekazywane jest z odpowiednimi parametrami do systemu reakcji na kolizję. Zdarzenie kolizji przekazywane jest do systemu reakcji na kolizję. W zdarzeniu tym przekazywane są dane takie jak pozycje obu obiektów z klatki bieżącej oraz następnej, wektor przesunięcia, dane obiektów takie jak masa, czy też materiał z którego zostały wykonane, modyfikujący właściwości fizyczne. Następnym krokiem systemu reakcji na kolizję jest przekazanie tych danych po wstępnej obróbce do systemu symulacji fizyki, lub też w przypadku jego braku zastosowanie procedur zapobiegania kolizji - w najprost- szym przypadku jest to wyzerowanie wektora prędkości, dzięki czemu obiekt pozostaje na pozycji z klatki biezącej. Innym, bardziej dokładnym rozwiązaniem jest wyliczenie dokładnego miejsca kolizji lub przecięcia między obiektami i przesunięcie obiektu kolidu- jącego wzdłuż wektora prędkości w to miejsce. 3.6.1 Pojęcia istotne dla zrozumienia zagadnienia detekcji kolizji Kolider (Collider) - Jest to dynamiczny obiekt kolidujący ze statycznym środowiskiem. Bounding Volume (BV) - Jest to najczęściej primityw geometryczny okalający zbiór geometrii w celu uproszczenia obliczeń związanych z interakcją z obiektami zawartymi w jego wnętrzu (rysunek 3.4). Axis Aligned Bounding Box (AABB) - Jest to prostopadłościan opisujący dany zbiór geometrii. AABB tworzony jest poprzez wyznaczenie wektorów miedzy punktami mini- malnymi i maksymalnymi w kazdej z trzech osi. AABB ułożone są wzdłuż osi układu współrzednych. Drzewo AABB - Jest to drzewo binarne posiadające bryły AABB w swych węzłach, tworzone jest w celu hierarchicznego podziału przestrzeni. Dzięki drzewom tym możliwe jest szybkie przeszukiwanie hierarchii w celu przyspieszenia obliczeń. Słabą stroną tej metody jest to iż dla każdego obiektu należy przygotować osobne drzewo, oraz przebu- dowywać je jeśli zajdzie zmiana położenia. Dlatego też metoda ta sprawdza się optymalnie jedynie w środowiskach statycznych lub środowiskach nie określanych mianem środowisk 28
  • 30. Rysunek 3.4: Bryły okalające, sześcian (bounding box) oraz sfera (bounding sphere). czasu rzeczywistego. 3.6.2 Algorytm detekcji kolizji Zaimplementowany algorytm detekcji kolizji opiera się o założenie, iż w scenie nie występują żadne kolizje poza kolizją sfery otaczającej ( Bounding Sphere) kamery ze środowiskiem, którego elementy reprezentowane są poprzez liście drzewa binarnego AABB. Ponizszy algorytm (rysunek 3.5) wykonywany jest w każdej kolejnej jednostce czasu (klatce animacji). Algorytm ten w klatce i-tej sprawdza położenie kolidera kamery wzglę- dem środowiska dla klatki i+1-szej. Aby dokonać tego testu, kolider przesuwany jest wzdłuż wektora prędkości z klatki i-tej. Pierwszym krokiem algorytmu jest sprawdzenie w którym (lub w których) z sektorów znajduje się obiekt kamery. Jest to realizowane przez test przecięcia się kolidera kamery z pierwszymi poziomami hierarchii dla każdego z sektorów. W ten sposób wyznaczany lub wyznaczane są sektory aktywne dla których bedą wykonywane dalsze obliczenia. Kolejnym krokiem algorytmu jest testowanie przecięcia (kolizji) sfery otaczającej kamery z drzewem hierarchii obiektu aktywnego. Dla każdej gałęzi na bierzącym poziomie drzewa wykonywany jest test przecięcia z koliderem kamery. Jeżeli da on wynik pozytywny to wykonywane są rekurencyjnie testy dla potomków bierzącej gałęzi aż do osiągnięcia liści drzewa, w których znajduje się maksymalnie jeden trójkąt geometrii, lub też do osią- gnięcia wystarczająco małej objętości bryły okalającej AABB. Osiągnięcie liści drzewa lub też gałęzi w której zapisana jest bryła okalająca o objętości mniejszej niż progowa nazywane jest kolizją i przekazywane do systemu reakcji na kolizję. 29
  • 31. Sprawdź kolizję dla tej gałęzi Czy jest to liść lub gałąź o wystarczająco małym rozmiarze? Wywołaj rekurencję dla prawej gałęzi Wywołaj rekurencję dla lewej gałęzi Zgłoś kolizję Nie Tak Tak Zakończ Nie START Rysunek 3.5: Algorytm detekcji kolizji dla drzewa AABB. 3.6.3 Charakterystyka struktur danych użytych do rozwiązania problemu detekcji kolizji Trzonem całego systemu jest niezbalansowane drzewo binarne, charakteryzującye się różną długością głównych gałęzi drzewa, oraz długim czasem przeszukiwania dla przy- padków pesymistycznych. Problemu tego można uniknąć dzięki zastosowaniu heurestyki podziału przestrzeni płaszczyzną prostopadłą do najdłuższej osi umieszczoną na środku jej długości. Dzięki zastosowaniu tej metody otrzymywane są zbalansowane lub pół- zbalansowane drzewa (gdzie większa część jest co najwyżej dwukrotnie większa od części mniejszej) gdzie nakładanie się na siebie brył otaczających jest minimalne [vdB98]. Główną zaletą drzew AABB nad drzewami OBB ( Oriented Bounding Box) jest znacznie większa prędkość konstrukcji oraz niewiele mniejsza precyzja. Kolejnym atutem drzew AABB jest także to iż zapisanie ich wymaga znacznie mniej (o połowę) mniej miejsca niż zapisanie drzew AABB [vdB98]. Sześciany okalające AABB definiowane są przez dwa punkty w przestrzeni utworzone na podstawie maksymalnych i minimalnych wartości punktów modelu w każdej z osi. W strukturze zawarta jest także objętość danego sześcianu, używana jako parametr precyzji detekcji kolizji. Geometria z której tworzone są bryły AABB jest zdefiniowana przez zbiór ścianek (faces) opisanych przez trójki punktów w przestrzeni. Strukura niesie ze sobą także środek ciężkości każdego z trójkątów, używany jako parametr determinujący przynależność danego 30
  • 32. prymitywu jako część lewą lub prawą podczas podpodziałów przestrzeni. 3.6.4 Test przecięcia sfery i bryły AABB Algorytm testowania przecięć pomiędzy sferą a sześcianem okalającym AABB został po raz pierwszy zaprezentowany przez Arvo [Jam90, TAM02] i jest zadziwiająco prosty. Trzonem tego algorytmu jest znalezienie punktu na AABB, który jest najbliżej środka sfery c. Używane do tego są testy jednowymiarowe, po jednym na każdą z osi AABB. Środek sfery porównywany jest z punktami granicznymi bryły okalającej. Jeśli znajduje się poza bryłą, obliczana jest odległość między bryłą a środkiem sfery (wzory 3.2 i 3.1) na bieżącej osi, a nastepnie podnoszona do kwadratu. Czynność ta wykonywana jest dla wszystkich trzech osiach, suma tych kwadratów porównywana jest z kwadratem promienia sfery, r2 . Jeśli suma jest mniejsza niż kwadrat promienia to nabliższy punkt bryły AABB znajduje się wewnątrz sfery i zachodzi przecięcie. ∀i ∈ {x, y, z} d = d + (ci − amin i )2 (3.1) ∀i ∈ {x, y, z} d = d + (ci − amax i )2 (3.2) gdzie : – ci to kolejne współrzędne środka sfery, – d to obliczana suma, – amin i i amax i to kolejne współrzędne punktów granicznych bryły AABB, odpowiednio minimalnego i maksymalnego. Algorytm ten obrazuje poniższy pseudokod. d=0; for each i in {x,y,z} if(c[i] < a_min[i]) // jesli dana skladowa jest mniejsza od minimalnej d=d+(c[i] - a_min[i])^2 // wykonaj obliczenie else if (c[i] > a_max[i]) // jesli jest wieksza od maksymalnej d=d+(c[i] - a_max[i])^2 // wykonaj obliczenia if (d > r^2) // jesli odleglosc jest wieksza od kwadratu promienia return(BRAK_KOLIZJI) // zwroc brak kolizji return(KOLIZJA) // w innym wypadku zwroc kolizje 3.6.5 Algorytm budowy drzewa binarnego AABB Przedstawiony poniżej algorytm (rysunek 3.6) jest wykonywany rekurencyjnie do mo- mentu osiągnięcia progu, którym jest zamkniecie nie wiecej jak jednego trójkąta we wnętrzu bryły AABB. Zadanie to wykonywane jest przez klasę nAABBTree. Pierwszym krokiem algorytmu jest odnalezienie wartości minimalnych i maksymal- nych w każdej z trzech osi (lx, ly, lz, ux, uy, uz), region taki opisany jest przez rownanie 3.3 i nazywany bedzie bryłą okalającą AABB. Procedury tworzące brylę AABB zawarte są w klasie nAABB. 31
  • 33. Stwórz AABB dla podanej geometrii Czy wewnątrz znajduje się wiecej jak jeden trójkąt? Podziel przestrzeń płaszczyzną na dwie części Wywołaj rekurencję dla prawej gałęzi Wywołaj rekurencję dla lewej gałęzi Utwórz liść. Zakończ rekurencje. Tak Nie START Rysunek 3.6: Algorytm konstrukcji drzewa AABB. 32
  • 34. R = {(x, y, z) | lx ≤ x ≤ ux, ly ≤ y ≤ uy, lz ≤ z ≤ uz} (3.3) Następnie tworzony jest wektor v(x, y, z) wg. wzoru 3.4. v = l − u. (3.4) Z wektora v(x, y, z) obliczana jest objętość danej bryły AABB, wg. wzoru 3.5. Jeśli we wnętrzu bryły okalającej znajduje się wiecej jak jeden obiekt (trójkąt) to algorytm wykonywany jest dalej, w przeciwnym wypadku tworzony jest liść drzewa i rekurencja jest kończona. VAABB = x · y · z. (3.5) Kolejnym krokiem jest dokonanie podziału przestrzeni płaszczyzną ( slicing plane). Płaszczyzna ta dzieli zbiory geometrii sub-optymalnie [vdB98] jeśli jej wektor normalny n jest równoległy do najdłuższej osi bryły AABB w bieżącym węźle, a płaszczyzna (rów- nanie 3.6) przechodzi przez punkt p0 znajdujący się na środku długości najdłuższej osi. Ax + By + Cz + D = 0. (3.6) gdzie: – A, B, C są współrzędnymi odpowiednio x,y,z wektora normalnego do płaszczyny n – x, y, z to wspolrzędne punktu p0 – D to odległość płaszczyzny od początku układu współrzędnych. Kolejnym etapem podziału przestrzeni jest segregowanie prymitywów na części lewą i prawą. Jeśli wynik równania 3.7 będzie większy lub równy zero, to trójkąt, którego środka ciężkości (równanie 3.8) użyliśmy do rozwiązania tego równania zaklasyfikowany będzie jako część prawa, w przeciwnym wypadku będzie on zaklasyfikowany jako część lewa. Implementacja tego kroku w klasie nAABBTree zawiera się w funkcji CreateNode() i wykorzystuje klasę pomocniczą nTriSort, która pozwala na zapisanie w swym wnętrzu środka ciężkości każdego z trójkątów oraz jego przynależności do części prawej lub lewej. Na wstępie tworzony jest obiekt dynamiczny klasy nTriSort or rozmiarze geometrysize, czyli ilości scianek w danym obiekcie. Dla każdej ze ścianek w bierzącym obiekcie obliczany jest środek ciężkości, który następnie porównywany jest z płaszczyzną przecięcia. W za- leżności od wyniku porównania, bierząca ścianka klasyfikowana jest jako lewa lub prawa oraz inkrementowane sa odpowiednie wartości numLeft oraz numRight odpowiadające za rozmiar obiektów dynamicznych, przechowujących geometrię dla lewego oraz prawego rozgałęzienia. Na tym etapie algorytm przeprowadza jeszcze jeden test. Dla niektórych, bardzo ekstremalnych przypadków zdarzyc się moze iż wszystkie scianki danego rozgałęzienia zostaną zaklasyfikowane jako część lewa lub prawa. Prowadzi to nieskończonego zapętlenia rekurencji (tzw. deadloop), co prowadzi do szybkiego wyczerpania zasobów pamięci oraz błędu ochrony pamięci. W przypadku takim, algorytm dzieli bierzący zestaw geometrii 33
  • 35. (subset) na dwie równe części, nadpisując wykonane wcześniej sortowanie. Przypadki takie mają miejsce zazwyczaj gdy bierzący zestaw składa się z bardzo małej ilości prymitywów. D = ax0 + by0 + cz0 + d √ a2 + b2 + c2 (3.7) gdzie: – (a, b, c) to współrzędne wektora normalnego do płaszczyzny n – x0, y0, z0 to współrzędne badanego punktu – d to odległość płaszczyzny od środka układu współrzędnych Równanie to daje wynik dodatni jeśli badany punkt znajduje się po tej samej stronie płaszczyzny co wektor normalny n, oraz wynik ujemny w przypadku przeciwnym. Jeśli S = (xs, ys, zs) jest środkiem trójkąta ABC to: xs = xa + xb + xc 3 , ys = ya + yb + yc 3 , zs = za + zb + zc 3 . (3.8) Końcowym etapem jest wykonanie rekurencji algorytmu dla części prawej oraz lewej. Wynikiem działania tego algorytmu jest półzbalansowane drzewo binarne, posiadające bryły AABB w swych gałęziach oraz bryły AABB okalające pojedyńcze primitywy w swych liściach [vdB98]. Wizualizację drzewa przedstawia rysunek 3.7 Na etapie tym klasa nAABBTree tworzy dwa nowe obiekty swej klasy, podając do konstruktora klasy zestawy geometrii zaklasyfikowane wcześniej jako prawy i lewy. Kon- struktor klasy nAABBTree zeruje wskaźniki na liście prawy i lewy, które zostana nadpisane podczas tworzenia kolejnych obiektów, lub też pozostaną wyzerowane, oznaczając bieżący punkt jako liść drzewa. Następnie wywoływana jest funkcja BuildNode, która tworzy ko- lejne gałęzie drzewa. 3.6.6 Wizualizacja drzewa AABB W silniku nGine zaimplementowano prosty system wizualizacji drzew AABB dla wszystkich obiektów. Funkcja rysująca daną bryłę AABB zawarta jest wewnątrz klasy nAABBTree i może być wywolywana rekurencyjnie dla wszystkich potomków danej gałęzi, dając w rezultacie obraz wybranej części drzewa (rysunek 3.7). Metoda ta została zaim- plementowana w celach badawczych i testowych, pozwala ona projektantowi na analizę wybranego modelu, i takie optymalizacje aby objętości wybranych węzłów drzewa były jak najmniejsze. Funkcja rysująca bryły AABB rysuje pary wierzchołków między którymi rysowane są linie za pomocą funkcji glBegin(GL LINES). W parze glBegin(), glEnd() zawarte jest 12 par definiujących wszystkie linie sześcianu. Współrzędne punktów wyliczane sa na postawie punktu minimalnego bryły AABB oraz wektora v stworzonego między pun- ktami minimalnym i maksymalnym. 34
  • 36. Rysunek 3.7: nGine - Wizualizacja drzewa AABB opisującego sferę. Bardzo waznym elementem porównawczym jest tutaj sposób rysowania brył okala- jących. Każdorazowe wywołanie funkcji DrawBV() pociąga za sobą wywołanie funkcji glVertex3f aż 24 razy. Przy każdorazwym wywołaniu należy także wyłączyć obie akty- wne jednostki teksturujące, oraz włączyć je po wizualizacji drzewa. Wykonanie tej pro- cedury rekurencyjnie dla całego drzewa owocuje spadkiem wydajności (ilości klatek na sekundę, FPS) aplikacji o ponad 50%. Gdyby wierzchołki brył AABB zapisać w obiekcie VBO, spadek wydajności niebyłby tak znaczny. 3.6.7 Algorytm ukrywania powierzchni niewidocznych oparty o bryły AABB Jednym z zastosowań brył okalających (ang. bounding volumes) jest szybkie wyłączanie dużych ilości danych z obliczeń. Dzieki tej metodzie możliwe jest pomijanie dużych ilości geometrii podczas rysowania sceny, co owocuje znacznym zwiększeniem wydajności. W ujęciu typowym, stosuje się testowanie przecięcia bryły okalającej z bryłą widzenia (frustum). Jeśli bryły te nie przecinają się to są one pomijane przy wyświetlaniu, pro- ces ten nazywany jest ukrywaniem obiektów niewidocznych, lub też selekcją za pomocą bryły widzenia (frustum culling). W ujęciu implementowanego środowiska, podejście za- proponowane w [TAM02], opierające się na testowaniu bryły AABB i sześciu płaszczyzn uznano za słuszne i rozbudowano je o dodatkowy stopień dokładności, jakim jest punkt środkowy bryły AABB. 35
  • 37. AABB Top Back Right Bottom Left Front Rysunek 3.8: Bryła widzenia oraz obiekt otoczony przez bryłę AABB. W każdej klatce animacji z bryły widzenia izolowane są płaszczyzny budujące tą bryłę. Następnie wykonywany jest test położenia punktu względęm płaszczyzny dla wszystkich wierzchołków bryły AABB oraz dla jej punktu środkowego. Test ten opiera się o rów- nanie 3.7. Jesli odległość między badanym punktem a płaszczyzną jest większa od zera to punkt klasyfikowany jest jako leżący w dodatniej półprzestrzeni wyznaczonej przez tą płaszczyznę, w przeciwnym wypadku bryła klasyfikowana jest jako niewidoczna. Jeśli punkt leży w dodatniej półprzestrzeni wszystkich sześciu płaszczyzn to bryła do której należy klasyfikowana jest jako widoczna. W pracy zmodyfikowano oryginalny algorytm frustum cullingu [TAM02] dodając dodatkowy test punktu środkowego, w celu zwiększenia dokładności testowania. Przed wprowadzeniem tej modyfikacji, dla ekstremalnych przypadków, w których bryła okala- jąca była większa niz bryła widzenia, obiekty były klasyfikowane jako niewidoczne, mimo iż znajdowały się dokładnie na wprost kamery. Dodanie punktu środkowego zwiększa dokładność testowania ośmiokrotnie, ponieważ przez punkt środkowy można przeprowadzic trzy płaszczyzny równoległe do osi szcześcianu, rozdzielające bryłę AABB na osiem części. Modyfikacja ta z powodzeniem wyeliminowała wszelkie występujące anomalia. 36
  • 38. Rozdział 4 Rezultaty i wnioski W rozdziale tym znajdują się wyniki testów wydajnościowych środowiska nGine. Zadaniem tych testów jest ocena wydajności aplikacji przy różnych parametrach wej- ściowych - głównie przy zwiększającej się ilości geometrii. 4.1 Opis procedury testowej Klasy środowiska nGine zostały wyposażone w specjalne moduły do badania i rapor- towania wydajności aplikacji. Głównym testem wydajnościowym jest liczba generowanych klatek animacji w ciągu sekundy (ang. Frames Per Second, FPS). W celu pomiaru FPS klasa nCamera została wy- posażona w funkcję calculateFramerate(), której zadaniem jest pomiar liczby klatek animacji rysowanych w ciągu sekundy, oraz obliczanie liczb średnich, maksymalnych i minimalnych. Funkcja RenderScene() odpowiedzialna jest za rysowanie kolejnych klatek animacji oraz odświeżanie widoku kamery. W każdej kolejnej klatce animacji wywołuje ona funkcję nCamera.Look() odpowiedzialną za odświeżenie parametrów kamery oraz wywołanie funkcji calculateFramerate(). Podczas każdego wywołania funkcja ta pobiera aktu- alny czas oraz inkrementuje liczbę narysowanych klatek. Jeżeli czas jaki upłynął pomiędzy kolejnymi wywołaniami jest większy od jednej sekundy to wartość FPS jest zapisywana i wyświetlana, a parametry pomiarowe zostają wyzerowane. Klasa nCamera jest sprzężona z funkcją calculateFramerate(), dzięki czemu możliwa jest regulacja prędkości kamery w zależności od prędkości komputera, na jakim aplikacja jest uruchamiana. Zmiana prędkości jest iloczynem ilości klatek narysowanych w ciągu ostatniej sekundy oraz stałej kSpeed. Dzięki zastosowaniu tej procedury kamera prze- będzie tą samą drogę w tym samym czasie, niezależnie od prędkości systemu, na którym działa aplikacja. Procedura testowa opiera się na mierzeniu wydajności środowiska poprzez wskaźnik, jakim jest liczba generowanych klatek animacji w ciągu sekundy przy następujących para- metrach :
  • 39. • Rozdzielczość płótna OpenGL. • Tryb okienkowy oraz pełnoekranowy. • Zastosowanie optymalizacji Frustum Culling. • Detekcja kolizji. • Ilość geometrii w scenie. • Poprawność środowiska. Wynikiem przeprowadzonych testów jest uzyskanie wartości średnich, maksymalnych i minimalnych dla ilości generowanych klatek animacji w ciągu sekundy dla złożeń wyżej wymienionych parametrów. Każdorazowy pomiar odbywał się podczas trzykrotnego prze- lotu kamery wewnątrz specjalnie zaprojektowanej jaskini, podczas którego zebrano około 100 próbek. Wszystkie testy zostały przeprowadzone na komputerze PC o następującej konfigu- racji : – Procesor : Intel Pentium IV 3.06 GHz HT. – GPU : Ati Radeon 9600XT (Sterowniki Omega 2.6.05a). – Pamięć : 1024 MB Dual Channel DDR CL 2.5, taktowane magistralą 200MHz. – Płyta Główna : Abit IS-7, taktowana magistralą 200MHz. System nGine pracuje w technologii jednowątkowej i nie wykorzystuje możliwości drugiego potoku procesora HT. 4.2 Analiza wyników przeprowadzonych testów 4.2.1 Wpływ rozdzielczości oraz trybu płótna OpenGL na wyda- jność środowiska Wpływ przyrostu rozdzielczości rysowanego płótna OpenGL na prędkość generowanego obrazu przedstawia wykres 4.1. Prezentowane dane pochodzą ze sceny testowej o złożoności siatki 9500 trójkątów oraz posiadającej 14 MB tekstur. W celu uniknięcia błędów pomia- rowych, oraz aby zapewnić stałą liczbę rysowanej geometrii wyłączono optymalizacje Frustum Culling. Jak łatwo zauważyc, spadek rozdzielczości powoduje wzrost liczby generowanych klatek o około 30%. Spowodowane jest to faktem, iż procesor graficzny musi wypełnić mniejszą liczbę pikseli w ciągu sekundy. Wykres 4.2 obrazuje wpływ przejścia aplikacji w tryb pełno ekranowy wraz ze zmianą rozdzielczości. 38
  • 40. Rysunek 4.1: Wpływ rozdzielczości oraz Frustum Culling’u na średnią prędkość generowa- nia animacji w trybie okienkowym. Rysunek 4.2: Wpływ rozdzielczości oraz Frustum Culling’u na średnią prędkość generowa- nia animacji w trybie pełnoekranowym. 39
  • 41. Rysunek 4.3: Wpływ ilości geometrii i Frustum Cullingu na ilość generowanych klatek animacji. Można zaobserwować tutaj wzrost wydajności systemu o kolejne 10−20% w stosunku do trybu okienkowego (wykres 4.1) związany z bezpośrednim dostępem do pamięci ekranu oraz brakiem rysowania elementów, które nie należą do systemu wizualizacyjnego nGine. 4.2.2 Wpływ optymalizacji Frustum Culling na wydajność sys- temu Wykresy 4.1, 4.2, 4.3 obrazują przyrost prędkości generowanej sceny przy zastosowa- niu optymalizacji Frustum Culling. Dzięki zastosowaniu tej optymalizacji uzyskano przyrost wydajności między 90% a 150%. Tak olbrzymi przyrost spowodowany jest faktem, iż większość geometrii znajdu- jącej poza bryłą widzenia jest usuwana z potoku renderującego, wobec czego procesor graficzny nie zajmuje się jej przetwarzaniem. Ma to szczególne znaczenie dla scen z dużą (150 000 trójkątów) ilością geometrii (wykres 4.3), ponieważ spadek ilości generowanych klatek poniżej 40-60 FPS jest zauważalny dla użytkownika i może powodować dyskomfort. 4.2.3 Wpływ detekcji kolizji akcelerowanej metodą drzew AABB na prędkość działania systemu Podczas przeprowadzonych testów nie zauważono wpływu włączenia mechanizmu detekcji kolizji na prędkość generowanej sceny przekraczającego założony błąd pomi- arowy ±5FPS. Fakt ten został potwierdzony dla obydwu scen testowych, różniących się ilością geometrii w stosunku 1:15,7. Brak wpływu na prędkość generowania animacji spowodowany jest faktem, iż algorytm detekcji kolizji kończy swoją pracę po zaledwie 40
  • 42. kilku krokach, ponieważ kolider kamery nie przecina brył okalających wewnętrznych części drzewa. Wynik ten można uznać za dobry w porównaniu z wynikami uzyskanymi w [Kos04], gdzie zagęszczenie geometrii z 1000 trójkątów do 10 000 trójkątów owocowało spadkiem wydajności o ponad 50% a detekcja kolizji została zaimplementowana za po- mocą sferycznej metody śledzenia promieni. 4.2.4 Wpływ ilości geometrii na prędkość działania systemu Wykres 4.3 obrazuje spadek wydajności systemu dla sceny o wysokiej złożoności (Hi-Poly) w stosunku do sceny Low-Poly z wykresu 4.1. Można zaobserwować tutaj znaczny spadek wydajności systemu, sięgający od 50% do 75% związany z przyrostem przetwarzanej geometrii o około 1570%. Mimo tak ogromnej różnicy w ilości geometrii, nie uzyskano nigdy średniej ilości FPS mniejszej niż 40 FPS, co jest znacznym osiągnięciem w stosunku do wcześniej prezentowanych metod [Kos04]. Różnicę wydajności można zm- niejszyć dzięki zastosowaniu optymalizacji Frustum Culling, co obrazuje wykres 4.3. Dal- szy przyrost wydajności możliwy jest dzięki zastosowaniu cullingu o większej dokładności, np. działającego w odniesieniu do pojedyńczych liści drzewa, a nie tylko w odniesieniu do jego korzenia. 4.2.5 Poprawność wizualizacji środowiska Testowane wirtualne środowisko jest fizycznie poprawne. Wizualizowana geometria nie posiada prześwitów ani żadnych braków. Wszystkie koordynaty geometryczne, współrzę- dne mapowania, wektory normalne nie zmieniły się w wyniku działania środowiska i są odbiciem tego, co zostało zaprojektowane w programie graficznym. Detekcja kolizji i reakcja na kolizje są poprawne, nie występują obszary z niewidzial- nymi bryłami kolidującymi, nie istnieją także miejsca gdzie użytkownik mógłby przejść przez ścianę lub inny obiekt w scenie. 4.3 Prezentacja uzyskanych wyników, rysunki W sekcji tej zaprezentowane są wyniki działania programu. Dołączone rysunki są niemodyfikowanymi zrzutami ekranu z działającego środowiska nGine. Rysunek 4.5 obrazuje zwiększenie jakości wyświetlanego środowiska poprzez użycie politeksturingu w stosunku do środowiska opisanego przez pojedyńcze tekstury na ry- sunku 4.4. Rysunek 4.6 prezentuje cieniowanie oraz efekty świetlne, takie jak pozorne świecenie. Rysunek 4.7 dokładniej obrazuje jakość uzyskanych cieni. Rysunek 4.8 obrazuje porównanie jakości wyświetlania sceny w środowisku nGine (OpenGL) oraz tej samej sceny wyrenderowanej w 3D Studio Max za pomocą programu Mental Ray. Klatka animacji w środowisku nGine została stworzona w czasie około 1/300 41
  • 43. sekundy, obraz z Mental Ray był przetwarzany przez około 3 minuty. Rysunek 4.9 obrazuje efekt pozornego świecenia obiektów, uzyskany dzięki zastosowa- niu light mappingu. Dzięki tej technice możliwe jest częściowe wyeliminowanie Pixel Shadingu dla prostych środowisk. Rysunki 4.10 oraz 4.11 obrazują ogólny widok na zaprojektowane środowisko. Specy- fiką tego projektu jest to, iż normalne ścian jaskini odwrócone są do wewnątrz, dzięki czemu po „wyjściu” z jaskini możliwe jest obejrzenie całości środowiska, ponieważ ścianki z wektorami normalnymi równoległymi do kamery nie są rysowane. W zaprojektowanym środowisku wyróżniono trzy tematycznie różne strefy : ruiny z otwartym sklepieniem (rysunek 4.10), tunel jaskini (rysunki 4.5, 4.10) oraz zasypaną starożytną komnatę (ry- sunki 4.7, 4.11, 4.12). Strefy te połączone są w sposób płynny, prezentując użytkownikowi ciekawe i zróżnicowane środowisko. Rysunek 4.4: nGine - Single Texturing oparty o glDrawArrays, widoczny znaczny rozmiar tekseli. Powierzchnie sceny dają wrażenie rozmytych. 42
  • 44. Rysunek 4.5: nGine - Politeksturing, znaczna poprawa jakości wyświetlanego obrazu 43
  • 45. Rysunek 4.6: nGine - Lightmapping, cienie i efekty świetlne 44
  • 46. Rysunek 4.7: nGine - Lightmapping, cienie 45
  • 47. Rysunek 4.8: nGine - Porównanie jakości wyświetlania 46
  • 48. Rysunek 4.9: nGine - Wejście do jaskini, widoczne świecące kryształy 47
  • 49. Rysunek 4.10: nGine - Widok ogólny na część południową 48
  • 50. Rysunek 4.11: nGine - Widok ogólny na część północną 49
  • 51. Rysunek 4.12: nGine - Wejście do północnej komnaty 50
  • 52. Rozdział 5 Podsumowanie i wnioski Osiągnięte podczas implementacji środowiska nGine rezultaty są pozytywne. Osią- gnięto zadowalający stopień realizmu oraz zrealizowano założenia postawione pracy. Teza pracy brzmiąca „Przy użyciu biblioteki OpenGL możliwa jest implementacja fizycznie poprawnego i wydajnego wirtualnego środowiska” została więc udowodniona. Wszystkie wybrane elementy wizualizacji zostały zaimplementowane od postaw dzięki użyciu biblioteki OpenGL i działają zgodnie z definicją. Wydajność wszystkich elementów wizualizacyjnych jest wysoka i spełnia wszelkie standardy komfortu pracy ze środowiskiem. Przy maksymalnym testowanym obciążeniu, prędkość animacji nie była niższa niż 39-41 klatek na sekundę, co jest rezultatem dość dobrym, zważając na stopień profesjonalizmu oraz ilość osób zaangażowanych w implementacje systemu nGine w stosunku do aplikacji komercyjnych. Zgodnie z założeniami pracy, opracowano w pełni funkcjonalne, poprawne fizycznie wirtualne środowisko obsługujące dowolony ruch kamery w przestrzeni środowiska, oraz detekcję kolizji kamery ze środowiskiem, uniemożliwiającą jej przenikanie przez elementy środowiska. W środowisku zaimplementowano także wybrane elementy wizualizacji pod- noszące relatywny stopień realizmu sceny, elementami tymi są : 1. Detekcja kolizji akcelerowana drzewem binarnym AABB. Metoda ta opiera się na zbudowaniu drzewa binarnego zawierającego w swych węzłach i liściach bryły okala- jące AABB. Drzewo jest hierarchiczną reprezentacją geometrii danego obiektu, dla- tego też możliwe jest szybkie przeszukanie go w celu odnalezienia szukanego ele- mentu oraz szybkie zakończenie przeszukiwania drzewa na wczesnych etapach jeżeli kolider nie znajduje się w pobliżu geometrii z którą może kolidować. Implementacja tej metody wymaga każdorazowego przebudowania drzewa podczas uruchamiania aplikacji, co wydłuża czas uruchomienia. Przeciwwagą jest fakt, iż przeszukiwanie drzewa nie wpływa w sposób widoczny na wydajność aplikacji. 2. Implementacja oświetlenia i cieniowania sceny za pomocą map oświetlenia. Metoda ta, oparta na multiteksturingu pozwala na uzyskanie realistycznych efektów świet- lnych w statycznym środowisku. Oświetlenie sceny obliczane jest wstępnie metodą oświetlenia globalnego (ang. Global Illumination, GI) a następnie zapisywane do
  • 53. tekstur oświetlenia. Kolejnym krokiem jest przemnożenie wartości pikseli mapy oś- wietlenia z odpowiadającym im fragmentom sceny uzyskując realistyczne efekty świetlne. 3. Implementacja wyświetlania geometrii za pomocą buforów pamięci karty graficznej. Zastosowanie tej metody skraca znacznie drogę jaką wyświetlane dane muszą po- konać, co owocuje wzrostem wydajności aplikacji o ponad 300%. Kolejnym plusem tej metody jest rysowanie całego przygotowanego zestawu funkcji za pomocą jednej funkcji, co znacznie zmniejsza czas jaki potrzebuje CPU na przygotowanie zestawu geometrii do wyświetlenia. 4. Opracowanie autorskiego, binarnego formatu eksportu grafiki o nazwie „n3D”. Dzięki temu formatowi zapisu danych, możliwe jest wyeksportowanie geometrii z programu 3D Studio Max i odczytanie jej za pomocą silnika nGine po bardzo niewielu ope- racjach wstępnych. Format ten został zoptymalizowany pod kątem współpracy z buforami pamięci karty graficznej. Podczas eksportowania danych nietracone są żadne informacje a scena zaimportowana do wirtualnego środowiska wygląda do- kładnie tak jak została zaprojektowana w programie graficznym. Dzięki temu, oraz przejrzystej strukturze formatu, możliwe jest rozgraniczenie funkcji programisty i grafika, co pozwala na zatrudnienie wyspecjalizowanej kadry dla każdej z osobnych dziedzin. 5. Opracowanie systemu politeksturingu. System ten pozwala na rysowanie i tekstur- owanie geometrii dokładnie tak jak została zaprojektowana w programie graficznym. Dzięki politeksturingowi możliwe jest nałożenie wielu tekstur na jeden obiekt, oraz użycie powtarzalnych tekstur w całej scenie, co owocuje znacznym zmniejszeniem zapotrzebowania na pamięć. Politeksturing współpracuje także z systemem mapowa- nia oświetlenia dając grafikom potężne narzędzie do projektowania wirtualnych środowisk. 6. Implementacja kamery. Zastosowana metoda implementacji kamery pozwala użyt- kownikowi na poruszanie się we wszystkich kierunkach, pozwala na ruch poprzeczny oraz blokuje możliwość pełnego obrotu pionowego, powodującego dezorientujący efekt. Klasa kamery posiada także skalowanie prędkości przemieszczania się kamery w locie, dzięki czemu wraz z rozwojem architektury komputerów animacja nigdy nie będzie zbyt szybka, powodując trudności w używaniu środowiska. 7. Zbudowanie w programie 3D Studio Max wirtualnego środowiska jaskini połączo- nej z elementami starożytnych ruin w celach prezentacji możliwości zaimplemen- towanego wirtualnego środowiska, oraz wersji o dużej ilości szczegółów w celach testowych. Zaprojektowane środowisko obrazuje przejścia pomiędzy różnymi tema- tycznie obszarami oraz pokazuje spektrum tematyczne środowisk jakie mogą być współcześnie wizualizowane. 8. Tekstury przejść. Metoda ta pomogła w połączeniu w sposób płynny dwóch ob- szarów o diametralnie różnej charakterystyce wystroju, tworząc spójną całość. 52
  • 54. 5.1 Dalsze prace związane z rozwojem wirtualnych środowisk 5.1.1 Wielowątkowość Testy wydajnościowe środowiska nGine zostały przeprowadzone na sprzęcie klasy PC wyposażonym w procesor opierający się na technologii Hyper Threading. Technologia ta opiera się o dwa potoki przetwarzające oraz jedną jednostkę wykonawczą, dzięki czemu możliwe jest uzyskanie wydajności zbliżonej do maszyn dwuprocesorowych. Środowisko nGine nie zostało jednak wyposażone w technologię wielowątkową, dlatego też korzysta jedynie z jednego potoku przetwarzającego. Implementacja wielowątkowości skróciłaby czas potrzebny na budowanie drzewa AABB oraz umożliwiła stworzenie osob- nych wątków dla mechanizmu detekcji kolizji i obsługi sceny oraz dla głównej funkcji renderującej, co znacznie zwiększyłoby wydajność środowiska. 5.1.2 Inne modele hierarchii sceny Zastosowane w systemie nGine drzewo binarne opierające się o bryły AABB jest metodą stosunkowo prostą w implementacji oraz w miarę wydajną, lecz może się nie sprawdzić dla bardzo dużych scen (powyzej miliona trójkątów), oraz jest metodą je- dynie dostatecznie dokładną, ponieważ sześciany okalające ułożone są wzdłuż osi układu współrzędnych, przez co zawierają bardzo dużo pustej przestrzeni. Alternatywnymi metodami reprezentacji hierarchii geometrii są drzewa binarne OBB, drzewa ósemkowe, oraz drzewa binarne BSP. Drzewa OBB (ang. Oriented Bounding Box) są podobne do drzew AABB z tą różnicą że sześciany okalające ułożone są naokoło opisywanej geometrii tak, aby zminimalizować ich objętość i zmniejszyć ilość pustej przestrzeni w ich wnętrzu (ang. Tight-fit). Metoda ta nie została zaimplementowana ze względu na skomplikowanie obliczeń oraz znacznie większe zapotrzebowanie na pamięć w stosunku do brył AABB. Drzewa ósemkowe (ang. Octrees) są regularnym odpowiednikiem drzew AABB. Drzewo ósemkowe tworzone jest przez rekurencyjny podział przestrzeni poprzez rozcięcie jej płaszczyznami we wszystkich trzech osiach posiadających punkt wspólny będący środ- kiem bryły okalającej. Metoda ta jest szybsza dla niektórych zapytań, ale wiąże się także z redundancją danych w przypadku, gdy obiekt leży w dwóch sektorach naraz [TAM02]. Zapobiec temu zjawisku można poprzez tworzenie geometrii w miejscu przecięcia, ale to wiąże się ze zwiększeniem zapotrzebowania na pamięć, dlatego też metoda ta nie została zaimplementowana. Drzewa BSP oparte o sortowanie poligonalne są odpowiednikiem zastosowanego drzewa BSP opierającego się o bryły okalające AABB. Podział przestrzeni w poligonalnym drzewie BSP opiera się o ułożenie płaszczyzny wzdłuż jednego z poligonów obranego według autorskiej heurestyki. Problemem tej metody, jak i opisywanej wyżej metody drzew 53
  • 55. ósemkowych jest rozdzielanie prymitywów na dwie części w miejscu przecięcia z pła- szczyzną podziału, powodując zwiększenie ilości geometrii w scenie. Kryterium to zade- cydowało o odrzuceniu tej metody. 5.1.3 Metody optymalizacji ilości renderowanej geometrii W systemie nGine zastosowano dwie metody akceleracji wyświetlania. Pierwszą z nich jest Frustum Culling opierający się o odrzucanie elementów sceny, których korze- nie (ang. root-node) nie znajdują się wewnątrz bryły widzenia. Drugą z użytych metod jest biblioteczna optymalizacja glEnable(GL CULL FACE), która odrzuca z potoku ren- derowania ścianki, których wektory normalne są równoległe do wektora widoku kamery. Z przeprowadzonych badań wynika, iż zastosowanie tych metod daje wzrost wydajności rzędu 50 − 150% (wykres 4.3), co jest wynikiem zadowalającym. W celu zwiększenia wydajności aplikacji na tym polu zastosować można dokładniejszą metodę Frustum Culling’u, opierającą się o wybór poszczególnych prymitywów z drzewa hierarchii oraz metodę odrzucania obszarów zasłoniętych (ang. Occulsion Culling). Metoda Occulsion Culling polega na odrzucaniu z potoku renderującego geometrii, która zasłonięta jest przez obiekty znajdujące się bliżej kamery. Jednakże określenie dokładnego obszaru zasłanianego przez obiekty jest bardzo skomplikowane zarówno ob- liczeniowo jak i algorytmicznie i dlatego metoda ta została pominięta w implementacji. Inną popularną metodą zmniejszania ilości geometrii będącej w potoku renderowania jest optymalizacja Level Of Detail, opierająca się o podstawianie geometrii danego obiektu o różnym stopniu skomplikowania w zależności od odległości od obserwatora. Metoda ta wymaga jednak przygotowania kilku wersji danej sceny przez grafika i podmienianie ich w czasie rzeczywistym, co zwiększa znacznie ilość czasu jaką należy przeznaczyć na przygotowanie danych oraz ilość pamięci potrzebnej na przechowanie geometrii, dlatego też metoda ta została zarzucona. 5.1.4 Efekty specjalne, Pixel Shading Realizm sceny można podnieść znacznie za pomocą zastosowania technik związanych z użyciem jednostek Pixel i Vertex Shader. Dzięki użyciu tych programowalnych i auto- nomicznych jednostek, projektanci są w stanie tworzyć filtry obejmujące swym działaniem całą wizualizowaną scenę. Możliwymi zastosowaniami tej techniki jest oświetlanie sceny za pomocą map HDR, tworzenie efektów imitujących niedoskonałości ludzkiego oka jak cho- ciażby brak umiejętności postrzegania obszarów o znacznej dynamice jasności obrazujący się świeceniem obszarów o wysokiej dynamice na małej przestrzeni. Innym zastosowaniem jest automatyczne tworzenie tekstur przejścia ze zdefiniowanych wcześniej zestawów tek- stur w zależności od przyjętych kryteriów przejścia, jak chociażby wysokość danego ob- szaru. 54
  • 56. 5.1.5 Wirtualny realizm - CAVE i dźwięk Kolejnym krokiem rozwoju środowiska powino być zaimplementowanie dźwięku prze- strzennego oraz punktowych i kierunkowych źródeł dźwięku. Zastosowanie dźwięku sur- round ma kluczowe znaczenie dla podniesienia realizmu wizualizowanej sceny. Użytkownik jest w stanie uwierzyć, iż znajduje się wewnątrz prezentowanego środowiska. Udźwięko- wione środowiska dostępne są na rynku od kilku lat, głównie w formie gier komputerowych i zdobywają coraz większą popularność. Ostatnim, najbardziej rozwojowym krokiem wizualizacji i tworzenia wirtualnego śro- dowiska jest przeniesienie go w rzeczywistość wirtualną. Zabiegu tego można dokonać poprzez wyposażenie go w specjalny hełm z wyświetlaczem ciekłokrystalicznym oraz czujnikiem ruchu, lub też poprzez wejście do systemu CAVE. System CAVE używany w labolatorium SARA w Holandii oraz na uniwersytecie w Helsinkach, jak i w innych placówkach naukowych jest pomieszczeniem, w którym obraz rysowany jest na trzech ścianach i podłodze. Użytkownik wyposażony w specjalne okulary oraz manipulator może poruszać się w tym środowisku w sposób dowolny. Podstawę oprogramowania systemu CAVE stanowi biblioteka OpenGL. System ten wyposażony jest także w system dźwięku przestrzennego podnoszącego znacznie stopień realizmu prezentowanego środowiska. 55
  • 57. Bibliografia [Cor04] Valve Corporation. Valve Source Engine Features. Valve Corporation, 2004. http://www.valvesoftware.com/sourcelicense/enginefeatures.htm. [Inc05] VRcontext Inc. Walkinside Product Features Page, 2005. http://www.walkinside.com/walkinside/virtual reality windows.htm. [Jam90] Arvo James. A simple method for box-sphere intersection testing. In Andrew S. Glassner, editor, Graphic Gems. Academic Press, 1990. [JDF01] Andries van Dam James D. Foley. Wprowadzenie do grafiki komputerowej., chapter Dązenie do wizualnego realizmu, pages 530,531. Wydawnictwo Naukowo Techniczne, 2001. [Kos04] Krystian Kostecki. Implementacja gier rpg z wykorzystaniem biblioteki gl4java. Master’s thesis, Wydział Informatyki Politechniki Szczecińskiej, 2004. [TAM02] Eric Haines Thomas Akenine-Moller. Real-Time Rendering. A.K Peters, second edition, 2002. [vdB98] Gino van den Bergen. Efficient collision detection of complex deformable models using aabb trees. Technical report, Department of Mathematics and Computing Science Eindhoven University of Technology, November 1998. [Wei99] Eric W. Weisstein. Rotation formula. Technical report, Mathworld, 1999. http://mathworld.wolfram.com/RotationFormula.html. 56
  • 58. Dodatek A Dodatek A.1 Specyfikacja formatu plikow .n3d. Ponizej zaprezentowana jest struktura autorskiego formatu n3d, pozwalającego na za- pis geometrii wraz z dwoma kanałami mapowania UV oraz wektorami normalnymi. float nVerts; // (4 bajty) liczba wierzchołków float nFaces; // (4 bajty) liczba scianek bryły float nTVChan3; // (4 bajty) liczba wierzchołków kanału mapowania UV dla LightMappingu float nTFChan3; // (4 bajty) liczba ścianek kanału mapowania UV dla LightMappingu float nTVChan3; // (4 bajty) liczba wierzchołków kanału mapowania UV dla tekstur float nTFChan3; // (4 bajty) liczba ścianek kanału mapowania UV dla tekstur nVertex VertexTable; // (4*3*nVerts bajtów) tablica wierzchołków geometrii nVertex FaceTable; // (4*3*nFaces bajtów) tablica ścianek geometrii nVertex TVChan3; // (4*3*nTVChan3 bajtów) tablica wierzchołków dla kanału UV Lightmapy nVertex TFChan3; // (4*3*nTFChan3 bajtów) indeksu wierzchołków dla UV Lightmapy nVertex TVChan3; // (4*3*nTVChan3 bajtów) tablica wierzchołków dla kanału UV tekstur nVertex TFChan3; // (4*3*nTFChan3 bajtów) indeksy wierzchołków dla UV tekstur nVertex NormalTable // (4*3*nFaces*3 bajtów) tablica wektorów normalnych short int MatIdTable // (2*nFaces bajtów) tablica indeksów materiałów A.2 Obsługa środowiska nGine W celu uruchomienia środowiska nGine należy uruchomic program nGine.exe zna- jdujący się w katalogu „/nGine/bin/nGine.exe” dołączonej płyty CD. Zaleca się aby skopiować całość katalogu „/nGine” do katalogu tymczasowego na dysku twardym i przeprowadzić procedurę uruchomienia z tego miejsca aby uniknąć możliwych przesto- jów związanych ze specyfiką napędów optycznych. Opis klawiszy kontrolujących zachowanie środowiska W - ruch kamery do przodu S - ruch kamery do tylu 57
  • 59. A - ruch kamery w lewo D - ruch kamery w prawo F2 - Tryb wyświetlania liści drzewa AABB F3 - Włączenie/Wyłączenie detekcji kolizji F4 - Włączenie/Wyłączenie mgły 58
  • 60. Dodatek B Dodatek B.1 Zawartość dołączonej płyty CD Do pracy została dołączona płyta CD zawierająca niezbędne materiały, o następującej strukturze katalogów : • /nGine - katalog zawierający środowisko nGine – /bin/ - katalog zawierający plik uruchomieniowy – /world/ - katalog zawierający dane geometryczne i tekstury • /source code/ - katalog zawierający kod źródłowy pracy • /reports/ - katalog zawierający zrzuty ekranowe z kolejnych etapów pracy • /latex - katalog zawierający źrodło pracy w języku LATEX – /rys/ - katalog zawierający rysunki użyte w pracy w formacie .eps – /temp/ - katalog zawierający źródła użytych rysunków w formacie .ai • /docs/ - katalog zawierający część użytych w pracy materiałów W katalogu głównym umieszczono tekst pracy w formacie PDF w pliku o nazwie „pd.pdf” oraz plik tekstowy „ZawartoscPlyty.txt” zawierający opis zawartości dołączonej plyty CD. 59