diplomski zadatak br. 1795 animacija fizikalno …sveuČiliŠte u zagrebu fakultet elektrotehnike i...
TRANSCRIPT
SVEUČILIŠTE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA
DIPLOMSKI ZADATAK br. 1795
ANIMACIJA FIZIKALNO TEMELJENOG MODELA KOSE
Klea Kolarić
Zagreb, srpanj 2009.
Sadržaj: 1. Uvod......................................................................................4
2. Problemi pri modeliranju kose.................................................... 5
3. Fizikalno temeljeni model kose................................................... 7
3.1 Fizikalno temeljeni model bez opruga................................ 8 3.2 Fizikalno temeljeni model s oprugama............................... 9 3.3 Utjecaj prigušenja.......................................................... 11 3.4 Fizičke veličine............................................................... 12
4. Programska implementacija modela............................................ 14
4.1 Korištenje sfernih koordinata........................................... 14 4.2 Lokalni koordinatni sustav............................................... 16 4.3 Početni uvjeti................................................................ 17 4.4 Korištene strukture podataka........................................... 18 4.5 Pseudokod.................................................................... 19 4.6 Korištene veličine........................................................... 20
5. Različiti primjeri modela............................................................ 22
5.1 Ponašanje kostura valovite vlasi nakon ekstremne deformacije (uvid u težinske faktore)...................................................... 22
5.2 Ponašanje kostura vlasi pri utjecaju vanjskih sila ................ 23 5.3 Kostur ravne vlasi kao njihalo......................................... 23
6. Modeliranje kose...................................................................... 25
6.1 Aproksimacijske uniformne B-splajn kubne krivulje............. 25 6.2 Modeliranje krivulja........................................ ................ 27 6.3 Modeliranje traka........................................................... 28
6.4 Modeliranje cijevi........................................................... 30
7. Animacija kose pomoću OpenGL-a.............................................. 32
7.1 Inicijalizacija OpenGL varijabli.......................................... 32 7.2 Prikazivanje vlasi........................................... ................ 33 7.3 Prikazivanje traka.......................................................... 34
7.4 Prikazivanje cijevi.......................................................... 36 7.5 Korištenje tekstura.........................................................39
8. Rezultati izvođenja simulacije.................................................... 42
8.1 Krivulje......................................................................... 42 8.2 Trake........................................................... ................ 44 8.3 Cijevi........................................................................... 45
9. Zaključak................................................................................ 46
10. Literatura.............................................................................. 47
2
Dodatak 1: Rješenje jednadžbe gibanja.......................................... 48
Dodatak 2: Uvjet stabilnosti.......................................................... 51
Sažetak...................................................................................... 53
Abstract..................................................................................... 54
3
1. Uvod
Još od početaka računalne grafike modeliranje i animacija kose
(pogotovo u stvarnom vremenu) predstavljali su veliki problem zbog
složene prirode kose. Model kose koji izgleda prirodno bio je nužan za
ostvarivanje realnog izgleda virtualnih ljudi za različite CG aplikacije. S
vremenom je razvijen niz modela koji su se djelomično zasnivali na
fizičkim svojstvima vlasi kose, a korišteni su za aproksimiranje gibanja
čitavog pramena te su tako omogućili realniju animaciju kose u stvarnom
vremenu.
Slika 1.1 Kosa je važan element pri modeliranju virtualnih ljudi. Animacija kose u stvarnom vremenu daje realniji izgled računalnim
igrama.
Cilj ovog rada je pokazati kako postići što realniju simulaciju kose u
stvarnom vremenu koristeći fizikalno temeljeni matematički model koji je
predložio Anjyo [1] te razvili Koh i Huang [2]. U radu se daje pregled
matematičkog modela, način implementacije i vizualizacije te osvrt na
probleme i prednosti modela i implementacije.
4
2. Problemi pri modeliranju kose
Osnovni problem pri modeliranju kose je njezina složenost: na
ljudskoj glavi obično se nalazi preko 100,000 vlasi, a fizička svojstva vlasi
drastično se razlikuju ovisno o tipu kose. Svaka zasebna vlas ima vrlo mali
promjer i masu. Ponašanje zasebne vlasi donekle se razlikuje od
ponašanja pramena: vlasi se obično grupiraju u pramenove zbog trenja
između vlasi, tako da se susjedne vlasi ponašaju slično. Izraženost
grupiranja vlasi ovisi jako o tipu kose (npr. ravna ili kovrčava, tanka ili
čvrsta itd.).
Slika 2.1 Površina vlasi kose nije glatka nego se sastoji od niza sitnih ljuskica. To znatno povećava trenje između
pramenova te trenje između kose i zraka.
Zbog veće mase i oblika pramen drugačije reagira na strujanje i
otpor zraka nego zasebna vlas. Također, unutarnje trenje u pramenu,
činjenica da su vlasi obično deblje pri korijenu i smjer rasta kose imaju
kao posljedicu veću pokretljivost kose pri vrhovima nego uz vlasište, što
je ponašanje koje se toliko ne primjećuje pri promatranju zasebne vlasi.
Postoji velik broj tipova kose i različitih frizura, a ponašanje kose mijenja
se drastično pod utjecajem proizvoda za oblikovanje ili pod utjecajem
vlage. Najrealističniji računalni modeli modelirali su zasebno pojedinačne
5
vlasi (npr. 60,000 zasebnih vlasi u animiranom filmu "Final Fantasy: the
Spirits Within"), no ovi modeli nisu bili pogodni za izvođenje u stvarnom
vremenu.
Slika 2.2 Veća pokretljivost pramena pri vrhu nego pri korijenu.
Većina današnjih modela za animaciju u stvarnom vremenu koristi
kostur sastavljen od opruga (koje slijede fizičke zakone za oprugu) koji se
onda modificira kako bi što realnije dočaralo kretanje pramena kose.
Zatim se taj kostur koristi kao osnova za stvaranje različitih NURBS
površina ili "omotnica" kojima se dočarava izgled pramena [3].
6
3. Fizikalno temeljeni model kose
Osnovu većine fizikalnih modela za kosu predložio je Anjyo 1992.
Model se sastojao od čvrstih segmenata duljine d koji su bili povezani
pokretnim zglobovima. Na segmente je djelovala vanjska sila F. Njegov
model je imao prednost jer je umjesto uobičajenog kartezijevog
koordinatnog sustava (s osima xyz) koristio sferni koordinatni sustav (s
komponentama rθφ). Svaki segment bio je učvršćen u ishodištu lokalnog
koordinatnog sustava i njegov pomak se izražavao promjenom kutova θ i φ (r je uvijek odgovarao duljini segmenta d koja je nepromjenjiva).
Takav koordinatni sustav je bio bolje prilagođen kretanju samog
segmenta koje je odgovaralo rotaciji štapa učvršćenog u jednom kraju
(tako da se umjesto mase koristi moment tromosti I, a umjesto sile
moment sile M). Anjyo [1] je predložio jednodimenzionalne projektivne
jednadžbe, nazvane tako jer se vanjska sila razloži na projekcije u θ i φ
ravnini i te se projekcije koriste pri računanju odgovarajućih kutova.
Slika 3.1 Kostur koji opisuje gibanje kose sastoji se od povezanih čvrstih segmenata.
7
3.1 Fizikalno temeljeni model bez opruga
Slika 3.1.1 Rotacija i-tog segmenta oko ishodišta lokalnog koordinatnog sustava opisana preko kutova θ i φ.
Osnovni oblik jednadžbe je:
ψψ M
dtd
=2
2
gdje je ψ kut, t je vrijeme, a Mψ projekcija vanjske sile F u ψ ravninu.
Kada to primijenimo na sferne koordinate:
8
ϕ
θ
ϕ
θ
FvIdt
d
FuIdt
d
ii
ii
i
1
1
2
2
2
2
=
=
gdje je Ii moment tromosti svakog segmenta, ui je polovica duljine
segmenta, a vi polovica duljine projekcije segmenta u φ ravninu. Uzima se
da imamo k segmenata koji su svi iste duljine. Komponenta vanjske sile
za svaku ravninu računa se kao skalarni produkt između vanjske sile F i
jediničnog vektora koji leži u dotičnoj ravnini, a okomit je na segment (tj.
na projekciju segmenta u tu ravninu). Uzima se da komponenta sile u
ravnini ima isti smjer kao i taj jedinični vektor.
Moment tromosti segmenta definira se kao:
2
31 dmwI iii ⋅=
gdje je d duljina segmenta, a mi masa segmenta (definirana kao d *
gustoća ρ * površina presjeka). Ovo je uobičajen izraz za moment tromosti
štapa koji rotira oko jednog kraja, ali je dodan i "težinski faktor" wi koji
omogućava realnije ponašanje kose tako da su segmenti uz vlasište teži,
dok su oni pri vrhovima pokretljiviji. wi se najčešće definira kao k/i, iako se
za modeliranje različitih tipova kose ili frizura faktori mogu i drukčije
definirati.
3.2 Fizikalno temeljeni model s oprugama
Kasnije je model opisan u "A Simple Method For Extracting The
Natural Beauty Of Hair" [1] proširen korištenjem opruga [2]. Opet, zbog
korištenja sfernog koordinatnog sustava opruge se definiraju tako da
imaju komponente u θ i φ ravninama. Ovo puno prirodnije opisuje
9
ponašanje kose nego definiranje opruga koje bi djelovale po xyz osima.
Možemo gledati kao da se θ u mirovanju odupire gravitaciji, dok se φ
opruga opire torziji. Dakle, ukupni moment sile možemo pisati kao:
vanjskoopruge
vanjskoopruge
MMM
MMM
ϕϕϕ
θθθ
+=
+=
Dalje, ovo se može raspisati kao:
ϕϕ
θθ
ϕϕ
θθ
ϕϕ
θθ
vFM
uFM
kM
kM
vanjsko
vanjsko
opruge
opruge
=
=
−−=
−−=
)(
)(
0
0
gdje je u polovica duljine segmenta, a v polovica duljine projekcije
segmenta u φ ravninu. Ne smijemo zaboraviti da radimo s vektorima, i to
treba uzeti u obzir pri zbrajanju i množenju.
Vanjska sila koja djeluje na segment je rezultanta sile gravitacije,
sile vjetra na vlasi i sile nastale zbog pokreta glave. Uvrštavanjem svega
navedenog dobivamo početnu diferencijalnu jednadžbu koja odgovara
jednadžbi opruge s prigušenjem uz djelovanje vanjske sile:
ϕ
θ
ϕγϕ
θγθ
Mdt
ddt
dI
Mdt
ddtdI
ii
ii
ii
ii
=+
=+
2
2
2
2
gdje γi predstavlja prigušenje. U numeričkoj simulaciji ove jednadžbe se
diskretiziraju kao:
10
ϕ
θ
ϕϕγϕϕϕ
θθγθθθ
Mtt
Mttn
i
n
ii
n
ii
nn
i
n
i
n
ii
n
iinn
i
′Δ=−Δ′++−
′Δ=−Δ′++−−−+
−−+
2111
2111
)()(2
)()(2
gdje ' označava da su Mθ i γi podijeljeni s Ii. Cijeli izračun ove formule
može se naći u Dodatak 1.
3.3 Utjecaj prigušenja
Kako bi sustav opruge prestao titrati nakon nekog vremena
potrebno je uvesti prigušenje γ. Obično se ovo naziva koeficijent
prigušenja i označava se sa c. Računa se kao:
kmc ζ2=
Pošto računamo kutne veličine možemo pisati I umjesto m. Važan
parametar ovdje nam je ζ tj. omjer prigušenja koji određuje koliko perioda
će sustav titrati prije nego što se zaustavi. Odnos između ζ i prigušenja
možemo vidjeti na Slici 2.3.1.
11
Slika 3.3.1 Odnos između omjera prigušenja i frekvencije titranja
3.4 Fizičke veličine
Pošto je ovo fizikalno temeljeni model, zahtjeva uvrštavanje i nekih
stvarnih svojstava kose poput dimenzije. Utvrđeno je da je prosječna
gustoća vlasi oko 1.3 g/cm3 [7]. Debljina vlasi znatno varira ovisno o tipu
kose, tako da promjer vlasi iznosi od 17 do 181 μm. Iako presjek vlasi nije
idealno kružan već eliptičan, za naše potrebe možemo vlas aproksimirat
kao dugačak cilindar s kružnim presjekom. Individualna vlas je vrlo
elastična i može se rastegnuti do 50% prije no što pukne, ali pramen koji
sadrži oko 100 vlasi je veoma čvrst i pri djelovanju sila poput vjetra ne
pokazuje znakove rastezanja.
Za neka svojstva kose ipak se moraju koristiti aproksimacije i
vlastita procjena jer:
1. Nema zadovoljavajućih mjerenja nekih veličina.
12
2. Model bi se znatno zakomplicirao da sadrži utjecaje strujanja i
otpora zraka u koje bi se mogli uvrstiti stvarna svojstva kose poput
iznosa trenja između kose i zraka.
3. Neka svojstva (poput iznosa konstante opruge) puno je lakše
izračunati s obzirom na sile (npr. gravitaciju) nego dobiti
mjerenjima ili korištenjem fizičkih formula.
Jedan od primjera je iznos sile vjetra. Silu vjetra za najbolje
rezultate najlakše je definirati tako da se iznos gravitacije pomnoži s
nekim koeficijentom (najbolje u granicama [0.01,10]) jer se tako dobiva
rezultantna sila u kojoj udio imaju obje sile (ni jedna sila nije toliko jaka
da se druga može zanemariti).
Drugi primjer je iznos konstante θ opruge kθ. Ova opruga u stanju
mirovanja određuje kovrčavost kose jer se opire gravitaciji (φ ravnina je
okomita na smjer gravitacije). Umjesto da se kθ izračunava iz svojstava
željenog tipa kose, puno lakše je izračunati takav kθ koji u stanju
mirovanja pobija komponentu sile gravitacije okomitu na segment (jer
komponenta koja djeluje po segmentu nema utjecaja). Tako se kθ može
definirati kao:
αθ sin⋅= gmk gdje je α kut između vlasi i vertikale.
Također potrebno je da početni kut θ = α0 .
Iznos kφ ne mora bit jednak iznosu kθ, ali zbog svojstava kose
uobičajeno je da on bude istog reda veličine.
13
4. Programska implementacija modela
Za implementaciju danog modela korišten je programski jezik C++ i
grafički standard OpenGL. Korištena je i biblioteka GLUT.
4.1 Korištenje sfernih koordinata
Slika 4.1.1 Veza između sfernih i kartezijevih koordinata (sustav ima orijentaciju kao u OpenGL-u)
Modeliranje pomoću sfernih koordinata (r, θ, φ) imalo je velike
prednosti pri opisu gibanja kose i pri rješavanju matematičkog modela.
Prvi problem javlja se zbog prilagodbe korištenog koordinatnog sustava
koordinatnom sustavu OpenGL-a. OpenGL zna iscrtavati samo s
14
kartezijevim koordinatama i ima koordinatni sustav postavljen drukčije
nego što je uobičajeno u matematici (uobičajeno je da z-os gleda prema
gore, dok u OpenGL-u prema gore gleda y-os). Iz ovog slijedi da je
potrebno prilagoditi jednadžbe za pretvaranje iz sfernih u kartezijeve
koordinate:
ϕθθ
ϕθ
cossincos
sinsin
rzryrx
===
gdje je r duljina segmenta u jedinicama OpenGL sustava.
Također potrebno je moći pretvarati iz kartezijevih u sferne
koordinate. Ovdje se koristi posebna funkcija atan2 (osmišljena upravo za
upotrebu u programskim jezicima), koja je verzija arctan funkcije, ali
može razlikovati dijametralno suprotne smjerove. atan2 može razlikovati
kutove između vektora (1,1) i (-1,-1) kao π/4 i –3π/4 za razliku od arctan
koja bi u oba slučaja vratila π/4. atan2 se definira kao:
gdje je φ kut iz intervala [0, π/2), a tanφ=|y/x|. Rješenja su iz
intervala (-π, π], s time da se definira:
Koristeći atan2 možemo izračunati sferne koordinate kao:
15
),(2tan
),(2tan22
222
yxza
zxazyxr
+=
=
++=
θ
ϕ
Drugi problem pri korištenju sfernih koordinata je u tome što se
obično sferne koordinate računaju unutar nekih intervala kako bi se
izbjegle višestruke mogućnosti pri definiranju istih kutova. Npr. sferne
koordinate (1,3π/2,π/2) i (1,π/2,3π/2) predstavljaju istu točku u kartezijevom
sustavu (tj. dolazi do poklapanja). Obično se definira da vrijedi: θ iz [0,π], φ iz [0,2π) i r ≥ 0. No ovdje pri računanju sile opruge računamo s razlikom
kutova (koja predstavlja pomak) i nije moguće se ograničiti samo na
kutove iz danih intervala. Ako bi imali takva ograničenja, mogli bi
preslikati negativne kutove u pozitivne i time promijeniti predznak izraza
(θ - θ ) 0 ili (φ - φ )0 , čime bi se promijenio i smjer djelovanja sile opruge.
Primjer ovog problema vidimo kada vlas, učvršćenu na jednom
kraju, ispustimo s neke visine poput njihala. Vlas ne prelazi ravnotežni
položaj nego se od njega odbija kao da je naišla na prepreku. Upravo
ovakve greške se događa zbog zrcaljenja negativnih kutova u pozitivne.
Dakle, kako bi model ispravno radio ne smije se upotrebljavati svođenje
kutova na intervale.
4.2 Lokalni koordinatni sustav
Radi jednostavnosti izračuna, za svaki segment se definira lokalni
koordinatni sustav. Lokalni koordinatni sustav ima isti položaj osi kao i
globalni, ali je translatiran tako da se početna točka segmenta (oko koje
se segment rotira) poklapa s ishodištem. Možemo gledati kao da se
izračun pomaka vrši dok je segment učvršćen u ishodištu globalnog
koordinatnog sustava (na početku se oba sustava poklapaju). Nakon
izračuna pomaka u kutovima, izračunava se položaj segmenta u
kartezijevim koordinatama i onda se lokalni koordinatni sustav translatira
tako da se dani segment nastavlja na prethodni segment (ishodište se
16
poklopi s krajem prijašnjeg segmenta). Translacija je jednostavna
transformacija za izvedbu, te je poželjno definirati lokalni koordinatni
sustav tako da se izbjegnu složenije transformacije poput rotacije ili
skaliranja.
4.3 Početni uvjeti
Još jedan problem vezan uz sferni koordinatni sustav je njegova
relativna neintuitivnost, pogotovo s obzirom na kartezijeve koordinate.
Osim posebne pažnje koju je potrebno posvetiti aritmetici, potrebno je
također paziti na način zadavanja položaja segmenata. Dobar primjer je
modeliranje kovrčave kose. Recimo da želimo kovrče koje su od vertikale
otklonjene za kut od 20°. Po formuli k =gmθ sinα izračunamo jačinu θ opruge, no da bi vlas izgledala kako želimo definirati i θ =20°0 . Ako bi
stavili da je početni kut 0° dobili bi ravan pramen. Također je potrebno
pravilno definirati i φ 0i kao što se vidi na Slici 4.3.1.
Slika 4.3.1 Lijevi kostur ima pravilno definirane θ0 i φ0 kutove – φ0i izmjenično iznose π/2 i 3π/2. Desni kostur ima dobro definiran θ0 ali svi φ0i iznose π/2.
17
4.4 Korištene strukture podataka
Iako je C++ objektno orijentirani programski jezik, odlučila sam
koristiti obične strukture umjesto objekata. Sve točke na vlasi (krajevi
segmenata) su pohranjene u strukturi Koor. Izgled strukture Koor:
typedef struct _Koor { GLdouble x; GLdouble y; GLdouble z; GLdouble r; GLdouble theta; GLdouble phi; } Koor; Koor koor[SEG+1];
x, y i z definiraju jedinični radij vektor dane točke. Uzet je jedinični
radij vektor kako bi se olakšalo računanje skalarnih produkata ili kutova
među vektorima. Važno je napomenuti da su sve točke vlasi definirane s
koordinatama u lokalnom koordinatnom sustavu (tj. s obzirom na njegovo
ishodište). r predstavlja duljinu segmenta u OpenGL jedinicama. theta i
phi su naravno kutovi u sfernim koordinatama. Prva točka u nizu
predstavlja ishodište.
Ove strukture koriste se još i za pohranu sila. Sile se definiraju na
isti način, s time da r predstavlja jačinu sile, a radij vektor predstavlja
smjer djelovanja sile. Pri modeliranju vjetra uzima se da je gustoća sile u
prostoru jednolika tj. izvor dovoljno udaljen da je njegov utjecaj neovisan
o udaljenosti i položaju izvora spram objekta.
Kako bi se segmenti ispravno translatirao iz lokalnog koordinatnog
sustava u globalni, postoji struktura Dots koja čuva koordinate segmenata
s obzirom na ishodište globalnog koordinatnog sustava.
typedef struct _Dots {
GLdouble x; GLdouble y; GLdouble z; } Dots;
18
Dots dot[SEG+1];
Ovakav niz točaka čuva ishodišta svakog segmenta u globalnom
koordinatnom sustavu, tako da kada se izračuna novi položaj neke točke
iz niza koor potrebno je samo odgovarajućoj točki iz dots pribrojiti radij
vektor.
dot[tocka].x = dot[tocka-1].x + koor[tocka].r * koor[tocka].x; dot[tocka].y = dot[tocka-1].y + koor[tocka].r * koor[tocka].y; dot[tocka].z = dot[tocka-1].z + koor[tocka].r * koor[tocka].z;
Iscrtavanje se vrši po točkama iz dots, dok se koor koriste samo za
izračun novog položaja. Postoje još strukture koor1 i koor0 koje čuvaju
vrijednost položaja u trenutku n-1 i n-2 jer nam je to potrebno za izračun
novog položaja.
4.5 Pseudokod
Glavni dio programa koji računa položaj kostura u svakom
vremenskom trenutku možemo opisati kao:
(za svaki vremenski interval T)
Za svaki segment i od 0 do k {
Uzmi krajnju točku segmenta;
Izračunaj moment opruge M_opruge;
Izračunaj vanjski moment M_vanjsko;
M_ukupno = M_vanjsko + M_opruge;
Izračunaj novi položaj krajnje točke segmenta;
Translatiraj točku na odgovarajući položaj u globalnom
koordinatnom sustavu;
}
Iscrtaj novu sliku;
Vanjska sila se računa zbrajanjem svih sila koje djeluju na kostur. U
ovom primjeru imamo zbrajanje sile gravitacije i vanjske sile:
19
rez.x = sila.r * sila.x + g.r * g.x; rez.y = sila.r * sila.y + g.r * g.y; rez.z = sila.r * sila.z + g.r * g.z; rez.r = sqrt(pow(rez.x,2) + pow(rez.y,2) + pow(rez.z,2)); // normaliziraj vektor rez.x /= rez.r; rez.y /= rez.r; rez.z /= rez.r;
Iz ovog se naknadno mogu izračunati sferne koordinate rezultantne
sile. U svakom koraku potrebno je izračunati projekciju vanjske sile u
željenu ravninu, a ona se po iznosu definira kao skalarni produkt između
vanjske sile i okomice na projekciju segmenta u danu ravninu. Ovo je
primjer za θ ravninu (φ ravnina se računa analogno):
thetaN.theta = koor[tocka].theta + M_PI_2; thetaN.phi = koor[tocka].phi; thetaN.x = sin(thetaN.theta) * sin(thetaN.phi); thetaN.y = cos(thetaN.theta); thetaN.z = sin(thetaN.theta) * cos(thetaN.phi); thetaN.r = 1.0;
thetaF = (thetaN.x*rez.x + thetaN.y*rez.y + thetaN.z*rez.z) *
rez.r;
Iscrtavanje se vrši pomoću uobičajenih OpenGL funkcija za linije i
točke.
4.6 Korištene veličine
Važno je paziti da pri računanju s fizičkim veličinama koristimo
odgovarajuće mjerne jedinice (metre, sekunde i kilograme, jer u tim
mjernim jedinicama su izražene i fizičke konstante). Iznosi konstanti
mjenjaju se s obzirom na to kakva svojstva kose (tj. koji tip kose) želimo
modelirati.
Primjer korištenih konstanti:
Kg 15 // iznos vanjske sile se definira kao Kg * G, G = m*g DR 0.1 // omjer prigušenja (c) gama = DR * 2*sqrt(k*I),
20
SEG 5 // broj segmenata LEN 0.05 // duljina segmenta u m R 50 * 1e-6 // radijus kose m NUM 100 // broj vlasi u pramenu STEP 5 // brzina glut animacije u milisekundama STEP1 1 // korak integracije u milisekundama
Iz ovih veličina moguće je izračunati silu gravitacije na vlas kose
kao: g.r = M_PI * (pow(R, 2.0)) * 1.3 / 1000.0 * LEN * NUM * 9.81
gdje je gusoća kose 0.0013 kg/m3.
Vidimo da korak integracije i brzina integracije nisu isti: animacija je
pet puta sporija od kretanja koje dobivamo rješavanjem jednadžbe.
Ovakav odnos vremena daje kosturu veću tromost koju u prirodi
primjećujemo zbog trenja zraka i kose, otpora zraka i činjenice da zrak
prolazi kroz pramen. Korak integracije određen je u skladu s uvjetom
stabilnosti (vidi Dodatak 2).
21
5. Različiti primjeri modela
Ovih par primjera izvođenja pokazuje ponašanje kostura u različitim
uvjetima. Program naravno izvodi kontinuiranu simulaciju no ovdje su
izdvojeni odgovarajući vremenski okviri kako bi se to gibanje moglo
ilustrirati.
5.1. Ponašanje kostura valovite vlasi nakon ekstremne
deformacije (uvid u težinske faktore)
U ovom primjeru modelirana je valovita vlas sa segmentima kostura
pod kutem od 20° spram vertikale. Zatim je vlas "spljoštena" tako da su
zadani početni kutevi koji su odgovarali pritiskanju vlasi u smjeru
pozitivne y osi (slično kao da pokušavamo pritisnuti oprugu). No za razliku
od obične metalne opruge koja bi nakon otpuštanja imala u svakom
trenutku konstantan razmak između segmenata, kod kostura vidimo da
zbog težinskih faktora niži segmenta imaju veći pokretljivost od onih bliže
ishodištu.
Napomena: početna točka prvog segmenta nalazi se u ishodišu, vlas
se proteže u smjeru negativne y osi, pogled je u smjeru negativne z osi.
22
Slika 5.1.1 Animacija valovite vlasi. Uočavamo da su niži segmenti puno pokretljiviji od segmenata bližih korijenu zbog različitih težinskih faktora wi = k/i, i=1..k.
5.2 Ponašanje kostura vlasi pri utjecaju vanjskih sila
Vlas iz prošlog primjera izložena je vanjskoj sili (uz gravitaciju)
jačine 15*mg. Ovo je prilično jaka sila, a pošto ima konstantno djelovanje
vlas nakon nekog vremena više ne treperi, nego zauzima stalni položaj u
smjeru djelovanja rezultante, tako da izgleda kao da netko povlači vlas u
danom smjeru.
Važno je napomenuti da ovako modeliramo silu koja odgovara
povlačenju. Ako bi željeli modelirati vjetar, morali bi primijeniti drukčiji
pristup. Stvarni pramenovi (i vlasi) ponašaju se drukčije na vjetru zbog
složenih interakcija vlasi i zraka, tako da bi za realniji dojam trebalo
definirati vanjsku silu kao funkciju čiji se iznos mijenja o vremenu.
Slika 5.2.1 Kostur pod utjecajem vanjske sile i gravitacije. Zbog konstantnog iznosa sile kostur na kraju zauzima položaj u smjeru rezultante sila.
5.3 Kostur ravne vlasi kao njihalo
Ravna vlas podignuta je za kut od 45° i ispuštena. Napravljene su
dvije verzije animacije: u prvoj je korištena uobičajena težinska funkcija
wi=k/i, a u drugoj oblik wi=k/(k-i+1) koji čini vršne segmente težima. Iako
je prva verzija ispravna, zbog manjka otpora zraka način kretanja u
drugoj verziji se čini prirodnijim.
23
Slika 5.3.1 Prva verzija animacije: njihanje kostura s lakšim vršnim segmentima. Iako ispravan, modul ne odgovara u potpunosti stvarnom slučaju jer nedostaje otpor zraka. On
se može naknadno modelirati ako je potrebno (inače nije toliko uočljiv zbog djelovanja vanjskih sila).
Slika 5.3.2 Druga verzije animacije: njihanje kostura s težim vršnim segmentima. Iako ovo ne odgovara u potpunosti realnim svojstvima kose, daje gibanje slično gibanju stvarne vlasi
zbog otpora zraka.
24
6. Modeliranje kose
Iako fizikalni model opisuje gibanje kose, kako bi se kosa što bolje
prikazala potrebno je modelirati i njen izgled i strukturu. Ponovo, zbog
složene prirode kose, nije moguće potpuno realno prikazati njezinu građu i
izgled, ali za većinu primjena to nije ni potrebno.
Za modeliranje kose obično se koristi prikaz zasnovan na B-splajn
krivuljama. Korištenjem ovih krivulja kosu je moguće prikazati na više
načina: kao samu krivulju (prikaz zasebnih vlasi), kao površinu/traku
(prikaz pramenova) ili kao "cijev" ili "omotnicu" oko krivulje (pogodno za
prikaz specifičnih frizura poput pletenica). Ponekad se ovi stilovi mogu
kombinirati ili mijenjati ovisno o složenosti prikaza (LOD – Level Of Detail
[3]). Model koji prikazuje vlas ili pramen kose oblikuje se s obzirom na
kostur fizikalnog modela kako bi objekt kasnije bilo moguće animirati. U
ovom radu ne obrađuju se modeli osvjetljenja kose, koji su posebno
razvijeni zbog složene prirode refleksije svijetlosti na pojedinačnim
vlasima.
6.1 Aproksimacijske uniformne B-splajn kubne krivulje
Aproksimacijska B-splajn krivulja definirana je kao:
∑=
=n
iii uNrup
03, )()( rr
Ako za aproksimacijsku B-splajn kubnu krivulju imamo uniformno
zadan vektor uzlova u -u = konstantai+1 i , znači da su uzlovi jednoliko
raspoređeni. Razmak je jediničan ako vrijedi u -u = 1i+1 i i u tom slučaju
krivulju možemo načiniti upotrebom samo periodičkog segmenta.
Periodički segment aproksimacijske kubne B-splajn krivulje određen je sa
četiri točke, a u tom slučaju i-ti segment krivulje zadan je kao:
25
[ ]⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢
⎣
⎡
⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢
⎣
⎡
−−
−−
=
+
+
−
2
1
1
23
0141030303631331
611)(
i
i
i
i
i
rrr
r
ttttp
r
r
r
r
r
Gdje se za svaki segment parametar t mijenja u intervalu 0≤t<1, a
svaki segment određen je sa 4 točke (Slika 6.1.1).
Za ovakvu krivulju jednostavno je odrediti i tangentu u svakoj točki.
Tangenta se može koristiti kako bi se npr. odredila orijentacija objekta
koji se giba po krivulji. Jednadžba tangente se dobiva deriviranjem
jednadžbe krivulje po parametru t:
[ ]⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢
⎣
⎡
⎥⎥⎥
⎦
⎤
⎢⎢⎢
⎣
⎡
−−
−−=
∂∂
=′
+
+
−
2
1
1
2
010102421331
211)()(
i
i
i
i
ii
rrr
r
ttttptp
r
r
r
r
rr
Treba primijetiti da se ovako dobiva vektor koji određuje smjer
tangente, a ne točka kao što je bio slučaj u jednadžbi krivulje.
Slika 6.1.1 Početni segment p1 (plavi) krivulje određen je točkama r0, r1, r2, r3, slijedeći segment p2 (crveni) određen je točkama r1, r2, r3, r4, a završi segment p3 (zeleni) određen je
točkama r2, r3, r4, r5.
26
6.2 Modeliranje krivulja
Krivulje se koriste za prikaz pojedinačnih vlasi. Ovaj način prikaza
nije učestao jer je zahtjevan za iscrtavanje (potrebno je iscrtati velik broj
vlasi – na ljudskoj glavi obično ima preko 100,000 vlasi) i zato jer
postojeći fizikalni modeli ne mogu obuhvatiti interakciju pojedinačnih
vlasi, dajući nerealistični izgled animaciji. Obično se krivulje koriste kao
dodatak u modelima uglavnom sastavljenih od traka ili cijevi koji prikazuju
pramenove. Manji broj zasebnih krivulja dodaje se kako bi se dočaralo
izdvajanje vlasi iz pramenova (koji se modeliraju trakama ili cijevima).
Krivulje se iscrtavaju koristeći "zglobove" kostura kao kontrolne
točke (cijeli kostur tada predstavlja karakteristični poligon krivulje). Za
prikaz je potrebno odrediti koliko segmenata krivulja ima (toliko
segmenata mora imati i kostur) i koliki je korak promjene parametra t unutar segmenta (Δt). Pošto je krivulja zapravo jednodimenzionalna linija,
modeli osvjetljenja ne mogu dovoljno dobro prekriti "uglatost" linije, te
stoga Δt mora biti dovoljno malen.
Napomena: Pri crtanju krivulje (kod sva tri načina prikaza) dodan je
poseban statični segment na sam početak kostura čime se dočarava
realan izgled korijena kose koji pri gibanju ostaje uz tjeme. Ovaj segment
se ne uzima u obzir pri proračunu položaja kostura pomoću fizičkog
modela.
27
Slika 6.2.1 Korištenje kostura za crtanje krivulje.
6.3 Modeliranje traka
Trake se koriste za modeliranje pramenova kose. Ovakav način
modeliranja je manje zahtjevan od modeliranja zasebnih vlasi (obično je
dovoljno između 20-50 traka za realni prikaz kose) i dobro odražava
činjenicu da se pojedinačne vlasi zbog trenja i masnoće obično povezuju u
pramenove. Problem traka je u njihovoj dvodimenzionalnosti te je obično
potrebno modificirati opruge kostura tako da kosa prividno dobije na
volumenu. Zbog toga ovaj način prikaza nije pogodan za izrazito kovrčavu
kosu. Kako bi se dobio realniji izgled kose, na traku se lijepi tekstura koja
podržava prozirnost, što omogućuje dočaravanje više manjih pramenova
dok se broj iscrtanih objekata ne povećava.
28
"Trake" zapravo predstavljaju površine omeđene dvjema B-splajn
krivuljama. Za definiranje ovih dviju krivulja potrebno je definirati dva
pomoćna kostura, koji se izvode iz središnjeg kostura [3]. Možemo
zamisliti strukturu koja nalikuje nizu paralelnih čvrstih šipki, pričvršćenih u
sredini za zglobove osnovnog kostura. Kako se središnji kostur pokreće
tako se pomiču i šipke, te se torzija središnjeg kostura također odražava
kao zakret šipki oko središta. Vrhovi tih šipki opisuju točke (zglobove)
pomoćnih kostura. Pomoćni kosturi se izvode s obje strane središnjeg
kostura (i to na jednakoj udaljenosti od njega) kako bi se bolje prikazala
torzija pramena.
Slika 6.3.1 Iz središnjeg kostura izvode se dva pomoćna kostura (s obje strane) pomoću kojih se određuju točke krivulje koje se tada spajaju tvoreći poligone.
29
Kada je određen položaj pomoćnih kostura, za svaki od njih računaju se
točke krivulje (s istim Δt) i onda se povezuju, tvoreći tako poligone.
Pomoću glatkog sjenčanja (smooth shading) dobiva se dojam da je cijela
površina zapravo glatka, a ne sastavljena od poligona (to također
omogućuje korištenje manjeg broja poligona i tako smanjuje vrijeme
iscrtavanja). Na samu površinu također je moguće primijeniti algoritme
koji prilagođavaju broj poligona željenoj složenosti prikaza (LOD [3]).
6.4 Modeliranje cijevi
Cijevi također predstavljaju pramenove kose, ali za razliku od traka
imaju određen volumen i moguće im je detaljnije oblikovati strukturu.
Najpogodnije su za prikaz specifičnih frizura poput pletenica, dreadlocksa
ili kose svezane u rep. Također zbog svog volumena cijevi se koriste za
prikaz izrazito kovrčave kose, ali tu se javlja problem jer je potrebno
iscrtati relativno velik broj sitnijih cijevi da bi se dobila zadovoljavajuća
struktura kose (prevelike cijevi rezultiraju efektom "meduze"). Cijevi zbog
pokretljivosti i zakrivljenosti obično zahtijevaju veći broj poligona za dobar
prikaz, a algoritmi za smanjenje broja poligona ovisno o složenosti prikaza
(LOD) ne daju tako dobre rezultate kao kod prikaza pomoću traka [3].
Cijev je zapravo omotnica oko B-spline krivulje određene kosturom.
Osim Δt također je potrebno definirati i složenost presjeka cijevi (da li će
presjek biti četverokut, peterokut itd.). Potrebno je definirati početnu
orijentaciju poligona koji predstavlja presjek cijevi (u našem primjeru kao
početna os korištena je y-os). U točkama krivulje koje su međusobno
udaljene za Δt računa se vektor tangente, te se onda poligon presjeka
rotira kako bi se poklopio s tangentom i translatira u točku u kojoj je
izračunata tangenta. Tako se dobiva niz poligona koji su okomiti na
krivulju u danim točkama, te ih je još samo potrebno povezati poligonima
kako bi se dobila cjevasta struktura.
Uporabom glatkog sjenčanja (smooth shading) dobiva se dojam da je
površina glatka. Radijus presjeka moguće je mijenjati duž cijevi kako bi se
dobio realniji izgled pramena (deblji pri korijenu i tanji prema vrhu).
30
Slika 6.4.1 Poligoni presjeka slažu se oko krivulje (lijevo). Isti objekt ali gledan odozdo (sredina). Objekt koji dobivamo povezivanjem poligona presjeka u trokute
(desno).
31
7. Animacija kose pomoću OpenGL-a
Za modeliranje kose korišten je prethodno izrađeni fizikalni model
koji je zatim nadograđen jednim od načina modeliranja kose (sve
programiranje izvršeno je u C++ i OpenGL-u). Korištena je još i dodatna
biblioteka GLUT. Dodatne biblioteke korištene su kako bi se učitale
teksture koje sadrže prozirnost (OpenGL podržava samo .bmp format, koji
ne podržava prozirnost). Za prikaz površina korišteni su trokuti, što je
prihvaćen standard za današnju grafičku sklopovsku opremu. Za sjenčanje
i osvjetljenje korištene su već ugrađene OpenGL funkcije.
7.1 Inicijalizacija OpenGL varijabli
Kako bi omogućili osvjetljenje, teksturiranje, spremnik dubine (z-
buffer) i sl. potrebno je prije crtanja inicijalizirati određene OpenGL
varijable:
glEnable(GL_DEPTH_TEST); // z-buffer glEnable(GL_LIGHTING); // omogući osvjetljenje glEnable(GL_LIGHT0); // koristimo 1 izvor – LIGHT0 glEnable(GL_NORMALIZE); // normaliziraj vektore glEnable(GL_COLOR_MATERIAL); // pamti boju objekta glEnable(GL_TEXTURE_2D); // omogući 2D teksture glEnable(GL_ALPHA_TEST); // omogući prozirnost glEnable(GL_BLEND); // omogući mješanje boja // način mješanja boja glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // postavi jakost ambijentalnog svijetla GLfloat ambientLight[] = {0.45f, 0.45f, 0.45f, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); // postavi jakost i položaj izvora svijetla GLfloat lightColor[] = {0.9f, 0.9f, 0.9f, 1.0f}; GLfloat lightPos[] = {5.0f, -1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glShadeModel(GL_SMOOTH); // omogući glatko sjenčanje
32
Pri iscrtavanju samo krivulja nije potrebno omogućiti teksture, ali
radi ljepšeg izgleda još su dodane naredbe glEnable(GL_LINE_SMOOTH) i
glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST).
Display mode mora biti postavljen tako da podržava spremnik
dubine, dvostruki spremnik (potreban pri animaciji) i RGB boje s
mogućnošću prozirnosti:
glutInitDisplayMode (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
7.2 Prikazivanje vlasi
Vlasi se prikazuju B-spline krivuljom određenom kosturom. Za svaki
okvir potrebno je ponovo računati i crtati točke krivulje zbog pomaka
kostura. Pamti se samo niz kontrolnih točaka iz kojih se onda izvodi
krivulja. Kako se krivulja ne bi doimala previše izlomljenom, Δt je
postavljen na 4.
#define SEG_C 8 // broj segmenata krivulje #define T_STEP 4 // delta t typedef struct _Dots { // struktura za spremanje tocka GLdouble x; GLdouble y; GLdouble z; } Dots; Dots dotC[SEG_C+1]; // kontrolne tocke krivulje
S obzirom na kontrolne točke onda se crta krivulja koja se sastoji od
(SEG_C-2)*T_STEP točaka (početni statični segment se ne crta). Točke se
međusobno povezuju linijama pomoću glBegin(GL_LINES). Kako bi se na
linije primijenilo osvjetljenje potrebno je OpenGL-u predati normalu na
objekt koji se želi osvijetliti. U ovom slučaju taj izračun je pojednostavljen
tako da se u točkama krivulje računa tangenta i onda okomica na nju koja
leži u xy ravnini. Ovaj vektor se pri crtanju svake linije predaje OpenGL-u
33
pomoću funkcije glNormal3d(i,j,k) (pošto smo omogućili GL_NORMALIZE
predani vektor se automatski normalizira).
Slika 7.2.1 Prikaz vlasi u OpenGL-u (u dva različita položaja) uz jednostavan modela osvjetljenja
7.3 Prikazivanje traka
Pri prikazivanju traka potrebno je imati strukture za spremanje
glavnog i pomoćnih kostura te poligona. Za pomoćne kosture A i B imamo
niz u kojem se pamte kontrolne točke kostura. Spremanje poligona trake
podijeljeno je u dva niza: u jednom se pamte svi vrhovi koji čine traku (tj.
svi vrhovi njezinih poligona), a u drugom nizu pamtimo indekse vrhova
koji tvore te poligone (i to s obzirom na određenu orijentaciju kako bi se
mogle definirati normale).
#define SEG_C 8 // broj segmenata krivulje #define T_STEP 5 // delta t typedef struct t_Dots { // struktura za spremanje tocaka GLdouble x; GLdouble y; GLdouble z; } Dots; typedef struct t_Traingle {// struktura za spremanje poligona
34
int v1; int v2; int v3; } Triangle; typedef struct t_NormGL { // struktura za spremanje normala double A; double B; double C; } NormGL; // kontrolne tocke sredisnjeg i pomocnih kostura Dots dotCA[SEG_C+1], dotCB[SEG_C+1]; // indeksi vrhova poligona Triangle strip[(SEG_C-2)*T_STEP*2]; // tocke koje predstavljaju vrhove poligona Dots skel[(SEG_C-2)*T_STEP*2];
Ovakav način zapisa nam omogućuje dohvat vrha poligona kao: skel[strip[1].v1].x;
Ovime smo za poligon broj 1 dohvatili x koordinatu prvog vrha (s
obzirom na danu orijentaciju). Orijentacija se može izabrati proizvoljno
(ovdje je korišteno opisivanje vrhova u smjeru kazaljke na satu). Normale
se OpenGL-u predaju pri iscrtavanja svakog vrha, i to tako da se dobiju
interpolacijom između normala svih poligona koji se sastaju u tom vrhu.
Važno je napomenuti da se ne smije omogućiti GL_CULL_FACE jer se time
miču stražnji poligoni te se stoga neće iscrtati stražnja strana trake.
Vrhovi poligona zapisuju se u niz strip i to tako da se prvo zapišu
sve točke kostura A i onda sve točke kostura B, nakon čega se ti vrhovi
povezuju u poligone koji se spremaju u niz skel. Poligoni se moraju
ponovo izračunavati prije iscrtavanja svakog okvira jer se i točke krivulje
računaju posebno za svaki okvir. Ovo ujedno onemogućuje "pucanje"
površine zbog deformacije, koje se javlja kad se koriste fiksni poligoni.
35
Slika 7.3.1 Prikaz traka u OpenGL-u. Vidimo kako se iz osnovnog kostura izvode pomoćni kosturi, zatim iz njih krivulje i poligoni. Na dobivenu površinu primjenjuje se osvjetljenje i
zatim tekstura (u ovom slučaju za crvenu kosu).
7.4 Prikazivanje cijevi Poligoni za prikazivanje cijevi spremaju se na isti način kao i kod
prikazivanja traka: zasebno se spremaju vrhovi i indeksi vrhova koji tvore
poligone. Također potrebno je spremati vrhove poligona presjeka (broj
ovih poligona ovisit će o broju segmenata krivulje i o Δt). Poligoni se
računaju nanovo za svaki okvir, čime se onemogućuje "pucanje" površine
pri deformaciji.
U točkama duž krivulje računaju se tangente, te se odgovarajući
poligon presjeka translatira u tu točku i rotira kako bi se njegova početna
os poklopila sa tangentom. Početna os se odabire tako da je okomita na
36
poligon presjeka – ako poligon leži u xz ravnini onda se kao os može
odabrati y-os. Kako bi se poligon rotirao koristi se isti postupak koji se
primjenjuje pri korištenju OpenGL naredbe glRotatef(kut,x,y,z) gdje su
x,y,z komponente osi oko koje se rotira za kut (sama naredba se ne koristi
jer se dobivene transformirane koordinate koriste u daljnjim
proračunima). To se postiže množenjem koordinata točke matricom:
[ ] [ ]zyxtstsstts
sttskji
tttssskji
tsos
zyxkutskutc
zyx
cczxscyzyscxzxsczyccyzscxyysczxzscyxccx
pRp
xyyx
zxzx
zyzy
zyx
zyx
p
p
p
=⎥⎥⎥
⎦
⎤
⎢⎢⎢
⎣
⎡
−−−−
==×=
=
==
⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢
⎣
⎡
⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢
⎣
⎡
+−−−+−+−+−−−−−+−+−
=⋅=′
)(
1),,()sin()cos(
110000)1()1()1(0)1()1()1(0)1()1()1(
2
2
2
rrr
rrr
Vidimo da se rotacija vrši oko posebne osi koja se dobiva vektorskim
umnoškom osi poligona presjeka i tangente na krivulju u danoj točki. Kut
rotacije izražava se u stupnjevima gledano u smjeru suprotnom od smjera
kazaljke na satu. Kada su svi poligoni presjeka na mjestu znači da smo
ujedno odredili sve točke cijevi i da ih možemo početi povezivati u
poligone koji će tvoriti omotnicu cijevi. Kao i kod prikazivanja trake,
normala se predaje za svaki vrh i predstavlja interpolaciju normala
poligona koji se sastaju u tom vrhu. Korištene strukture također
odgovaraju onim korištenim kod prikazivanja trake.
#define SEG_C 8 // broj segmenata krivulje #define KRUG_SEG 5 // broj stranica poligona presjeka #define STEP_T 2 // delta t typedef struct t_Dots { GLdouble x; GLdouble y;
37
GLdouble z; } Dots; typedef struct t_Traingle { int v1; int v2; int v3; } Triangle; typedef struct t_NormGL { double A; double B; double C; } NormGL; Dots dotC[SEG_C+1]; // kontrolne točke krivulje Dots krug[KRUG_SEG*(SEG_C-2)*STEP_T]; // poligoni presjeka Dots tubeDots[KRUG_SEG*(SEG_C-2)*STEP_T]; // vrhovi Triangle tube[KRUG_SEG*(SEG_C-2)*STEP_T*2]; // poligoni
Slika 7.4.1 Položaj tangenata (crne linije) duž krivulje (lijevo). Osjenčana cijev (sredina). Dorada izgleda cijevi korištenjem različitih polumjera poligona presjeka i
dodavanjem teksture (desno).
38
7.5 Korištenje tekstura
Pošto OpenGL podržava samo rad s teksturama u BITMAP formatu
(.bmp) koji ne podržava prozirnost, za rad s teksturama koje podržavaju
prozirnost morale su se koristiti vanjske biblioteke (ili knjižnica rutina)
(library). Pri radu s ovakvim besplatnim bibliotekama otvorenog koda
(open-source library) javio se problem jer su relativno zastarjele
(uglavnom su programirane negdje oko 2000.) i često su pisane za Linux,
te ih treba prilagoditi za rad u MS Visual Studiu na Windows platformi.
Kao formati koji mogu podržati prozirnost odabrani su PNG (Portable
Network Graphics - .png ) i TGA (Truevision Graphics Adapter - .tga), još
znan i kao TARGA (Truevision Advanced Raster Graphics Adapter). Format
koji također podržava prozirnost je TIFF (Tagged Image File Format - .tiff)
no biblioteka za ovaj format podržava samo prikaz i obradu .tiff slika bez
mogućnosti uporabe za teksturu.
Na kraju su ostale dvije mogućnosti:
1. glpng (autor: Ben Wyatt – 2000.)
Ova biblioteka [9] omogućuje učitavanje .png tekstura s
prozirnošću. Iako je pokazala bolji prikaz prozirnosti od ostalih
biblioteka, kod učitavanja više različitih tekstura (ili dodjeljivanja
iste teksture različitim teksturnim objektima), samo prva tekstura se
učitava dobro, dok ostale imaju grešku u ALPHA kanalu (koji
određuje prozirnost). Ovaj problem nije uočen kad su učitavane
teksture bez prozirnosti.
2. TGA Loader (autor: Ronny André Reierstad – 2002.)
Ova biblioteka [10] (zapravo niz include datoteka) omogućuje
učitavanje .tga tekstura s prozirnošću. Ovaj put učitavanje više
tekstura i teksturnih objekata nije uzrokovalo probleme, iako se
ponekad znaju javiti nepravilnosti poput nekoliko bijelih slikovnih
elemenata uz rubove prozirnosti. Datoteke su izvorno bile
namijenjene uporabi na Linux platformama tako da se pri
kompajliranju koda javljaju problemi zbog toga što Linux i Windows
koriste različite kodne stranice. Ovaj problem javlja se samo u
39
naredbama za ispis grešaka, tako da nakon što se ove naredbe
uklone program se može iskompajlirati. Također treba napomenuti
da se način zapisa ALPHA kanala u .tga datotekama zna razlikovati
među aplikacijama, tako da prozirnost tekstura kreiranih u
PhotoShopu nije radila, dok su one kreirane u Paint.NET radile
normalno.
Na kraju je izbor pao na TGA Loader jer je s njime moguće koristiti
više teksturnih objekata – naime, za svaki novi iscrtani objekt moguće je
koristiti istu teksturu, ali ona mora biti vezana za različite teksturne
objekte. Ovdje vidimo funkciju za učitavanje jedne teksture i njezino
vezivanje na više različitih teksturnih objekata (dijelovi su preuzeti iz
TGA.cpp naredbe TGA_texture i modificirani jer bi inače morali za svaki
novi objekt ponovo učitavati istu teksturu):
GLuint tList[100]={0}; void getTexture() { // funkcija za učitavanje teksture char strFileName[] = "braid.tga"; // ime datoteke if(!strFileName) exit(0); tImageTGA *pBitMap = Load_TGA(strFileName); if(pBitMap == NULL) exit(0);
// postavljanje 100 teksturnih objekata for(int ID=0; ID<100; ID++){ glGenTextures(1, &tList[ID]); glBindTexture(GL_TEXTURE_2D, tList[ID]); int textureType = GL_RGB; if(pBitMap->channels == 4) textureType = GL_RGBA; gluBuild2DMipmaps(GL_TEXTURE_2D, pBitMap->channels,
pBitMap->size_x, pBitMap->size_y, textureType, GL_UNSIGNED_BYTE, pBitMap->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
} if (pBitMap){ if (pBitMap->data) { free(pBitMap->data);
}
40
free(pBitMap); }
}
Teksture se vežu za objekt tako da se za svaki vrha specificira
položaj na teksturi u obliku koordinata (s,t), s time da donji lijevi ugao
predstavlja koordinatu (0,0) a gornji desni koordinatu (1,1). Pri apliciranju
teksture na trake ili cijevi koordinate su određene tako da se cijela
tekstura po dužini preslika na objekt tj. omota oko njega (Slika 7.5.1).
Slika 7.5.1 Primjena teksture na traku (gore) i cijev (dolje). Slike tekstura nalaze se s lijeva, i bijela područja zapravo označavaju prozirne slikovne elemente.
41
8. Rezultati izvođenja simulacije
Sva testiranja obavljena su na prijenosnom računalu ACER
TravelMate 5720G sa slijedećim komponentama:
- Intel Core 2 Duo T7300 procesor (2.0 GHz, 800 MHz FSB, 4
MB L2 cache)
- ATI Mobility Radeon 1024 MB grafička kartica
- 2 GB DDR2 radne memorije
- Windows Vista Home Primium OS
Testiranje je vršeno dok je računalo bilo spojeno na struju jer je rad
na bateriju usporavao brzinu simulacije gotovo za pola. Kao mjera
performansi korišten je broj okvira koji se iscrtavaju u sekundi (FPS –
frames per second) s obzirom na broj prikazanih objekata na ekranu.
Mjerenje vremena vrši se preko funkcije glutGet(GLUT_ELAPSED_TIME).
Kako ljudsko oko ne bi primjetilo zasebne okvire u animaciji potrebna je
brzina veća od 16 FPS, standard za filmsku animaciju je 24 FPS, a
današnje video igre postižu brzinu od 30 do 60 FPS.
8.1 Krivulje
Krivulje su se sastojale od 8 kontrolnih točaka, a je Δt iznosio 4,
tako da je krivulja iscrtana povezivanjem 24 točke. Ovo je minimum pri
kojem se ne zamjećuje "izlomljenost" krivulje. Kao orijentir treba
napomenuti da prosječan čovjek ima oko 100,000 vlasi na glavi, a
najnapredniji računalni modeli mogli su prikazati oko 60,000 vlasi
(naravno, ne u stvarnom vremenu).
42
Broj iscrtanih krivulja FPS (prosječni)
1 1024.27
10 808.0
100 252.2
1000 34.0
10,000 3.0
Tabela 8.1.1 Broj okvira koji se mogu iscrtati u sekundi u ovisnosti o broju prikazanih krivulja.
Vidimo da pri iscrtavanju 10,000 objekata FPS značajno opada i da
ova brzina animacije nije prihvatljiva jer se vidi zastajkivanje između
zasebnih okvira.
Slika 8.1.1 Scena koja se sastoji od 100 krivulja.
43
8.2 Trake
Trake imaju dva pomoćna kostura sastavljena od 8 segmenata, a Δt iznosi 5 (što je dovoljno da se ne primjećuje da je traka sastavljena od
čvrstih poligona). Svaka traka sastoji se od 60 poligona i na svaku je
aplicirana ista struktura, s time da broj teksturnih objekata ("pokazivača"
na teksturu) mora biti koliko i traka. Treba napomenuti da je OpenGL
uspio prikazati 100,000 traka kad su uklonjene teksture.
Tabela 8.2.1 Broj okvira koji se mogu iscrtati u sekundi u ovisnosti o broju
prikazanih traka.
Broj iscrtanih traka Ukupan broj poligona FPS (prosječni)
1 60 1147.0
10 600 732.8
100 6,000 173.07
1000 60,000 19.73
10,000 600,000 Nije moguće prikazati
Slika 8.2.1 Scena koja se sastoji od 100 traka.
44
8.3 Cijevi
Cijevi koriste isti središnji kostur od 8 segmenata, no Δt ovaj put
iznosi iznosi 2 (vizualno su rezultati bili prihvatljivi), a kao poligoni
presjeka korišteni su pentagrami. Svaka cijev sastoji se od 120 poligona i
na svaku je aplicirana ista struktura, s time da broj teksturnih objekata
("pokazivača" na teksturu) mora biti koliko i cijevi.
Tabela 8.3.1 Broj okvira koji se mogu iscrtati u sekundi u ovisnosti o broju prikazanih cijevi.
Broj iscrtanih traka Ukupan broj poligona FPS (prosječni)
1 120 1063.53
10 1200 514.07
100 12,000 84.73
1000 120,000 10.0
10,000 1,200,000 Nije moguće prikazati
Slika 8.3.1 Scena koji se sastoji od 100 cijevi.
45
9. Zaključak
Prilikom modeliranje kose potrebno je prvo modelirati kostur koji će
opisivati njezino gibanje. Za modeliranje kostura potrebno je dobro
razraditi teoretski dio: važno je poznavati fizikalnu osnovu gibanja, te
matematiku koja je potrebna za točno rješavanje tog modela.
Rješavanjem dobivamo općeniti model na temelju kojeg se onda dalje
razvija vizualizacija. Iako model opisuje gibanje vlasi, moguće ga je
primijeniti i za opis gibanja snopova kose, čime se smanjuje broj iscrtanih
objekata. Testiranja su pokazala da ovakva primjena omogućuje
zadovoljavajuću brzinu animacije, čak i uz prikaz velikog broja objekata.
Iako zahtjeva dosta računanja, preciznog podešavanja i iskustva,
ovaj model je dovoljno općenit da pruži velike mogućnosti proširenja, a
mogućnost primjene pri simuliranja snopova kose (pramenova)
omogućuje značajnu uštedu u broju iscrtanih objekata i vremenu obrade.
46
10. Literatura
[1] K. Anjyo, Y. Usami, T. Kurihura, "A Simple Method For Extracting
The Natural Beauty Of Hair", SIGGRAPH (92), pp. 111-120 [2] C. Koh and Z. Huang, "Real-time animation of human hair modelled
in 2D strips", in Computer Animation and Simulation’00, Sept. 2000, pp. 101–112.
[3] Kelly Ward, Ming C. Lin, Joohi Lee, Susan Fisher, Dean Macri
"Modeling Hair Using Level-of-Detail" [4] Florence Bertails, Basile Audoly, Marie-Paule Cani, Bernard
Querleux, Fr´ed´eric Leroy, Jean-Luc L´evˆeque, "Super-Helices for Predicting the Dynamics of Natural Hair"
[5] "Realistic Hair Simulation, Animation and Rendering", SIGGRAPH
2008 Course Notes [6] www.cs.unc.edu/~geom/HSLOD/ [7] www.hair-science.com/ [8] L. Budin, "Analiza i Projektiranje Računalom – skripta s predavanja",
2002. [9] www.fifi.org/doc/libglpng-dev/glpng.html [10] www.morrowland.com/apron/tut_gl.php
47
Dodatak 1: Rješavanje jednadžbe gibanja Za rješavanj jednadžbe koristimo izravni eulerov postupak u kojem se
provodi supstitucija (za varijablu x u vremenskom trenutku k+1 i s
korakom integracije T):
),(),(1
txfxtxfTxx
kk
kkk
=⋅+=+
&
Ilustrirat ćemo postupak rješavanja za θ (postupak rješavanja za φ je
analogan). Krećemo od jednadžbe gibanja za i-ti segment:
θθγθ Mdt
ddtdI i
ii
i =+2
2
gdje je Ii moment tromosti svakog segmenta, γi prigušenje, a Mθ ukupan
moment sile na segment. Kako bi lakše ilustrirali postupak dobivanja
rješenja provodimo supstituciju:
122
2
1
xxdtd
xdtd
&&&
&
==
=
θ
θ
Napomena: od sada ćemo izostavljati indeks za i-ti segment, a novi indeks
će predstavljati vremenski trenutak.
2112
21
xMxMxII
Mx
xx
⋅′−′=⋅′−′=−=
=
γγγθθ
θ &&&
&
gdje ' označava da su Mθ i γi podijeljeni s Ii.
48
Provodimo eulerovu supstituciju:
)(),(),(
,2,2,22,21,2
,1,1,2,1,11,11,1
kkkkk
kkkkkkk
xMTxtxfTxxxTxxTxtxfTxx
⋅′−′⋅+=⋅+=
⋅+=⋅+=⋅+=
+
+
γθ
&
Možemo ponovo pisati θ, a iz prve jednadžbe možemo izraziti dθ/dt:
)(1
11
kkk
kkkkkk
MTT
T
θγθθ
θθθθθθ
θ&&&
&&
⋅′−′⋅+=
−=⇒⋅+=
+
++
Izraz za dθ/dt uvrštavamo u drugu jednadžbu i provodimo preindeksiranje
druge jednadžbe s (k,k+1) na (k-1,k):
θ
θ
θ
θ
θθγθθθ
θθγθθθθ
θθγθθθθ
θθθθγθθ
MTT
TMTT
MTTT
TMT
kkkkk
kkkkkk
kkkkkk
kkkkkk
′=−⋅⋅′−+−
−⋅⋅′−′+−=−
−⋅′−′⋅+
−=
−⇓
−=⋅′−′⋅+=
−−+
−−+
−−+
+−−
2111
12
11
111
111
)(2
)(
)(
,)( &&&&
49
Ako pišemo Δt umjesto T, i ponovimo isti postupak za φ, dobivamo
konačno rješenje jednadžbe gibanja za i-ti segment:
ϕ
θ
ϕϕγϕϕϕ
θθγθθθ
Mtt
Mttn
i
n
ii
n
ii
nn
i
n
i
n
ii
n
iinn
i
′Δ=−Δ′++−
′Δ=−Δ′++−−−+
−−+
2111
2111
)()(2
)()(2
50
Dodatak 2: Uvjet stabilnosti
Kako bi izračunali uvjet stabilnosti prvo trebamo raspisati jednadžbu
gibanja:
vanjskovanjsko
vanjsko
MxxkxIkx
IIM
x
xkMxxI
′+⋅′−⋅′−=⋅−⋅−=
⋅−=⋅+⋅
&&&&
&&&
γγ
γ
gdje je I moment tromosti svakog segmenta, γ prigušenje, k konstanta
opruge, a Mvanjsko ukupan vanjski moment sile na segment.
Sustav možemo zapisati u matričnom obliku:
vanjskoMxx
kxx
′⎥⎦
⎤⎢⎣
⎡+⎥
⎦
⎤⎢⎣
⎡⎥⎦
⎤⎢⎣
⎡′−′−
=⎥⎦
⎤⎢⎣
⎡1010
&&&
&
γ
gdje ' označava da su Mvanjsko , k i γ podijeljeni s I. Tražimo karakteristični polinom zadanog sustava:
kP
kPkk
P
kA
IAP
′+′+=
′+−′−−=
⎥⎦
⎤⎢⎣
⎡−′−′−
−=⎟⎟
⎠
⎞⎜⎜⎝
⎛⎥⎦
⎤⎢⎣
⎡−⎥
⎦
⎤⎢⎣
⎡′−′−
=
⎥⎦
⎤⎢⎣
⎡′−′−
=
−=
λγλλ
λγλλ
λγλ
λλ
γλ
γ
λλ
2)(
)()(
1det
0010
det)(
10)det()(
51
Rješenje karakterističnog polinoma (svojstvene vrijednosti):
242
2,1k′−′±′−
=γγλ
Uvjet stabilnost pri izravnoj eulerovoj metodi integracije je:
11 ≤+ λT
Ovaj uvjet mora biti zadovoljen za sve svojstvene vrijednosti.
Napomena: Pri podešavanju parametara kako bi dobili različite tipove kose
moramo voditi računa da uvijek bude ispunjen uvjet stabilnosti.
52
Sažetak
U radu je dan teorijski pregled i matematičko rješenje modela za
animaciju kose predloženog u "A Simple Method For Extracting The
Natural Beauty Of Hair" [1] i kasnije razvijenog u "Real-time
animation of human hair modeled in 2D strips" [2]. Implementacija
osnovnog modela napravljena je pomoću programskog jezika C++ i
grafičkog standarda OpenGL. Također je dan osvrt na neke od
problema na koje nailazimo prilikom rada s ovim modelom te
primjeri izvođenja programa koji implementira model.Ključne riječi:
modeliranje kose, fizikalno temeljeni model, prikaz, računalna
grafika, računalna animacija
53
Abstract title: Animation of a physicaly based hair model
In this paper we give a theoretical overview and a mathematical
solution of the hair model proposed in "A Simple Method For
Extracting The Natural Beauty Of Hair" [1] and later developed in
"Real-time animation of human hair modelled in 2D strips" [2]. The
implementation of the hair model was made by using the C++
programming language and the OpenGL graphic standard. We also
give a survey of some of the problems we encountered while
working with this model and provide examples of animation made by
implementing this model.Keywords: hair modeling, physically-based
model, rendering, computer graphics, computer animation
54