Consideratii de implementare
In
cadrul acestui capitol sunt descrise modul de implementare si tehnicile
folosite pentru realizarea aplicatiei, modul de configurare al mediului
de programare, modul de configurare al sistemului pentru ca aplicatia
sa ruleze in conditii optime. Se specifica de asemenea, bibliotecile de
functii utilizate.
Configurarea mediului de programare
Aplicatia a fost realizata utilizind Microsoft Visual C++
5.0. Pentru lucrul cu grafica 3D, bibliotecile OpenGL si GLUT, este
necesara o configurare deosebita a mediului de programare (mai ales a
compilatoruli si editorului de legaturi - "link-editor").
Desi biblioteca OpenGL este inclusa in MS VC++
acesta nu dispune de un model de proiect predefinit pentu a lucra cu
aceasta biblioteca impreuna cu GLUT. Pentru aceasta poate folosit un
template predefinit care creaza o aplicatie de tip consola sub Windows
95 ("Win32 Console Application").
Pentru utilizarea bibliotecii OpenGL trebuie inclus fisierul gl.hcare se gaseste in directorul .../include/GL deci trebuie inclus astfel:
#include "GL/gl.h"
Biblioteca GLUT nu este una din bibliotecile standard care se gasesc in
MS VC++ si aceasta trebui fie inclusa in mod standard de catre
programator in proiect, fie sa fie integrata in MS VC++ urmand sa fie
utilizata ca o biblioteca standard a VC++. Instalarea acestei
biblioteci in MS VC++ persupune copierea fisierului glut.h in directorul .../include/GL a VC++ precum si a fisierelor glut32.lib si glut.lib in directorul .../lib al VC++ deaorece acestea trebuie sa fie utilizate de catre link-editor.
Obs: Acest procedeu trebuie facut si pentru biblioteca OpenGL daca aceasta nu este inclusa sau nu a fost instalata.
Pentru ca proiectul sa poata fi compilat si
link-editat link-editorul trebuie sa fie setat astfel incit sa
foloseasca librariile opengl32.lib, glu32.lib, glaux.lib si glut32.lib. Pentru aceasta in dialogul "Linker" din fereastra de configurare "Project Settings" a VC++:
Configurarea sistemului
De cele mai multe ori sistemul de operare (Windows
95) nu este configurat astfel incit sa foloseasca OpenGL. Pentru a rula
corect aplicatia trebuie sa aiba instalat in directorul Windows/System librariile dinamice opengl32.dll, glu32.dll si glut32.dll. Deci aceste fisiere trebuie sa se afle in directorul specificat pentru a putea fi utilizate de catre aplicatie.
Observatie:Instalarea acestor fisiere se poate face automat, la
instalarea aplicatiei pe sistem, prin intermediul programului de
instalare, fara ca utilizatorul sa intervina. Totusi exista
posibilitatea ca utilizatorul sa nu instaleze aceste fisiere in cazul
in care ele exista pe sistem deoarece exita posibiltatea afectarii
functionarii altor programe care utilizeaza aceste librarii. In acest
caz aplicatia va folosi librariile existente.
Implemenatarea aplicatiei - functii principale
In acest paragraf este descris modul de implementare al
functiilor mai importante ale aplicatiei. Sunt explicate mai ales
functiile care utilizeaza apelul functiiolr OpenGL si GLUT.
Functia main(int argc,char** argv)
Este functia principala (main) a aplicatiei, principalele operatii realizate de aceasta functie sunt:
- initializarea GLUT,
1. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
2. glutInitWindowSize(400, 400);
3. glutInitWindowPosition(0,0);
4. glutInit(&argc, argv);
Linia 1: are ca efect setarea modului de lucru pentru GLUT si
OpenGL, indicind utilizarea formatului RGB pentru afisarea scenei,
initializarea bufferului de adincime (depth buffer), si utilizare
buffer-ari duble pentru afisarea cadrelor animatiei (frame-urilor).
Utilizarea un mod SINGLE BUFFER (GLUT_SINGLE) duce la o animatie de
proasta calitate (imaginea are un efect accentuat de palpaire - fliker).
Linia 2: fixeaza dimensiunea ferestrei utilizate pentru afisarea scenei (render window).
Linia 3: stabileste pozitia ferestrei in coordonatele 0,0 ale display-ului.
Linia 4: activeaza functiile GLUT. Inaite de aceasta functie nu pot fi
folosite decit cele trei functii din liniile 1, 2, 3, orice alta
functie GLUT fiind disponibila numai dupa apelarea functiei
glutInit(...).
- stabilirea functiilor care vor fi apelate prin intermediul
GLUT pentru a gestiona afisarea, evenimentele de la mouse si tastatura,
functiile folosite la animatie etc.
- citirea, prelucrarea imaginii folosite pentru textura care va fi aplicata pe obiect.
- initializarea si afisarea ferestrelor de control, prin
interemdiul carora utilizatorul poate sa specifice parametrii
transformarilor sau a altor operatiuni.
Modul de selectie al operatiilor. Variabile globale
Selectarea operatiilor si a modului de efectuare a
acestora se face prin intermediul unor flaguri (variabile booleene sau
intregi) care sunt setate fie prin intermediul interfetei, fie prin
intermediul comenzilor date de la tastatura. Manipularea acestor
flaguri este facuta in functiile de tratare a meniului si tastaturii
care sunt atasate ferestrei principale a aplicatiei (fereastra scenei).
//flaguri pt operatii
GLboolean swapped = GL_FALSE;
GLboolean world_draw = GL_TRUE; //afiseaza componente scena in world
GLint selection = 0; //selecteaza operatiune 0=rot;1=transl;2=scale
GLboolean scena=GL_FALSE; //flag scena (world) vizibila
GLint model=GL_TRUE; //model on/off
GLint axes=GL_FALSE; //axe scena on/off
GLint m_axes=GL_FALSE; //axe model on/off
GLint sursa0=1; //sursa de lumina 0 activa
GLint sursa1=0; //sursa de lumina 1 inactiva
GLint lumini=0; //afisarea pozitiei luminilor
GLint flor=1; //afisarea podelei
GLint tex=1; //incarcarea texturii
GLboolean z_enable=GL_FALSE; //operatiune pe z
GLboolean observer = GL_FALSE; //operatii asupra poz camerei
//flaguri pentru pornirea/oprirea animatiei
GLint animatie1=0; //obiect
GLint animatie2=0; //animatia camerei(observator)
GLint animatie3=0; //deformare obiect
GLint obj_speed=3; //viteza rotatie obiect
GLfloat cam_speed=0.15; //viteza de rotatie a camerei(observator)
GLint dir=1; //directie animatie camera
Pe
linga aceste flaguri mai exista un numar de variabile globale care
cotroleaza diferiti parametri, mai ales in animatie, cum ar fi viteza
animatiei, pozitia curenta a obiectului in scena, pozitia
observatorului, pozitia surselor de lumina, etc. Aceste variabile sunt
fie valori numerice fie vectori care descriu anumite operatii (rotatie,
translatie, scalare).
Functiile pentru afisarea scenei
Functiile pentru afisarea componentelor scenei sunt:
- drawmodel() realizeaza citirea si trasarea modelului in scena
- drawfloor() realizeaza trasarea "podelei"
- drawaxes() asigura trasarea axelor de coordonate atit pentru scena cit si pentru model
- drawlights() afisarea pozitiei si directiei luminilor
-
Aceste
patru functii sunt apelate din functiile principale de trasare, in care
pe linga apelul functiilor de trasare sunt utilizate si functii
standard OpenGL pentru stabilirea modului de trasare, activarea si
dezactivarea unor elemente ale scenei, operatiile cu stiva de apel a
OpenGL, etc.
Functiile principale de trasare sunt:
- screen_reshape(...)
este functia care realizeaza trasarea elementelor scenei, zona in care
actioneaza aceasta functie este fereastra principala de trasare.
Aceasta functie trebuie sa fie in prealabil declarata ca fiind functie
folosita de GLUT pentru trasarea scenei de obiecte intr-o fereastra
GLUT.
- screen_display() este tot functie de trasare dar care nu
realizeaza o modificare a parametrilor mediului fiind raspunzatoare de
reafisarea obiectelor care isi modifica pozitia de la un cadru la altul
in timpul animatiei sau cind utilizatorul da unele comenzi de
modificare a geometriei scenei. Este utilizata deoarece ofera
posibilitatea de reafisare mai rapida a elemntelor scenei fara a mai
modifica si parametrii de control.
- world_reshape(...) este functia care asigura trasarea
elementelor scenei in fereastra "World", fereastra in care sunt afisate
toate elementele care compun scena (inclusiv pozitia observatorului).
Aceasta functie face o scalare uniforma a obiectului si aplica unele
transformari pentru modificarea pozitiei acestuia. Restul componentelor
scenei sun afisate fie prin trasarea lor directa in functie fie prin
apelul functiilor specializate amintite mai sus (draw...).
- world_display() este functie similara cu screen_display() realizind acxeleasi functii insa pentru fereastra "World".
- reshape_all() functie care realizeaza apelul pentru
functiile enumerate mai sus in functie de ferestrele vizibile la un
moment dat, deoarece fereastra "World" poate sa fie inchisa si deschisa
in functie de dorintele utilizatorului.
Functiile de control a meniului
In aplicatie exista doua functii de control al
meniurilor. Aceste functii efectueaza comenzile care sunt date de
utilizator prin intermediul meniurilor atasate celor doua ferestre in
care se face trasare de elemente grafice. Aceste functii trebuie sa fie
declarate ca functii utilizate de GLUT pentru tratarea evenimentelor
legate de meniuri.
- screen_menu(...) asigura procesarea comenzilor pentru meniul atasat ferestrei principale.
- world_menu(...) realizeaza acelasi lucru ca si functie precedenta, numai pentru fereastra "World".
Obs: Selectia comenzii care
a fost data din meniu este facuta prin interemediul unei variabile
transmise de GLUT. Evenimentele legate de meniu (afisare, generare
eveniment pentru selectie etc.) sunt gestionate de GLUT.
Functiile de control a tastaturii si mouse-ului
Controlul tastaturii este realizat numai pentru fereastra
principala de trasare. La fel ca si functiile de control al meniurilor
aceste functii au doar rolul de tratare a evenimentelor care sunt
generate automat de GLUT.
- main_keyboard(...) functia care controleaza apasarea tastelor "standard"
- screen_key(...) la fel ca si main_keyboard() dar
controleaza apasarea tastelor functionale si a tastelor sageti. Tastele
sageti sunt utilizate pentru aplicarea unor operatii de rotatie,
translatie si scalare asupra modelului.
- mouse(...) functie care asigura prelucrarea evenimentelor generate de apasarea butoanelor de la mouse.
- motion(...) controleaza evenimentele generate de miscaraea cursorului de mouse in fereastra principala de trasare.
Functiile utilizate la realizarea animatiei
In aplicatie sunt realizate trei tipuri de
animatie: animatia modelului, animatia camerei si deformare. Aceste
trei tipuri de animatie pot fi combinate rezultind pe ansamblu o
miscare destul de complexa a scenei. Datorita faptului ca aplicatia nu
utilizeaza accelerarea hardware pentru afisare animatia este nerealista
char daca nu a fost realizata prin utilizarea unor functii de
interpolare foarte complexe. S-a utilizat numai acccelerare soft
deoarece nu toate adaptoarele grafice existente in PC-uri dispun de o
implementare hardware, cel putin minimala, a setului de functii OpenGL
sau nu dispun de drivere adecvate pentru utilizarea OpenGL.
Animatia modelului si a camerei este realizata
relativ simplu prin aplicarea unor operatii de rotatie si translatie
asupra modelului, respectiv asupra pozitiei observatorului.
- my_GlutIdle()
este o functie care realizeaza apelul functiilor de calcul a
urmatorului cadru in timp ce se face afisarea cadrului curent. Este o
functie specifica GLUT fiind apelata ori de cite ori se face afisare.
Biblioteca GLUT asigura apelul acestei functii independent de aplicatie
sau de apelurile date de utilizator. Pentru a se putea utiliza aceasta
functie este necesara declarararea ei ca functie care supraincarca
functia corespunzatoare din libraria GLUT.
- frame_obiect() este functia care aplica operatiile de
transformare asupra obiectuli. Aceste transformari sunt memorate in
matrici in care se memoreaza parametrii operatiilor de rotatie sau
translatie care se aplica asupra obiectului numai la afisare.
- frame_camera() realizeaza calculul pozitiei observatorului pentru urmatorul cadru (frame).
Functiile frame... sunt apelate de catre functia myGlutIdle() pentru fixarea valorilor utilizate la afisarea urmatorului cadru.
Animatia prin deformare
Functiile utilizate la realizarea deformarii obiectului se gasesc in fiserul "deform.cpp".
Functia principala de deformare este functia deform(GLMgroup*, GLflot step) care realizeaza umatoarele:
- primeste ca si parametri un pointer la structura de date a modelulului grafic si pasul cu care va face deformarea;
- prin intermediul functiei glmFindGroup(...) identifica grupul de puncte care formeaza "felia";
- pentru fiecare punct din grup seteaza flagul care indica ca a fost modificat la FALSE;
- translateaza fiecare punct al grupului pe fiecare axa cu valoarea
data de pasul de deformare, simultan setind flagul de modificare la
TRUE;
Aceasta functie este apelata de functia frame_deform() din programul principal in care pasul de deformare este calculat dinamic astfel incit animatia sa ruleze intr-un ciclu.
Efectul care rezulta este departarea si apropierea "feliei" de para.