Zadán´ı bakalárské práce - ExtBrain
Zadán´ı bakalárské práce - ExtBrain
Zadán´ı bakalárské práce - ExtBrain
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Zadání bakalářské <strong>práce</strong>
České vysoké učení technické v Praze<br />
Fakulta elektrotechnická<br />
Katedra počítačové grafiky a interakce<br />
Bakalářská <strong>práce</strong><br />
Webová platforma pro interakci uživatelů v 3D<br />
prostoru<br />
Ondřej Psota<br />
Vedoucí <strong>práce</strong>: Ing. Tomáš Novotný<br />
Studijní program: (BN2)Softwarové technologie a management,<br />
Bakalářský<br />
Obor: (2612R062)Web a multimedia<br />
28. května 2012
Poděkování<br />
Rád bych poděkoval svému konzultantovi a vedoucímu <strong>práce</strong> panu Ing. Tomášovi Novotnému<br />
za jeho cenné rady a vstřícný přístup při řešení problémů. Dále bych chtěl rovněž poděkovat<br />
všem, kteří mi byli nápomocni a vytvořili podmínky pro to, abych se své práci mohl plně<br />
věnovat.<br />
iii
Prohlášení<br />
Prohlašuji, že jsem práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém<br />
seznamu.<br />
Nemám závažný důvod proti užití tohoto školního díla ve smyslu §60 Zákona č. 121/2000<br />
Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých<br />
zákonů (autorský zákon).<br />
V Praze dne 28. května 2012 ...............................................................................................<br />
v
Abstract<br />
This work deals with creating a web platform using the WebGl technology. The web platform<br />
should be designed with regard to its future development. Objectives and requirements of<br />
the web platform are determined. There is a description of selected technologies enabling<br />
to display 3D graphics in a web browser and the current solution in the form of WebGl<br />
frameworks is evaluated. The procedure is that the solution is analyzed and proposed with<br />
regard to the requirements based on the needs of the resulting application where the user is<br />
located in the space environment with asteroids and compete with other users.<br />
The test did not reveal any significant shortcomings of the application. The application<br />
mostly appeared to be stable. Problems have been resolved with the recording of objects in<br />
the scene. Basic collisions, physics, network communication and many more features were<br />
implemented. A good basis was created on which it could be built in the future. Some gaps<br />
could be found in the scene lighting and some other imperfections.<br />
Abstrakt<br />
Tato <strong>práce</strong> se zabývá tvorbou webové platformy v technologii WebGl, která by měla být<br />
navržena s ohledem na její budoucí vývoj. Jsou stanoveny cíle a požadavky na webovou<br />
platformu. Dochází k popisu vybraných technologií umožňujících zobrazení 3D grafiky ve<br />
webovém prohlížeči a hodnotí se stávající řešení v podobě WebGl frameworků. Postup je<br />
takový, že se analyzuje a navrhuje řešení s ohledem na požadavky, které vycházejí z potřeb<br />
výsledné aplikace, kde se uživatel nachází v prostředí vesmíru s asteroidy a závodí s jinými<br />
uživateli.<br />
Test neobjevil významné nedostatky aplikace, která se vesměs jevila jako stabilní. Byly<br />
vyřešeny problémy s nahráváním objektů do scény, naimplementovány základní kolize, fyzika,<br />
sít’ová komunikace a mnoho dalších. Podařilo se vytvořit dobrý základ, na kterém lze v<br />
budoucnosti stavět. Určité mezery lze najít v osvětlení scény a některých nedokonalostech.<br />
vii
viii
Obsah<br />
1 Úvod 1<br />
2 Popis problému 2<br />
2.1 Cíl <strong>práce</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />
2.2 Požadavky na ukázkovou aplikaci . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />
2.3 Požadavky na webovou platformu . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />
3 Popis vybraných technologií 4<br />
3.1 Technologie pro zobrazení 3D grafiky ve webovém prohlížeči . . . . . . . . . . 4<br />
3.1.1 VRML a X3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
3.1.2 Flash (Stage 3D) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
3.1.3 Unity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
3.2 Technologie WebGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
3.2.1 Specifikace API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
3.2.2 Názorná ukázka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
3.2.3 Výsledek názorné ukázky . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
3.3 Technologie WebSockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
3.3.1 WebSocket protokol . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
3.3.2 Použití API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
ix
4 Analýza a návrh řešení 10<br />
4.1 Stručný přehled WebGl frameworků . . . . . . . . . . . . . . . . . . . . . . . 10<br />
4.2 Architektura platformy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
4.2.1 Inspirace pro návrh . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
4.2.2 Privátní proměnné . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
4.2.3 Přehledový diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
4.2.4 Objekt GameObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
4.2.5 Komponenty objektu GameObject . . . . . . . . . . . . . . . . . . . . 13<br />
4.2.6 Nahrání dat do scény . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />
4.2.7 VirtualWorld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
4.2.8 Shadery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />
4.2.9 Vstup z klávesnice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
4.3 Obalová tělesa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
4.3.1 Obalová koule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />
4.3.2 OBB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />
4.3.3 AABB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
4.3.4 Testy kolizí mezi tělesy . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
4.3.5 Objekt Contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26<br />
4.4 Základní fyzikální systém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
4.4.1 Integrační metoda rigidního tělesa . . . . . . . . . . . . . . . . . . . . 27<br />
4.4.2 Pružina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />
4.4.3 Registr působících sil . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29<br />
4.5 Rozdělení prostoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29<br />
4.5.1 Mřížky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.5.2 Stromy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.5.3 Řadící mechanismy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />
5 Realizace 34<br />
5.1 Herní smyčka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34<br />
5.1.1 RequestAnimationFrame API . . . . . . . . . . . . . . . . . . . . . . . 34<br />
5.1.2 Použití RequestAnimationFrame API v aplikaci . . . . . . . . . . . . . 36<br />
5.2 Průhlednost objektů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.2.1 Z-buffer a jeho nevýhody . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
x
5.2.2 Vykreslení průhledných objektů . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.3 Viditelnost objektů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />
5.3.1 View frustum culling . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />
5.3.2 Backface culling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
5.4 Multiplayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
5.4.1 Známé architektury . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
5.4.2 Implementace multiplayeru v ukázkové aplikaci . . . . . . . . . . . . . 40<br />
5.5 Generátor asteroidů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />
5.5.1 Algoritmus pro generování asteroidů . . . . . . . . . . . . . . . . . . . 42<br />
5.5.2 Problém s generováním více asteroidů . . . . . . . . . . . . . . . . . . 43<br />
5.6 Laser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44<br />
5.6.1 Billboarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44<br />
5.6.2 Nejpoužívanější typy billboardů . . . . . . . . . . . . . . . . . . . . . . 45<br />
5.6.3 Tvorba laseru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />
6 Testování 47<br />
6.1 Uživatelský test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />
6.2 Test aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />
7 Závěr 49<br />
A Balíky platformy 54<br />
B Celkový UML diagram 56<br />
C Uživatelská příručka 58<br />
C.0.1 Ovládání . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61<br />
C.0.2 Hra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
D Obsah přiloženého CD 64<br />
xi
xii
Seznam obrázků<br />
3.1 Výsledný čtverec na černém pozadí . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
4.1 GameObject a možné komponenty . . . . . . . . . . . . . . . . . . . . . . . . 13<br />
4.2 Obrázek znázorňuje objekty, které mezi sebou komunikují, pokud nastane<br />
změna v komponentě Transform a nebo v objektu GameObject. . . . . . . . 14<br />
4.3 Komponenta NetworkView a všechny důležité třídy se kterými spolupracuje. 16<br />
4.4 Obrázek znázorňuje načtení geometrických objektů do scény včetně materiálů<br />
a textur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />
4.5 Mesh renderer, přiřazený mesh, buffery a materiály . . . . . . . . . . . . . . 19<br />
4.6 Objekt VirtualWorld se všemi objekty, na které si drží referenci. . . . . . . . 20<br />
4.7 Všechny objekty a konstruktory, které v platformě mají na starosti shadery. . 21<br />
4.8 Objekt Input s přidruženými objekty . . . . . . . . . . . . . . . . . . . . . . . 22<br />
4.9 Nejpoužívanější obalová tělesa. Převzato z [13] . . . . . . . . . . . . . . . . . 23<br />
4.10 Nalezený OBB ve 2D. Převzato z [15] . . . . . . . . . . . . . . . . . . . . . . 25<br />
4.11 Ukázka kolize OBB s koulí. Převzato z [12] . . . . . . . . . . . . . . . . . . . 26<br />
4.12 (a) Buňky jsou moc malé. (b) Buňky jsou zbytečně velké. (c) Buňky jsou velké<br />
s ohledem na velikost objektu. (d) Buňky jsou moc velké a zároveň moc malé.<br />
Převzato z [13] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.13<br />
Číslování jednotlivých potomků stromu. Převzato z [13] . . . . . . . . . . . . 31<br />
4.14 Minimální a maximální body jednotlivých AABB v dané ose jsou seřazeny dle<br />
velikosti. Převzato z [13] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />
4.15 Na obrázku vidíme objekty, které se nacházejí kousek od sebe v jedné ose.<br />
Pouze malý pohyb objektu může způsobit, že se hodnota uložená v seznamu<br />
posune o mnoho pozic. Převzato z [13] . . . . . . . . . . . . . . . . . . . . . . 32<br />
5.1 Rozdíl ve výkonu mezi setTimeout a RequestAnimationFrame API. Převzato<br />
z [18] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.2 Některé verze prohlížečů implementují API již nějakou dobu, jiné prohlížeče<br />
naopak API zatím ignorují a nebo ho připravují v budoucích verzích. Převzato<br />
z [19] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
5.3 a) Obrázek znázorňuje chyby ve vykreslení, pokud nejsou průhledné objekty<br />
seřazeny. b) Průhledné objekty jsou seřazeny. . . . . . . . . . . . . . . . . . . 38<br />
5.4 a) Počáteční koule rozpůlená rovinou. b) Koule je rozpůlena jinou rovinou.<br />
Vertexy před rovinou se posunuly směrem ke středu a vertexy za rovinou<br />
směrem od středu. c) Výsledek po několika iteracích. . . . . . . . . . . . . . . 43<br />
5.5 Billboardy orientované směrem k pozorovacímu bodu . . . . . . . . . . . . . 45<br />
5.6 Laser z ukázkové aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46<br />
xiii
A.1 Balíčky, které strukturují zdrojový kód . . . . . . . . . . . . . . . . . . . . . . 54<br />
B.1 Celkový uml diagram, který obsahuje všechny důležité třídy (konstruktory) . 56<br />
C.1<br />
Úvodní obrazovka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59<br />
C.2 a) Okno, které se objeví po stisknutí klávesy S v úvodním okně. b) Okno<br />
informující o stavu scény po jejím spuštění. Pomocí tlačítka Uložit scénu lze<br />
uložit aktuální stav scény. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59<br />
C.3 a) Okno, kde se uživatel může připojit jako nový hráč. b) Okno, kde si uživatel<br />
může vybrat ze seznamu odpojených hráčů a přebrat jeho vesmírnou lod’. . . 60<br />
C.4 Okno se scénou. Vlevo nahoře je vidět vzdálenost uživatele od středu, rychlost<br />
a uplynulý čas od průletu první brány. Vpravo nahoře se objevují informace<br />
o nově připojených nebo odpojených hráčích. . . . . . . . . . . . . . . . . . . 61<br />
D.1 Výpis souboru readme.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64<br />
xiv
1 Úvod<br />
Současný technologický vývoj umožňuje vytvářet aplikace spustitelné ve webovém prostředí,<br />
které se svým vzhledem a chováním blíží desktopovým aplikacím. Přesně takovou technologii<br />
představuje WebGl[6], pomocí které lze docílit velice zajímavých výsledků v oblasti počítačové<br />
grafiky. Velkou výhodou technologie WebGl je možnost vytváření vlastních shaderů, s<br />
jejichž pomocí lze docílit efektů, které jsme si dříve ve webovém prohlížeči nedokázali ani<br />
představit. I přesto, že se objevují konkurenční technologie, které jsou schopné dosáhnout<br />
obdobných výsledků, má WebGl tu výhodu, že případnou aplikaci lze spustit, aniž by bylo<br />
nutné instalovat doplněk do webových prohlížečů. Jedná se o novější technologii, a proto není<br />
podporována jejich staršími verzemi. Bohužel podpora Internetu Exploreru zatím chybí.<br />
Cílem této bakalářské <strong>práce</strong> je navrhnout a naimplementovat webovou platformu umožňující<br />
interakci uživatelů v 3D prostoru pomocí WebGl, které vychází z OpenGl ES 2.0[5].<br />
Implementované vlastnosti dané platformy budou demonstrovány na ukázkové aplikaci. Koncový<br />
uživatel bude moci ovládat vesmírné plavidlo a pohybovat se mezi asteroidy či jinými<br />
objekty. Serverová komponenta umožní vzájemnou interakci uživatelů a sdílení jejich scény.<br />
Aby si uživatelé mohli vyzkoušet ovládání plavidla a celkově si vychutnat možnosti vytvořeného<br />
virtuálního prostředí, bude pro ně připraven jednoduchý závod. Kontrolní body ve<br />
formě hvězdných bran zajistí hladký průběh závodu. Plavidla budou moci kolidovat s okolními<br />
předměty a reagovat na kolizi. Vývoj platformy se bude odvíjet s ohledem na požadavky<br />
ukázkové aplikace.<br />
V kapitole 2 se definují požadavky na výslednou platformu včetně ukázkové aplikace.<br />
Kapitola 3 se zabývá popisem technologií, které se používají k zobrazování 3D grafiky ve<br />
webovém prohlížeči. Především jde o VRML, Stage3D a Unity. Dále se zaměřuje na základní<br />
stavební prvky WebGl a přibližuje technologii WebSockets[8]. V kapitole 4 se provádí analýza<br />
možností řešení a dochází k návrhu jednotlivých prvků platformy. Kapitola 5 popisuje<br />
detailněji zajímavá či neobvyklá řešení, která se týkají vývoje ukázkové aplikace na navržené<br />
platformě. V kapitole 6 jsou shrnuty poznatky, které vyplynuly z testování aplikace.<br />
1
2 Popis problému<br />
V podkapitole 2.1 je obecně popsán cíl <strong>práce</strong> a možnosti využití vytvořené platformy. V<br />
podkapitolách 2.2 a 2.3 se kladou požadavky, které by měly výsledná platforma a ukázková<br />
aplikace splňovat.<br />
2.1 Cíl <strong>práce</strong><br />
Cílem <strong>práce</strong> je navrhnout a naimplementovat základ webové platformy pro interakci uživatelů<br />
v 3D prostoru pomocí technologie WebGl. Očekává se, že tato platforma bude nadále<br />
rozvíjena a postupně rozšiřována. Ve výsledku by mohla například sloužit jako součást či<br />
doplněk výuky, jejíž pomocí by studentům byla názorně předváděna funkce určitých zařízení.<br />
Pohyb pístů motoru by si dokázali ihned lépe představit. Samozřejmě se najde širší<br />
oblast působnosti. Jak již bylo zmíněno v úvodu 1, vlastnosti platformy budou demonstrovány<br />
na ukázkové aplikaci v podobě hry z prostředí vesmíru. Platforma bude založena na<br />
rozšířené specifikaci jazyka HTML, čímž je jazyk HTML5[1]. Technologie WebGl využívá<br />
pro vykreslování plátno canvas, které je součástí zmíněného jazyka . Z této skutečnosti vyplývá,<br />
že zvolená technologie nebude dostupná v prohlížečích, které nepodporují HTML5.<br />
Aktuální verze nejrozšířenějších prohlížečů již tuto specifikaci podporují. Všechny prohlížeče<br />
jako je Firefox, Chrome, Opera, či Safari podporují ve standardním nebo editačním módu<br />
také technologii WebGl. Bohužel jeden významný hráč na trhu v seznamu zatím chybí a tím<br />
je Internet Explorer. Ani jeho verze číslo 9 si s touto technologií neporadí, a to v momentě,<br />
kdy Khronos Group standardizovalo grafické rozhraní WebGl 1.0.<br />
2.2 Požadavky na ukázkovou aplikaci<br />
Závod bude individuální časovka, která se pro jedince spustí průletem první brány. Závodit<br />
bude moci i více závodníků najednou, ale každému se čas měří od prvního průletu. Každý<br />
závodník vidí zvýrazněnou příští bránu a méně zvýrazněné příští brány ostatních připojených<br />
účastníků. Pokud nemá bránu v zorném poli, vidí po straně obrazovky šipku ukazující<br />
nejbližší vzdálenost. Mapu bude možné stavět z lodi, čímž se otevře prostor ke stavbě zajímavých<br />
map. Hráč bude moci po stisku klávesy nechat vygenerovat asteroid nebo bránu.<br />
Z důvodu zpětné vazby bude vygenerovaný asteroid poloprůhledný a nebude kolidovat. Po<br />
opuštění prostoru všemi hráči se zhmotní. Asteroidy půjde odstřelovat laserem, který když<br />
zasáhne asteroid, tak dojde k jeho zmizení. Obdobným způsobem půjde přidávat a odebírat<br />
brány. Laser ostatním hráčům nebude vadit. Pokud během závodu někdo zruší aktuální<br />
bránu, najde se další brána s vyšším číslem. Vytvořený svět i s pozicemi hráčů půjde uložit<br />
do souboru, odkud bude moci být znovu načten. Poslední pozice hráče bude uložená na<br />
serveru. Pokud se hráč odpojí, jeho lod’ se zastaví a zůstane pro ostatní lodě viditelná ve<br />
vesmíru. Při připojení se hráči zobrazí seznam odpojených hráčů a hráč si vybere, za koho<br />
se připojí, nebo zadá nové jméno do editu a vytvoří se tím nový hráč.<br />
2
2.3 Požadavky na webovou platformu<br />
Požadavky na webovou platformu byly již částečně zmíněny v úvodu 1 <strong>práce</strong>. Ve své podstatě<br />
se jedná o základní návrh a implementaci herního enginu. Samotné téma herních enginů je<br />
natolik rozsáhlé a složité, že bude nutné si vymezit určitý okruh vlastností, které by výsledná<br />
platforma nebo ukázková aplikace měli splňovat:<br />
ˆ Platforma by měla mít určitou strukturu s důrazem na její snadnou rozšiřitelnost.<br />
ˆ Základem každého enginu jsou 3D modely, bude tedy nutné vyřešit jejich nahrávání<br />
do scény.<br />
ˆ Na jednotlivé objekty by měly být aplikovatelné různé shadery podle potřeby.<br />
ˆ Objekty ve scéně budou uspořádány ve stromové struktuře.<br />
ˆ Na jednotlivé uzly stromu bude možné aplikovat známé transformace rotace, posunutí<br />
a zvětšení, popřípadě jiné vlastnosti.<br />
ˆ Jelikož by měly objekty ve scéně mezi sebou interagovat, tak je zapotřebí vytvořit<br />
základ fyzikálního systému a s tím související detektor kolizí.<br />
ˆ S předešlým bodem přímo souvisí různá obalová tělesa objektů ve scéně, například<br />
koule, orientovaný kvádr atd.<br />
ˆ Pohyb kamery by měl být dynamický, kamera by se neměla nacházet pouze na jednom<br />
místě za objektem.<br />
ˆ Scéna by měla být rozdělena do určitých sekcí. Objekty, které se nenachází ve viditelném<br />
prostoru, by neměly být předány grafické kartě k renderování.<br />
ˆ Ve scéně se budou nacházet průhledné objekty, je tedy nutné vyřešit problémy týkající<br />
se blendingu a z - bufferu.<br />
ˆ Pro asteroidy je třeba vytvořit generátor, aby se docílilo různého vzhledu asteroidů.<br />
ˆ Je třeba vyřešit problémy týkající se multiplayeru a vybrat konkrétní architekturu jako<br />
je klient - server nebo například peer - to - peer.<br />
Serverová komponenta je tvořena javovským Jetty serverem. Bohužel to má tu nevýhodu, že<br />
nebude moci být použit na aplikační logiku výsledného programu. Kód pro WebGl je totiž<br />
psán v javascriptu. Jetty server byl původně vybrán, protože je malý a podporuje technologii<br />
WebSockets, která bude použita pro vzájemnou komunikaci uživatelů. API WebGl je<br />
oproti původnímu OpenGl hodně redukované. Základ tvoří primitiva, buffery a programovatelná<br />
grafická část. Chybí zcela objekty Begin, End, v API se nenachází žádné metody<br />
pro výpočet matic, kvaternionů, není zde žádná metoda lookAt. Ve WebGl není třeba hledat<br />
žádnou podporu pro světla, materiály, žádná tam totiž není, vše je nutné udělat pomocí<br />
shaderů. Z toho vyplývá tedy to, že určité vlastnosti musejí být doplněny různými externími<br />
javascriptovskými knihovnami a nebo vlastní implementací.<br />
3
3 Popis vybraných technologií<br />
V následující podkapitole 3.1 jsou stručně popsány známé technologie pro zobrazování 3D<br />
grafiky ve webovém prohlížeči. Další podkapitola 3.2 se zaměřuje na WebGl a nastiňuje<br />
princip tvorby pomocí této technologie. Poslední podkapitola 3.3 přibližuje technologii Web-<br />
Sockets pro sít’ovou komunikaci.<br />
3.1 Technologie pro zobrazení 3D grafiky ve webovém prohlížeči<br />
WebGl není jediná technologie, která umožňuje zobrazení 3D grafiky pomocí webového prohlížeče.<br />
Podkapitola 3.1.1 se zaměřuje spíše na starší technologii VRML. V podkapitole 3.1.2<br />
je stručně popsána poměrné nová technologie Stage3D. Podkapitola 3.1.3 se zaměřuje na<br />
kompletní vývojový nástroj Unity.<br />
3.1.1 VRML a X3D<br />
Již v roce 1997 byla publikována norma pro popis virtuálního prostředí pod jménem VRML[2].<br />
Jedná se o jazyk, který je zaměřen na prezentaci virtuální reality ve webovém prohlížeči a<br />
zároveň jde o formát souborů. Scéna je organizována do stromové struktury. Tělesa a další<br />
objekty jsou popsány pomocí hraniční reprezentace. Na jejich plošky je možné mapovat textury.<br />
Scéna v sobě zahrnuje běžně používané prvky jako jsou světelné zdroje, předdefinované<br />
polohy, charakteristiky kamer atd. VRML není žádný programovací jazyk, neobsahuje žádné<br />
programovací konstrukce. Funkční vlastnosti nových objektů lze popsat jazyky Java a JavaScript.<br />
Pomocí různých prostředků lze definovat animace objektů a interakci s uživatelem.<br />
Klíčové hodnoty založené na lineární interpolaci definují výslednou animaci. Pro interakci<br />
slouží různé senzory, které reagují na různé aktivity avatara. Může se jednat o kliknutí myši,<br />
o průchod určitým místem atd. Pro interakci se využívá principu událostí. VRML postupně<br />
přestalo dostačovat současným požadavkům, což se snaží napravit formát X3D, který doplňuje<br />
nové vlastnosti.<br />
3.1.2 Flash (Stage 3D)<br />
S vydáním Flashové přehrávače číslo 11 se otevřely nové možnosti použití, které dřívější<br />
verze neposkytovaly. Nový Flash již podporuje rendering pomocí 3D hardwarové akcelerace.<br />
Dřívější verze Flash se spoléhaly pouze CPU. Adobe s touto verzí vydalo API Stage3D[3],<br />
které využívá všech schopností GPU přímo z Flashe, což rozšiřuje oblast působnosti tohoto<br />
velice rozšířeného přehrávače. Již bude možné vytvářet různé efekty pomocí shaderů. Scéna<br />
se pouze připraví(vertexy, transformační matice, atd ) a všechna potřebná data se pošlou do<br />
GPU, které data postupně zpracuje v několika fázích. Mimo jiné se jedná o velice podobný<br />
princip, který využívá právě WebGl.<br />
4
3.1.3 Unity<br />
Unity 3D[4] je herní vývojový nástroj, který poskytuje spoustu možností pro vývoj interaktivních<br />
3D aplikací. Nejedná se pouze o grafické API, ale o kompletní vývojové prostředí.<br />
Výsledné výtvory mohou být spuštěny na mnoha známých platformách. Od Windows, Mac,<br />
XBox360 až po mobilní Android. Navíc existuje doplněk, pomocí kterého je možné výsledný<br />
projekt spustit ve webovém prohlížeči. Aktuální verze 3.5 podporuje export do SWF formátu,<br />
který je doménou Adobe Flash. Hlavním stavebním prvkem je GameObject, který se může<br />
skládat z mnoha komponent od fyziky po různá světla a zvuky. Objektům je možné přiřadit<br />
komponentu script pomocí, které se tvoří hlavní logika a ovládání hry. Unity podporuje tři<br />
skriptovací jazyky. Javascript, C# a Boo, který vychází z Pythonu. Nahrávaní vytvořených<br />
modelů ze známých modelovacích nástrojů je otázkou několika málo kliknutí. Jedná se celkově<br />
o propracovanou platformu s vývojovým prostředím, pomocí kterého je možné vytvářet<br />
opravdu pohledné scény a využít tím možnosti dnešních grafických karet. Unity například<br />
podporuje Nvidia PhysX.<br />
3.2 Technologie WebGL<br />
Několik následujících řádků se bude týkat pouze technologie WebGl. První podkapitola 3.2.1<br />
pouze nastiňuje konkrétní specifikaci. V podkapitolách 3.2.2 a 3.2.3 je ukázán základní princip<br />
tvorby aplikací pomocí webGl.<br />
3.2.1 Specifikace API<br />
Technologie WebGl byla již částečně popsána v kapitole 1 a 2.1. Kompletní specifikace<br />
OpenGl ES 2.0 [5] lépe popisuje všechny možnosti tohoto API, které je určeno pro vestavěné<br />
systémy, mobilní telefony, konzole, spotřebiče či auta. Specifikace WebGl 1.0[6] vychází z<br />
OpengGl ES 2.0, na kterou se velmi často odvolává a případně popisuje rozdíly mezi těmito<br />
API.<br />
3.2.2 Názorná ukázka<br />
Na WebGl bude postavena výsledná platforma, a proto následuje velice jednoduchá ukázka,<br />
která se snaží nastínit princip tvorby aplikací pomocí WebGl.[7]<br />
Vertex shader a Fragment shader - Bloky vertex shaderů a pixel shaderů jsou napsány<br />
v jazyku GLSL, který vychází ze syntaxe jazyka C. Vertex shader v tomto případě<br />
pouze vynásobí každý vertex projekční a modelovou maticí. V ukázce jsou 2 typy proměnných.<br />
Uniform proměnné se v průběhu provádění nemění, matice mají tedy stále stejnou<br />
hodnotu. Naproti tomu proměnné Attribute se neustále mění. Vertex shader je totiž spuštěn<br />
pro každý vertex zvlášt’. Fragment shader nepřijímá žádnou proměnnou z vertex shaderu a<br />
pouze nastaví vykreslenému objektu konkrétní barvu.<br />
var vertexSh = ” a t t r i b u t e vec3 poziceVertexu ;”+<br />
5
”\ } ”;<br />
”uniform mat4 p r o j e k c n i M a t i c e ;”+<br />
”uniform mat4 MMatice ;”+<br />
”void main ( void ) \{”+<br />
” g l P o s i t i o n = p r o j e k c n i M a t i c e * MMatice<br />
* vec4 ( poziceVertexu , 1 . 0 ) ; ”+<br />
var fragmentSh = ” p r e c i s i o n mediump f l o a t ;”+<br />
”void main ( void ) {”+<br />
”gl FragColor = vec4 ( 0 . 5 , 0 . 5 , 0 . 5 , 1 . 0 ) ; ”+<br />
”} ”;<br />
Kompilace programu - Následující kód získá WebGl kontext, pomocí kterého je možné<br />
přistupovat k funkcím jádra WebGl. Dále se provede kompilace shaderů a vlastního programu.<br />
var canvas = document . getElementById ( ” platno ”) ;<br />
var g l = canvas . getContext ( ”moz−webgl ”) ;<br />
var vertexShader = g l . createShader ( g l .VERTEX SHADER) ;<br />
g l . shaderSource ( vertexShader , vertexSh ) ;<br />
g l . compileShader ( vertexShader ) ;<br />
var fragmentShader = g l . createShader ( g l .FRAGMENT SHADER) ;<br />
g l . shaderSource ( fragmentShader , fragmentSh ) ;<br />
g l . compileShader ( fragmentShader ) ;<br />
var program = g l . createProgram ( ) ;<br />
g l . attachShader ( program , vertexShader ) ;<br />
g l . attachShader ( program , fragmentShader ) ;<br />
g l . linkProgram ( program ) ;<br />
g l . useProgram ( program ) ;<br />
6
Tvorba a plnění bufferů - Proto, aby bylo možné vykreslit daný objekt, musí mít grafická<br />
karta k dispozici potřebná data. K těmto účelům slouží buffery, které jsou po vytvoření<br />
uloženy v paměti grafické karty. Buffery jsou pro 3D modely ideální volbou. Array buffer<br />
slouží v tomto případě k uložení pozic vertexů a Element array buffer uchovává indexy, které<br />
odkazují na konkrétní vertexy. Metoda gl.createBuffer() vytvoří nový buffer a gl.bindBuffer()<br />
určuje aktuálně používaný buffer. \<br />
v e r t e x B u f f e r = g l . c r e a t e B u f f e r ( ) ;<br />
g l . bindBuffer ( g l .ARRAY BUFFER, v e r t e x B u f f e r ) ;<br />
vertexy = [ 1 . 0 , 1 . 0 , 0 . 0 , −1.0 , 1 . 0 , 0 . 0 , 1 . 0 ,<br />
−1.0 , 0 . 0 , −1.0 , −1.0 , 0 . 0 ] ;<br />
g l . bufferData ( g l .ARRAY BUFFER,<br />
new Float32Array ( vertexy ) , g l .STATIC DRAW) ;<br />
v e r t e x B u f f e r . v e l i k o s t P o l o z k y = 3 ;<br />
v e r t e x B u f f e r . pocetPolozek = 4 ;<br />
i n d e x B u f f e r = g l . c r e a t e B u f f e r ( ) ;<br />
g l . bindBuffer ( g l .ELEMENT ARRAY BUFFER, i n d e x B u f f e r ) ;<br />
var indexy = [ 0 , 1 , 2 , 1 , 3 , 2 ] ;<br />
g l . bufferData ( g l .ELEMENT ARRAY BUFFER,<br />
new Uint16Array ( indexy ) , g l .STATIC DRAW) ;<br />
i n d e x B u f f e r . pocetPolozek = 6 ;<br />
program . v e r t e x A t t r i b u t e = g l . g e t A t t r i b L o c a t i o n (<br />
program , ”poziceVertexu ”) ;<br />
g l . enableVertexAttribArray ( program . v e r t e x A t t r i b u t e ) ;<br />
Nastavení Uniform proměnných<br />
- Na následujících několika řádcích se nejprve nastaví<br />
hodnoty matic a následně se přiřadí k Uniform proměnným použitých v shaderech.<br />
var p r o j e k c n i M a t i c e = mat4 . c r e a t e ( ) ;<br />
var MMatice = mat4 . i d e n t i t y ( ) ;<br />
mat4 . t r a n s l a t e ( MMatice , [ 0 , 0 . 0 , − 7 . 0 ] ) ;<br />
g l . viewport ( 0 , 0 , 400 , 4 0 0 ) ;<br />
mat4 . p e r s p e c t i v e (45 , 400 / 400 , 0 . 1 , 1 0 0 . 0 , p r o j e k c n i M a t i c e ) ;<br />
program . l o k a c e P r o j e k c n i M a t i c e = g l . getUniformLocation (<br />
program , ”p r o j e k c n i M a t i c e ”) ;<br />
g l . uniformMatrix4fv ( program . lokaceProjekcniMatice ,<br />
f a l s e , p r o j e k c n i M a t i c e ) ;<br />
program . lokaceMMatice = g l . getUniformLocation (<br />
program , ”MMatice ”) ;<br />
g l . uniformMatrix4fv ( program . lokaceMMatice , f a l s e , MMatice ) ;<br />
7
Vykreslení objektu<br />
- V posledním kroku se určí buffery, se kterými má grafická karta aktuálně<br />
pracovat. Zavoláním metody drawElements dojde k vykreslení objektu na obrazovku.<br />
g l . c l e a r C o l o r ( 0 . 0 , 0 . 0 , 0 . 0 , 1 . 0 ) ;<br />
g l . c l e a r ( g l .COLOR BUFFER BIT ) ;<br />
g l . bindBuffer ( g l .ARRAY BUFFER, v e r t e x B u f f e r ) ;<br />
g l . v e r t e x A t t r i b P o i n t e r ( program . vertexAttribute ,<br />
v e r t e x B u f f e r . v e l i k o s t P o l o z k y , g l .FLOAT, f a l s e , 0 0 ) ;<br />
g l . bindBuffer ( g l .ELEMENT ARRAY BUFFER, i n d e x B u f f e r ) ;<br />
g l . drawElements ( g l .TRIANGLES, i n d e x B u f f e r . pocetPolozek ,<br />
g l .UNSIGNED SHORT, 0 ) ;<br />
3.2.3 Výsledek názorné ukázky<br />
V minulé podkapitole 3.2.2 byl popsán postup, jak na obrazovku vykreslit čtverec. Zde je<br />
výsledek snažení:<br />
Obrázek 3.1: Výsledný čtverec na černém pozadí<br />
3.3 Technologie WebSockets<br />
Specifikace technologie WebSocket[8] definuje API, které dovoluje webovým stránkám používat<br />
obousměrnou komunikaci se vzdáleným hostem. Uvádí WebSocket rozhraní a definuje<br />
full duplexní komunikační kanál přes TCP spojení. HTML5 WebSockets výrazně redukuje<br />
objem přenesených dat a zkracuje zpoždění až na 50ms ve srovnání s jinými technologiemi.<br />
Existují sice technologie polling a long-polling, ale ty nemohou websockets konkurovat co<br />
se týče rychlosti. Není již třeba se neustále dotazovat serveru, zda nejsou k dispozici nová<br />
data k přenesení. Na technologii Websockets je unikátní, že dokáže posílat data bez větších<br />
omezení skrz různé firewally a proxy servery.<br />
8
Podkapitola 3.3.1 přibližuje samotný WebSocket protokol. V podkapitole 3.3.2 se rozebírá<br />
základní API této technologie.<br />
3.3.1 WebSocket protokol<br />
WebSocket protokol byl navržen s ohledem na stávající webovou infrastrukturu. Specifikace<br />
protokolu definuje, že je spojení nejprve navázáno pomocí HTTP, což garantuje zpětnou<br />
kompatibilitu se systémy z dob, kdy WebSocket vůbec neexistovalo. Navázání spojení se<br />
provádí v několika krocích:<br />
ˆ Webový prohlížeč odešle na server žádost o přepnutí HTTP protokolu na protokol<br />
WebSocket. Žádost je odeslána v podobě aktualizovací hlavičky.<br />
ˆ Server okamžitě přepne na nový protokol, pokud podporuje technologii WebSocket.<br />
ˆ V tomto bodě dojde k nahrazení protokolu HTTP spojením WebSocket přes vrstvu<br />
TCP/IP. WebSocket spojení používá stejný port jako HTTP(80) a zabezpečené HTTPS(443).<br />
ˆ Je-li spojení úspěšně navázáno, je možné přijímat a odesílat jednotlivé framy mezi<br />
klientem a serverem ve full-duplexním módu. Jak binární, tak textové framy mohou<br />
být přijímány a odesílány najednou v jeden okamžik.<br />
3.3.2 Použití API<br />
Pro navázání spojení stačí vytvořit novou instanci WebSocket a vložit do konstruktoru URL<br />
s předponou ws nebo wss, chceme-li zabazpečené spojení:<br />
var myWebSocket = new WebSocket ( ”ws : / /www. adresa . cz ”) ;<br />
Rozhraní WebSocket definuje několik posluchačů, které jsou zavolány, pokud nastane konkrétní<br />
událost :<br />
myWebSocket . onopen = f u n c t i o n ( evt ) {<br />
a l e r t ( ” S p o j ení navázáno ”) ;<br />
} ;<br />
myWebSocket . onmessage = f u n c t i o n ( evt ) {<br />
a l e r t ( ” P ř i j a t a zpráva : ” + evt . data ) ;<br />
} ;<br />
myWebSocket . o n c l o s e = f u n c t i o n ( evt ) {<br />
a l e r t ( ” S p o j ení ukončeno ”) ;<br />
} ;<br />
Zprávy jsou odesílány pomocí metody send :<br />
myWebSocket . send ( ” Hello ! ”) ;<br />
Ukončení spojení:<br />
myWebSocket . c l o s e ( ) ;<br />
9
4 Analýza a návrh řešení<br />
V následující podkapitole 4.1 jsou rozebrány různé frameworky, které jsou pro WebGl k<br />
dispozici. Podkapitola 4.2 se zaměřuje na architekturu a je zde snaha najít ideální návrh<br />
výsledné platformy. Následující podkapitoly jsou úzce svázány s architekturou platformy.<br />
Konkrétně se v podkapitole 4.3 rozebírají nejpoužívanější obalová tělesa a vybírají se ta,<br />
která následně budou implementována. V podkapitole 4.4 je přiblížen základní fyzikální<br />
systém, který bude použit. Podkapitola 4.5 je sice poslední, ale určitě není méně důležitá.<br />
Zaměřuje se na metody rozdělující scénu a vybírá se ta ideální pro ukázkovou aplikaci.<br />
4.1 Stručný přehled WebGl frameworků<br />
HTML5,CSS3 a WebGl jsou technologie, které mění podobu dnešních webových stránek.[9]<br />
Očekává se, že se tyto technologie budou navzájem doplňovat a vzniknou velice zajímavé<br />
projekty. Takto velké rozsáhlé aplikace není možné tvořit jen pomocí API, které WebGl nabízí.<br />
Je potřeba přidat určité vrstvy, které budou mít na starosti například světla, rendering,<br />
nahrávání objektů, fyziku, dělení scény, stromovou strukturu, atd. Za tímto účelem vznikají<br />
různé frameworky, které implementují tyto vlastnosti a mnoho dalších. Ačkoliv počet<br />
WebGl frameworků neustále roste, tak některé jsou již na konci svého vývoje. V době, kdy<br />
se začala tvořit výsledná platforma nebyly frameworky dobře zdokumentované. Například<br />
framework Three.js vypadal jako dobrý kandidát, ve kterém by se dala platforma naimplementovat,<br />
ale existoval pouze jednoduchý příklad, a to je velice málo. Navíc chyběla podpora<br />
fyziky, částicového systému a pokročilejších funkcí. X3DOM framework vychází z X3D, o<br />
kterém bylo zmíněno v kapitole (3.1.1). Podporuje stromovou strukturu, rozmanité efekty,<br />
shadery, světla, interpolaci, atd. Obecně je nedodělaný a zatím nepoužitelný pro větší projekt,<br />
ale určitou perspektivu před sebou má, protože vychází z X3D. GLGE jako jeden z mála<br />
frameworků disponuje rozsáhlejší dokumentací a zajímavými příklady. Podporuje základní<br />
vlastnosti OpenGl ES. Explicitně chybí fyzikální systém. Třídy nejsou vždy ideálně navrženy<br />
a neuškodilo by rozdělení na více modulů. CubicVR 3D má slibné příklady, velice působivou<br />
dokumentaci a obsahuje základní matematiku (vektory, matice). Používá OPP přístup kombinovaný<br />
s objektovými poli, které se předávají jako parametr. Gettery a settery nejsou díky<br />
tomu potřeba, což udělalo kód přehlednějším. Toto API plně nepodporuje animace, fyziku,<br />
křivky, vlastní renderery. Je naimplementována většina známých světel. Obecně se jedná<br />
o velice zdařile navrženou architekturu od matematických možností po shadery. Podporuje<br />
formát COLADA.<br />
Obecně mají frameworky problém s horší dokumentací, nejsou dodělané a není vždy<br />
jisté, zda jejich vývoj bude dále pokračovat. Zatímco většina frameworků podporuje meshe,<br />
modely, kamery, osvětlení, jeden renderer. Pokročilejší funkce jako animace, fyzika, octrees,<br />
zvuky, video textury, sít’ování chybí. Také toto byly hlavní důvody, proč se výsledná platforma<br />
začala tvořit od začátku, nebylo by vždy jisté, zda budou naimplementovány potřebné<br />
vlastnosti. Kdyby existovalo opravdu dokonalé API, nebylo by celkem co řešit, ale WebGl je<br />
tu jen krátce a frameworky mají určité porodní bolesti. Proto bylo rozhodnuto, že platforma<br />
nebude vycházet z žádného existujícího frameworku a vytvoří se nová.<br />
10
4.2 Architektura platformy<br />
Návrh celé plaformy je stěžejní částí této <strong>práce</strong>. Špatný návrh by mohl způsobit velké komplikace<br />
v průběhu budoucího vývoje.<br />
V podkapitole 4.2.1 se hledají různé techniky, které by mohly být použity ve výsledné<br />
platformě. V podkapitole 4.2.2 je přiblížen problém javascriptu s veřejnými a privátními proměnnými<br />
či metodami. V podkapitole 4.2.3, respektivě v příloze B na straně 56 se nachází<br />
přehledový diagram platformy. V podkapitolách 4.2.4 a 4.1 jsou popsány vlastnosti konstruktoru<br />
GameObject a možné komponenty, které lze přiřadit případnému objektu. Další<br />
podkapitola 4.2.6 popisuje, jakým způsobem jsou do scény nahrávána data ze souboru json.<br />
Hlavní uzel scény je detailněji přiblížen v podkapitole 4.2.7. Jak jsou v platformě uspořádány<br />
shadery, je možné nalézt v podkapitole 4.2.8. Poslední podkapitola 4.2.9 se zaměřuje na vstup<br />
z klávesnice.<br />
4.2.1 Inspirace pro návrh<br />
Inspirace pro návrh byla hledána u jiných frameworků. Svým poměrně jednoduchým návrhem<br />
zaujal framework GLGE[10]. Ten využívá při tvorbě vlastností javascriptu, který umožňuje<br />
řetězení prototypů a také dynamicky přidávat a nebo odebírat metody či proměnné určitého<br />
objektu. Zde je malý příklad konstruktoru Group:<br />
GLGE. Group=f u n c t i o n ( uid ){<br />
t h i s . c h i l d r e n = [ ] ;<br />
var that=t h i s ;<br />
t h i s . downloadComplete=f u n c t i o n ( ) {<br />
i f ( that . isComplete ( ) )<br />
that . f i r e E v e n t ( ”downloadComplete ”) ;<br />
}<br />
GLGE. Assets . r e g i s t e r A s s e t ( t h i s , uid ) ;<br />
}<br />
GLGE. augment (GLGE. Placeable ,GLGE. Group ) ;<br />
GLGE. augment (GLGE. Animatable ,GLGE. Group ) ;<br />
GLGE. augment (GLGE. QuickNotation ,GLGE. Group ) ;<br />
GLGE. augment (GLGE. JSONLoader ,GLGE. Group ) ;<br />
Z výše uvedeného kódu je možné vyčíst několik věcí :<br />
ˆ Každá metoda, či konstruktor začíná slovem GLGE, které nejen informuje, o tom,<br />
že se jedná o konkrétní framework, ale také omezuje kolize mezi jinými použitými<br />
javascriptovskými aplikacemi, které by náhodou obsahovaly stejnou metodu se stejným<br />
názvem. Pro výslednou platformu byla zvolena proměnná WGLP(WebGl Platform),<br />
která bude v budoucnu nejspíš nahrazena jiným slovem.<br />
ˆ Dále zaujme metoda augment. Prvním parametrem je konstruktor, jehož vlastnosti přiřazené<br />
prototypu budou přidány do prototypu konstruktoru, který se metodě předává<br />
11
pomocí druhého parametru. Prototyp konstruktoru Group bude ve výše uvedeném<br />
případě rozšířen o vlastnosti prototypů konstruktorů Placeable a Animatable. Group<br />
tím tyto vlastnosti přijme za své. Jedná se konkrétně o uzel libovolného stromu, který<br />
bude moci být umístěn a nebo animován. Tato metoda je velice užitečná a bude zajisté<br />
naimplementována do nové platformy. Takový postup přidávání vlastností má ale tu<br />
nevýhodu, že by se programátor mohl za chvíli ztrácet v tom, jakou vlastnost daný<br />
objekt má.<br />
Trochu jinou filozofii využívá vývojová platforma Unity z kapitoly (3.1.3), která se stala<br />
hlavním zdrojem inspirací pro výslednou platformu. Každý objekt ve scéně je typu Game-<br />
Object, který má určité Id. Dále se podle potřeby přidávají různé komponenty, které jsou<br />
nutné k dosažení potřebného efektu. Mezi komponenty patří například Transform, Renderer,<br />
RigidBody, Světlo, Kamera, Animace, atd. Chceme-li například animovaný objekt, je<br />
nezbytné vytvořit GameObject, poté přiřadit komponenty Renderer, která má na starosti<br />
rendering, Transform, pomocí které je objekt pozicován a nakonec Animace, která zařídí<br />
výslednou animaci. Velice zajímavá je komponenta Script, pomocí které je možné přiřadit<br />
logiku danému objektu.<br />
Všechny výše zmíněné vlastnosti platformy Unity přebírá výsledně vytvořená platforma.<br />
4.2.2 Privátní proměnné<br />
Javascript ve své implementaci nezná pojem veřejná a privátní proměnná. Pro potřeby platformy<br />
by bylo vhodné proměnné či metody takovým způsobem odlišit. Pomocí určitých<br />
programových struktur lze dosáhnout podobných vlastností, které privátní a veřejné metody(proměnné)<br />
mají, ale kód by se stal složitějším a méně přehledným. Proto bylo přistoupeno<br />
k velice jednoduchému až primitivnímu řešení. Před každou privátní metodou nebo<br />
proměnou se bude nacházet dolní podtržítko. Takto vývojář ihned na první pohled pozná,<br />
s jakou metodou aktuálně pracuje. Příkladem privátní proměnné může být position” z<br />
”<br />
komponenty Transform.<br />
4.2.3 Přehledový diagram<br />
Přehledový diagram se nachází v příloze B na straně 56. Vybrané části jsou popsány v<br />
následujících podkapitolách.<br />
4.2.4 Objekt GameObject<br />
Každý objekt, který bude umístěn do scény by měl být vytvořen konstruktorem GameObject(id)<br />
se zvoleným Id, které musí být unikátní. Dále do vytvořeného objektu GameObject<br />
mohou být přidávány různé komponenty, což přibližuje následující obrázek (4.1)<br />
12
Obrázek 4.1: GameObject a možné komponenty<br />
Z výše uvedeného obrázku 4.1 je patrné, že objektu mohou být nastaveny proměnné,<br />
které určují:<br />
ˆ Zda objekt může kolidovat s ostatními objekty ve scéně.<br />
ˆ Jestli se objekt pohybuje a nebo je statický.<br />
ˆ Zda je objekt ve scéně viditelný.<br />
ˆ Jestli je objekt průhledný či nikoliv.<br />
ˆ V neposlední řadě lze objekt přiřadit ke konkrétní skupině. Například se může jednat o<br />
asteroid, vesmírnou lod’, a podobně. Konkrétní příklad použití lze nalézt u kolizí, kdy<br />
je někdy potřeba vyřadit jeden pár objektů, který mezi sebou nemá nikdy kolidovat.<br />
Může se jednat například o laser, který není schopen zasáhnout vesmírnou lod’.<br />
ˆ Poslední, ale důležitá vlastnost se týká vlastníka objektu. Vždy při zavolání konstruktoru<br />
GameObject je této proměnné přiřazena hodnota self”, která říká, že objekt patří<br />
”<br />
uživateli, který sedí aktuálně u PC. Vlastníkem ale může být například server nebo jiný<br />
vzdálený uživatel. Takto lze určit, kdo má daný objekt pod kontrolou a může s ním<br />
popřípadě hýbat.<br />
4.2.5 Komponenty objektu GameObject<br />
Transform je velice důležitá komponenta, pomocí které je možné objekt pozicovat, rotovat,<br />
a to bud’ relativně ke svému předkovi a nebo absolutně ve světových souřadnicích.<br />
Ostatní hodnoty se vždy dopočítají automaticky. Pomocí tohoto uzlu je dále možné vytvářet<br />
hierarchii objektů. Každý uzel Transform může mít neomezeně mnoho potomků. V<br />
13
neposlední řadě existují možnosti zvětšování / zmenšování, přepočítání lokálního bodu do<br />
světových souřadnic, to samé platí i v opačném směru, atd. Všechny změny provedené v uzlu<br />
Transform jsou postupně propagovány stromovou strukturou až k listům.<br />
Obrázek 4.2: Obrázek znázorňuje objekty, které mezi sebou komunikují, pokud nastane<br />
změna v komponentě Transform a nebo v objektu GameObject.<br />
Výše uvedený obrázek 4.2 znázorňuje objekty, které mezi sebou komunikují, pokud nastane<br />
důležitá změna v komponentě Transform, a nebo v objektu GameObject. Například,<br />
pokud dojde k pohybu objektu, tak uzel Transform neprodleně informuje všechny své zaregistrované<br />
pozorovatele o dané změně. Při vytváření nového objektu pomocí konstruktoru<br />
Transform se mezi pozorovatele automaticky přidá objekt Hierarchy, který má za úkol informovat<br />
o změně všechny přímé i nepřímé potomky, které na základě nových dat změní<br />
také svůj stav. Mezi pozorovateli se dále může nacházet například obalové těleso přiřazené<br />
přímo objektu GameObject, a nebo jeho rendereru, pokud samozřejmě nějaký vůbec má.<br />
Obalové těleso je automaticky přidáno mezi pozorovatele, pokud je přiřazeno objektu game-<br />
Object, a nebo případnému rendereru. Všechna tělesa by také měla mít naimplementovanou<br />
metodu update(), která je volána v případě , že nastane změna a je potřeba změnit pozici<br />
či orientaci obalového tělesa. Objekt Hierarchy nemá na starosti pouze aktualizaci všech potomků,<br />
které jsou instance Transform, ale také informuje kořenový uzel scény VirtualWorld<br />
o požadovaných změnách. Konkrétně se jedná především o informace, zda objekt instance<br />
GameObject přiřazený uzlu Tranform nezměnil některou ze svých proměnných. Například<br />
jestli se z dynamického objektu nestal statický. Na základě těchto dat by následně došlo k<br />
aktualizaci kolekcí, ve kterých si uchovává VirtualWorld ukazatele na různé typy objektů.<br />
Více o VirtualWorld je v kapitole 4.2.7.<br />
Pro uložení pozice v uzlu Transform je použit třísložkový vektor. Rotace jsou uloženy<br />
ve formě matic o velikosti 4x4. Jedná se o redundanci, protože pro rotační matici dostačuje<br />
velikost 3x3. Použitá knihovna gl-matrix[11] pro výpočet matic pracuje primárně s maticemi o<br />
velikosti 4x4, proto byla zvolena tato velikost. Matice nejsou jedinou volbou pro uložení rotace<br />
objektu, velice často se používají Kvaterniony. Jejich výhoda spočívá především ve snadnější<br />
a lepší interpolaci. Další výhodou je menší pamět’ová náročnost, protože jsou uloženy ve<br />
formě čtyř reálných čísel. Grafické karty pracují pouze s maticemi, proto je vždy potřeba<br />
každý kvaternion převést před renderováním do maticové formy. Výhody kvaternionů nejsou<br />
pro výslednou platformu až tak zásadní, proto jsou rotace uloženy ve formě matic, z kterých<br />
14
je možné ihned extrahovat jednotlivé osové vektory(up, right, forward), což se v některých<br />
případech hodí.<br />
RigidBody je komponenta, která zaručí, že bude mít objekt určité fyzikální vlastnosti.<br />
Více o rigidních tělesech je napsáno v podkapitole 4.4 na straně 27, kde jsou informace<br />
týkající se použitého fyzikálního systému. K použití komponenty dojde v případě, kdy je<br />
potřeba, aby byl objekt ovlivňován různými fyzikálními vlivy.<br />
Camera je hluboce svázána s komponentou Transform, protože upravuje její pozici a rotaci.<br />
Kamera se ve skutečnosti nikam nepohybuje, stále se nachází v počátku světového<br />
souřadnicového systému a je natočena směrem k ose Z v negativním směru. Musí být tedy<br />
hýbáno s okolním světem přesně v opačném směru. Takzavaná View matice, kterou si kamera<br />
uchovává je vypočítána jako inverze z modelové matice, která je dodána pravě komponentou<br />
Transform. Velice důležitou maticí pro rendering je projekční matice, která se také nachází<br />
v již zmíněné komponentě. Kameře je možné přiřadit avatara a případně používaný skybox.<br />
Její součástí je také takzvané ViewFrustum, které definuje viditelnou oblast pomocí šesti<br />
rovin, které musejí být při každém pohybu kamery přepočítány.<br />
BoundingVolume je komponenta, která zaručuje obklopení objektu obalovým tělesem.<br />
Idea je taková, že téměř každý objekt může jím může být obklopen. Těleso by nemělo obklopovat<br />
pouze objekt, ke kterému je přiřazeno, ale také všechny objekty, které se nacházejí v<br />
hierarchii pod ním. Pokud dojde k posunutí nebo k rotaci objektu, je nutné také aktualizovat<br />
polohu obalového tělesa. Více o použitých obalových tělesech je napsáno v podkapitole 4.3.<br />
Script je komponenta, která může být přiřazena každému objektu, a pomocí které může<br />
být objekt obohacen o určitou logiku. Například ve výsledné ukázce je takto uděláno ovládání<br />
a chování vesmírné lodi. Každá komponenta Script musí mít povinně metodu start(),<br />
která provádí počáteční nastavení dle potřeby uživatele. Další povinnou metodou je update(duration),<br />
která je spuštěna v každém snímku a očekává hodnotu intervalu, o kterém<br />
je více napsáno v kapitole 4.4.1.<br />
NetworkView<br />
Každý objekt, který je sdílený mezi uživateli po síti, musí mít přiřazenu<br />
komponentu NetworkView, která obsahuje Id, které jednoznačně identifikuje objekt v síti.<br />
15
Obrázek 4.3: Komponenta NetworkView a všechny důležité třídy se kterými spolupracuje.<br />
Komponenta poskytuje dvě důležité metody sendMessage a onMessage, které slouží pro<br />
příjem a odesílání dat týkajících se daného objektu. Odeslané zprávy se doručí všem uživatelům<br />
v síti, kteří mají ve scéně objekt se stejným Id. Objektům, které jsou řízeny takto na<br />
dálku a nejsou ovládané uživatelem, je potřeba přiřadit komponentu Script, která obstará<br />
příjem příchozích zpráv pomocí metody onNetworkViewMessage, a která změní například<br />
stav objektu či provede jeho odstranění ze stromu. Jedná se o upravený skript, o kterém je<br />
více napsáno zde [25]. Skript by měl být přiřazen komponentě NetworkView, k čemuž slouží<br />
proměnná observer. Tím je docíleno toho, že v případě příchodu nové zprávy je zavolána<br />
výše uvedená metoda skriptu, které se neprodleně předají příchozí data. Skript by měl navíc<br />
obsahovat proměnnou interpolationEnabled, která říká, jestli má dojí k interpolaci mezi posledními<br />
známými stavy objektu. Z toto důvodu si skript pamatuje přibližně posledních 15<br />
stavů objektů. Stavem se většinou myslí pozice, rotace a rychlost. V samotné metodě update<br />
komponenty Script by mělo docházet k již zmíněné interpolaci.<br />
Renderer je komponenta, která si uchovává data potřebná k renderování. Především by<br />
měla obsahovat informace o geometrické reprezentaci, materiálech, texturách a bufferech.<br />
Ve scéně jsou naimplementovány celkem tři renderery. Konkrétně se jedná o MeshRenderer,<br />
BillboardRenderer a SkyboxRenderer. První dva zmíněné jsou detailněji popsány v kapitolách<br />
4.2.6 a 5.6.1. Každý z nich obsahuje název shaderu, jehož pomocí má být vyrenderován<br />
výsledný objekt. Další podmínkou pro správnou funkci komponenty je přítomnost metody<br />
render, která má za úkol zavolat zkompilovaný program, který provede samotný rendering.<br />
Metoda na vstupu očekává projekční a takzvanou view” matici, které jsou dostupné v kameře.<br />
”<br />
Light<br />
je komponenta mající na starosti světla. Ve výsledné platformě zatím světla nejsou<br />
naimplementována.<br />
16
4.2.6 Nahrání dat do scény<br />
Některé stávající frameworky podporují pro nahrávání dat do scény formát COLLADA[16]<br />
založený na XML. Jde o velice komplexní formát, který neobsahuje pouze geometrii objektů,<br />
ale také podporuje animace, efekty, shadery, inverzní kinematiku a podobně. Výhoda formátu<br />
Collada spočívá, že je pod záštitou stejné společnosti, která provedla standardizaci WebGl a<br />
také, že je podporován některými modelovacími nástroji. Z pohledu výsledné platformy jde<br />
o zbytečně komplikovaný formát. Jedná se ale o zajímavou alternativu, která by mohla být<br />
v budoucnu naimplementována, pokud by bylo zapotřebí nahrávat komplikovanější scény z<br />
externího souboru.<br />
Platforma nahrává informace o geometrických objektech z JSON souboru, který může<br />
vypadat takto:<br />
{<br />
”name ”: ”Vesmír ” ,<br />
” d e s c r i p t i o n ”: ” V i r t u a l n i r e a l i t a ve vesmiru ” ,<br />
” e x t e r n a l o b j e c t f i l e s ”: [<br />
{ ”id ”: ” VesmirnaLod ” , ” o b j e c t f i l e ”: ” spaceShip . obj ” ,<br />
” m a t e r i a l f i l e ”: ” spaceShip . mtl ”} ,<br />
{ ”id ”: ” Brana ” , ” o b j e c t f i l e ”: ” gate . obj ” ,<br />
” m a t e r i a l f i l e ”: ” gate . mtl ”}<br />
] ,<br />
”meshes ”: {<br />
”nazevMeshe ”: { ” vertexCoords ”: [ ] , ” normalCoords ”: [ ] ,<br />
”UV”: [ ] , ” f a c e I n d i c e s ”: [ ] , ” nazevTextury : ” ”. . . ”<br />
}<br />
} ,<br />
” m a t e r i a l s ”: {<br />
nazevMaterialu : { ”AmbientColor ”: [ ] , ”specularColor ”: [ ] ,<br />
” d i f f u s e C o l o r ”: [ ] , alpha : 1<br />
}<br />
} ,<br />
” t e x t u r e s ”: {<br />
”brana−vyrazna zare ”: { t e x t u r e S c a l e : [ 1 , 1 ] ,<br />
fileName : ”brana−vyrazna zare . png ” } ,<br />
”brana−zare ”: { t e x t u r e S c a l e : [ 1 , 1 ] ,<br />
fileName : ”brana−zare . png ” }<br />
} ,<br />
” o b j e c t s ”: [ ]<br />
}<br />
JSON soubor obsahuje meshe, materiály, textury. Další důležitou položkou je external<br />
”<br />
object files”, která říká, z jakých externích souborů se mají načíst další data a jaký má<br />
mít načtený objekt název.<br />
17
Ze zmíněných souborů jsou načteny další meshe, textury, materiály a v neposlední řadě<br />
informace o objektech, které mají být z těchto komponent vytvořeny. Informace o objektech<br />
a jejich komponentách jsou následně uloženy do poslední položky objects”. ”<br />
Průběh načítání dat do scény znázorňuje následující obrázek 4.4:<br />
Obrázek 4.4: Obrázek znázorňuje načtení geometrických objektů do scény včetně materiálů<br />
a textur<br />
Uživatel, který si přeje vytvořit novou kopii renderovatelného objektu, zavolá metodu<br />
objektu JsonLoader, do které vloží dvě důležité informace:<br />
ˆ Název objektu, jehož nová kopie se má vytvořit. Ten se musí shodovat s názvem uloženým<br />
v položce ”<br />
objects” ve výše zmíněném JSON souboru.<br />
ˆ Druhým parametrem je id nově vzniklého GameObjectu<br />
Platforma zatím podporuje pouze jeden externí formát obj, což je jednoduchý datový formát,<br />
který uchovává 3D geometrii jednoho nebo více objektů. Z tohto formátu lze vyčíst<br />
pozici každého vertexu, UV pozici pro každý vertex, normály a jednotlivé plošky, které jsou<br />
z vertexů vytvořeny(tzv. faces). Formát poskytuje informace, jaký materiál je přiřazen konkrétním<br />
ploškám. V jednom obj souboru může být najednou více objektů, ale všechny sdílejí<br />
jeden společný lokální souřadnicový systém. Pokud je v jednom souboru více objektů, tak<br />
se v takovém případě vytvoří jeden kořenový objekt, který bude mít potomky odpovídající<br />
objektům v souboru. S každým souborem je většinou svázán mtl formát, který si uchovává<br />
informace o materiálech.[17] Z každého materiálu je potřeba získat vlastnosti ambient, diffuse,<br />
specular a průhlednost. Popřípadě název textury a její velikost.<br />
Při exportu objektů do formátu obj ze známých modelářů je nutné si dát pozor na několik<br />
věcí:<br />
18
ˆ Model před exportem musí být složen z trojúhelníků, čtyřhranné polygony nejsou podporovány.<br />
ˆ Při tvorbě materiálů je nutné vybrat takový, aby obsahoval výše zmíněné složky.<br />
ˆ Geometrická reprezentace objektu musí nést informace jak o vertexech, UV souřadnicích,<br />
tak o normálách. Ani jedna složka nesmí chybět.<br />
Mesh renderer má za úkol uchovávat důležitá data pro rendering objektu. Především<br />
musejí být vytvořeny a naplněny buffery, které používá grafická karta. Bufferů, které<br />
uchovávají indexy, může být více, protože části, které mají své vlastní materiály, musejí<br />
být vyrenderovány odděleně. O bufferech již bylo psáno v 3.2.2 na straně 7. Mesh renderer<br />
přibližuje následující obrázek :<br />
Obrázek 4.5: Mesh renderer, přiřazený mesh, buffery a materiály<br />
Struktura MeshRenderu vlastně kopíruje jeden objekt uložený v obj formátu. Jednotlivé<br />
meshe, materiály, textury se mohou ve scéně opakovat vícekrát, proto jsou uloženy pouze<br />
na jednom místě v objektu Components. Mesh renderery se pouze odkazují na jednotlivé<br />
stavební komponenty, z kterých se objekt skládá.<br />
4.2.7 VirtualWorld<br />
Objekt VirtualWorld tvoří základní uzel celé scény. Pozor, nejedná se o konstruktor, ale již<br />
vytvořený objekt.<br />
19
Obrázek 4.6: Objekt VirtualWorld se všemi objekty, na které si drží referenci.<br />
Jakmile se ve scéně vytvoří prví uzel Transform, měl by být ihned přiřazen objektu VirtualWorld,<br />
aby došlo při následném renderování k vykreslení všech objektů ve stromu. Je<br />
doporčeno vždy vytvořit GameObject s identifikátorem root”, jehož komponenta Transform<br />
”<br />
bude přiřazena objektu VirtualWorld. Tento základní uzel scény si dále drží odkazy na stavební<br />
komponenty objektů, aktuálně používanou kameru, na všechny dynamické,statické a<br />
renderovatelné objekty GameObject” ve stromu. Ke všem objektům GameObject”, které<br />
” ”<br />
se nacházejí v hierarchické struktuře je možné přistupovat pomocí speciální proměnné $”. ”<br />
Například, pokud je potřeba pracovat s objektem GameObject” s id SpaceShip2”, tak se<br />
” ”<br />
použije následující zápis:<br />
var spaceShip = VirtualWorld . $ [ ’ SpaceShip2 ’ ] ;<br />
spaceShip . transform . rotateLocalY ( 9 0 ) ;<br />
V případě, že je ve scéně použit strom Octree, o kterém je napsáno více v kapitole 4.5.2<br />
na straně 30 nebo řadící algoritmus jménem Sort and sweep, měli by být jejich reference<br />
přiřazeny k objektu VirtualWorld, který si zároveň drží ukazatel na celou scénu. Jelikož se<br />
kolekce objektů zobrazené na obrázku 4.6 neustále mění, je potřeba informovat všechny pozorovatele,<br />
kteří se nacházejí v poli Observers. Jako příklad může posloužit strom Octree,<br />
který uchovává pouze statické objekty. Pokud je nějaký statický objekt odstraněn z kolekce,<br />
je nutné také smazat referenci na obalové těleso objektu ve stromu. Octree strom je<br />
automaticky přidán mezi pozorovatele hned v momentě, kdy se na něj VirtualWorld dozví<br />
referenci.<br />
4.2.8 Shadery<br />
Ze začátku vývoje byly shadery uloženy ve zvláštním souboru, který se načítal pomocí Ajaxu.<br />
Nevýhody zmíněného řešení spíše převažovaly nad klady. Javascript nemá právo zapisovat<br />
do souborů na disku, takže editace souboru musela být řešena pomocí serveru. Aktuální<br />
řešení zabudovává zdrojový kód shaderů přímo do zdrojového kódu javascriptu. Sice je psaní<br />
kódu zdlouhavější, ale naopak může být shader dynamicky rozšířen podle potřeby o některé<br />
funkce. Například mohou být někde připravené shaderovské funkce, které mají na starosti<br />
jednotlivé typy světel. V případě, že by byl konkrétní typ světla použit, mohla by být funkce<br />
20
do kódu dynamicky přidána. Pro uchovávání zkompilovaných shaderů slouží již vytvořený<br />
objekt WGLP.ShaderPrograms.<br />
Obrázek 4.7: Všechny objekty a konstruktory, které v platformě mají na starosti shadery.<br />
Každý renderer musí obsahovat název shaderu, který má být použit pro renderování<br />
konkrétního objektu. Při renderingu dojde k přepnutí na potřebný shader pomocí metody<br />
useProgram(jmenoShaderu). V objektu ShaderPrograms může existovat libovolné množství<br />
zkompilovaných shaderů pod různými jmény. Pro renderování normálních geometrických<br />
objektů je připraven defaultní shader. Taktéž je k dispozici program pro renderování skyboxu.<br />
Shadery nejsou v počátečním stavu zkompilovány, proto je potřeba vždy zavolat metodu<br />
initDefaultShaders(). Pod pojmem shader se skrývá dvojice vertex shader, fragment shader.<br />
Na následujících několika řádcích je část ukázky z kapitoly 3.2.2 na straně 5 přepsána do<br />
kódu vytvořené platformy:<br />
var sP = WGLP. ShaderPrograms ;<br />
var vertexShader = new WGLP. Shader ( ) ;<br />
vertexShader . setType ( ” vertex ”) ;<br />
vertexShader . addSCLine ( ” a t t r i b u t e vec3 poziceVertexu ; ”) ;<br />
vertexShader . addSCLine ( ”uniform mat4 p r o j e k c n i M a t i c e ; ”) ;<br />
vertexShader . addSCLine ( ”uniform mat4 MMatice ; ”) ;<br />
vertexShader . addSCLine ( ”{ ”) ;<br />
vertexShader . addSCLine ( ” g l P o s i t i o n = p r o j e k c n i M a t i c e * MMatice *<br />
vec4 ( poziceVertexu , 1 . 0 ) ; ”) ;<br />
vertexShader . addSCLine ( ”} ”) ;<br />
vertexShader . compileShader ( ) ;<br />
Stejným způsobem jako výše je nutné zkompilovat fragment shader. Poté se vytvoří program<br />
pomocí následující metody:<br />
var program = sP . createShaderProgram ( vertexShader ,<br />
fragmentShader , ” nazevShaderu ”) ;<br />
V dalším kroku je zapotřebí získat lokace proměnných attribute a uniform, aby jim mohly<br />
být přiřazeny hodnoty.<br />
sP . assignUniformsLocation ( program , [ ” p r o j e k c n i M a t i c e ” , ”MMatice ”] ) ;<br />
sP . a s s i g n A t t r i b u t e s L o c a t i o n ( program , [ ” poziceVertexu ”] ) ;<br />
21
Výše vytvořená proměnná program” v tuto chvíli obsahuje proměnné uniforms a attributes,<br />
které tvoří asociativní pole, které obsahuje lokace shaderovských proměnných. K lokacím<br />
”<br />
je možné přistupovat takto:<br />
var l o k a c e = program . uniforms [ p r o j e k c n i M a t i c e ] ;<br />
V posledním kroku musí být objektu program přiřazena metoda render, která má na starosti<br />
naplnění shaderovských proměnných potřebnými daty pro vyrenderování konkrétního<br />
objektu, a která nakonec zavolá funkci pro vykreslení.<br />
program . render = f u n c t i o n ( gameObject , , p r o j e c t i o n M a t r i x ){<br />
.<br />
t ě l o metody<br />
.<br />
}<br />
4.2.9 Vstup z klávesnice<br />
Součástí platformy je již vytvořený objekt WGLP.Input, který usnadňuje práci se vstupem.<br />
Pozor, nejedná se o konstruktor.<br />
Obrázek 4.8: Objekt Input s přidruženými objekty<br />
Na začátku je vždy nutné obsloužit události z klávesnice. K tomuto účelu slouží metody<br />
handleKeyDown a handleKeyUp, které musí být volány, kdykoliv nastanou události ”<br />
Key-<br />
Down” a ”<br />
keyUp”. Objekt Input si uchovává asociativní pole currentlyPressedKeys, kde ke<br />
každému kódu klávesy je přiřazena hodnota true nebo false, podle toho, zda je konkrétní<br />
klávesa zmáčknuta.<br />
Existuje několik možností, jak lze objekt Input využít:<br />
1. Použitím metody getKey(nazevKlavesy) lze zjistit, zda je klávesa s požadovaným názvem<br />
aktuálně zmáčknuta. Metodu je možné použít na všechny názvy základních kláves.<br />
Čísla se zadávají ve tvaru NUM0,NUM2,.., NUM9”.<br />
”<br />
22
2. Další možností je objektu Input přiřadit pozorovatele na konkrétní klávesu. Takový<br />
pozorovatel musí mít naimplementovánu metodu update(param1, param2), kde první<br />
parametr říká, zda došlo ke stisknutí nebo uvolnění klávesy. Druhým parametrem je<br />
název klávesy, která vyvolala danou událost. Pozorovatele lze přidat metodou addKey-<br />
Observer(klic, observer). Metoda, která odstraní dvojici klíč - pozorovatel” se jmenuje<br />
”<br />
removeKeyObserver(klic, observer).<br />
3. Zbývá poslední metoda se jménem getAxis(jmenoOsy). V objektu Input je defaultně<br />
uloženo několik os. Každá osa si uchovává svůj název a dva kódy požadovaných kláves.<br />
Pokud je zmáčknuta první klávesa, metoda vrátí hodnotu -1. Pokud je zmáčknuta<br />
druhá klávesa, metoda vrátí hodnotu 1. Pokud ani jedna z těchto kláves není zmáčknuta,<br />
metoda vrátí hodnotu 0. Jedná se o to, že se vlastně definují klávesy pro kladný<br />
a záporný pohyb po dané ose. V případě, že nám stávající osy nevyhovují, je možné<br />
přidat své vlastní, a to tak, že se vytvoří nový objekt, který bude rozšiřovat ten stávající.<br />
K tomuto slouží metoda WGLP.extend, založená na jQuery[26] knihovně, kterou<br />
platforma využívá. Poté stačí do pole Input.Axes přidat osu s novým názvem a přiřadit<br />
jí dva nové kódy kláves. Metody getAxis(jmenoOsy) lze například využít při ovládání<br />
vesmírné lodi. Lze nadefinovat osu pohybu vpředVzad”, přiřadit jí potřebné klávesy<br />
”<br />
a pak už jen stačí sílu motoru vynásobit návratovou hodnotou funkce. Síla bude bud’<br />
kladná nebo záporná, při nulové hodnotě nulová. Pak už stačí sílu předat objektu<br />
RigidBody a ten už se o zbytek postará sám.<br />
4. Objekt Input obsahuje asociativní pole Input.KeyMap, které pod každým názvem klávesy<br />
uchovává její kód. Existuje také pole Input.rKeyMap, které si naopak uchovává<br />
kódy a přiřazuje k nim názvy kláves.<br />
4.3 Obalová tělesa<br />
Ačkoliv je možné koliznímu systému předat celý objekt, tak jak byl vymodelován, je zde<br />
několik důvodů, proč daný objekt aproximovat či obalit jiným geometrickým tělesem. [13]<br />
Takové těleso musí kopírovat pohyb původního objektu. Obrázek 4.9 obsahuje pětici dnes<br />
nejvíce používaných obálek.<br />
Obrázek 4.9: Nejpoužívanější obalová tělesa. Převzato z [13]<br />
23
Dnešní počítače nejsou dostatečně rychlé na to, aby 60x za sekundu zkontrolovaly, zda<br />
nekoliduje mezi sebou 50 různých geometrických objektů, které se navíc skládají například<br />
z 10000 trojúhelníků. V takovém případě by bylo nutné ověřit kolizi jednoho trojúhelníku<br />
se všemi ostatními, a to je nemožné v reálném čase. V následujících podkapitolách se budou<br />
rozebírat a hodnotit jednotlivé naimplementované typy obalových těles. V podkapitole 4.3.4<br />
se přibližují všechny možné naimplementované testy kolizí. Sekci uzavírá podkapitola 4.3.5,<br />
která popisuje případný objekt Contact, který slouží k uchovávání kolizních dat a obsahuje<br />
metody na jejich vyhodnocení.<br />
4.3.1 Obalová koule<br />
Obalová koule může být přiřazena jak celému GameObjectu, tak pouze MeshRendereru,<br />
o kterém bylo více napsáno v kapitole 4.2.6 na straně 19. Existují různé algoritmy, které<br />
dokáží rychle a efektivně vypočítat ze sady vertexů obalovou kouli, která je jednoznačně<br />
definována pozicí středu a poloměrem. Ve výsledné platformě je naimplementován Jackův<br />
Ritterův algoritmus, který pracuje v lineárním čase.[14] Výsledná obalová koule je maximálně<br />
o 5% větší než minimální možný výsledek. Algoritmus se provádí ve dvou fázích:<br />
ˆ V první fázi se ke každé ose naleznou maximální a minimální hodnoty. Z těchto hodnot<br />
je vypočítána prvotní koule.<br />
ˆ Ve druhé fázi se každý bod porovná s aktuální koulí. Pokud se bod nachází mimo kouli,<br />
tak dojde ke zvětšení poloměru a k upravení pozice středu.<br />
4.3.2 OBB<br />
Zkratka OBB znamená v angličtině Oriented bounding box, což je libovolně orientovaný<br />
kvádr. Existuje mnoho reprezentací tohoto kvádru. Jako nejvýhodnější se jeví reprezentace,<br />
kdy se uchovává polovina velikosti kvádru ve všech směrech. Rotace je uložena ve formě matice,<br />
jako je tomu u komponenty Transform. Reprezentace v tomto tvaru umožňuje snadnější<br />
test kolize mezi dvěma kvádry. Nalezení nejmenšího kvádru není triviální záležitost. Existuje<br />
například metoda, kdy se kvádr natáčí postupně v různých směrech a hledá se nejmenší<br />
kvádr. Již podle popisu jde o velice nepraktický a zdlouhavý algoritmus. Původně byl naimplementován<br />
ve výsledné platformě, ale nakonec se od něj upustilo. Pokud se kvádr natáčel<br />
do všech směrů a krok natočení byl 10°, tak i přes to výpočet trval neúměrně dlouho.<br />
24
Obrázek 4.10: Nalezený OBB ve 2D. Převzato z [15]<br />
O mnoho lepší algoritmus[15], který k výpočtu využívá kovarianční matici, dojde k požadovanému<br />
kvádru v několika krocích:<br />
ˆ Vstupem je pole vertexů, ze kterých se vypočítá průměrná pozice, která je použita pro<br />
výpočet kovarianční matice spolu se vstupními vertexy.<br />
ˆ Dalším krokem je nalezení vlastních vektorů kovarianční matice C, které definují natočení<br />
výsledného kvádru. Pro vlastní čísla a vektory platí následující vztah : (C -<br />
lambda*E) * v = 0, na který lze nahlížet jako na homogenní soustavu lineárních rovnic<br />
o n neznámých. Ta má nenulové řešení, pokud je det(C - lambda*E) = 0. Vlastní čísla<br />
jsou kořeny kubického polynomu. Vlastní vektory je možné získat vyřešením již zmíněné<br />
soustavy rovnic. Pozici středu a velikost kvádru je již snadné dopočítat pomocí<br />
skalárních součinů a sčítáním vektorů.<br />
Výše zmíněný algoritmus není vhodný pro objekty, kde se vertexy vyskytují ve shlucích. Z<br />
toho vyplývá, že je vhodný pouze na jednotlivé meshe. Pokud by se používal pro obalení<br />
více meshů najednou, tak by výsledky nemusely být ideální. OBB nebude tedy k dispozici<br />
jako obálka pro GameObject.<br />
4.3.3 AABB<br />
AABB je osově zarovnaný kvádr. Ve výsledné platformě se nejedná vlastně o kvádr, ale o<br />
krychli, protože je vypočítána z obalové koule. Pokud by se jednalo o standardní AABB,<br />
tak by jeho velikost musela být přepočítána vždy, když by došlo k pootočení objektu. Pozice<br />
AABB ve scéně bude uložena ve formě minimálních a maximálních hodnot na každé ose.<br />
Toto obalové těleso bylo do platformy přidáno pouze z důvodu, že jako kolizní algoritmus<br />
byl vybrán Sort and sweep, který pracuje právě s AABB. Více o tomto algoritmu je napsáno<br />
v podkapitole .<br />
4.3.4 Testy kolizí mezi tělesy<br />
Platforma v sobě integruje již vytvořený objekt jménem CollisionDetector, který má na<br />
starosti provádění testů kolizí mezi obalovými tělesy. Navíc obsahuje metodu která umí<br />
25
určit, jestli se koule nachází před rovinou nebo za rovinou. CollisionDetector dokáže také<br />
zjistit, jestli se krychle nachází za konkrétní rovinou. V neposlední řadě detekuje kolizi mezi<br />
jednotlivými uzly stromu Octree a takzvaným ViewFrustum kamery. Výsledná platforma<br />
podporuje tyto typy kolizí :<br />
ˆ Koule vs koule.<br />
ˆ Koule vs OBB.<br />
ˆ OBB vs OBB.<br />
ˆ GameObject vs GameObject s automatickým rozeznáním obalového tělesa.<br />
ˆ GameObject vs strom objektů GameObject tvořený hierarchií uzlů Transform. Opět<br />
dojde k automatickému rozpoznání obalového tělesa.<br />
ˆ AABB vs AABB.<br />
ˆ Octree vs ViewFrustum kamery.<br />
Za zmínku stojí algoritmus, pomocí kterého se testuje kolize mezi OBB a OBB. Překvapivě se<br />
nejedná o tak jednoduchý algoritmus, jak se na první pohled zdá. Anglicky se metoda testu<br />
nazývá jako Separating Axis Theorem. Princip je takový, že se nejprve oba OBB promítnou<br />
na osu. Pokud jsou promítnuté intervaly disjunktní, tak tělesa mezi sebou nekolidují. Celkem<br />
stačí otestovat 15 různých os.<br />
4.3.5 Objekt Contact<br />
V případě, že objekty mezi sebou nekolidují, tak testovací metody vrátí booleovskou hodnotu<br />
false. Jiné je to však v momentě, kdy dojde k detekci kolize. Fyzikální systém si bohužel<br />
nevystačí pouze s informací, že dva objekty do sebe narazily. Příklad kolize je na následujícím<br />
obrázku 4.11<br />
Obrázek 4.11: Ukázka kolize OBB s koulí. Převzato z [12]<br />
Zde přichází na řadu objekt Contact, který v sobě zahrnuje tyto doplňující informace:<br />
26
Kolizní normálu - Kolizní normála určuje směr, ve kterém došlo ke kolizi, a ve kterém by<br />
měla být dvě kolidující tělesa oddělena.<br />
Hloubku zanoření - Kolidující objekty se pouze nedotýkají. Jelikož se kolize testuje po<br />
určitých časových intervalech, tak dojde k zanoření objektů. Hloubka zanoření určuje,<br />
o kolik by se měla tělesa posunout ve směru/protisměru kolizní normály, aby již nedocházelo<br />
ke kolizi.<br />
Kolizní body - Kolizní bod může být jen jeden, například dvě kolidující koule se dotýkají<br />
pouze v jednom bodě. Jiný případ nastane, pokud dva OBB objekty do sebe narazí<br />
hranami, to má za následek, že vnikne více kolidujících bodů. Kontaktní body zatím<br />
nebudou naimplementovány.<br />
Koeficient odrazu - Tato vlastnost se nikterak nevypočítává. Je dána podle toho, jaká<br />
dvě rigidní tělesa kolidují.<br />
Třecí sílu - Třecí síla udává, jestli se tělesa mohou smýkat v bodě odrazu. Taktéž se nejedná<br />
o vypočítanou hodnotu, ale je součástí vlastností rigidních těles. Protože výsledný<br />
fyzikální systém nebude zatím podporovat rotace, nebude tato síla zatím naimplementována.<br />
4.4 Základní fyzikální systém<br />
Fyzikální vlastnosti objektu má ve výsledné platformě na starosti komponenta RigidBody,<br />
o které již bylo zmíněno v podkapitole 4.2.5 na straně 15. Fyzikální simulace poskytuje realističtější<br />
chování objektů, než kdyby docházelo k přímému ovlivňování uzlu Transform.[12]<br />
Hned na začátku je nutné napsat, že ve výsledku bude naimplementována jen část potřebných<br />
vlastností. Rotace budou z důvodu větší složitosti prozatím vynechány a bude je nutné<br />
naimplementovat někdy v budoucnu. Fyzikální systém se tím pádem svým chováním bude<br />
spíše blížit částicovému systému.<br />
První podkapitola 4.4.1 přibližuje integrační metodu komponenty RigidBody a popisuje<br />
samotnou komponentu. Další podkapitola 4.4.2 se zaměřuje na fyziku založenou na pružině.<br />
Poslední podkapitola 4.4.3 se zabývá registrem působících sil.<br />
4.4.1 Integrační metoda rigidního tělesa<br />
V každém snímku je zapotřebí aktualizovat pozici objektu. Integrátor se skládá ze dvou částí:<br />
ˆ První část aktualizuje pozici objektu<br />
ˆ novaP ozice =<br />
pozice ˆ + rychlost ˆ · interval<br />
ˆ Druhá část aktualizuje rychlost objektu<br />
ˆ novaRychlost =<br />
rychlost ˆ + zrychlení ˆ · interval<br />
27
Nová pozice objektu závisí na rychlosti a na zrychlení. Zatímco nová hodnota rychlosti<br />
závisí pouze na zrychlení, podle druhého Newtonova zákona, který říká, jestliže na těleso<br />
působí síla, pak se těleso pohybuje se zrychlením, které je přímo úměrné působící síle a<br />
nepřímo úměrné hmotě tělesa, se vypočte hodnota zrychlení takto :<br />
ˆ zrychlení =<br />
ˆF<br />
hmota<br />
Rigidnímu tělesu je tedy nutné předat informaci o hmotě. Integrátor vždy jako poslední<br />
operaci provede vynulování působící síly. Jednotlivé síly, které jsou předány rigidnímu tělesu<br />
se sčítají a zrychlení je vypočítáno z výsledné síly.<br />
Vstupem do integrátoru je hodnota, která udává čas, který uplynul mezi minulým a aktuálním<br />
snímkem. Frame-rate pro fyzikální systém by měl být v budoucnu vylepšen, protože<br />
každý počítač může mít frame-rate rozdílný. Používá se například stanovení hodnoty pro<br />
další frame, atd. Výsledná implementace používá stejnou smyčku pro provádění fyziky a<br />
pro rendering. Tyto smyčky se někdy oddělují a pro každou se vytvoří vlastní vlákno. V<br />
javascriptu takovou věc bohužel nelze provést, protože neumí pracovat s vlákny. Lze použít<br />
jen určitou techniku časování.<br />
Rigidní těleso obsahuje ve výsledku dvě důležité proměnné:<br />
ˆ Hmotu tělesa v kilogramech, která určuje, jak je těleso těžké a jak dobře je s ním možné<br />
hýbat.<br />
ˆ Výslednou sílu v newtonech, která v sobě obsahuje všechny síly aplikované na objekt.<br />
Jiné proměnné jako je rychlost a zrychlení by neměly být ovlivňovány přímo, ale jsou vypočítány<br />
integrační metodou.<br />
4.4.2 Pružina<br />
Pružina je ve fyzikálních enginech velice často používána. Pomocí pružiny lze naimplementovat<br />
například pohyb kamery za avatarem, pohyb vlajky, vlny na moři, pohyb oblečení,<br />
atd. Hookeův zákon matematicky popisuje chování pružiny. Hook objevil, že síla vyvinutá<br />
pružinou závisí na délce stlačení a nebo roztažení pružiny. Tento jev je určen vzorcem:<br />
ˆF = =tuhostP ružiny · roztažení ˆ<br />
Další silou, která působí proti stlačení nebo roztažení je tlumící síla, která je dána vztahem:<br />
ˆF = =tlumícíKonstanta · rychlost ˆ<br />
Tyto síly se ve výsledku sečtou a vznikne výsledná síla.<br />
Všechny tyto výpočty týkající se pružiny má na starosti konstruktor Spring. Po jeho<br />
zavolání vznikne objekt, u kterého je nutné nastavit vlastnosti vyplývající z výše uvedeného<br />
textu:<br />
ˆ tlumící konstantu<br />
ˆ tuhost pružiny<br />
28
Další dvě důležité proměnné jsou pozice a požadovaná pozice. Pokud jsou tyto hodnoty<br />
stejné, tak pružina nevyvíjí žádnou sílu. Rozdílem těchto vektorů je vektor roztažení. Z výše<br />
napsaných vztahů již zbývá jen pokrýt rychlost a jakému rigidnímu tělesu mát být vzniklá síla<br />
přiřazena. Pro tento účel slouží metoda updateForce(duration, gameObject), která by měla<br />
být volána v každém snímku. GameObject je objekt, který obsahuje komponentu RigidBody<br />
a bude mu do výsledné síly připočítána síla vzniklá pružinou. Tlumící síla se vypočte z<br />
rychlosti daného rigidního tělesa. Duration je opět interval mezi jednotlivými snímky. V<br />
pružině sice není potřeba, ale tato metoda by měla ve všech objektech, které vyvíjejí nějakou<br />
sílu, vypadat stejně. Například takto může být přidán objekt, který vyvíjí gravitační sílu,<br />
atd.<br />
4.4.3 Registr působících sil<br />
Sil působících na konkrétní objekt může být velice mnoho. Jedna síla může navíc ovlivňovat<br />
více objektů, například vítr, gravitační síla, atd. Myšlenka je taková, že se vytvoří generátor<br />
síly, jako příklad může posloužit výše zmíněná pružina. Takový generátor musí mít vždy<br />
metodu updateForce(duration, gameObject), kde GameObject je objekt s rigidním tělesem,<br />
na který bude působit výsledná síla.<br />
Registr sil má tři jednoduché metody:<br />
ˆ add(gameObject,forceGenerator), pomocí které dojde k registraci dvojice GameObject<br />
- ForceGenerator. Síla vyvinutá tímto generátorem bude ovlivňovat rigidní těleso v<br />
gameObjectu. Takto může být přidáno neomezené množství dvojic.<br />
ˆ remove(gameObject,forceGenerator), pomocí které dojde k vymazání dvojice Game-<br />
Object - ForceGenerator.<br />
ˆ updateForces(duration), která v cyklu projde všechny zaregistrované dvojice a pokaždé<br />
spustí metodu updateForce(duration, gameObject) příslušného generátoru síly. Za gameObject<br />
dosadí zaregistrovaný objekt.<br />
Výše popsaný způsob se hodí pro scény, kde se vyskytuje velké množství sil a objektů, na<br />
které síly působí. Ve výsledné ukázce není Registr sil použit. Síla je do rigidního tělesa<br />
přidána z komponenty Script, která je přiřazena vesmírnému plavidlu.<br />
4.5 Rozdělení prostoru<br />
Objektům ve scéně mohou být přiřazena obalová tělesa, která urychlují detekci kolizí mezi<br />
objekty, ačkoliv to má tu nevýhodu, že detekce není tak přesná, jako kdyby kolidovaly přímo<br />
samotné meshe mezi sebou. Tímto ale není vyřešeno to, jak najít dvojice objektů, které<br />
mezi sebou mohou kolidovat. Testování typu každý z každým by bylo v tomto případě velice<br />
neefektivní, protože se ve scéně bude nacházet velké množství objektů.<br />
Existují techniky, které rozdělují prostor na menší části, a které testují, zda dva nebo<br />
více objektů nesdílí stejný prostor. Jelikož objekty mohou vzájemně kolidovat pouze tehdy,<br />
29
sdílí-li stejnou část prostoru jako druhý objekt, tak je tímto způsobem významně redukován<br />
počet možných kolidujících dvojic.<br />
Existují 3 hlavní typy metod pro rozdělení prostorů, které jsou rozebírány v následujících<br />
podkapitolách.<br />
4.5.1 Mřížky<br />
Existují mřížky, které prostor rozdělují na stejné části. Jedná se o tzv. Uniform grids. Objekty<br />
jsou přiřazeny oblastem, ve kterých jsou obsaženy. Jedná se o velice oblíbenou metodu.<br />
Problém, který je s mřížkami spojen, spočívá ve stanovení velikosti buňky, což je znázorněno<br />
na následujícím obrázku 4.12<br />
Obrázek 4.12: (a) Buňky jsou moc malé. (b) Buňky jsou zbytečně velké. (c) Buňky jsou velké<br />
s ohledem na velikost objektu. (d) Buňky jsou moc velké a zároveň moc malé. Převzato z<br />
[13]<br />
Výše zmíněný problém řeší hierarchické mřížky, kde větší objekty jsou umístěny do<br />
mřížky, která má větší rozměr buněk. Malé objekty jsou naopak umístěny do mřížky s menšími<br />
buňkami. Pro výslednou ukázku, která se odehrává ve vesmíru, jsou mřížky dobrou<br />
volbou, ale přednost dostala metoda založená na řazení.<br />
4.5.2 Stromy<br />
Scéna je rozdělena do stromové struktury. Kořen stromu obaluje celou scénu. Potomci pokrývají<br />
části scény, které obaluje jejich rodič. Takto může být vytvořen strom o požadované<br />
hloubce. Na dalších několika řádcích bude popsán strom typu Octree, který byl vybrán k<br />
implementaci do výsledné platformy.<br />
Octree je osově zarovnaný strom, kde každý uzel má přesně osm potomků. Kořen stromu<br />
tvoří co nejmenší krychle, která pokrývá celou scénu.<br />
Tato krychle je rozdělena na osm podkrychlí, které tvoří potomky daného uzlu, což zobrazuje<br />
následující obrázek 4.13. Další potomci jsou dále tvořeny rekurzivně stejným způsobem.<br />
Typické kritérium pro zastavení rekurzivního algoritmu je maximální hloubka stromu.<br />
30
Obrázek 4.13: Číslování jednotlivých potomků stromu. Převzato z [13]<br />
Každý uzel stromu si uchovává tyto hodnoty:<br />
ˆ pozici středu<br />
ˆ poloviční velikost hrany<br />
ˆ reference na osm potomků<br />
ˆ pole obalových koulí, které jsou přiřazeny danému uzlu<br />
Existují dva rozdílné přístupy při vkládání objektu do stromu. Zde bude popsán pouze ten<br />
způsob, který je ve výsledku naimplementován. Při vkládání objektu se nejprve detekuje,<br />
zda se obalová koule nenachází uvnitř některého z osmi potomků. Pokud se rozprostírá přes<br />
více než jednu buňku, tak bude odkaz na obalovou kouli uložen do aktuálního uzlu. Je-li<br />
koule obsažena pouze v jedné buňce, tak se algoritmus bude rekurzivně opakovat, dokud<br />
koule nepřesáhne více jak jednu buňku a hloubka bude menší než maximálně povolená.<br />
Nevýhodou tohoto postupu je, že se obalová koule někdy nebude nacházet tak hluboko, jak<br />
by bylo ve skutečnosti možné. Pro statickou scénu by bylo lepší dělení objektu a ukládání<br />
odkazu na kouli do všech buněk, ve kterých se vyskytuje. Pro pohyblivý objekt je naopak<br />
vhodnější první způsob, protože se nemusí aktualizovat více ukazatelů, ale pouze jenom<br />
jeden. Ve výsledné ukázce se ale i přesto používá tento strom pouze pro statickou scénu,<br />
protože i přes použití první verze algoritmu, není standardní Octree strom vhodný pro mnoho<br />
pohybujících se objektů. Pokud bude problém s výkonem, tak je možné naimplementovat<br />
druhou verzi algoritmu. Strom nemusí být na začátku vytvořen celý. Potomci uzlů se mohou<br />
tvořit dynamicky podle toho, zda je do nich přiřazena některá obalová koule. Za zmínku stojí<br />
informace, že existuje Loose octree, který dovoluje dynamicky měnit velikost buněk, což řeší<br />
některé problémy.<br />
4.5.3 Řadící mechanismy<br />
Jak mřížky, tak stromy řeší problémy spojené s přesahem obalových těles do více buněk.<br />
Alternativou k těmto metodám jsou určitým způsobem seřazené objekty ve scéně. Výsledně<br />
naimplementovaná metoda se nazývá Sweep and prune.<br />
Sweep and prune<br />
je metoda, která funguje na principu, že si v obousměrně zřetězeném<br />
spojitém seznamu uchovává minimální a maximální hodnoty pro jednotlivé AABB konkrét-<br />
31
ních těles. Celkem obsahuje 3 spojité zřetězené seznamy pro každou osu. Metodu přibližuje<br />
následující obrázek:<br />
Obrázek 4.14: Minimální a maximální body jednotlivých AABB v dané ose jsou seřazeny dle<br />
velikosti. Převzato z [13]<br />
Pokud dojde k posunutí AABB, je nutné aktualizovat pozici minimálního a maximálního<br />
bodu ve spojitém seznamu. Metoda, která toto provádí, se nejprve podívá nalevo, zda aktuální<br />
hodnota není menší než předchozí hodnota. Pokud zjistí, že je menší, podívá se dále,<br />
dokud není nalezeno správné místo pro danou hodnotu. Ta je z původního místa smazána a<br />
následně vložena mezi dvě správné hodnoty. Obdobným způsobem se porovnávají hodnoty<br />
směrem doprava ve zřetězeném seznamu. Během hledání správného místa pro konkrétní hodnotu<br />
se hlídá, zda nedošlo k překrytí intervalu AABB s jiným AABB. Pokud se zjistí, že ano,<br />
tak je proveden test detekce kolize mezi těmito AABB. V případě, že je test pozitivní, je<br />
nalezená dvojice přidána mezi kandidáty na kolizi. Dále se během hledání musí ohlídat, zda<br />
naopak nedošlo k oddělení dvou intervalů. Pokud ano a objekty se nacházejí mezi kandidáty<br />
na kolizi, je nutné konkrétní záznam odstranit. Ve skutečnosti nejsou v seznamu uložené<br />
samotné hodnoty, ale reference na AABB. Navíc je součástí informace, která říká, zda se<br />
jedná o minimální nebo maximální hodnotu. Metoda, která vkládá nové AABB do seznamu,<br />
pracuje na podobném principu.<br />
Obecně se očekává, že se aktualizace seznamu provede v lineárním čase. Pokud se nachází<br />
mnoho objektů v jedné ose moc blízko u sebe, může být složitost O(n 2 ). Například se jedná<br />
o objekty položené na podlaze, jak znázorňuje následující obrázek 4.15 :<br />
Obrázek 4.15: Na obrázku vidíme objekty, které se nacházejí kousek od sebe v jedné ose.<br />
Pouze malý pohyb objektu může způsobit, že se hodnota uložená v seznamu posune o mnoho<br />
pozic. Převzato z [13]<br />
Jelikož se jedná o poměrně efektivní metodu a zároveň nemusí být řešeny problémy s<br />
velikostí buněk, byla použita do výsledné ukázkové aplikace. Další nespornou výhodou je, že<br />
32
se ukázka odehrává v prostředí vesmíru. Objekty se proto většinou neshlukují podél jedné z<br />
os, ale jsou různě rozprostřeny, což přesně vyhovuje použité metodě.<br />
33
5 Realizace<br />
V této kapitole se klade za cíl popsat zajímavá a neobvyklá řešení, která byla vybrána z<br />
výsledné implementace ukázkové aplikace.<br />
Hned první podkapitola 5.1 se zaměřuje na popis herní smyčky a možností jejího řešení.<br />
Ve výsledné ukázce bylo nutné řešit vykreslování průhledných objektů. Na problémy s tím<br />
spojené se snaží upozornit podkapitola 5.2. V podkapitole 5.3 je přiblížen postup, jak dochází<br />
k redukci zpracovávaných objektů grafickou kartou. Podkapitola 5.4 detailněji rozebírá<br />
způsob, jakým si uživatelé mezi sebou vyměňují informace po síti a upozorňuje na problémy<br />
s tím spojené. Poslední dvě podkapitoly 5.6 a 5.5 se zaměřují na konkrétní implementace<br />
laseru a generátoru asteroidů.<br />
5.1 Herní smyčka<br />
Herní smyčka určuje, kolikrát za sekundu dojde k aktualizaci scény a jak často se překreslí<br />
plátno, DOM ve webovém prohlížeči. Frekvence by měla být co možná největší, aby nedocházelo<br />
k zasekávání scény. Maximální hodnota opakování by neměla být vyšší než obnovovací<br />
frekvence monitoru, protože by nemuselo dojít k vykreslení některého ze snímků na obrazovku.<br />
První podkapitola 5.1.1 se zabývá samotným popisem RequestAnimationFrame API,<br />
které dnešní prohlížeče nabízejí pro lepší výkonnost. Druhá podkapitola 5.1.2 přibližuje možnosti<br />
použití tohoto API.<br />
5.1.1 RequestAnimationFrame API<br />
Web se v dnešní době stává stále více interaktivním. S vydáním HTML5 bylo uvedeno plátno<br />
Canvas [1], které dovoluje vykreslování různorodé grafiky. S jeho vydáním vzrostl požadavek<br />
na tvorbu efektivnějších animací ve webovém prohlížeči. Dříve se k modifikaci DOMu<br />
webového prohlížeče za běhu používaly a stále se někdy používají metody setTimeout a nebo<br />
setInterval, které dovolují překreslení stránky několikrát za sekundu. Tyto metody nejsou z<br />
pohledu výkonnosti moc efektivní. Animace jsou stále spuštěny i přes skutečnost, že došlo<br />
například k minimalizaci okna prohlížeče, přepnutí na jiný panel a podobně. Dokud nebylo<br />
tvůrci webových prohlížečů poskytnuto RequestAnimationFrame API”[18], tak webová platforma<br />
nenabízela tvůrcům aplikací jiný efektivní způsob, jak naplánovat jejich časování. V<br />
”<br />
dnešní době mnoho aplikací překresluje okno prohlížeče jednou za 10ms. Jde o zbytečně malou<br />
hodnotu, protože většina dnešních monitorů nedokáže aktualizovat obraz častěji než za<br />
16.7ms. To má za následek, že se některé snímky ztratí a vůbec se nevykreslí, což někdy vede<br />
k trhání výsledné animace.<br />
34
RequestAnimationFrame API”pracuje podobně jako setTimeout nebo setInterval. Hlavní<br />
”<br />
rozdíl spočívá v upozornění aplikace, že prohlížeč potřebuje aktualizovat obsah svého okna.<br />
Aplikace jsou tedy více svázány s obnovovací frekvencí okna webového prohlížeče. Počet opakování<br />
za sekundu není určen pevně, ale je dán zmíněným API. Na následujícím obrázku 5.1<br />
je vidět rozdíl ve výkonu mezi setTimeout a RequestAnimationFrame API.<br />
Obrázek 5.1: Rozdíl ve výkonu mezi setTimeout a RequestAnimationFrame API. Převzato<br />
z [18]<br />
API není zatím naimplementováno ve všech prohlížečích. Následující obrázek ukazuje<br />
podporu API jednotlivých verzí prohlížečů.<br />
Obrázek 5.2: Některé verze prohlížečů implementují API již nějakou dobu, jiné prohlížeče<br />
naopak API zatím ignorují a nebo ho připravují v budoucích verzích. Převzato z [19]<br />
35
RequestAnimationFrame API stejným způsobem jako setTimeout provádí jedno zpětné<br />
volání libovolné funkce. Z tohoto důvodu je nutné v případě potřeby více opakování, volat<br />
zmíněné API na konci cyklu, který má na starosti animační smyčku. Každý prohlížeč<br />
poskytuje API pod jiným názvem, protože jeho implementaci nemají zcela ukončenou.<br />
5.1.2 Použití RequestAnimationFrame API v aplikaci<br />
Nejdříve je nutné zjistit, pod jakým pracovním názvem se API v nejrozšířenějších prohlížečích<br />
nachází. Toto má na starosti níže uvedený fragment kódu, který je k dispozici ve výsledné<br />
platformě:<br />
window . requestAnimFrame = ( f u n c t i o n ( ) {<br />
// RequestAnimationFrame API j e z c e l a naimplementováno<br />
return window . requestAnimationFrame | |<br />
// implementace v p r o h l í ž e č i Chrome<br />
window . webkitRequestAnimationFrame | |<br />
// F i r e f o x implementace<br />
window . mozRequestAnimationFrame | |<br />
// p r a c o v í verze Opera Presto<br />
window . oRequestAnimationFrame | |<br />
// implementace IE<br />
window . msRequestAnimationFrame | |<br />
// případ , kdy p r o h l í ž e č nepodporuje<br />
RequestAnimationFrame API<br />
f u n c t i o n ( c a l l b a c k , element ) {<br />
return window . setTimeout ( c a l l b a c k , 1000/60);<br />
} ;<br />
} ) ( ) ;<br />
Herní smyčka poté ve výsledné ukázce vypadá následovně:<br />
f u n c t i o n loop ( ) {<br />
var currentTime = new Date ( ) . getTime ( ) ;<br />
i f ( t h i s . lastTime !=0){<br />
var elapsedTime = currentTime − that . lastTime ;<br />
/ / . . metody ř e š í c í animace , k o l i z e , r e n d e r i n g . . .<br />
that . lastTime = currentTime ;<br />
}<br />
// nekonečné opakování smyčky pomocí RequestAnimationFrame API<br />
nebo metody setTimeout<br />
window . requestAnimFrame ( loop , $(”#webGl−canvas ”) [ 0 ] ) ;<br />
}<br />
36
5.2 Průhlednost objektů<br />
Existují různé [?]způsoby, jak dosáhnout efektu průhlednosti. Z pohledu renderovacích algoritmů<br />
jsou uplatňovány 2 typy efektů:<br />
ˆ Takzvaný View based” efekt, kdy je poloprůhledný objekt sám vyrenderován.<br />
”<br />
ˆ Druhým způsobem je tzv Light-based” efekt, kdy objekt způsobí utlumení nebo odklonění<br />
světla. Výsledkem je větší osvětlení jiných objektů, které jsou nakonec vyren-<br />
”<br />
derovány odlišným způsobem.<br />
V ukázkové aplikaci je použita jednodušší varianta prvního způsobu, kde se poloprůhledný<br />
objekt ve své podstatě chová stejně jako barevný filtr, který je aplikován na všechny objekty<br />
za ním.<br />
První podkapitola 5.2.1 se zaměřuje na popis Z-bufferu a jeho nevýhody. Podkapitola<br />
5.2.2 popisuje techniku pro správné vykreslení průhledných objektů ve scéně.<br />
5.2.1 Z-buffer a jeho nevýhody<br />
Z-buffer v počítačové grafice řeší problém s viditelností objektů. Pokud je objekt vyrenderován,<br />
hloubka vykresleného pixelu je zaznamenána v Z-bufferu. Tento buffer je většinou<br />
udělán jako dvojrozměrné pole, které odpovídá jednotlivým pixelům. V případě, že musí být<br />
na obrazovku vykreslen jiný objekt, který se překrývá s původním, tak dojde k porovnání<br />
hloubky jednotlivých pixelů. Do Z-bufferu se zapíší pouze pixely, které se nacházejí blíže<br />
k pozorovateli. Ostatní pixely budou ignorovány a nedojde k jejich vykreslení. Z-buffer je<br />
součástí většiny moderních grafických akcelerátorů.<br />
Proč jsou vlastně v tuto chvíli zmiňovány Z-buffery? Jejich nevýhoda spočívá ve faktu,<br />
že si drží hodnotu pouze pro jeden naposledy uložený pixel. Výsledkem je, že Z-buffer sám<br />
o sobě nemůže vyřešit efekt průhlednosti. Jestliže se více průhledných objektů nachází v<br />
rámci jednoho pixelu, tak je nemožné vyhodnotit efekt průhlednosti pro všechny objekty.<br />
Dalším příkladem může být těleso, které má být vidět skrze jiný průhledný objekt. Jelikož<br />
dojde k jeho vykreslení později, jsou pixely za průhledným objektem ignorovány a nedojde<br />
k jejich vykreslení. Zmíněný problém je možné vyřešit pomocí takzvaného A-bufferu, který<br />
pracuje na podobném principu. Velice podstatnou nevýhodou je, že není mezi grafickými<br />
akcelerátory tolik rozšířen, takže jeho použití nepřipadá v úvahu.<br />
5.2.2 Vykreslení průhledných objektů<br />
Pro vykreslování průhledných objektů se často využívá techniky nazvané Alpha blending<br />
”<br />
”, kdy dochází k mísení barvy průhledného tělesa s barvou objektu za ním. Průhlednost<br />
objektu určuje hodnota alpha”. Každý pixel tedy obsahuje informaci o barvě RGB” a o<br />
” ”<br />
průhlednosti a”, dohromady RGBa. Hodnota 1.0 znamená, že je objekt zcela matný, naopak<br />
”<br />
při hodnotě alpha = 0.0 je objekt zcela průhledný.<br />
37
Operace mísení barev je zcela závislá na pořadí. Nejprve musí dojít k vykreslení matných<br />
objektů, aby bylo možné průhledné objekty míchat s objekty za nimi. Následně je zapotřebí<br />
seřadit všechny poloprůhledné objekty podle vzdálenosti od pozorovatele. Samozřejmě od<br />
nejvzdálenějšího po nejbližší. Až poté je možné poslat grafické kartě poloprůhledné objekty<br />
k vykreslení. Z-buffer v takovém případě může zůstat povolený a vykonávat svoji funkci,<br />
protože se vše vykresluje ve správném pořadí. Obrázek 5.3 z ukázkové aplikace znázorňuje<br />
situaci, kdy nejsou poloprůhledné objekty seřazeny a kdy naopak mají správné pořadí.<br />
Obrázek 5.3: a) Obrázek znázorňuje chyby ve vykreslení, pokud nejsou průhledné objekty<br />
seřazeny. b) Průhledné objekty jsou seřazeny.<br />
5.3 Viditelnost objektů<br />
Grafické karty dokáží velice efektivně provádět paralelní výpočty nad geometrickými objekty.<br />
Pokud bychom ale chtěli vyrenderovat 5000 objektů s 10000 trojúhelníky, tak bychom si moc<br />
nezahráli. Grafické kartě není nutné posílat ke zpracování vše, co se ve scéně nachází. Proč<br />
zpracovávat geometrická tělesa, která uživatel na obrazovce nevidí. Proto se používá metoda,<br />
která je popsána v podkapitole 5.3.1. Další metodu optimalizace přibližuje podkapitola 5.3.2.<br />
5.3.1 View frustum culling<br />
Takzvané View frustum[?] ve tvaru pyramidy je definováno celkem 6 plochami, které jsou<br />
uloženy v komponentě Camera. Těchto 6 ploch přesně určuje oblast, kterou uživatel aktuálně<br />
vidí. Následujícím způsobem dojde k identifikaci statických objektů, které mají být<br />
vyrenderovány:<br />
ˆ Každý objekt je umístěn v uzlu stromu Octree, o kterém bylo psáno v kapitole 4.5.2<br />
na straně 30.<br />
ˆ Před renderováním každého snímku se provede test kolize mezi výše zmíněným stromem<br />
a pyramidou, která definuje viditelnou oblast.<br />
ˆ Kolizní algoritmus vrátí všechny objekty, které se nacházejí v uzlech kolidujících s<br />
pyramidou.<br />
38
Výše zmíněným postupem došlo k významné redukci objektů, které mají být poslány k<br />
vyrenderování. Ale přesto je strom Octree naimplementován tak, že se mezi objekty dostanou<br />
i takové, které se nenacházejí ve viditelné oblasti. Pokud by výkon grafických karet nestačil,<br />
může dojít k testu kolize mezi pyramidou a nalezenými objekty. Jedná se konkrétně o test<br />
View frustum - koule. Tím se dosáhne požadovaného výsledku. Bohužel strom Octree se<br />
nehodí v aktuální implementaci k uchovávání dynamických objektů. Takový objekt by při<br />
každém pohybu musel být ze stromu vymazán a následně do něj vložen. Z tohoto důvodu je<br />
nutné provést test kolize mezi pyramidou pro každý objekt zvlášt’. Teoreticky by šlo použít<br />
způsob, kterým se testují kolize mezi všemi objekty ve scéně. Pyramida by v takovém případě<br />
musela být obalena krychlí. Poté už by se jen při každém pohybu hledali kandidáti na kolizi.<br />
5.3.2 Backface culling<br />
Backface culling je proces, při kterém dochází k identifikaci polygonů, které uživatel vidí.<br />
Tentokrát není potřeba nic implementovat, jedná se o standardní výbavu grafických karet.<br />
Pokud je Backface culling povoleno, tak dochází k ignorování polygonů, které uživatel nevidí.<br />
Nedochází ke zbytečnému zpracování vertexů, které se nacházejí na odlehlé straně. Ve<br />
výsledné aplikaci je Backface culling povoleno.<br />
5.4 Multiplayer<br />
Ukázková aplikace se odehrává v prostředí vesmíru, kde uživatelé mohou například ovládat<br />
vesmírné plavidlo, vytvářet nové brány a asteroidy. Všechny tyto změny a mnohé další se<br />
musejí promítnout u ostatních uživatelů, kteří se nacházejí ve stejný okamžik ve scéně. V<br />
prostředí internetu nikdy nelze dosáhnout stavu, že by uživatelé na druhé straně viděli změny<br />
v reálném čase. Vždy bude existovat určité zpoždění, s kterým se musí tvůrci her pro více<br />
hráčů vypořádat.<br />
Popisem známých architektur se zabývá podkapitola 5.4.1. Druhá podkapitola 5.4.2 popisuje<br />
vlastní implementaci multiplayeru v ukázkové aplikaci.<br />
5.4.1 Známé architektury<br />
V herním průmyslu existují dvě základní metody pro synchronizaci scény mezi uživateli[21]:<br />
Peer - too - peer - Jednotliví klienti komunikují přímo mezi sebou a vyměňují si informace<br />
formou zpráv. Například, pohnul jsem se o tolik a tolik, postavil jsem budovu na tomto<br />
místě, atd. Neexistuje žádný centrální server a nebo je pouze použit pro navázání<br />
komunikace mezi jednotlivými klienty. V dnešní době se metoda peer-to-peer už tolik<br />
nepoužívá. Můžeme ji vidět například v některých RTS hrách. Jsou s ní spojeny určité<br />
nevýhody. Není vždy zaručeno, že hra bude vypadat u každého hráče stejně. Někdy se<br />
mohou lišit jednotky, takže dojde k posunutí o jinou vzdálenost. Hráč se nemůže jen<br />
tak připojit v průběhu hry. Dále bývá problém v animacích a obecně v synchronizaci<br />
scény.<br />
39
Klient - server - Jedná se o doménu většiny akčních her. Místo toho, aby každý klient<br />
vykonával stejný kód a jednotliví klienti komunikovali mezi sebou, tak každý klient<br />
komunikuje pouze se serverem. Hlavní logika hry se vykonává pouze na serveru a<br />
jednotlivý klienti tvoří jakýsi terminál. Na server se odesílají pouze data ze vstupních<br />
zařízení jako je myš a klávesnice. Server aktualizuje na základě těchto dat stav scény a<br />
vrátí data s novou polohou hráče včetně informací o polohách ostatních hráčů. Aby byl<br />
pohyb ostatních hráčů plynulý, je nutné provádět interpolaci mezi předchozími stavy.<br />
Co se týče vlastní postavy ve hře, tak je nutné provádět predikci pohybu. Nějakou<br />
dobu totiž trvá než server vrátí novou polohu postavy. Odezva na vstup by tedy nebyla<br />
okamžitá a k pohybu postavy by došlo se zpožděním. Z tohoto důvodu se nečeká na<br />
odpověd’ serveru, ale normálně dojde k pohybu postavy. Server je autoritativní, takže<br />
pokud se pozice dodaná serverem bude lišit od té predikované, tak je nutné ji změnit.<br />
Zde ale nastává problém, server totiž poskytne data například 200ms stará a hráč by se<br />
posunul zpět v čase. Proto existuje buffer, který si pamatuje po určitou dobu všechny<br />
minulé stavy postavy včetně všech zmáčknutých kláves a tlačítek. Pokud přijde korekce<br />
od serveru, tak se zahodí všechny stavy, které jsou starší než aktuálně příchozí stav.<br />
Postava hráče se vrátí na pozici příchozího stavu a následně se na ni aplikují všechny<br />
vstupy uložené v bufferu. V takovou chvíli se postava nachází na správném místě a<br />
nedojde k posunutí v čase. Tento postup se neustále opakuje.<br />
5.4.2 Implementace multiplayeru v ukázkové aplikaci<br />
Do této doby Jetty server splnil vše, co se od něj očekávalo. Problém nastal při implementaci<br />
multiplayeru. Jetty server je totiž javovský a kód pro WebGl je psán v javascriptu. Z tohoto<br />
důvodu nemohla být použita implementace typu klient - server. Zde přichází v úvahu otázka,<br />
zda neexistuje lepší řešení, než kombinace WebGl + WebSocket + Jetty server? Odpověd’<br />
zní ano. Jako ideální volba se jeví kombinace WebGl + WebSocket + Node.js. Node.js se<br />
totiž chová jako standardní server, jehož kód se píše v javascriptu.<br />
Z výše napsaného textu vyplývá, že každý klient bude muset vykonávat svůj vlastní herní<br />
kód, což odpovídá metodě Peer-to-peer. Není to tak úplně pravda, protože jednotliví klienti<br />
nebudou mezi sebou komunikovat přímo, ale přes prostředníka. Technologie WebSockets totiž<br />
neumožňuje přímou komunikaci mezi webovými prohlížeči. Jednotliví klienti jsou připojeni<br />
k Jetty serveru, který má za úkol rozesílat data všem ostatním připojeným klientům. Ve<br />
vytvořené platformě je připraven objekt Multiplayer, pomocí kterého je možné se připojit<br />
k serveru. Každý klient je identifikován pod svým Id. Objekt Multiplayer obsahuje metodu<br />
pro odesílání dat ve formátu JSON ostatním klientům. Do této metody je možné vložit id,<br />
kterému klientovi se má informace poslat. Výchozí hodnotou je all”, což znamená, že se data<br />
”<br />
rozešlou všem ostatním klientům.<br />
Klienti se ve výsledné aplikaci mohou kdykoliv odpojovat a připojovat, což je pro metodu<br />
Peer-to-peer problém. Další problém nastal, kdy do scény měly být na začátku vygenerovány<br />
různé asteroidy. Kdyby každý klient při spuštění vygeneroval své asteroidy, tak by se vlastně<br />
každý hráč na začátku pohyboval v jiném prostředí. Oba zmíněné problémy řeší připojení<br />
speciálního klienta, který plní úlohu serveru a jehož Id je Server”. Takový klient musí být<br />
”<br />
40
vždy jen jeden.<br />
V dalším textu je pod pojmem server myšlen připojený speciální klient, nejedná se tedy o<br />
Jetty server. Na serveru je spuštěn stejný kód jako na jednotlivých klientech, ale nedochází k<br />
renderování informací na obrazovku. Další důležitou vlastností serveru je, že si pamatuje stav<br />
aktuální scény se všemi objekty a hráči. Pokud je zapotřebí na začátku vytvořit společnou<br />
scénu, například výše zmíněné asteroidy, tak musí být vytvořena jen pomocí serveru. V<br />
případě, že dojde k připojení nového klienta k Jetty serveru, je uplatněn následující postup:<br />
ˆ Klient informuje server, že se připojil.<br />
ˆ Server přidá mezi své objekty novou lod’ a přiřadí jí komponentu NetwokView, o které<br />
bylo psáno v kapitole 4.2.5 na straně 15. Následně jí nastaví unikátní Id. V dalším<br />
kroku přiřadí lodi komponentu Script, která má na starosti přijímání a odesílání zpráv<br />
pro daný objekt. Navíc tato komponenta provádí interpolaci stavu daného objektu,<br />
aby byl pohyb plynulý.<br />
ˆ Server odešle novému klientovi všechny informace o aktuální scéně a o ostatních hráčích.<br />
Poté všem ostatním klientům odešle všechna potřebná data o nově připojeném<br />
klientovi.<br />
ˆ Nově připojený klient vytvoří objekty na základě dat, které přijal ze serveru. Všechny<br />
takto vytvořené objekty musejí mít komponentu NetworkView s Id, které přiřadil server<br />
dané komponentě konkretního objektu. Stejně jako na serveru je novým objektům<br />
přiřazena komponenta Script, která slouží k interpolaci stavu jednotlivých pohyblivých<br />
objektů a k přijímání (odesílání) zpráv, které se týkají konkrétního objektu.<br />
ˆ Všichni ostatní klienti provedou podobné úkony jako výše popsaný klient, ale pouze<br />
pro nově přidanou lod’ připojeného klienta.<br />
ˆ Poté již dochází ke standardní komunikaci mezi klienty. Pomocí komponenty Script a<br />
metody sendState se posílá všem klientům a serveru informace o nové pozici hráče.<br />
Stejná komponenta u jiných objektů slouží pro příjem nového stavu daného objektu.<br />
U pohyblivých objektů, které neřídí sám uživatel, dochází pomocí komponenty Script<br />
k interpolaci rotace a pozice z minulých stavů objektu, aby byl pohyb plynulý.<br />
Server a jednotliví klienti používají dva rozdílné objekty multiplayer, které dědí vlastnosti<br />
z objektu WGLP. Multiplayer z výsledné platformy. Rodičovský objekt obsahuje základní<br />
metody pro připojení a komunikaci. Všechny odchozí zprávy musí obsahovat název příkazu,<br />
který se má spustit u protějšího klienta nebo serveru. Jeden z výše uvedených multiplayer<br />
objektů zprávu přijme a spustí metodu se stejným názvem, který byl uveden v příkazu.<br />
Využívá se vlastnosti javascriptu, že názvy objektů či metod mohou být doplněny dynamicky.<br />
V javascriptu jsou si totiž následující zápisy rovny:<br />
// neměnný název metody<br />
s e r v e r M u l t i p l a y e r . addSpaceShip ( ) ;<br />
// název volané metody může být změněn<br />
s e r v e r M u l t i p l a y e r [ ” addSpaceShip ”] ( ) ;<br />
41
Skript, který provádí interpolaci, potřebuje ke své činnosti vědět, s jakým zpožděním<br />
přicházejí nové stavy objektu. Z tohoto důvodu má objekt WGLP.Multiplayer zabudovanou<br />
metodu checkLatency, která následujícím způsobem zjistí zpoždění mezi Jetty serverem a<br />
připojeným klientem :<br />
ˆ Metoda odešle na Jetty server informaci o aktuálním času.<br />
ˆ Jetty server ihned odešle informaci klientovi zpět.<br />
ˆ Klient zjistí zpoždění pomocí vztahu : zpoždění = (aktuálníČas - původníČasOdesláníZprávy)/2.<br />
Každý klient musí jednou za čas aktualizovat zpoždění mezi Jetty serverem. Pokud se posílá<br />
stav některého z objektů, tak se v rámci jedné zprávy vždy odešle informace o zpoždění<br />
prvního klienta s Jetty serverem. Na druhém konci se k tomuto zpoždění přičte zpoždění<br />
druhého klienta s Jetty serverem, který zprávu obdržel. Tím se získá celková hodnota, která<br />
je potřebná k interpolaci.<br />
Klient, který tvoří server, není autoritativní. Všichni klienti nedostávají informace o stisknutých<br />
klávesách, tlačítkách, ale přímo obdržují nový stav objektu. Takový způsob není<br />
ideální z pohledu bezpečnosti, protože kdykoliv někdo může ostatním klientům podstrčit<br />
upravená data. Například se hráč může uměle teleportovat na jiné místo a ostatní klienti<br />
tomu uvěří, což u autoritativního serveru není možné. Takový přístup by nebyl ve stávající<br />
architektuře vhodný, protože server není ve skutečnosti server, ale speciální klient. Data by<br />
musela cestovat přes Jetty server ke speciálnímu klientovi a zase zpět, což by akorát zvětšovalo<br />
hodnotu zpoždění, a to není žádoucí. Navíc nemusí být řešen problém s predikcí.<br />
Očekává se také, že případní uživatelé aplikací postavených na koncové platformě, nebudou<br />
podvádět.<br />
5.5 Generátor asteroidů<br />
Ve scéně se nachází mnoho asteroidů. Z pohledu uživatele není dobrým řešením, aby každý<br />
asteroid vypadal zcela totožně. Jejich tvar a velikost by měly být variabilní. První, ne zcela<br />
ideální možností je vymodelovat několik asteroidů v modeláři a ty podle určitého vzorce ve<br />
scéně střídat. Jelikož uživatelé mají možnost generovat své vlastní asteroidy, tak by došlo k<br />
velice brzkému okoukání těch stávajících. Scéna by si zasloužila asteroidy rozmanitých velikostí,<br />
tvarů a případně barev. Proto bylo hledáno ideální řešení, jak programově vygenerovat<br />
tyto skalní útvary.<br />
Prví podkapitola 5.5.1 ukazuje princip použitého algoritmu. Druhá podkapitola 5.5.2 se<br />
zabývá popisem problému, který nastává v případě, kdy spuštěný skript trvá moc dlouhou<br />
dobu.<br />
5.5.1 Algoritmus pro generování asteroidů<br />
Nakonec bylo nalezeno řešení, které vyhovuje potřebám výsledné scény. Došlo k modifikaci<br />
algoritmu[22], pomocí kterého se dají například vytvořit různě zvrásněné kontinenty na mo-<br />
42
delu planety země. Postupuje se v několika krocích:<br />
1. Na začátku se nachází pravidelná koule získaná z modeláře.<br />
2. Dojde k náhodnému zvětšení nebo zmenšení koule.<br />
3. Koule je rozpůlena náhodně vygenerovanou rovinou.<br />
4. Všechny vertexy, které se nachází před rovinou, jsou posunuty o náhodnou hodnotu<br />
směrem od středu.<br />
5. Všechny vertexy, které se nachází za rovinou, jsou posunuty o stejnou hodnotu směrem<br />
ke středu.<br />
6. Body 3 až 5 jsou opakovány x krát, kde x je náhodně vygenerované celé číslo.<br />
Následující obrázek zobrazuje náhodně vygenerované plochy a výsledek po několika iteracích:<br />
Obrázek 5.4: a) Počáteční koule rozpůlená rovinou. b) Koule je rozpůlena jinou rovinou.<br />
Vertexy před rovinou se posunuly směrem ke středu a vertexy za rovinou směrem od středu.<br />
c) Výsledek po několika iteracích.<br />
5.5.2 Problém s generováním více asteroidů<br />
Webové prohlížeče si obecně neumějí poradit se skripty, které trvají moc dlouhou dobu.[23]<br />
V takovém případě zobrazí hlášku, která upozorňuje uživatele, že skript pracuje neúměrně<br />
43
dlouho a zda si přeje počkat na jeho dokončení. Nejspíše se jedná o nějakou formu bezpečnostního<br />
opatření. Navíc v typické smyčce vytvořené pomocí cyklů for” nelze aktualizovat DOM<br />
”<br />
prohlížeče, protože je zablokovaný. Bohužel není zablokovaný jen pro vývojáře, ale také pro<br />
uživatele, takže prohlížeč nereaguje na žádná kliknutí. Při generování například 1000 asteroidů<br />
dojde k vyskočení zmíněné hlášky, uživatel nemůže být informován o průběhu generování<br />
a navíc je blokované okno prohlížeče.<br />
Výše uvedené problémy lze vyřešit pomocí metody setTimeout(). Při jejím vykonávání<br />
se na chvíli uvolní DOM prohlížeče, takže může být aktualizován jeho obsah. Cyklus for” ”<br />
lze bud’ celý nahradit metodou setTimeout(), a nebo je možné uvedenou metodu volat jen<br />
jednou za x provedených cyklů for”. S tímto způsobem jsou spojeny určité problémy, ale<br />
”<br />
svůj hlavní účel plní. V ukázkové aplikaci se uživateli takto zobrazuje číslo generovaného<br />
asteroidu.<br />
5.6 Laser<br />
Laser je ve výsledné aplikaci používán k sestřelování bran a asteroidů. Měl by mít hezký<br />
vzhled a působit realisticky.<br />
Podkapitoly 5.6.1 a 5.6.2 popisují techniku zvanou Billboarding. Podkapitola 5.6 používá<br />
techniku popsanou v předchozích dvou podkapitolách.<br />
5.6.1 Billboarding<br />
Z důvody tvorby laseru byla do platformy přidána podpora billboardů [?] ve formě nového<br />
BillboardRendereru. Jedná se o orientovaný a otexturovaný polygon, který se otáčí v závislosti<br />
na pohybu kamery. Pomocí Billboardů s průhlednými texturami a animacemi mohou<br />
být vytvářeny různorodé efekty, které není možné udělat efektivně pomocí geometrických<br />
těles. Výborným příkladem je vegetace, obzvláště tráva. Dále kouř, oheň, mlha, exploze, atd.<br />
Billboardy se někdy používají k nahrazení objektu. Především v momentě, kdy se uživatel<br />
nachází ve větší vzdálenosti a již není schopen rozeznat detaily původního geometrického<br />
tělesa. Tím se ušetří výpočetní výkon, protože není potřeba renderovat komplexní objekt,<br />
ale pouze otexturovanou plochu. Dalším příkladem užití je HUD, na kterém se uživateli zobrazují<br />
informace o hře. Při programování WebGl aplikací je snadnější HUD vytvořit pomocí<br />
elementů jazyka HTML, protože se jedná o webovou stránku.<br />
Rotace billboardu se většinou určuje dvěma vektory(up, forward). Problém je v tom,<br />
že na sebe nebývají většinou kolmé, což není přípustné. Podle typu billboardu se jeden z<br />
těchto vektorů stane fixním. Pomocí vektorového součinu se nejprve vypočte třetí vektor,<br />
který je kolmý na oba zmíněné. Poté dojde k výpočtu vektoru, který není fixní a to tak,<br />
že se provede vektorový součin mezi fixním a nově vypočítaným vektorem. Všechny tyto tři<br />
vzniklé a následně normalizované vektory tvoří rotační matici billboardu.<br />
44
5.6.2 Nejpoužívanější typy billboardů<br />
Existují tři základní druhy billboardů, které se nejčastěji používají. Všechny tři jsou naimplementovány<br />
ve výsledné platformě. Při tvorbě komponenty BillboardRenderer je nutné si<br />
zvolit požadovaný typ billboardu. Samozřejmě je potřeba poskytnout rendereru všechny důležité<br />
informace o požadovaném billboardu. Především jde o rozměry, kameru a směr fixního<br />
vektoru.<br />
Billboard zarovnaný s obrazovkou již svým názvem napovídá, že jde o billboard rovnoběžný<br />
s obrazovkou a jehož vektor směřující vzhůru (up vector) je konstantní. Up ”<br />
vektor” je totožný s up vektorem” kamery. Jde o typ billboardu, který se v různých<br />
”<br />
aplikacích používá například jako HUD.<br />
Billboard orientovaný směrem k pozorovacímu bodu je vždy natočený směrem ke<br />
kameře (fixní vektor) a jehož vektor směřující vzhůru je pevně daný a nezávislý na<br />
rotaci kamery.<br />
Obrázek 5.5: Billboardy orientované směrem k pozorovacímu bodu<br />
Osově zarovnaný billboard není primárně natočen směrem ke kameře a navíc může rotovat<br />
kolem libovolné osy. Jednoduše řečeno má fixní ”<br />
up vector” a jeho ”<br />
forward vektor”,<br />
který ukazuje směrem ke kameře, je až podružný.<br />
5.6.3 Tvorba laseru<br />
Laser je vytvořen pomocí osově zarovnaného billboardu pokrytého průhlednou texturou červeného<br />
laseru. Orientace vesmírné lodi určuje směr up vektoru”. Pokud uživatel stiskne<br />
”<br />
klávesu, která obsluhuje laser, dojde k jeho roztažení ve směru up vektoru”. S roztažením je<br />
”<br />
nutné posunout laser tak, aby vždy začínal na špičce vesmírné lodi. MeshRendreru laseru je<br />
přiřazen obalový OBB, který nejlépe odpovídá tvaru billboardů. Reakce laseru na stisknutou<br />
klávesu zařizuje komponenta Script, která je přiřazena konkrétnímu objektu GameObject.<br />
Podle polohy objektu se obalová tělesa sice posouvají a rotují, ale nedochází k jejich zvětšení.<br />
Proto je nutné s roztahováním laseru také zvětšovat OBB ve stejném směru. Výsledný laser<br />
je zobrazen na následujícím obrázku 5.6 na následující straně:<br />
45
Obrázek 5.6: Laser z ukázkové aplikace<br />
46
6 Testování<br />
Aplikace byla otestována nejen z uživatelského hlediska, ale také s důrazem na nalezení<br />
implementačních chyb. V první podkapitole 6.1 se rozebírají nalezená zjištění od uživatelů<br />
především co se týče ovládání ukázkové aplikace. Druhá podkapitola 6.2 se zaměřuje na<br />
implementační chyby aplikace.<br />
6.1 Uživatelský test<br />
Výsledná aplikace je zaměřena spíše na mladší generaci, ale nic nebrání starším lidem, aby<br />
si ji vyzkoušeli. Pokud má uživatel základní znalosti počítačů, je schopen ovládat myš a<br />
klávesnici, může se ponořit do vytvořené virtuální reality.<br />
Uživatelé obecně neměli problém s pochopením uživatelského rozhraní. Spuštění scény<br />
se obešlo většinou bez větších komplikací. Lod’ se ovládá jen pomocí klávesnice, což byl asi<br />
největší kámen úrazu. Lidé jsou z dnešních her spíše zvyklí na ovládání pomocí myši. Velice<br />
často se stávalo, že si uživatelé pletli klávesy. Chtěli se například otočit kolem osy x a místo<br />
toho zrychlili pohyb lodě. V několika případech se stalo, že uživatel místo brány vygeneroval<br />
nový asteroid. Pro nové hráče by asi byla každá brána malá, protože se častěji stávalo, že<br />
došlo k nárazu. Velikost zůstane ale nezměněna, protože jde spíše o již zmíněný problém s<br />
ovládáním.<br />
Z provedeného testu lze usuzovat, že by uživatelé uvítali alespoň částečné ovládání pomocí<br />
myši. Dále z testování vyplynulo, že trvá delší dobu, než si uživatelé zapamatují funkcionalitu<br />
jednotlivých kláves. Přeci jenom možností, kam se může lod’ pohybovat, je trochu více.<br />
6.2 Test aplikace<br />
Aplikace byla otestována takovým způsobem, že se spustila hlavní scéna a připojilo se několik<br />
uživatelů. Problémů nebylo nalezeno mnoho, ale přeci jenom se určité nedokonalosti aplikace<br />
projevily. Při masivnějším přístupu uživatelů došlo k pádu aplikace. V konzoli se následně<br />
začaly objevovat samé hodnoty null, popřípadě jiné výjimky týkající se kolekce, ve které<br />
jsou na serveru uloženi všichni připojení uživatelé. Problém aktuálně není vyřešen, ale text<br />
výjimek naznačuje, že by se mohlo jednat o chybu způsobenou vlákny, které se snaží najednou<br />
přistupovat v jeden okamžik k výše zmíněné kolekci. Jedno vlákno například čte z kolekce<br />
data a druhé se snaží vymazat záznam, což u kolekce HashMap najednou nelze. Jak již bylo<br />
napsáno, aplikace zcela spadla, takže správně nepracovalo ani počítadlo aktuálně připojených<br />
uživatelů. Scénu bylo sice možné uložit, ale následné spuštění se nezdařilo, protože soubor<br />
obsahoval chybná data.<br />
Dalším zjištěným problémem bylo, že scéna nevydržela připojená přes noc. Technologie<br />
WebSockets totiž automaticky po nějaké době odpojuje klienta, který dlouho nevykazoval<br />
žádnou činnost a ani nedocházelo z jeho strany k příjmu dat od jiných uživatelů. Z tohoto<br />
důvodu se řídící scéna nejspíše odpojila, protože neměla s kým komunikovat. Řešením by<br />
bylo pravidelné informování serveru, že klient zůstává aktivní.<br />
47
Problémy se týkaly především sít’ové komunikace. Co se týče samotné hry a prostředí,<br />
významné chyby nebyly zatím objeveny.<br />
48
7 Závěr<br />
Cílem <strong>práce</strong> bylo navrhnout a naimplementovat webovou platformu pro interakci uživatelů v<br />
3D prostoru. Vlastnosti platformy měly být demonstrovány na ukázkové aplikaci. V kapitole<br />
2 byly stanoveny cíle <strong>práce</strong>, které se vesměs podařilo splnit, a to bud’ s menšími nebo většími<br />
obtížemi. WebGl není jedinou technologií, pomocí které je možné prezentovat 3D objekty<br />
ve webovém prohlížeči. Vývojová platforma Unity se zdá být výborná a také posloužila<br />
jako hlavní inspirace pro návrh struktury platformy. Co se týče Stage3D, tak i zde je velký<br />
potenciál k masivnějšímu rozšíření, protože téměř není člověka, který by neměl nainstalovaný<br />
Flash přehrávač na svém PC. Bude velice zajímavé sledovat, jaká z těchto technologií se více<br />
prosadí, a která spíše zapadne do stavu zapomnění.<br />
Co se týče architektury, tak se podařilo najít celkem použitelnou strukturu, která dává<br />
určitý smysl. Každý objekt ve scéně je vytvořen konstruktorem GameObject s jedinečným<br />
Id, na který jsou následně nabalovány komponenty podle potřeby. Komponenty objektu<br />
přidají fyzikální vlastnosti, obalí ho tělesem, obohatí ho o určitou logiku, umožní jeho vykreslení<br />
a obecně doplní různou funkcionalitu. Není problém vytvořit si vlastní konstruktor<br />
objektu s požadovanými proměnnými, metodami a následně zdědit všechny vlastnosti objektu<br />
GameObject. Platforma totiž neobsahuje jen objekty, metody,třídy, které jsou potřeba<br />
k vykreslování či fyzice. Ale musely být naimplementovány takové struktury jako je oboustranně<br />
zřetězený seznam, dále metoda umožňující dědění vlastností jiného objektu , metoda<br />
umožňující rozšíření stávajícího objektu a podobně.<br />
Analýza dále ukázala, že existuje velké množství obalových těles, která se hodí jen na<br />
určité typy objektů. To samé platí v případě stromů, mřížek, řadících algoritmů, pro které<br />
platí, že ne vždy se hodí do každé situace. Proto je třeba vždy velice zvážit jaké obalové těleso<br />
se přiřadí objektu, a nebo jaká se použije metoda na dělení prostoru. Fyzikální systém je<br />
určitě velice užitečný, protože dokáže simulovat chování reálného světa. Pomocí pružiny lze<br />
dosáhnou takových efektů, jako je houpání hladiny moře, pohyb oblečení a podobně. Pružina<br />
je také ideální volbou pro to, aby byl pohyb kamery za avatarem dynamický a nestála stále na<br />
jednom místě. Škoda jen, že se nestihl naimplementovat částicový systém, pomocí kterého je<br />
možné vytvářet efekty jako je kouř, oheň, mlha, exploze a podobně. Implementaci takového<br />
systému lze budoucímu vývojáři jen doporučit.<br />
V kapitole 5 bylo ukázáno, že není dobré pro různé animace v prohlížeči používat metodu<br />
setTimeout, protože je neefektivní s ohledem na výpočetní výkon. Je lepší využívat prohlížečem<br />
nabízené API, které šetří čas i peníze. Dále bylo ukázáno, jak tvořit zajímavé tvary<br />
asteroidů pomocí náhodně vygenerovaných rovin a posouváním vertexů. Musel být také vyřešen<br />
problém se sdílením scény mezi uživateli, kdy nakonec byla použita taková podivná<br />
kombinace metod klient - server a peer - to - peer. Rozhodně by bylo lepší v budoucnosti<br />
vyměnit Jetty server za Node.js, protože je možné jeho kód psát v javascriptu.<br />
Testování v kapitole 6 ukázalo, že ukázková aplikace netrpí zásadními nedostatky. Většinou<br />
se jednalo o problémy spojené se sít’ovou komunikací, které zatím nebyly vyřešeny.<br />
Nejspíše to bylo způsobeno tím, že se dvě vlákna snažila najednou měnit či číst jednu a tu<br />
samou kolekci. Tímto směrem by se měl budoucí vývojář vydat při hledání chyby.<br />
49
Celkově se nejednalo o snadnou práci, protože se týkala najednou více témat, která spolu<br />
více či méně souvisela, ale za to těch zkušeností bylo získáno opravdu velké množství, které<br />
budou určitě někdy zužitkovány. Pro budoucího vývojáře je připraven základ platformy, která<br />
se nadále může vesele rozvíjet a nadále rozšiřovat.<br />
50
Reference<br />
[1] LAWSON, Bruce ; SHARP, Remy . Introducing HTML5. Berkeley : New Riders, 2011.<br />
223 s.<br />
[2]<br />
JIŘÍ, Žára, Bedřich BENEŠ, Jiří SOCHOR a Petr FELKEL. Moderní počítačová grafika.<br />
Vyd 1. Brno: Computer Press, 2004, 609 s. ISBN 80-251-0454-0<br />
[3] SCABIA, Marco. How Stage3D works. Adobe [online]. 3.10.2011 [cit. 2012-05-<br />
18]. Dostupné z: http://www.adobe.com/devnet//flashplayer/articles/how- stage3dworks.html<br />
[4] UNITY: Game Development Tool [online]. San Francisco, © 2012 [cit. 2012-05-17].<br />
Dostupné z: http://unity3d.com<br />
[5] MUNSHI, Aaftab a Jon LEECH. OpenGL ES Common Profile Specification [online].<br />
Verze 2.0.25. The Khronos Group Inc., 2.11.2010 [cit. 2012-05-18]. Dostupné z:<br />
http://www.khronos.org/registry/gles/specs/2.0/es full spec 2.0.25.pdf<br />
[6] MARRIN, Chris. WebGL Specification. The Khronos Group Inc.<br />
[online]. Version 1.0. 10.2.2011 [cit. 2012-05-18]. Dostupné z:<br />
https://www.khronos.org/registry/webgl/specs/1.0/<br />
[7] THOMAS, Giles. Learning WebGL [online]. 13.10.2009 [cit. 2012-05-18]. Dostupné z:<br />
http://learningwebgl.com/blog/?p=28<br />
[8] WebSocket.org – A WebSocket Community [online]. Kaazing Corporation, © 2012 [cit.<br />
2012-05-19]. Dostupné z: http://www.websocket.org/index.html<br />
[9] SOMMER, Benjamin. Benjamin Sommer Weblog [online]. 13.5.2012 [cit. 2012-05-<br />
19]. Dostupné z: http://weblog.benjaminsommer.com/blog/2012/05/13/comparison-ofwebgl-framework-apis/<br />
[10] GLGE WebGL Library/Framework [online]. GLGE, 12.2.2012 [cit. 2012-05-20]. Dostupné<br />
z: http://www.glge.org/api-docs/<br />
[11] JONES, Brandon. High performance matrix and vector operations for WebGL<br />
[online]. GitHub · Social Coding, ©2011 [cit. 2012-05-20]. Dostupné z:<br />
https://github.com/toji/gl-matrix<br />
[12] MILLINGTON, Ian. Game physics engine development: how to build a robust<br />
commercial-grade physics engine for your game. 2nd ed. Boston: Morgan Kaufmann<br />
Publishers, c2010, xxix, 522 p. ISBN 01-238-1976-8.<br />
[13] ERICSON, Christer. Real-time collision detection. Vyd. 1. Boston: Morgan Kaufmann,<br />
2005, 591 s. ISBN 15-586-0732-3.<br />
[14] GLASSNER, A. Graphics gems I. San Diego: Academic Press, 1998, 301 - 303. ISBN<br />
0-12-286166-3.<br />
51
[15] LENGYEL, Eric. Mathematics for 3D game programming and computer graphics, third<br />
edition. 3rd Ed. Boston, MA: Cengage Learning, 2011, 212 - 216. ISBN 1435458869.<br />
[16] COLLADA - 3D Asset Exchange Schema. The Khronos Group Inc. [online]. ©2012 [cit.<br />
2012-05-22]. Dostupné z: http://www.khronos.org/collada/<br />
[17] Wavefront .obj file. In: Wikipedia: the free encyclopedia [online]. San Francisco<br />
(CA): Wikimedia Foundation, 2.5.2012 [cit. 2012-05-22]. Dostupné z:<br />
http://en.wikipedia.org/wiki/Wavefront .obj file<br />
[18] Using PC Hardware more efficiently in HTML5: New Web Performance APIs,<br />
Part 1. MANN, Jatinder. MSDN Blogs [online]. 6.7.2011 [cit. 2012-05-22]. Dostupné<br />
z: http://blogs.msdn.com/b/ie/archive/2011/07/05/using-pc-hardware-moreefficiently-in-html5-new-web-performance-apis-part-1.aspx<br />
[19] When can I use requestAnimationFrame?. When can I use...: Compatibility tables for<br />
support of HTML5, CSS3, SVG and more in desktop and mobile browsers. [online]. 2012<br />
[cit. 2012-05-23]. Dostupné z: http://caniuse.com/requestanimationframe<br />
[24] MÖLLER, Tomas Akenine. Real-time rendering. 3rd ed. Wellesley, Mass.: A.K. Peters,<br />
c2008, xviii, 1027 s. ISBN 978-1-56881-424-7.<br />
[21] FIEDLER, GLENN. What every programmer needs to know about game networking.<br />
Glenn Fiedler’s Game Development Articles and Tutorials [online].<br />
24.1.2010 [cit. 2012-05-23]. Dostupné z: http://gafferongames.com/networking-forgame-programmers/what-every-programmer-<br />
needs-to-know-about-game -networking/<br />
[22] Spherical Landscapes. The good-looking textured light-sourced bouncy fun<br />
smart and stretchy page [online]. 22.11.2003 [cit. 2012-05-24]. Dostupné z:<br />
http://freespace.virgin.net/hugo.elias/models/m landsp.htm<br />
[23] The Secret of Keeping Web Apps Responsive. Windy Road [online]. 30.3.2007 [cit.<br />
2012-05-25]. Dostupné z: http://windyroad.org/2007/03/30/web -apps-the-new-singlethreaded-gui/<br />
[25] FALCONER, Aubrey. NetworkView Position Sync. Unify Community<br />
[online]. 10.1.2012 [cit. 2012-05-27]. Dostupné z:<br />
http://www.unifycommunity.com/wiki/index.php?title=NetworkView Position Sync<br />
[26] JQuery: The Write Less, Do More, JavaScript Library [online]. © 2012 [cit. 2012-05-27].<br />
Dostupné z: http://jquery.com/<br />
52
A<br />
Balíky platformy<br />
Obrázek A.1: Balíčky, které strukturují zdrojový kód<br />
54
B<br />
Celkový UML diagram<br />
Obrázek B.1: Celkový uml diagram, který obsahuje všechny důležité třídy (konstruktory)<br />
56
C<br />
Uživatelská příručka<br />
Instalace<br />
Není nutné nic instalovat. Aplikace pouze vyžaduje javu minimálně ve verzi 1.7. Ke spuštění<br />
stačí webový prohlížeč s podporou WebGl a WebSockets. Chrome a Firefox již minimálně<br />
rok obě technologie podporují. Internet Explorer bohužel technologii WebGl nepodporuje a<br />
zatím to ani nemá v plánu.<br />
Nastavení<br />
Před spuštěním je potřeba nastavit v souboru websockets settings.js ip adresu a port. Soubor<br />
se nachází v adresáři ./webapp/scenes/space/app/.<br />
Spuštění Jetty serveru<br />
Zkompilovaný server se nachází v kořenovém adresáři projektu. Server se spouští přes konzoli<br />
pomocí následujícího přikazu:<br />
java − j a r s e r v e r . j a r parametr1 parametr2 parametr3<br />
kde<br />
parametr1 je ip adresa, na které se má spustit server. Nastavena defaultně na ”<br />
localhost”.<br />
parametr2 je port. Defaultně nastaven na 8080.<br />
parametr3 je webový adresář s aplikací. Defaultně nastaven na ”<br />
./webapp”.<br />
Spuštění<br />
Po zadání ip adresy do prohlížeče se objeví následující úvodní okno:<br />
58
Obrázek C.1: Úvodní obrazovka<br />
Vždy při prvním načtení úvodního okna je třeba spustit hlavní řídící scénu. Ta se spouští<br />
stisknutím klávesy S a následným kliknutím na tlačítko Spustit novou scénu. Pozor, neklikat<br />
v tomto případě na tlačítko Spustit v úvodním okně . Řídící scéna musí být spuštěna vždy<br />
jen jedna.<br />
Obrázek C.2: a) Okno, které se objeví po stisknutí klávesy S v úvodním okně. b) Okno<br />
informující o stavu scény po jejím spuštění. Pomocí tlačítka Uložit scénu lze uložit aktuální<br />
stav scény.<br />
59
Řídící scéna nejprve vygenerovala několik asteroidů a poté došlo k jejímu spuštění. Objevilo<br />
se informační okno, které ukazuje aktuální počet připojených uživatelů. Scénu je možné<br />
kdykoliv uložit. V průběhu hraní nesmí dojít k zavření okna webového prohlížeče, ve kterém<br />
je spuštěna řídící scéna.<br />
V tuto chvíli je potřeba otevřít nové okno prohlížeče a zadat opět ip adresu serveru.<br />
Otevřelo se Úvodní okno, stejné jako na obrázku C.1 na předchozí straně. Po kliknutí na<br />
tlačítko Spustit se objeví nová zatím neznámá obrazovka. Viz další obrázek C.3:<br />
Obrázek C.3: a) Okno, kde se uživatel může připojit jako nový hráč. b) Okno, kde si uživatel<br />
může vybrat ze seznamu odpojených hráčů a přebrat jeho vesmírnou lod’.<br />
Na první pohled zaujme přepínač, který nabízí 2 možnosti:<br />
Nový hráč - V případě zvolení této možnosti musí uživatel vyplnit přezdívku pod jakou si<br />
přeje ve scéně vystupovat. Poté stačí kliknout na tlačítko Spustit scénu.<br />
Vybrat hráče - Zde se uživatel nepřipojuje jako nový hráč, ale může si vybrat ze seznamu<br />
odpojených hráčů. Po spuštění scény je mu přiřazena lod’ bývalého hráče na poslední<br />
známé pozici. Nový hráč přebírá původní přezdívku odpojeného hráče.<br />
Nyní je spuštěna scéna.<br />
60
Obrázek C.4: Okno se scénou. Vlevo nahoře je vidět vzdálenost uživatele od středu, rychlost a<br />
uplynulý čas od průletu první brány. Vpravo nahoře se objevují informace o nově připojených<br />
nebo odpojených hráčích.<br />
Kdykoliv je potřeba uložit stávající scénu, tak je nutné otevřít okno webového prohlížeče,<br />
kde se nachází spuštěná řídící scéna. Jde o stejné okno jako na obrázku C.2 na straně 59,<br />
konkrétně jde o obrázek b).<br />
Co se týče načtení uložené scény, tak se postupuje zcela stejně jako když se spouští nová<br />
řídící scéna, akorát s tím rozdílem, že se neklikne na tlačítko Spustit novou scénu, ale na<br />
tlačítko Nahrát uloženou scénu. Tím dojde ke spuštění uložené scény.<br />
C.0.1<br />
Ovládání<br />
Vpřed / vzad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .W/S<br />
Zastavení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C<br />
Vlevo / vpravo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Q/E<br />
Nahoru / dolu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .R/F<br />
Rotace kolem osy x (pitch) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . U/J<br />
Rotace kolem osy y (yaw) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A/D<br />
Rotace kolem osy z (roll) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . H/K<br />
Vytvoření brány . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B<br />
Vygenerování asteroidu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . V<br />
Laser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Mezerník<br />
Kamera nahoru / dolu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 / 1<br />
Kamera vpřed / vzad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 / 4<br />
61
Označení první brány (restart závodu) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0<br />
C.0.2<br />
Hra<br />
Závod se spustí průletem první brány. Závodit může i více závodníků najednou, ale každému<br />
se čas měří od prvního průletu. Každý závodník vidí zvýrazněnou příští bránu (pro sebe) a<br />
méně zvýrazněné příští brány ostatních připojených účastníků. Pokud nemá bránu v zorném<br />
poli, vidí po straně obrazovky šipku ukazující nejbližší vzdálenost. Hráč může po stisku<br />
klávesy nechat vygenerovat asteroid nebo bránu. Asteroidy a brány je možné sestřelovat<br />
laserem. Závod lze pro sebe restartovat stisknutím klávesy 0.<br />
62
D<br />
Obsah přiloženého CD<br />
Obrázek D.1: Výpis souboru readme.txt<br />
64