Zadán´ı bakalárské práce

Transkript

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

Podobné dokumenty

DocBy.TEX – nástroj na dokumentování zdrojových kódů Obsah

DocBy.TEX – nástroj na dokumentování zdrojových kódů Obsah příkazem \module cosi . V souboru cosi.d je možno se literárně vyřádit a kdykoli vložit část existujícího zdrojového kódu programu se stejným jménem modulu. To provedeme příkazem \ins c keyword , k...

Více

Zobrazit nápovědu v souboru

Zobrazit nápovědu v souboru Prostředí Adobe® AIR® je víceobrazovkový běhový modul pro více operačních systémů, pomocí něhož můžete využít své stávající znalosti v oblasti vyvíjení webů při vytváření a zavádění aplikací RIA (R...

Více

Rozs20 s19 r20 ren19 ExtBrain Communicatoru o dals20 s19

Rozs20 s19 r20 ren19 ExtBrain Communicatoru o dals20 s19 za překlad a korekturu a samozřejmě také Florian Quèze, hlavnı́mu vývojáři Instantbirdu.

Více

Semestráln´ı práce

Semestráln´ı práce 3. Je-li aktuálnı́ vrchol obarvený, algoritmus se opakuje od bodu 2. Je-li zásobnı́k prázdný, pokračuje se na dalšı́ neobarvený vrchol v grafu (bod 1). Může totiž dojı́t k situaci, kdy s...

Více

XNA Game Studio 3.1

XNA Game Studio 3.1 Základy operačních systémů Struktura a návrh síťových služeb Rozšířené služby a role Bezpečnost

Více

Maxidort Tvrdlovec

Maxidort Tvrdlovec zabývající se „narozeninovým Leošem“ (jak jsem ho pracovně nazval) číslo 30. Těm, které zatím nenapadá žádná souvislost s předchozím odstavcem, budiž pro tentokrát odpuštěno. Vždyť násobek čísel pa...

Více