Simulacija

Jedan od ciljeva računarske grafike je da prikaže prirodne pojave i procese što je realnije moguće (talasanje vode, izgled tkanine, vatra i dim, lepršanje kose na vetru, ...). Ti efekti se postižu simulacijom, odnosno imitiranjem ponašanja nekog procesa kroz tok vremena.

Da bi bilo moguće računski simulirati procese, najpre moramo precizno, matematički, definisati ono sa čime radimo.

U daljem tekstu razlikovaćemo pojmove izgled i stanje sistema u nekom trenutku.

U nastavku dajemo primer jednog procesa, kroz koji ćemo potom prikazati nekoliko različitih načina simulacije.

Primer procesa: Loptica skočica

Posmatraćemo lopticu skočicu koja odskače od poda. Loptica je predstavljena tačkom, a pod je prava . Na lopticu deluje gravitaciono ubrzanje dato vektorom , koji je usmeren vertikalno ka dole (, ). Kada loptica dodirne pod, ona se odbija od njega potpuno elastično (ne gubi energiju prilikom odbijanja), tako što komponenta brzine u tom trenutku promeni smer, dok se komponenta brzine ne menja. Možemo zamisliti da je ovaj ceo proces odskakanja loptice počeo davno u prošlosti i da će trajati daleko u budućnost.

Sistem nam ovde čini samo jedan objekat, a to je loptica skočica. Njen izgled je definisan njenim položajem i brzinom. Model koji koristimo je dat osnovnim formulama za kretanje tela, a početni izgled je dat konstantama , , i , što znači da u trenutku loptica ima položaj i brzinu .

Cilj simulacije je pratiti kretanje loptice kroz vreme i u svakom trenutku znati izgled sistema, tj. brzinu i položaj loptice.

 

 

U svim prikazanim načinima simulacije koristićemo osnovne formule za kretanje tela koje znamo iz Njutnove mehanike. Pomoću njih ćemo računati položaj i brzinu u trenutku , ako znamo položaj i brzinu u trenutku , pri čemu pretpostavljamo da se između ta dva trenutka nije dogodio ni jedan događaj koji je promenio slobodno kretanje loptice (jedini događaj tog tipa u našem primeru je odbijanje od poda). Pod tom pretpostavkom, izgled sistema (položaj i brzina ) u trenutku se dobijaja sledećim formulama.

Primetimo da formule daju tačne rezultate bez obzira na to šta dolazi pre, ili . Ako je možemo smatrati da računamo kako je izgledao sistem u prošlosti.

💻 BouncyBalls

Analitičko rešenje

Za neke procese je moguće izvesti formulu kojom ćemo direktno moći da izračunamo izgled u traženom trenutku. Tako dobijena formula naziva se analitičko rešenje simulacije. U ovom načinu simuliranja, cela simulacija je pokrivena samo jednim stanjem, jer se interno ne menja ništa dok se krećemo kroz vreme.

 

center width:800

 

Ovo je najtačnija i najefikasnija simulacija. Međutim, retko kad možemo da je koristimo, jer je već i za veoma jednostavne sisteme formula previše komplikovana, a najčešće je uopšte nije moguće matematički izvesti.

Prikaz na primeru

Stanje sistema ćemo predstaviti trojkom koje čine trenutak, položaj i brzina, i u ovom tipu simulacije ono opisuje celokupno kretanje loptice koja u tom trenutku ima taj položaj i tu brzinu. Dakle, bez obzira na to što je jedna od komponenti stanja vremenski trenutak, stanje ovde ne predstavlja lopticu samo u tom trenutku, već celokupno kretanje loptice, sa svim odbijanjima, od velikog praska do toplotne smrti univerzuma.

Primetimo da se -komponenta brzine loptice nikada ne menja, pa se -komponente položaja i brzine mogu dobiti jednostavno.

Zato ćemo se dalje fokusirati samo na -komponente položaja i brzine.

Najpre, vratimo lopticu unazad tako da nam početak bude u prvom prethodnom trenutku kada je loptica dodirivala pod. Trenutak , kada se to desilo, položaj i brzina u tom trenutku će činiti trojku , koja predstavlja jedino stanje sa kojim ćemo ovde raditi.

 

 

Kada loptica dodiruje pod tada je -komponenta položaja , pa rešavanjem kvadratne jednačine po dobijamo vremenski interval između i prethodnog trenutka dodirivanja poda.

i sada lako dobijamo vreme, položaj i brzinu u tom trenutku.

Ovde treba voditi računa da postoje dva rešenja ove kvadratne jednačine, koja predstavljaju trenutke kada bi parabola po kojoj se kreće loptica presekla osu. Pošto nama treba trenutak prethodnog odbijanja, biramo manje od dva rešenja, pa će rezultat, , biti negativan, jer se to odbijanje desilo pre trenutka . Drugo, pozitivo, rešenje bi predstavljalo vreme do trenutka narednog odbijanja.

Ovim smo dobili stanje koje nam opisuje celokupno kretanje, i sada još treba da vidimo kako ćemo na osnovu njega odrediti položaj i brzinu loptice u proizvoljnom trenutku .

Primetimo da je način kretanja loptice između svaka dva odbijanja isti. Nakon svakog odbijanja brzina će biti jednaka , pa je vremenski period između dva uzastopna odbijanja . Pošto su odbijanja periodična, -koordinata položaja je određena samo vremenom koje je prošlo od poslednjeg odbijanja. Vreme proteklo od odbijanja koje je prethodilo trenutku do se lako dobija kao ostatak pri deljenju vremena proteklog od do sa dužinom perioda, . Položaj po osi je u tom trenutku (pri čemu prvi sabirak možemo izostaviti, jer znamo da je ), a brzina je . Ovim smo kompletirali formule za položaj i brzinu u trenutku .

Za opisani sistem nije bilo teško dobiti analitičko rešenje, odnosno formulu koja daje izgled sistema u proizvoljnom trenutku. Međutim, ako bismo samo malo zakomplikovali model, zahtevajući da se deo brzine gubi pri svakom odbijanju (što je realniji model loptice skočice), bilo bi dosta teže dobiti analitičko rešenje. Ako bismo pokušali da model učinimo još realnijim, na primer, uzimanjem otpora vazduha u razmatranje, analitički oblik rešenja verovatno ne bi bilo moguće dobiti.

💻 Ball_Formula

Simulacija bazirana na događajima (Event-based)

U procesima koje simuliramo ponekad možemo uočiti da postoje predvidivi događaji koji značajnije menjaju objekte sistema, ali da se između tih događaja ponašanje objekata može opisati jednostavno (npr. događaji su odbijanje loptice od poda). Ako je to slučaj, onda simulacija bazirana na događajima može biti pogodna za simuliranje tog procesa.

U ovoj vrsti simulacije svaki objekat će imati stanje koje opisuje njegov izgled u intervalu između dva uzastopna događaja u kojem učestvuje. Nakon što se neki događaj desi svi objekti koji se promene kao rezultat tog događaja dobijaju novo stanje.

Simulacija ovog tipa se izvršava tako što se posmatra skup mogućih budućih događaja, i iz tog skupa odabira onaj događaj koji se dešava najranije. Kako na taj događaj nije mogao uticati ni jedan drugi događaj nakon njega, taj događaj će se sigurno realizovati. Realizaciju događaja u radimo tako što vreme simulacije premeštamo u trenutak tog događaja, menjamo stanja objekata koji učestvuju u njemu, i ažuriramo skup mogućih budućih događaja.

Prilikom izvođenja simulacije neprestano se pomeramo iz trenutka u kom se nalazimo u neki budući trenutak. Međutim, trenutak u koji želimo da se premestimo ne mora biti blizu trenutnog, što znači da moramo uzeti u obzir mogućnost da se između ova dva trenutka desilo više događaja. Zato se premeštanje u zadati trenutak radi u petlji koja se izvršava sve dok trenutak sledećeg događaja nije nakon zadatog trenutka.

 

center width:800

 

Prikaz na primeru

U našem primeru, jedina vrsta događaja koja se može desiti je odbijanje loptice od poda. Neka loptica ima položaj i brzinu u nekom trenutku . Posmatramo vremenski interval između odbijanja koje je neposredno prethodilo trenutku i odbijanja koje mu neposredno sledi. Za sve trenutke iz tog intervala možemo lako izračunati položaj i brzinu loptice na osnovu već viđenih formula za kretanje. Zato ćemo stanje objekta u celom tom intervalu definisati trojkom , i to stanje će se menjati samo prilikom događaja odbijanja od poda.

U ovom primeru je veoma lako utvrditi kada će se desiti prvi sledeći događaj. To je najraniji trenutak u budućnosti kada će -komponenta položaja biti jednaka nuli. Postupak računanja tog trenutka je analogan postupku koji smo videli u prethodnom odeljku, gde smo računali prvi prethodni trenutak kada se loptica nalazila na podu.

Kada imamo trenutak tog događaja, izvršavamo ga na sledeći način. Najpre računamo položaj i brzinu loptice u trenutku tog događaja, pa zbog odbijanja menjamo znak -komponente brzine. Za novo stanje loptice uzimamo taj trenutak i izračunati položaj i brzinu.

Za razliku od analitičkog rešenja, u ovom načinu simuliranja ne bi bio nikakav problem realizovati model u kome se gubi energija prilikom svakog odbijanja.

💻 Ball_Events

Simulacija bazirana na otkucajima (Tick-based)

Najčešći slučaj je da je kompleksnost sistema koji se želi simulirati takva da nije moguće primeniti ni jedan od prethodno opisanih metoda simulacije. Tada se pribegava simulaciji baziranoj na otkucajima, u kojoj vreme pomeramo unapred u veoma sitnim koracima. Svaki taj pomeraj se naziva tick (tj. otkucaj), i vreme između dva uzastopna otkucaja, , je bitan parametar simulacije.

Pri svakom otkucaju računamo nova stanja objekata, uzimajući u obzir sve njihove moguće interakcije. Na primer, ako simuliramo mnoštvo kuglica koje se sudaraju, prilikom jednog otkucaja ćemo ažurirati položaj i brzinu svake kuglice, proveriti koje kuglice su se sudarile i odreagovati na sve te sudare tako što kuglicama izmenimo brzine na odgovarajući način.

Ovaj način simulacije uglavnom neće dati tačan rezultat koji je definisan modelom, već ćemo dobiti približan rezultat. Najčešće je slučaj da se rezultat može dobiti sa željenom preciznošću ako za uzmemo dovoljno malu vrednost. Međutim, što je ovo vreme manje, to se otkucaji dešavaju češće i više procesorskog vremena je potrebno za simulaciju.

 

center width:800

 

Prikaz na primeru

U posmatranom primeru, lopticu ćemo prilikom svakog otkucaja pomeriti kao da se kretala vremena brzinom koja je zapisana u trenutnom stanju, a brzinu ćemo izmeniti kao da je na objekat vremena delovala gravitacija.

Međutim, pre pomeranja ćemo uraditi proveru da li je loptica već dodirnula pod, tj. da li važi . Ako ovo važi, onda treba promeniti znak -komponente brzine. Ovde treba voditi računa da zbog nepreciznosti simulacije loptica može da se nađe ispod poda, a da joj brzina ima smer ka gore, u kom slučaju ne treba realizovati odbijanje.

💻 Ball_Ticks

Poređenje različitih metoda simulacije

Najsrećniji smo ako je simulaciju moguće realizovati preko formule, tj. ako postoji analitičko rešenje. U tom slučaju će naša simulacija imati mnoge pozitivne karakteristike, poput brzine, preciznosti i mogućnosti da lako skočimo u bilo koji trenutak u vremenu. Ipak, retko se dešava da je ovaj način simulacije moguće realizovati. Sledeća po kvalitetu je simulacija bazirana na događajima, ali nju možemo svega malo češće realizovati nego prethodni metod. Ono što nam uvek ostaje kao mogućnost je da radimo simulaciju baziranu na otkucajima. Ta simulacija neće imati tako dobre karakteristike kao prethodne, ali razvijeni su razni metodi da se ona poboljša. Takođe je dobro što je njena implementacija uglavnom jednostavnija od implementacija pomoću druge dve metode.

 FormulaEventsTicks
Brzina🚀🐢
Preciznost💯🎯😐
Premotavanje u napred😊🙂🤕
Premotavanje u nazad😊🚫🚫
Izvodljivost😭😢😊

Real-time simulacija

Često je neophodno simulaciju raditi u realnom vremenu, što znači da vreme unutar simulacije mora proticati istom brzinom kao i vreme u stvarnom svetu. Ovo je slučaj gde god je potrebna interakcija korisnika uživo sa objektima iz simulacije, kao što je to na primer slučaj u video igrama. U tom slučaju je potrebno da korisnik može da vidi trenutni izgled objekata, ali i da može da prosledi akcije koje utiču na objekte.

U ovom slučaju, stanje simulacije želimo da prikažemo više desetina do nekoliko stotina puta u sekundi. Svaki prikaz odgovara jednom frejmu. Da bi smo u trenutnom frejmu prikazali izgled sistema u trenutku prikazivanja frejma, najpre moramo simulaciju da "doguramo" do tog trenunka, tako da aktuelno stanje obuhvati trenutak prikazivanja.

U sledećem primeru radimo sa simulacijom baziranom na otkucajima, i metod updateTo nam premešta simulaciju neposredno do zadatog trenutaka time. To se postiže tako što u while petlji realizujemo otkucaj po otkucaj, sve dok sledeći otkucaj ne bude prelazio trenutak u koji želimo da se premestimo.

 

Na slici su trenuci u kojima se iscrtavaju frejmovi prikazani kao vertikalne linije.

 

center width:800

 

Ako simulaciju implementiramo na ovaj način, postižemo da konkretne vrednosti zapisane u stanjima objekata ne zavise od tačnih trenutaka kada se prikazuju frejmovi. Ovo je izuzetno bitno ako želimo da rezultati simulacije budu deterministički i ponovljivi.

Najčešća greška koju početnici čine je upravo da simulaciju na neki način vezuju za frejmove, što je veoma loša praksa. Ako je fiksiran, onda će simulacija biti brža na višim frame-rate-ovima i sporija na nižim. Ako to proba da se reši tako što se za koristi vreme proteklo između dva frejma, onda rezultat simulacije nije konzistentan, jer vreme proteklo između dva frejma uvek malo varira. Na primer, pomeranje simulacije za 0.015 s, pa za 0.017 s, neće proizvesti sasvim isti rezultat kao pomeranje dva puta za 0.016 s.

Uvek je poželjeno imati determinističku simulaciju, što znači da isti početni izgled daje isti rezultat. Međutim, često želimo da postignemo nekakvo "nasumično" ponašanje, i u tom slučaju treba koristiti generatore pseudoslučajnih brojeva sa fiksiranim seed-om, što znači da će prilikom svakog pokretanja simulacije biti konstruisan isti niz pseudoslučajnih brojeva.