Nefotorealistični
prikaz objekta

diplomski rad br. 1819
Ante Radman, studeni 2009.    FER

5  Programsko ostvarenje

Uz rad je priložen program koji se razvijao tijekom rada na temi, s pripadajućim izvornim kodom. Korišten je jezik C++ uz OpenGL kao grafičko sučelje. Teksture su nacrtane koristeći poseban grafički program.

Program učitava 3D-model iz datoteke i generira prikaz uz mogućnost korisnikovog mijenjanja pogleda i promjene parametara prikaza.

Odabran je Wavefrontov OBJ-format datoteke modela kao glavni format. S obzirom da obrada složenih modela može potrajati i do pola minute, izvedena je mogućnost snimanja već obrađenih modela u vlastiti format s nastavkom NPR. Kasnije se takva ulazna datoteka može otvoriti umjesto izvorne OBJ-datoteke bez čekanja na obradu.

Uz program je priloženo nekoliko primjera modela u OBJ-formatu, koji se mogu slobodno koristiti u akademske svrhe.

Rješenje je namijenjeno Microsoft Windows platformi s uobičajenom podrškom za OpenGL u vidu biblioteka opengl32.dll i glu32.dll, koje su priložene uz operacijski sustav, ili njihovih zamjena. Poželjno je da računalo ima suvremenu grafičku karticu, zbog naglaska na radu s teksturama.

5.1  Korištenje programa

Pri pokretanju programa moguće je navesti ime ulazne datoteke kao parametar. Ona se može i kasnije odabrati putem izbornika Datoteka Otvori ili pak dovući mišem iz drugih programa i ispustiti na radnu površinu. Obrađena datoteka može se snimiti za kasnije brzo učitavanje putem izbornika Datoteka Snimi.

Izgled radnog prozora prikazan je na slici 5.1.

Slika 5.1. Glavni prozor programa

Na alatnoj traci na raspolaganju su korisničke opcije:

Rotiranje učitanog modela se izvodi prevlačenjem lijevom tipkom miša preko radne površine, dok se kotačićem na mišu prikaz zumira u željenoj mjeri. Prevlačenje desnom tipkom miša pomiče model, odnosno pogled u stranu.

Korisniku su na raspolaganju i tipke gore/dolje/lijevo/desno za rotiranje modela preko tipkovnice, kao i tipka Escape za brzi izlazak iz programa.

Ako tijelo nije ispravno iscrtano, pogotovo nakon što se uključi face culling, preporuka je uključiti prikaz normala i provjeriti da li su sve normale usmjerene van tijela. Ako nisu, pripadni poligoni su orijentirani u smjeru suprotnom od kazaljke na satu. Program ne podržava takvu orijentaciju poligona.

Drugi problemi s pogrešnim iscrtavanjem modela koji imaju uzroke u samim modelima mogu biti kada se više točaka preklapa na istom mjestu, odnosno kad se više poligona preklapa u istoj ravnini. Takvi slučajevi mogu se pak brzo ispraviti u nekom 3D editoru.

5.2  Organizacija izvornog koda

Dijagram razvijenih C++ razreda prikazan je na slici 5.2.

Slika 5.2. Dijagram razredâ

Svaki razred pohranjen je u vlastitoj .cpp datoteci, s pripadnom .h datotekom. U tablici 5.1 dan je kratak opis svake od njih.

Tablica 5.1. Organizacija izvornog koda po datotekama

Datoteke Opis funkcionalnosti
vektor.cpp

vektor.h

Razred Vektor, koji implementira vektor kao geometrijski element

kvaternion.cpp

kvaternion.h

Razred Kvaternion, koji služi za rotacije vektora

matrica.cpp

matrica.h

Razred Matrica, potreban za matrične izračune oko normalnih zakrivljenosti

vrh.h

Razred Vrh je jednostavna nadgradnja razreda Vektor, predstavlja element poligona

trokut.cpp

trokut.h

Razred Trokut predstavlja poligon 3D-mreže

predmet.cpp

predmet.h

Razred Predmet predstavlja jedan objekt u sceni

prostor.cpp

prostor.h

Razred Prostor predstavlja scenu, i sadrži cjelokupan opis prostora

program.cpp

program.h

datoteka.cpp

Razred Program je glavni program, rasterećen svih nebitnih poslova; dio posvećen čitanju datoteka modela je izdvojen u zasebnu datoteku

mfcprogram.cpp

mfcprogram.h

Razred MFCProgram predstavlja tipični program za MS Windowse; iz njega je deriviran razred Program

mfcprozor.cpp

mfcprozor.h

Razred MFCProzor ostvaruje glavni prozor aplikacije u MS Windowsima

mfctraka.cpp

mfctraka.h

Razred MFCTraka je alatna traka na glavnom prozoru

mfcploha.cpp

mfcploha.h

Razred MFCPloha predstavlja radnu površinu u sredini prozora

Slike tekstura (mipmape) pohranjene su u svojim zasebnim mapama.

5.3  Programi jedinica za sjenčanje

Zbog optimizacije prikaza, stapanje tekstura je vlastoručno programirano u jedinicama za sjenčanje, u jeziku GLSL. Koristi se mogućnost procesora vrhova i fragmenata da sami utvrde koje točno teksture treba kombinirati na bilo kojem mjestu na poligonu, bez da moraju izvoditi bilo kakve nepotrebne poslove. Ranije je izračun bio moguć u samo tri krajnja vrha na pojedinom poligonu, pa je nužno bilo stapati šest tekstura na svakom poligonu kako bi oni u konačnici imali ispravne prijelaze između krajnjih nijansi.

U ostvarenom mehanizmu glavni program daje na raspolaganje procesoru vrhova sve teksture i položaj izvora svjetla putem uniformnih varijabli, te standardnim putem normalu interpoliranu između tri vrhova poligona za određenu točku na poligonu. Procesor vrhova prosljeđuje procesoru fragmenata prostorne koordinate dotične točke, danu normalu i koordinate tekstura. Procesor fragmenata dobivenim podacima izračuna intenzitet osvjetljenja i odredi potrebne teksture koje treba stopiti, te izračuna konačnu boju kao zbroj najviše dviju tekstura.

Program za procesor vrhova u GLSL-u je sljedeći:

varying vec3 vrh, normala;
void main () {
  gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
  gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
  gl_TexCoord[2] = gl_TextureMatrix[2] * gl_MultiTexCoord2;
  gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord3;
  gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord4;
  normala = gl_Normal;
  vrh = vec3 (gl_Vertex);
  gl_Position = ftransform();
}

Program za procesor fragmenata:

uniform sampler2D tex1, tex2, tex3, tex4, tex5;
uniform vec3 svjetlo;
varying vec3 vrh, normala;
void main () {
  vec4 boja1 = texture2D (tex1, gl_TexCoord[0].st);
  vec4 boja2 = texture2D (tex2, gl_TexCoord[1].st);
  vec4 boja3 = texture2D (tex3, gl_TexCoord[2].st);
  vec4 boja4 = texture2D (tex4, gl_TexCoord[3].st);
  vec4 boja5 = texture2D (tex5, gl_TexCoord[4].st);
  float intenzitet = max (0.0, dot (
    normalize (svjetlo - vrh), normalize (normala))) * 4;
  float razina = floor (intenzitet);
  float ostatak = intenzitet – razina;
  if (razina <= 0)
    gl_FragColor = boja2 * ostatak + boja1 * (1.0 – ostatak);
  else if (razina == 1)
    gl_FragColor = boja3 * ostatak + boja2 * (1.0 – ostatak);
  else if (razina == 2)
    gl_FragColor = boja4 * ostatak + boja3 * (1.0 – ostatak);
  else if (razina == 3)
    gl_FragColor = boja5 * ostatak + boja4 * (1.0 – ostatak);
  else
    gl_FragColor = boja5;
}

5.4  Napomene pri prevođenju

Rješenje je razvijeno u Microsoft Visual Studiju 2008, sa statički povezanim MFC-bibliotekama i uključenom punom podrškom za Unicode. Pri povezivanju se koriste standardne biblioteke opengl32.lib i glu32.lib, a za proširenja OpenGL-a 2.0 standardna datoteka glext.h.

Svi resursi aplikacije, uključujući bitmape za teksture, uključeni su u sam projekt i moraju biti povezani u konačnu izvršnu datoteku.