Uvod

Matematička podloga

Opis rada programa

Ulazni podaci

Interpolacija na cijelom modelu

Interpolacija na označenom području

Izlazni podaci

Rezultati

Zaključak

Literatura

Download

Opis rada programa


Program je pisan u programskom jeziku C i OpenGL API-u za 3D grafiku. Postoje verzije za Microsoft Visual Studio .NET i Visual Studio 6. Budući da se koristi C bez Microsoftovih specifičnosti, te samo osnovne funkcije iz OpenGL-a, kompajliranje za bilo koje druge platforme ne bi trebao biti problem.

U programu se za razne primjene koristi nekoliko gotovih rješenja koje su njihovi autori dali na slobodno korištenje. Ta rješenja su:


Trackball - skup funkcija za kontrolu nad pomacima miša, te kontrolu pogleda kamere u ovisnosti o pomacima miša

AviGenerator - funkcije razvijene za izradu prikaza (renderiranje) animacije u AVI datotečnom formatu

Neke funkcije iz NeHe OpenGL tutoriala - poslužile kao kostur za realizaciju metoda za izabir točke iz 3D scene.

 

 

Opis bitnih funkcija i struktura podataka

Program započinje sa funkcijom

GLint LoadMesh(char *file, char *file1, ..., char *file4)

kojom učitavamo pet 3D modela lica u memoriju: četiri lica sa izrazom i jedno neutralno lice. Modele zapisujemo u dvije najbitnije strukture. To su meshPoints[n] i meshTriangles[n] i u njima su zapisi o točkama modela i pripadajućim trokutima. Zatim radimo inicijalizaciju funkcijama

InitGLut(argc, argv),
InitGL(),
InitScene().

Funkcijom InitGLut inicijaliziramo postavke vezane uz Glut podAPI. To je definiranje veličine i kreiranje prozora i definiranje callback funkcija za upravljanje mišem i tipkovnicom. U funkciji InitGL definiramo postavke vezane uz sam grafički API. Postavlja se vrsta sjenčanja, Z buffer, osvjetljenje i slično. Funkcija InitScene služi za postavljanje scene, ali ovdje to možda i ne izgleda kao standardna procedura. Naime, OpenGL nam omogućuje da 'prekompajliramo' funkcije za iscrtavanje Glvoid DrawMesh() i da ih sve stavimo u listu, a sve to u svrhu ubrzavanja iscrtavanja.

Kada je inicijalizacija završila, ulazimo u petlju u kojoj su bitne slijedeće funkcije:

GLvoid ProcessKey(unsigned char key, int x, int y)
GLvoid ProcessSpecialKey(int key, int x, int y).

Navedene funkcije služe za nadzor nad unosom znakova sa tastature. Za sve znakove iz ASCII tablice se koristi prva funkcija, dok se za funkcijske i ostale specijalne tipke koristi druga funkcija.

Osim tastature, pratimo i unos s miša funkcijama

GLvoid ProcessMouse(int button, int state, int x, int y)
GLvoid ProcessMouseActiveMotion(int x, int y).

Prvom funkcijom kontroliramo i stvaramo događaje koji slijede nakon pritisnute tipke miša. Ako je pritisnuta desna tipka gleda se pomak miša i aktivira se pomak kamere pomoću funkcija iz TrackBall.cpp-a. A ako je pritisnuta lijeva tipka pristupa se postupku izabire točke o kojem nešto više u daljem tekstu. Druga funkcija je aktivna dok se miš kreće i u njoj se također obavlja pomak kamere u ovisnosti o pomaku miša. Da nema te funkcije pomicanje kamere bi bilo trzavo i razmjerno neupotrebljivo.

 

 

Izabir točaka


Izabir točaka (eng. picking) je jedno od najizazovnijih područja za početnike u programiranju u OpenGL API-ju. Picking je metoda koja služi za odabir jednog ili više elemenata 3D scene (točka, linija, trokut, ...), ali samo preko njegovih ekranskih koordinata. Postoji mnogo načina za ostvarivanje te metode, ovdje ćemo se osvrnuti na najčešću.

Smisao te metode jest da oko odabranih koordinata odredi mali prozor proizvoljne veličine te da se zatim iscrta scena. OpenGL će znati koji elementi scene su iscrtani u tom prozoru i u poseban međuspremnik će biti pohranjeni podaci o tim elementima. Zatim iz tog međuspremnika vadimo elemente i prema vlastitim uvjetima određujemo odabrane elemente.

Primjer međuspremnika:

Zapis u međuspremniku   Opis

0                       Niti jedan objekt u prvom pogotku
4.2822e+009             Minimalna dubina za prvi pogodak
4.28436e+009            Maksimalna dubina za prvi pogodak
1                       Broj elemenata u drugom pogotku
4.2732e+009             Minimalna dubina za drugi pogodak
4.27334e+009            Maksimalna dubina za drugi pogodak
6                       Ime elementa u drugom pogotku
2                       Broj elemenata u trećem pogotku
4.27138e+009            Minimalna dubina za treći pogodak
4.27155e+009            Maksimalna dubina za treći pogodak
2                       Prvo ime elementa u trećem pogotku
5                       Drugo ime elementa u trećem pogotku


U ovom programu se izabir točaka realizira kroz tri funkcije:

GLvoid StartPicking(),
GLvoid DrawPickScene(),
GLvoid StopPicking() i
GLvoid ProcessHits (GLint hits, GLuint buffer[], int sw).

Funkcija StartPicking() se poziva kada je pritisnuta lijeva tipka na mišu. U njoj se zatim inicijaliziraju postavke scene i matrica za odabir točaka (pick matrica). U toj matrici određujemo visinu i širinu našeg prozora za iscrtavanje. Zatim funkcijom DrawPickScene() iscrtamo elemente scene za koje želimo da postoji mogućnost odabira. Nakon toga zovemo funkciju StopPicking() u kojoj vraćamo postavke grafičkog sustava, te zovemo funkciju za obradu pogodaka ProcessHits. U toj funkciji iz spremnika (eng. buffera) u kojem je pohranjen zapis o elementima scene koji su upali u naš prozor za iscrtavanje vršimo selekciju točaka koje nam odgovaraju.

 

 

 

TrackBall


Za rad u 3D prostoru potreban nam je intuitivan način kontrole nad objektima u sceni. Za te svrhe vjerojatno najpogodniji je uređaj engleskog naziva trackball (ne postoji adekvatan hrvatski naziv). Uređaj se može opisno nazvati kao miš s kuglicom za pozicioniranje. Budući da taj uređaj nema svatko potrebno je razviti jednostavnije rješenje u tom smjeru. Za to je iskorišten miš koji, uz odgovarajuću programsku podršku simulira trackball.


Smisao toga je da se točka na ravnini po kojoj se kreće miš projicira na sferu po kojoj se kreće trackball. I tako točka (x, z) na ravnini odgovara točki (x, y, z) na sferi gdje je

 

Slika 3.1 Projekcija sa sfere na ravninu

Pomicanjem miša dobivamo dvije točke (t1, t2) koje na sferi tvore luk. Sada je samo potrebno pronaći os rotacije i kut između t1 i t2 da možemo izvesti rotaciju t1 u t2. Os rotacije se određuje kao normala na sferu određena točkom ishodišta i točkama t1 i t2:

gdje su t1 i t2 vektori od ishodišta do točaka t1 i t2.

Slika 3.2 Rotacija t1->t2

Kut između točaka se dobije prema formuli

Klasa se koristi vrlo jednostavnom upotrebom slijedećih funkcija:

void TrackballInit(int width, int height) - Inicijalizacija objekta, prima veličinu i širinu prozora u kojem će se prikazivati 3D objekt.

void TrackballResize(int width, int height) - Koristi se u slučaju promjene veličine prozora.

int TrackballMouseDown(int mouseX, int mouseY, int button) - Poziva se kada korisnik stisne tipku miša, preuzima trenutne koordinate miša.

int TrackballMouseUp(int mouseX, int mouseY, int button) - Poziva se kada korisnik otpusti tipku miša.

void TrackballMouseMove(int mouseX, int mouseY) - Poziva se kada korisnik miče miša.

void TrackballCalcRotMatrix(float matRot[4][4]) - Poziva se prije iscrtavanja tijela. Metoda izračunava krajnju rotacijsku matricu.

 

AviGenerator

AviGenerator je open-source kod za OpenGL sa prilagođenim funkcijama koje koriste Video for Windows API. Napisao ga je Jonathan de Halleux, te je dao kod na slobodno korištenje. Funkcije iz AviGeneratora vrše brojne potrebne inicijalizacije i sakrivaju pozive funkcija iz drugih biblioteka tako da su vrlo jednostavne za korištenje.


CAVIGenerator();

Osnovni konstruktor. Njegovim pozivom ostvarujemo animaciju 30 fps u datoteci untitled.avi.


void SetFileName(const CString& _sFileName)

Za podešavanje imena izlazne AVI datoteke.


void SetRate(DWORD dwRate)

Za podešavanje broja sličica u sekundi.


HRESULT InitEngine();

Inicijalizira VfW objekt i određuje format kojim ćemo kodirati (codec). Poziva se prije nego što počnemo snimati animaciju.


HRESULT AddFrame(BYTE* bmBits);

Dodaje sličicu u animaciju. *bmBits je pokazivač na buffer u kojeg ostvarujemo prikaz scene.