tinr skripta predavanj 3

20
TINR @ FRI, draft v09, Peter Peer ++ 31 Predavanje #3 (premikanje) Aktualne škatlice: arhitektura igre o arhitektura pogona matematika o osnovna linearna algebra scena o graf scene (scene graph) o enostavni grafi 2d fizika o delci o premikanje trki (selektivno samo enostavni pojmi) o vrste teles delci z osmi poravnane ploskve z osmi poravnani pravokotniki (AABB) o detekcija trkov delecdelec delecAABB AABBAABB o odboj po trku vrnitev na najbližje dovoljeno stanje inverzija hitrosti gibalna količina koeficient prožnosti vhodne naprave o stanje naprave o tradicionalni vmesniki

Upload: luka-kozuh

Post on 14-Apr-2016

27 views

Category:

Documents


3 download

DESCRIPTION

games

TRANSCRIPT

TINR @ FRI, draft v09, Peter Peer ++   31  

Predavanje #3 (premikanje) 

Aktualne škatlice: 

 

• arhitektura igre  o arhitektura pogona 

• matematika  o osnovna linearna algebra 

• scena  o graf scene (scene graph)  o enostavni grafi 

• 2d fizika  o delci  o premikanje 

• trki (selektivno samo enostavni pojmi)  o vrste teles  

delci   z osmi poravnane ploskve   z osmi poravnani pravokotniki (AABB) 

o detekcija trkov   delec‐delec   delec‐AABB   AABB‐AABB 

o odboj po trku   vrnitev na najbližje dovoljeno stanje  inverzija hitrosti   gibalna količina   koeficient prožnosti 

• vhodne naprave  o stanje naprave  o tradicionalni vmesniki  

TINR @ FRI, draft v09, Peter Peer ++   32  

o dotikovni vmesnik 

 

1. Arhitektura pogona 

Različni pogoni: pogon igre, grafični pogon, fizikalni pogon ipd. Pogon igre dejansko zaobjema vse ostale in je neodvisen od igre (not game specific). Eden izmed bistvenih ciljev pogona je izolacija same igre od strojne opreme na kateri teče. Dejansko ustvari abstrakten nivo med igro in strojno opremo. Na ta način se v sami igri ni treba posvečati platform, ampak se lahko osredotočimo na samo logiko igre. Primeri abstrakcije: branje vhoda s kontrolerja, izris grafike na ekran, predvajanje zvoka; podpora serializaciji (branje in zapisovanje stanja objektov), mrežna komunikacija, sinhronizacija v igrah večih igralcev, preiskovanje prostora (UI), detekcija trkov. 

XNI + Artificial I                              …??? 

 XNI: 

Ogrodje 

‐ host (okno, stanja) 

‐ glavna zanka igre (game loop) 

‐ komponente, servisi 

Grafika 

‐ grafična naprava (device) 

  ‐ stanje upodabljanja (render state) 

  ‐ stanje teksture (texture state) 

  ‐ luči 

  ‐ izris primitivov 

  ‐ izris indeksiranih primitivov 

‐ optimizacija izrisa (sprite batch) 

‐ 3D modeli 

‐ senčilniki (v delu) 

Vhod 

‐ miška 

‐ dotiki 

‐ pospeškomer 

‐ kompas 

TINR @ FRI, draft v09, Peter Peer ++   33  

Matematika 

‐ vektor 

‐ matrika 

‐ kvaternion 

Cevovod 

‐ uvoz tekstur 

‐ uvoz 3D modelov 

Zvok (v delu) 

 

XNI v bistvu služi kot neka medplatformska plast (cross platform layer), ki odpravi razliko med DirectX in OpenGL ter vsemi  ostalimi povezanimi zadevami (input, zvok). Nad tem pride šele pravi grafični pogon, kjer je notri kamera, graf scene, izbiranje (culling), grafični uporabniški vmesnik ipd. 

Primer arhitekture pogona igre: 

 

2. Linearna algebra 

Z vidika linearne algebra moramo poznati vse okoli štirih glavnih pojmov: točka, vektor, matrika, kvaternion. 

Dotaknimo se bistvenih povezanih pojmov . Vektor: seštevanje, odštevanje, skalarji, komponente, dolžina, normalizacija, zapisovanje z matrikami, ortogonalnost, transformacija, normala, tangentnost, skalarni product, vektorski product, nekomutativna operacija, pravilo desnega. Matrike: elementi, množenje, transponiranje, simetrija, singularnost, identiteta, ortogonalnost, inverzija. 

…??? Čem razložiti matematiko zadaj?! 

3. Scena 

TINR @ FRI, draft v09, Peter Peer ++   34  

Graf scene: 

Teorija grafa scene (scene graph) predlaga, da postavimo vse na sceni v en sam zedinjen, poenoten graf (lahko drevo, ki je le ena oblika grafa). Tako vanj postavimo od mrež, verteksov, senčilnikov do tekstur. Čez takšen graf se nato ob izrisu sprehodimo in zaradi posebne organiziranosti samih vozlišč dosežemo optimalno učinkovitost upodabljanja. Čeprav v teoriji koncept zveni zelo lepo, praksa ni tako rožnata, saj potrebujemo obilico časa, dela, da takšno ogromno podatkovno strukturo urejujemo glede na aktualne dogodke v igri. Kompleksno vzdrževanje teorijo torej postavi na realna tla in zabriše prednosti, ki jih teorija obljublja. Še več, v praksi je treba večkrat graf zgraditi na novo, kar izniči veliko teoretičnih prednosti. 

Seveda pa so drevesa in grafi zelo uporabni pri upodabljanju, vendar je v praksi potrebnih več različnih grafov in dreves za različne namene. Torej mogoče ideja poenotenja le ni tako uporabna. 

Da je upodabljanje učinkovito seveda vedno ne izrisujemo našega celega navideznega sveta. Prva ideja je seveda, da ne izrisujemo, upodabljamo tistih objektov našega sveta, ki niso vidni iz zornega kota navidezne kamere, ki dejansko izrisuje sliko na naš ekran. V osnovi ta koncept imenujemo stožčasto izbiranje (frustum culling) (razlaga: http://www.youtube.com/watch?v=kvVHp9wMAO8, primer: http://www.youtube.com/watch?v=‐lJsMk6nxOs). Samo izbiranje (culling) (ki v osnovi pomeni, da ne izrisujemo določenih objektov) lahko seveda še dodatno zakompliciramo tako, da tudi v vidnem polju kamere določenih objektov ne izrisujemo; na primer objektov za goro ne vidimo in jih zato ne izrisujemo, čeprav so v vidnem polju kamere, podobno ne izrisujemo objektov za zaprtimi vrati.  

Zakaj določenih stvari ne izrisujemo? Jasno, da hitreje upodobimo in izrišemo aktualno sceno. Vendar pri konceptu izbiranja za učinkovitost, hitrost izrisa, pri recimo miljonih in miljonih objektov v našem navideznem svetu, ni dovolj, da se vprašamo »Ali je objekt viden?« v vsaki sličici (frame) našega izrisa na ekran. Potrebujemo način, da vprašamo »Kateri objekti so vidni?« In graf je odgovor! Objekti živijo v vozliščih teh grafov, sprehod skozi graf pa vedno začnemo v vozlišču, kjer se nahaja kamera, nato pa potujemo po njemu dokler ne naletimo na neko mejo vidnosti objektov. Na ta način vozlišč grafa, ki niso vidna v nekem trenutku, sploh ne obravnavamo, pravtako ne obravnavamo objektov znotraj njih. Grafi, ki pridejo v poštev so: portali, BSP (binary space partitioning), quad‐drevesa, okt‐drevesa, PVS (potentially visible set), ABT (adaptive binary tree) ipd. Lahko jih seveda tudi kombiniramo, recimo, ker so lahko vozlišča za zunanje scene ogromna, uporabimo okt‐drevo znotraj vsakega portala v portalnem sistemu.  Lahko jih uporabimo tudi vzporedno, recimo PVS sistem je uporaben za test vidnosti, okt‐drevo pa je lahko bolj uporabno za propagiranje zvoka. 

Opisano uporabo grafov navadno s skupnim imenom poimenujemo razdeljevanje volumna upodabljanja (render volume partitioning). 

Primer ABT drevesa je zgoraj desno: 

TINR @ FRI, draft v09, Peter Peer ++   35  

 

 

(SceneCamera/RealCamera !?) 

Zakaj je vse to že dobro? Sicer smo na to vprašanje že odgovorili zgoraj, vendar dajmo ponovno, z zornega kota časovne kompleksnosti O() ter dejanskega časa. Na sceni zgornje slike imamo recimo 200 objektov. Z uporabo ABT drevesa opazimo skrajšanje izrisa za polovico (stožčasto izbiranje (frustum culling) je bilo uporabljeno že prej in je kar za 6‐krat pospešilo izvajanje), na okoli 2‐3ms na izris. Še bolj bi bila razlika očitna pri sceni z večjim številom objektov. Osnovni pristop s preverjanjem obsegajoče krogle ali kvadra za vsak objekt posebej ima velikostni red O(n), pri čemer je n število objektov v sceni. Z uporabo dvojiškega drevesa, algoritma deli in vladaj in malo fleksibilnosti pri deljenju in umeščanju v binarno drevo pridemo do ABT drevesa ter naredimo iskanje tistih 10 ali 20 objektov v našem vidnem polju z operacijo velikostnega reda O(log n). Če bi 400 objektov povečali na 10.000 objektov na sceni, bi pri O(n) pristopu potrebovali 10.000/400=25‐krat več časa. Pri redu O(log n) bi enako povečanje potrebovalo samo log(10.000)/log(400)=1,5‐krat več časa. V praksi se za 

TINR @ FRI, draft v09, Peter Peer ++   36  

primer s slike izkaže, da če namesto 200 objektov ustvarimo svet s 50.000 objekti, brez ABT drevesa število sličic na sekundo (frames per second) pade na okoli 6 sličic na sekundo, z ABT drevesom pa je to število še vedno višje od 200. Vsekakor dovolj prepričljiv napredek, da smo zelo praktično prikazali uporabnost snovi, ki se marsikateremu študentu računalništva zdi brez prevelike uporabne vrednosti v praksi. 

Enostavni grafi: 

Portali: 

V sistemu portalov je scena razdeljena na vozlišča, vsako obsega določen proctor scene, ki je navadno opisano kar z geometrijo obsega, vsebine. Recimo tem vozliščem sektorji. Portal te sektorje povezuje med sabo. Kako? Portal v splošnem definira prehod v nek drug svet. Predstavljajmo si veliko sobo. Na sredi te sobe naj neka lebdeča stvar, ki od daleč izgleda kot ogledalo, ko pa pridemo blizu lahko vidimo, da dejansko prikazuje povsem drugo sceno. Je povezava do druge lokacije, okno v prostoru. Oziroma, če smo bolj egzaktni, predstavlja geometrijsko nezveznost. To je recimo opis dejanskega portala v igri Unreal, vendar je v resnici portal širši pojem, saj lahko recimo povezuje tudi dve sobi na povsem naraven način, skozi vrata. Torej vse kar moramo narediti je, da našo sceno razdelimo na vozlišča in jih povežemo s portali. Portal je navadno v igri predstavljen kot planaren konveksen poligon, največkrat kar s pravokotnikom (recimo vrata, okna). Vse kar vidimo skozi portal enostavno obrežemo (clipped), hkrati pa na zelo enostaven način v grafu označimo vozlišča, ki so vidna skozi posamezne portale z zornega kota kamere. 

Plus:  

+ Sistem portalov je enostaven, fleksibilen, intuitiven, poceni glede na procesorske in pomnilniške zahteve. Za notranje (indoor) scene je sistem ekstremno učinkovit. 

Minusi: 

‐ Funkcija upodabljanja more vedeti, v katerem vozlišču se nahaja kamera. Do te informacije pridemo tako, da sledimo igri in ustrezno preskakujemo iz vozlišča v vozlišče v grafu. Posebni primeri sledenja vključujejo tudi prehode skozi stene ali teleportiranje, kjer portali niso definirani. 

‐ Ker sistem temelji na geometriji scene, samodejni generatorji grafov niso najbolj učinkoviti (če najdejo premalo portalov, bo potrebno izrisati veliko stvari, če pa jih najdejo preveliko, jih moramo  sprocesirati (trošimo procesorski čas), izris pa zato ne bo nič detalnejši). Tako se največrat zgodi, da je treba grafe sestaviti ročno, kar največkrat naredi oblikovalec stopnje.  

‐ V zunanjih (outdoor) scenah, npr. mesta z veliko zgradbami, nebotičniki, je težko določiti razmeroma malo število portalov tako, da se skozi njih ne vidi praktično vsega, saj tako pač ne omejujemo izrisa. Imeti ogromno portalov pa, kot omenjeno že zgoraj, tudi nima pravega smisla. 

Binarno razdeljevanje prostora (BSP – binary space partitioning): 

BSP je posplošena oblika hierarhičnega razdeljevanja prostora (HSP). Med posebne tipe BSP štejemo med drugim tudi kd‐drevesa, quad‐ in okt‐drevesa, čeprav imajo posebne lastnosti, zaradi katerih jih obravnavamo ločeno. Tudi BSP je drevo. To drevo predstavlja, opisuje celoten prostor igre, celotno 

TINR @ FRI, draft v09, Peter Peer ++   37  

sceno. Vsako vozlišče predstavlja del prostora, ki se ne seka s svojimi brati, vsakega pa lahko nadalje razdelimo v otroke. Vozlišča, ki nimajo otrok, imenujemo listi drevesa. Slednji predstavljajo nedeljiv del prostora, kot vozlišča v sistemu portalov. Sicer lahko ima vsako vozlišče dva otroka, ki ju ločimo z ravnino na dve polovici. Označevanje vidnih vozlišč iz enega vozlišča je nekoliko težje kot pri portalih, temelji pa na označevanju listov kot votel (hollow) ali trden (solid), kjer votli listi označujejo prostor z objekti v njih, ki zahtevajo upodabljanje v primeru vidnosti tega lista. 

Plusa:  

+ Z BSP drevesom je klasificiran celoten prostor. Enostavno izberemo točko (recimo lokacijo naše kamere) v prostoru, nato začnemo v glavnem vozlišču, pogledamo na kateri strani delilne ravnine se nahaja naša točka, sledimo v drevesu temu otroku in ponavljamo postopek deljenja in sledenja otroku vse dokler ne pridemo na lista, kjer se naša točka nahaja. Ta postopek je hiter, zanesljiv in vedno izračuna, poda pravilen odgovor, kar je veliko bolje kot pri portalih. 

+ BSP drevesa je veliko lažje ustvarjati samodejno in ni potrebe po ročni gradnji le‐teh. 

Ker sta sistem portalov in BSP drevo podobna po strukturi, vendar dobra za različne stvari, veliko iger dejansko uporablja nekakšen hibrid obeh, vsak pristop v različnih situacijah. 

Quad‐drevesa in okt‐drevesa: 

Pri obeh drevesih gre za praktično enako podatkovno strukturo, s to razliko, da so quad‐drevesa 2D, okt‐drevesa pa 3D. Nadgradnja v dodatno dimenzijo je dokaj enostavna, zato se posvetimo quad‐drevesu. Vsako vozlišče predstavlja kvadrat v prostoru, ki je poravnan z x in y osjo in ima ali nobenega otroka (list drevesa) ali štiri enako velike otroke, ki razdelijo prostor na četrtine. Navadno korensko vozlišče poravnamo z izhodiščem; izhodišče postavimo levo zgoraj glede na celoten prostor. Te lastnosti nam omogočajo, da na zelo enostaven način najdemo lokacijo točke zanimanja v drevesu. Vzamemo x in y koordinati (začnemo z 0, koordinati zaokrožimo na celo število) točke in začnemo v korenskem vozlišču. Koordinati zapišemo binarno ter v vsakem vozlišču vzamemo prvi bit obeh koordinat. Število stopenj delitve celotnega prostora pove, koliko mest ima binarno število. Nato oba bita združimo in dobimo število med 0 in 3, ki pove, v katero podvozlišče moramo iti. Potem zamaknemo (shift) obe binarno zapisani koordinati v levo za en bit in postopek ponavljamo dokler ne pridemo do lista. Sprehod skozi drevo, iskanje naše točke je tako zelo hitro. 

Recimo, da nas zanima točka s koordinatami (3,6) (na spodnji sliki je sprehod označen s polnimi črtami). Zapišimo koordinati binarno, pri čemer najmanjši prostor pove, da je bil celoten prostor 

razdeljen v štirih stopnjah, torej imamo pred sabo štirimestni binarni števili: (3,6) ⇒ (0011,0110). Sledimo zgoraj zapisanemu algoritmu: 

1. Vzamemo prva dva bita: 0 0, ki binarno definirata vozlišče 0 (del prostora levo zgoraj), v katerega se sprehodimo iz korenskega vozlišča. Zamik bitov v levo pripelje do naslednjih vrednosti: (0110,1100). 

2. Spet ponovimo postopek, vzamemo prva dva bita: 01 = 1 (levo spodaj)  ⇒ (1100,1000). 

3. 11 = 3 (desno spodaj) ⇒ (1000,0000) 

4. 10 = 2 (desno zgoraj) ⇒ To je list in torej točka iskanja. 

TINR @ FRI, draft v09, Peter Peer ++   38  

Slika prikazuje sprehod skozi quad‐drevo: 

 

Quad‐drevesa navadno uporabljamo za detekcijo trkov in hitro stožčasto izbiranje (frustum culling) v zunanjih (outdoor) scenah.  

Čeprav se zdi, da je večina iger 3D in bi tako morali uporabiti okt‐drevesa, je resnica nekje vmes. Veliko iger je dejansko le 2,5D, njihov svet pa je po večini raven. Tipičen primer so realno časovne strategije – čeprav pokrajina lahko gre gor in dol in je višina pomembna informacija za strategijo, je število primerov v katerih sta dva upodobljena objekta v prostoru eden nad drugim izredno majhno. Poleg tega pa v tem primeru dodatna kompleksnost okt‐drevesa ne prinese nobene bistvene prednosti z vidika stožčastega izbiranja v primerjavi s quad‐drevesom. Tako sta obe drevesi enako pogosti v igrah.  

Bližnja sorodnika obema drevesoma sta tudi njuni ohlapni (loose) različici. Imata enako uporabnost pri upodabljanju, a sta veliko bolj praktični pri detekciji trkov kot standardno quad‐drevo. 

Potencialno vidna množica (PVS – potentially visible set): 

Tudi sistem PVS temelji na vozliščih in ga lahko vpeljemo kot nadgradnja poljubnega drugega na grafu temelječega sistema. Osnovna ideja je, da ima vsako vozlišče spisek vozlišč, ki so potencialno vidni iz tega vozlišča. Nekatera vozlišča iz spiska sicer niso nujno vidna iz trenutne lokacije kamere, vendar zagotovo drži, da vsa ostala vozlišča nikoli niso vidna iz tega vozlišča. Čeprav je koncept enostaven pa ustvarjanje teh spiskov ni enostavno. PVS sistem se tudi ne spopada dobro s spreminjajočo se geometrijo, na primer, če se lahko vrata v igri odpirajo, potem moramo v tem sistemu predvideti, da so vedno odprta. PVS sistem je torej statičen seznam, ki se ne spreminja glede na trenutno lokacijo kamere ali trenutno stanje scene, zatorej je konzervativen.  Ravno zato se PVS sistem največkrat kombinira s kakšnim dinamičnim sistemom za določanje vidnosti (recimo kar standardnim stožčastim izbiranjem), da lažje izločamo nadaljna vozlišča. Najlepša stran sistema PVS je zagotavljanje ekstremno hitrega načina zavračanja vozlišč, ki niso vidna. Te informacije v tem primeru ne dobimo s sprehajanjem po grafu, ampak je enostavno dana v obliki spiska. 

Prilagodljivo binarno drevo (ABT – adaptive binary tree): 

TINR @ FRI, draft v09, Peter Peer ++   39  

Oglejmo si še, kako bi optimizirali izris z ABT drevesi. Začnemo iz standardnega dvojiškega drevesa, s seznamom objektov v listih. Če hočemo izrisati sceno, zgolj rekurzivno, po principu deli in vladaj, pogledamo ali sta vidni obe polovice, leva in desna, in, za tisto ki je, sprožimo pregledovanje otrokov. Ko pridemo do listov izrišemo vse objekte, ki se nahajajo v njem. Problem je, da smo pri delitvi zvrha navzdol sceno vsakič razdelili z neko ravnino na dve polovici. Prej ali slej se pojavi kakšen objekt, ki leži ravno na sredini in torej spada tako v levo kot desno polovico. Da nam ni treba objekta podvajati v obe strani, ustvarimo prilagodljivo dvojiško drevo. Pri tem pristopu objekt postavimo v samo eno od polovic in njen obseg (bounding box) povečamo toliko, da vsebuje tudi nov objekt. Seveda se obsega obeh polovic pri tem prekrivata, vendar s tem ni nič narobe. Le vsakič, ko v sceno dodamo nov objekt moramo obseg ustrezno prilagoditi, če slučajno sega čez rob. 

Mimogrede, tudi zvok je lahko objekt, ki pa ga seveda ne izrisujemo, ga prožimo. Vsi sistemi lahko pridejo prav tudi pri iskanju urejenih seznamov objektov glede na globino na sceni, še posebej so aktualni izrisi prosojnih (translucent) (izris od zadaj naprej) in neprozornih (opaque) (izris od spredaj nazaj) objektov. Rezultat iskanja je pravzaprav sortiran seznam po globini. 

Zgornji primeri pristopov, sistemov (z izjemo ABT) so našteti tako, da znižujejo ceno sprehoda iz vozlišča v vozlišče. V veliko primerih pa velja pravilo, da je bolj pomembno zakaj uporabljamo določeno shemo, sistem razdeljevanja, kot pa kako učinkovita, hitra je ta shema. Tako se navadno, zagotovo pa velikokrat, uporabljajo portali za pregled vidnosti in quad/okt‐drevo za detekcijo trkov znotraj iste igre. V večini primerov pa velja, da je uporaba katerekoli sheme pomembnejša odločitev kot katera točno je uporabljena. Če izraba CPE in poraba pomnilnika po prvi uporabljeni shemi kažata željene rezultate, potem nima smisla iskati, implementirati kompleksnejših shem. 

4. Fizika 

Fizika je del naše življenske izkušnje, brez nje ne gre, tudi v igrah ne. Naši možgani so naučeni, da gibanje, ki temelji na pravilih fizike, ki jih srečujemo v vsakodnevnem življenju, razpoznajo kot tisto pravo, pričakovano gibanje. Poznamo vsaj tri glavne pristope, kako prikazati realistično gibanje v igri:  

‐ s pomočjo animacije, ki jo sestavimo sličico za sličico (keyframe animation),  ‐ s pomočjo tehnologje zajemanja gibanja recimo dejanskih ljudi (motion capture technology) 

in ‐ s simulacijo fizikalnih zakonov. 

Slednji je zagotovo najcenejši (za razvijalce in založnike) in omogoča tudi simulacijo gibanja v času izvajanja (runtime), torej je ta način bolj fleksibilen in za nas v tem trenutku najbolj zanimiv. 

Delci in gibanje: 

Osnovni elementi vsake igre so delci, tisti najmanjši samostojni gradniki v igri na katere lahko apliciramo zakone fizike.  Lastnosti gibanja delcev poznamo pod imenom kinematika delcev. Fizika definira delec kot objekt brez volumna, recimo zgoščena masa v neskončno majhni krogli. Za naše potrebe definiramo delec malce drugače: delec je povsem gladka krogla s končnim radijem in brez trenja. Zakaj krogla s temi lastnostmi? Da nam ni treba upoštevati rotacijskega gibanja, torej zaradi poenostavitve.  

TINR @ FRI, draft v09, Peter Peer ++   40  

Osnovni pojmi kinematike delcev so: čas t, lokacija p=<px,py,pz>, lokacija gibajočega delca je funkcija 

časa p(t), p(t+Δt), povprečna hitrost med dvema časoma V, pospešek a.  

Časovno odvisna lokacija gibajočega se delca po poti: 

 

lim  

 

 

Seveda mimo Newtonovih zakonov gibanja ne moremo, vsaj prvih dveh ne. Prvi pravi, da se bo objekt gibal s konstantno hitrostjo vse dokler ga v spremembo hitrosti ne bodo primorale zunanje sile. Drugi pa pravi, da je sprememba hitrosti objekta proporcionalna na objekt delujoči sili. 

Newtonovi zakoni gibanja so: 

1. Telo miruje ali se giblje premo enakomerno, če nanj ne deluje nobena sila ali pa je vsota vseh sil, ki delujejo nanj enaka nič. 

2. Pospešek je sorazmeren sili in ima smer sile ( ). 3. Če deluje prvo telo na drugo z dano silo, deluje to na prvo z nasprotno enako silo. 

Od tukaj se nato lahko pogovarjamo o  gibanju delca na katerega deluje konstantna sila (

,  ), gibanju projektila 

( ) ipd., nato lahko naredimo preskok na gibanje delcev in nato na druge oblike objektov, 

čeprav jih v igrah marsikdaj aproksimiramo ravno s kroglo. 

Gibanje projektila na zemlji: 

 

TINR @ FRI, draft v09, Peter Peer ++   41  

5. Trki 

Objekti, nad katerimi ne izvajamo detekcije trkov (collision detection) in se na le‐te ne odzivamo (collision response/resolution), prehajajo eden čez drugega kot duhovi čez stene. Torej jim manjka lastnost trdnosti, ki jo zagotovimo prav z ustrezno obravnavo trkov. Postopek detekcije trkov poskrbi za odgovor na vprašanje: če in kdaj se bosta dva objekta zaletela? Postopek odziva na trk pa bo odgovoril na vprašanje: kje se mora posamezne objekt po trku nahajati? Izračun, kako se objekti gibajo po trku je stvar fizike v igri. 

Vrste teles: 

Detekcija trkov je lahko enostavna za objekte kot so krog, pravokotnik, vendar stvar zagotovo postane kompleksnejša, ko imamo opravka s poligoni. V splošnem velja pravilo, da moramo poligone aproksimirati z enostavnimi geometrijskimi oblikami, če želimo doseči delovanje v realnem času. 

Primer aproksimacije nazobčanega objekta z elipso – ni nujno, da aproksimacija obsega celoten objekt: 

 

Delce kot osnovno vrsto teles smo obdelali že zgoraj. Dejansko lahko poljuben objekt opišemo kot krog (ali krogla), ki takšen objekt aproksimira. Površina kroga oz. volumen krogle tako vsebujeta celoten objekt in prav krog/krogla je najenostavnejši približek objekta. Temu približku pravimo v splošnem omejujoča površina/volumen (bounding surface/volume).  

Naslednja velikokrat uporabljena površina/volumen je pravokotnik/škatla. Poznamo dva načina aproksimacije: z osmi poravnani pravokotniki (AABB – axis‐aligned bounding box) in s smerjo poravnani pravokotniki (OBB – oriented bounding box). AABB aproksimacija ogradi objekt v 3D tako, da stranice škatle poravna z osmi koordinatnega sistema igre. To navadno povzroči  malce slabši opis objekta, vendar je detekcija trkov tako še bolj poenostavljena in cenejša. OBB pa ogradi objekt tako, da se škatla kar najbolje prilega objektu, kar pomeni, da je škatla poravnana z vodilno osjo objekta. 

Primer ograditve z AABB in OBB aproksimacijo: 

TINR @ FRI, draft v09, Peter Peer ++   42  

 

Če je naš objekt kompleksen, ga lahko opišemo tudi z večimi omejujočimi površinami/volumni. Recimo človeka bi lahko opisali tako, da glavo opišemo s kroglo, posamezno okončino in trup pa z OBB. Pravtako lahko objekte opišemo tudi na več različnih nivojih. Na višjem nivoju bi tako lahko celega človeka opisali le s kroglo. Tako je lahko tudi test detekcije trka večnivojski, kjer preverjanje na nižjem nivoju naredimo le, če je na višjem nivoju trk bil ustrezno detektiran. 

Detekcija trkov: 

Ugotavljanje če in kdaj se bosta dva objekta zaletela ni tako enostavna, kot se zdi na prvi pogled. Nekateri objekti so lahko zelo hitri (metek), lahko jih je ogromno (rafal), lahko imajo kompleksno geometrijo (ljudje). Dejansko gre tudi za drago operacijo, saj moramo v osnovi preveriti trk vsakega objekta z vsakim drugim, kar pomeni, da imamo opravka s časovno kompleksnostjo O(n2). Na srečo lahko kompleksnost detekcije trkov ublažimo s poenostavljeno geometrijo, omejujočimi površinami/volumni in razdeljevanjem prostora. Za detekcijo trkov poznamo dve tehniki: testiranje prekrivanja (overlap testing) in testiranje preseka (intersection testing). Bistvena razlika med njima je ta, da prva detektira, ali je do trka že prišlo, druga pa napoveduje, ali bo do trka prišlo v prihodnosti. 

Testiranje prekrivanja: 

Cilj testa je dognati, ali je katerikoli del prvega objekta znotraj kateregakoli dela drugega objekta. Recimo, da imamo dva delca, ki smo ju opisali s kroglama. Detekcija trka v tem primeru je zelo enostavna, saj je jasno, da je do trka prišlo, če je razdalja med središčema obeh krogel manjša od vsote obeh radijev. V primeru dveh AABB objektov gledamo le razdaljo stranic, enkrat po horizontali, drugič po vertikali. (Do posplošitve tega še pridemo na samem koncu opisa detekcije trkov.) 

Če je trk detektiran, potrebujemo dva rezultata za pravilen odziv na trk: čas trka in vektor normale trka. Čas trka izračunamo tako, da vzamemo čas zadnje simulacije, ko objekta še nista bila v trku ter čas detekcije prekrivanja in nato s pomočjo bisekcije najdemo vmesni čas dejanskega trka. V praksi skonvergiramo k željenemu času v petih iteracijah. Z določitvijo tega časa tik pred trkom, poznamo točno, neprekrivajočo se lokacijo objektov, kamor ju postavimo pred korakom odziva na trk. 

Primer določitve časa dejanskega trka po metodi bisekcije: 

TINR @ FRI, draft v09, Peter Peer ++   43  

 

Pristop zveni enostaven, a ima tudi grozno pomanjkljivost: detekcija trka je neuspešna pri objektih z zelo veliko hitrostjo.  

Malo verjetno je, da se bo hiter metek kadarkoli v simulaciji prekril s tankim steklom okna: 

 

Tako moramo v zakup vzeti pravilo, da bo testiranje prekrivanja delovalo, če bo hitrost najhitrejšega objekta v igri, katero pomnožimo z našim časovnim korakom v igri, manjša od velikosti najmanjšega objekta, ki je lahko vpleten v trk. 

Kako s poenostavljeno geometrijo učinkovito testirati prekrivanje (ali presek) z namenom detekcije trkov s statičnimi objekti? Z geometrijsko operacijo imenovano vsota Minkowskega (Minkowski sum). Operacija iz dveh konveksnih objektov ustvari nov objekt, ki omogoča detekcijo trka tako, da testiramo vsebovanost zgolj ene točke objekta v tem novem objektu. 

Vsoto Minkowskega dveh objektov, torej nov objekt, ustvarjen za namen detekcije trkov, dobimo tako, da izhodišče enega objekta postavimo v vse točke drugega objekta: 

 

Sedaj, ko imamo ta nov objekt, lahko prekrivanje enostavno testiramo tako, da vzamemo izhodišče (središče) kroga in pogledamo, ali je le‐to znotraj tega novega objekta. Če je, sta realna objekta v trku. 

Testiranje preseka: 

TINR @ FRI, draft v09, Peter Peer ++   44  

Ta tehnika napoveduje trke, še preden se zgodijo. Če bi lahko prejšnji tehniki rekli, da rešuje problem vsebovanja, lahko tej rečemo, da rešuje problem vidnosti. Ker trke predvidimo, lahko simulacijo ustrezno postavimo v čas trka in nadaljujemo od tam. Pri testiranju preseka objekt raztegnemo v smeri potovanja med dvema časoma. Tako na primer krog dobi obliko kapsule. Enako naredimo tudi z vsemi ostalimi objekti, ki so lahko udeleženi v trku. Nato pogledamo, ali se ti raztegnjeni objekti kje sekajo in če se, potem lahko izračunamo čas trka. 

Krog, ki predstavlja naš objekt, raztegnemo v smeri potovanja med dvema časoma: 

 

Tako lahko recimo dokaj ilustrativno prikažemo prihodnost. 

Napovedovanje trka med dvema krogoma: 

 

Za izračun bo potrebnega nekaj matematičnega znanja, za implementacijo pa kakšen algoritem iz numerične matematike [2]. 

Seveda pa lahko tudi tukaj za detekcijo trkov s statičnimi objekti uporabimo operacijo vsota Minkowskega. V tem primeru prej (pri testiranju prekrivanja) omenjena točka izhodišča postane daljica, ki povezuje izhodišči objekta v času t1 in t2. Nato le pogledamo, ali se ta daljica seka z novim objektom, ki smo ga dobili z vsoto Minkowskega ‐ če se, bo prišlo do trka: 

 

Na prvi pogled izgleda, da ta pristop, torej testiranje preseka v splošnem, nima problemov. Vendar ko govorimo o mrežnih igrah lahko zaradi zamujanja paketkov pri komunikaciji operiramo s svetom 

TINR @ FRI, draft v09, Peter Peer ++   45  

igre, ki ne odraža dejansko stanje. Hkrati pa ta pristop predvideva, da se objekt giblje s konstantno hitrostjo, brez pospeška, skozi simulacijski korak. Ta je načeloma res kratek, a kljub temu je lahko ta predpostavka v nasprotju s fizikalnim modelom igre. 

Kako doseči časovno kompleksnost O(n)? 

En odgovor smo podali že pri debati o grafu scene, torej v splošnem z uporabo razdeljevanja prostora. Če imamo recimo 15 objektov, naš svet pa razdelimo z enostavno mrežo, potem moramo za trk testirati vsak objekt v isti celici s trenutno aktualnim objektom ter vse objekte v sosednjih celicah: 

 

Da dobimo v povprečju en objekt na celico, kar v osnovi podpira linearno časovno kompleksnost, se 

moramo pri zasnovi mreže držati pravila, da za N objektov na 2D sceni potrebujemo vsaj √    √  

celic in vsaj √   √ √  celic na 3D sceni. 

Alternativna metoda za doseganje (skoraj) linealne časovne kompleksnosti temelji na zrcaljenju na osi (plane sweep). Osnovna ideja zahteva, da objekte prezrcalimo na vsako od osi našega sveta: 

 

Nato podrobneje (?!) pogledamo le primere, kjer se preslikave istih objektov sekajo na vseh oseh našega sveta. 

Iskanje preseka se tukaj prevede na problem učinkovitega sortiranja preslikav in tako dosežemo skoraj linearen čas detekcije trkov: preslikave na vsaki osi sortiramo le enkrat, nato pa zaradi koherentnosti iz okvirja v okvir (frame) (objekti ostajajo med dvema okvirjema na skoraj enaki lokaciji) uporabimo sortiranje z mehurčki (bubblesort) nad vsemi preslikavami, ki so v zadnjem okvirju pokvarile urejeno zaporedje. 

TINR @ FRI, draft v09, Peter Peer ++   46  

Z zrcaljenjem na osi je povezan teorem ločitvene osi (separating axis), ki pravi, da če v primeru, ko imamo opravka z dvema konveksnima objektoma, najdemo os na kateri se projekciji teh dveh objektov ne prekrivata, potem se tudi objekta ne prekrivata. 

 (http://www.metanetsoftware.com/technique/tutorialA.html 

N Tutorial A ‐ Collision Detection and Response: 

[Demo 0: učinek različnega trenja in koeficienta prožnosti ε] 

Slika 1: definicija potencialnih ločitvenih osi 

Demo 2: projekcija pravokotnika na poljubno os 

Demo 3: uporaba teorema z dvema AABB škatlama (enako kot na zgornji sliki) 

Demo 5: uporaba teorema pri detekciji trkov AABB škatle in pravokotnega trikotnika 

Demo 6: kaj pa v primeru uporabe AABB škatle in krožnega objekta? (dodatna os je definirana kot vzporednica osi, ki povezuje središči obeh objektov) 

Demo 8: in kako v primeru uporabe AABB škatle in polnega kroga? (uporabimo tudi vse osi, ki jih definira središče kroga in ogljišče škatle, za izračun je važna le os, ki povezuje središče z najbližjim ogljiščem) 

Vendar, kako učinkovito najti najbližjega? Uporabimo Voronojeve regije (slika 9, demo 10), ki so regije okoli poligona, objekta, ki vsebuje vse točke najbližje neki značilki (robu ali oglišču, verteksu). 

Opomba: majhni (točkasti) in izredno hitri objekti lahko predstavljajo problem pri uporabi teorema!) 

Odziv na trk: 

Gre za korak, ki velja za težjega od detekcije trka. V primeru detekcije trka s testiranjem prekrivanjem smo pokazali, kako se vrnemo na najbližje dovoljeno stanje, pri testiranju preseka pa tega problema nismo imeli. 

Na osnovi izračunanega časa trka in vektorja normale trka (o njem bomo detalneje govorili spodaj) lahko sedaj izračunamo potreben odziv, ki seveda sledi fizikalnemu modelu sveta v igri. V osnovi to pomeni, da moramo poznati fizikalne pojme inverzija hitrosti, gibalna količina in tudi koeficient prožnosti. 

Postopek za odziv, ki mora ustrezati različnim zahtevam, ima tri dele: prolog, trk in epilog. Da so zahteve lahko resnično zelo različne, zapišimo tri ilustrativne primere: trk dveh krogel bilijarda, raketa zadane skalo, lik lahko prehaja skozi posebno steno. 

Prolog: Na tem mestu vemo, da je do trka prišlo, vendar mogoče bi ga bilo treba ignorirati (kot v zadnjem primeru zgoraj), kar preverjamo ravno v tem koraku. V prologu lahko prožimo tudi dodatne dogodke, kot recimo zvočni efekt, enostavno s pošiljanjem obvestila o dogodku ustreznemu objektu. Znotraj pravega objektno usmerjenega stila, arhitekture igre, se lahko nato takšen objekt odzove na sporočilo, kot mu paše. 

TINR @ FRI, draft v09, Peter Peer ++   47  

Trk: V tem koraku postavimo objekte na točko trka (izračunano v koraku detekcije trka) in izračunamo nove hitrosti na podlagi fizike v igri. Podkoraki so odvisni od uporabljene tehnike detekcije trkov: 

Odziv ob uporabi testiranja prekrivanja je sestavljen iz štirih podkorakov: 

1. Najdi vektor normale trka. 2. Izračunaj globino penetracije (prodiranje objektov enega v drugega). 3. Prestavi objekta na globino penetracije nič, torej na točko stika. 4. Izračunaj nove hitrosti. 

Vektor normale lahko učinkovito izračunamo tako, da najdemo lokaciji objektov tik pred samim trkom. Navadno pri tem uporabimo kar postopek bisekcije. Sedaj lahko za normalo uporabimo kar povezavo med dvema najbližjima točkama na obeh objektih. Razultati takšnega pristopa k iskanju normale bodo dobri, če lahko dobro lociramo objekte tik pred samim trkom, hkrati pa noben objekt nima velikega kotnega momenta. 

Ilustracija izračuna vektorja normale: 

 

Seveda je lahko izračun dveh najbližjih točk problematičen, kompleksen. Inkrementalni algoritem Lin‐Canny [3] lahko najde takšni točki za splošen, konveksen volumen, sestavljen iz poligonov. Za kroge/krogle pa lahko normalo izračunamo enostavno kot razliko med središčema obeh objektov v točki trka: 

 

V naslednjem podkoraku izračunamo globino penetracije, da lahko objekta ločimo, postavimo na točko samega trka. Kot že rečeno, lahko to naredimo s postopkom bisekcije, alternativen postopek pa je Gilbert‐Johnson‐Keerthi (GJK) [4], ki je še posebej dober ob uporabi konveksnih objektov.  

Sedaj lahko postavimo objekta na lokaciji samega trka ter izračunamo nove hitrosti z uporabo Newtonove fizike oziroma pravil igre.  

Odziv ob uporabi testiranja preseka je veliko enostavnejši, saj v tem primeru objekta dejansko nikoli ne penetrirata. Tako iz zgornjih podkorakov izločimo koraka 2 in 3 ter izračunamo zgolj vektor normale in novi hitrosti. 

TINR @ FRI, draft v09, Peter Peer ++   48  

Epilog: V tem koraku moramo propagirati, razposlati vplive trka, udejaniti posledice trka. To lahko vključuje uničenje enega ali obeh objektov, predvajanje zvoka, prikaz škode ipd. Kot v prologu lahko tudi tukaj uporabimo koncept rapošiljanja sporočil ustreznim objektom. Kdaj uporabiti določen efekt, udejaniti posledico trka, ali v prologu ali v epilogu, je odvisno od okoliščin, same zasnove igre. 

...??? čem nadalje razložiti tudi izračun hitrosti po trku?! JA! 

Odziv na trk (brez trenja) dveh delcev: 

Linearen moment definiramo kot zmnožek skalarja mase in vektorja hitrosti. Njegov odvod po času je enak sili na objekt (gre za zapis drugega Newtonovega zakona): 

 

(Za večino objektov je masa konstanta, zato lahko le‐to zapišemo zunaj odvoda in tako dobimo standarden zapis drugega Newtonovega zakona:  ). Če zgornjo enačbo integriramo po času, določi gibanje objekta. Od tod ime enačbi Newtonova enačba gibanja. Ko integriramo silo na objekt po času, torej dobimo spremembo v linearnem momentu (in hitrosti) v tem času. 

Velike, praktično takojšnje spremembe v hitrosti se lahko zgodijo le, če so sile trka velike. Sile trka so navadno tako velike, da dominirajo nad vsemi drugimi silami med trkom. V takšnih primerih je sprejemljivo, da ostale sile ignoriramo za kratek čas trka. 

Z integracijo zgornje enačbe po času trajanja trka, dobimo enačbo linearnega impulznega momenta:  

 

Indeks 1 označuje prvi delec, ki je udeležen v trku. Z – označimo velikosti pred trkom, s + pa po trku. Vektor Λ imenujemo linearni impulz, ki je dejansko integral sile trka čez čas trajanja trka. Impulz poda količino linearnega momenta, ki ga objekt pridobi ali izgubi med trkom. 

Ker Newtonov tretji zakon pravi, da je za vsako akcijo enaka, a nasprotna reakcija, lahko direktno zapišemo podobno enačbo za drugi delec, ki je udeležen v trku (skupna sprememba momentov obeh objektov je nič, skupen linearni moment ima torej lastnost, da se ohranja): 

 

Naš cilj je seveda najti hitrosti obeh objektov po trku. Obe zgornji enačbi lahko rešimo, če lahko izračunamo impulz. Ker predpostavljamo trk brez trenja, lahko impulz zapišemo poenostavljeno kot zmnožek skalarja in vektorja normale trka (slednjega smo izračunali malo višje zgoraj): 

 

TINR @ FRI, draft v09, Peter Peer ++   49  

Če to enačbo vstavimo v zgornji dve, dobimo dve enačbi in tri naznanke ( , , ). Torej potrebujemo za izračun še tretjo enačbo, ki jo dobimo z opazovanjem fizičnega obnašanja realnih objektov pri trku – pozorni smo na periodo deformacije in periodo obnovitve: 

 

Naša tretja enačba bo aproksimacija odziva materiala realnih objektov med trkom. Splošnejši primer trka (kjer objekta ne potujeta direktno eden proti drugemu): 

 

V zgornjem primeru (ob trku brez trenja) tudi, če objekta za kratek čas ostaneta v kontaktu (ker ne potujeta direktno eden proti drugemu), bosta enostavno zdrsnila eden mimo drugega brez zmanjšane hitrosti. Naša tretja enačba to upošteva in definira relacijo med komponentami normale hitrosti objektov pred in po trku: 

 

Skalar ε imenujemo koeficient prožnosti, ki je povezan z ohranjanjem ali izgubo kinetične energije med trkom. Spomnimo se, da je skupna energija enaka vsoti kinetične in potencialne energije, ki se pravtako ohranja (kot linerani moment). Če je ε=1, potem je trk povsem elastičen, kar pomeni, da je vsota kinetičnih energij obeh delcev enaka pred in po trku. Če je ε=0, potem je trk povsem plastičen, torej objekt nima periode obnovitve, izguba kinetične energije pa je maksimalna. V realnosti je ε funkcija lastnosti materialov, iz katerih so objekti narejeni. Tako je recimo ta koeficient približno 0,85 v primeru trka tenis loparja in žogice, v primeru trka povsem mehke košarkaške žoge z igriščem pa skoraj nič. 

Sedaj lahko na podlagi zapisanih treh enačb s tremi neznankami izračunamo linearni impulz: 

TINR @ FRI, draft v09, Peter Peer ++   50  

 

Ko slednjega izračunamo, damo to vrednost v drugo in tretjo enačbo, delimo z maso objekta in končno dobimo hitrosti po trku. 

6. Vhodne naprave 

Tradicionalni vmesniki za interakcijo z igro so: tipkovnica, miška, igralni plošček (gamepad), igralna palica (joystick), igralni volan. Vedno bolj pa se v igrah uporabljajo tudi drugi vmesniki, recimo: kamera, pespeškometri, dotikovni vmesnik ipd. Predvsem na slednjega bomo mi dali velik poudarek. 

Da zagotavljamo konsistenten vhod in s tem dajemo uporabniku boljši občutek odzivnosti in nadzora, moramo prebrati vhod enkrat na vsako upodobljeno sličico (frame) in shraniti te vrednosti za trajanje celotnega postopka za to sličico. V nasprotnem primeru, če bi spraševali po stanju naprave prepogosto ali premalo pogosto, bi lahko prišli do zelo nekonsistentnih rezultatov znotraj igre. Kot smo se že naučili, navadno preberemo vhod na začetku glavne zanke, pred korakom simulacije. Tako minimiziramo reakcijski čas med samim zajetjem vhoda in reakcijo na zahtevo. 

Dodatni viri: 

[1] http://www.flipcode.com/archives/Building_a_3D_Portal_Engine‐Issue_09_2D_Portal_Rendering.shtml [2] Numerical Recipes in C: http://www.fizyka.umk.pl/nrbook/bookcpdf.html, http://www.nr.com/  [3] Lin‐Canny ...??? (VanDerBergen03) [4] Gilbert‐Johnson‐Keerthi ...??? (VanDerBergen03) 

Naloga na vajah: 

• izris vseh elementov prvega zaslona (še brez interakcije, postavitev elementov shranjena direktno v kodi) 

• ločitev pogona igre, animacija (neobvezna naloga) 

• naredi interaktivno sceno: spreminjanje scene preko dotikov in premikanje stvari na sceni s pomočjo fizikalnega pogona (recimo premikanje po enačbi za hitrost) 

• integracija trkov (neobvezna naloga).