You are on page 1of 70

Universitatea din București

Facultatea de Matematică și Informatică

Domeniul de licență Informatică

Lucrarea de licență

Physix -bazele unui motor fizic în OpenGL

Coordonatori: Lect.dr. Stupariu Sorin

Conf. dr. Tataram Monica

Student: Zaharia Andrei, grupa 333


Cuprins

1. Introducere................................................................................................................4

2. Descrierea aplicatiei.................................................................................................6

2.1 Scopul aplicației.......................................................................................................6

2.2 Obiectivele aplicației .............................................................................................6

2.3 Suportul matematic al aplicației............................................................................7

3 Realizarea aplicatiei..................................................................................................18

3.1 Tehnologii folosite..................................................................................................18

3.1.1 Descriere C++...................................................................................................................18

3.1.2 Descriere Managed C++..................................................................................................19

3.1.3 Descriere Visual Studio...................................................................................................23

3.1.4 Descriere Windows Forms.............................................................................................25

3.1.5 Descriere OpenGL..........................................................................................................27

-2-
3.1.6 Alternative OpenGL.......................................................................................................40

3.1.7 Descriere XML................................................................................................................43

3.2 Diagrama claselor..................................................................................................53

3.3 Realizarea legaturii intre Windows Forms si OpenGL........................................54

4 Instalarea si utilizarea aplicatiei, interfața utilizatorului.......................................57

5 Concluzii..................................................................................................................70

6 Bibliografie................................................................................................................71
1. Introducere

Într-o lume tehnologic avansată, precum cea în care ne aflăm în acest moment, este
imposibil să înţelegem tot ceea ce este în jurul nostru dar este important să ştim cum a început
totul şi principiile de bază. Un exemplu bun este Sir Isaac Newton, care a explicat ce este
gravitaţia, astfel încât să putem să o folosim în avantajul nostru. Deşi această forţă a existat din
totdeauna, pentru oameni era un mister şi tot ce ştiam e că dacă dai drumu la un obiec, el va
cădea. Numai după ce a fost tradusă într-un mod riguros, Newton a putut să redacteze
faimoasele legi în fizică ce îi poartă numele.

Pentru a înţelege lucrurile complicate mai întâi trebuie să avem o bază de cunoştinţe. Spre
accest scop am realizat această aplicaţie care imită într-un mod simplist, accentuând ceea ce nu
se observă cu ochiul liber din lumea reală. În acest spaţiu virtual putem să abstractizăm, folosind
obiecte simple, o realitate complexă cu o infinitate de variabile şi să observăm interacţiunea
dintre acestea.

Mai întâi trebuie să înțelegem partea matematică ce se află la baza aplicației. Concepte
importante precum forța de frecare, gravitația, impulsul si altele vor fi explicate precum și
modelarea lor în limbajul informatic. Pe lângă aceste concepte este util să înțelegem cum
folosește OpenGL-ul concepte din matematică pentru realizarea calculelor și de ce acestea sunt
mai eficiente.

La realizarea aplicației a fost nevoie utilizarea multor tehnologii care a trebuit să fie
îmbinate pentru ca totul să lucreze în armonie. Când e vorba de aplicații 3D nu există decât
opțiunea de a folosi DirectX sau OpenGL. Ambele prezintă aproximativ aceleași capabilități deci
folosind doar criteriul cerințelor aplicației nu ajută la selectarea unei tehnologii. O aprofundare a
arhitecturii fiecăreia arată diferențele cruciale și abordările complet diferite pe care fiecare
standard a ales să implementeze.

-4-
Pentru realizarea interfeței cu utilizatorul, tehnologia Windows Forms nu are rival pe
platforma Windows, având predecesori cunoscuți precum MFC și o îndelungată utilizare, lucru
ce se observă și în maturitatea codului, trecut de multe ori pe sub ochii critici ai dezvoltatorilor.

O caracteristică importantă a acestei platforme este posibilitatea încapsulării lucrului cu


limbajul de nivel jos al plăcii video apelat de API-ul OpenGL într-un mediu de nivel înalt fără a
avea de suferit performanțele aplicației.

De asemenea portarea pe platforma .Net a limbajului C++ este un lucru esențial pentru
aplicația aceasta, fiind necesar utilizarea codului librăriei grafice, ce este scrisă în C, pe o
platformă ce rulează pe o mașină virtuală. În lipsa existenței limbajului Managed C++ această
portare ar fi necesitat multe linii de cod, apeluri de sistem care sunt costisitoare și scrierea unui
serviciu COM pentru apelul codului C nativ.
2. Descrierea aplicatiei

2.1 Scopul aplicației

Physix este un motor fizic ce ilustreaza un spațiu virtual unde obiectele pot fi vizualizate
din orice punct pentru a le studia comportamentul.

În această aplicaţie am încercat să ilustrez o modalitate de a realiză legătură între limbajul


low-level al instrucţiunilor folosite de OpenGL pentru a comunică cu procesorul grafic şi o
interfaţă modernă oferită de Windows Forms.

2.2 Obiectivele aplicației

Aplicaţia poate fi folosită cu uşurinţă şi de aceea ar putea avea un rol educativ la orele de
fizică din gimnaziu. De exemplu, înţelegerea legilor lui Newton ar putea fi înlesnită prin crearea
unui context simplificat care să ilustreze mai precis aceste principii. În același timp prin
utilizarea unui set de clase prototip ce sunt construite astfel încât să oblige dezvoltatorul să se
încadreze în normele cerute de aplicație, aceasta poate fi extinsă și astfel creând seturi noi de
funcționalități.

-6-
2.3 Suportul matematic al aplicației

Concepte matematice folosite de OpenGL

OpenGL folosește pentru reprezentarea punctelor 3D spațiu proiectiv și nu spațiu


Euclidian. Acest lucru înseamnă că va stoca punctele folosind coordonate omogene. Acestea fac
posibil realizarea de calcule în spațiu proiectiv la fel ca și coordonatele Carteziene în spațiul
Euclidian.

Coordonatele omogene ale unui punct dintr-un spațiu proiectiv de dimensiune n se


notează cu (x,y,z,...,w), un vector de lungime n+1, altul decât (0,0,0,...,0). Două seturi de
coordonate ce sunt proporționale denotă același punct într-un spațiu proiectiv: pentru orice
scalar nenul c din câmpul K, (cx,cy,cz,...,cw) reprezintă un același punct. Acest sistem de
coordonate poate fi explicat astfel: dacă spațiul proiectiv este construit din spațiul vectorial V de
dimensiune n+1, introducem coordonate în V prin alegerea unei baze și le folosim pe acestea în
P(V), clasa de echivalență a vectorilor proporționali din V.

Considerând un spațiu proiectiv de dimensiune trei, un punct de coordonate omogene


este (x,y,z,w). Planul de la infinit este identificat de obicei de punctele cu componenta w = 0. În
afară de acesta, restul punctelor le putem folosi ca fiind ( x/w , y/w , z/w ) coordonate într-un
sistem Cartezian; spațiul afin complementar planului de la infinit este transformat folosind baza
( 1 , 0 , 0 , 1), ( 0 , 1 , 0 , 1), ( 0 , 0 , 1 , 1).

Dacă intersectăm două plane date prin ecuațiile x = w și x = 2w ajungem la concluzia ca w


= 0 și x = 0, ceea ce înseamnă că intersecția are loc pe planul de la infinit și coprinde toate
punctele de coordonate ( o , y , z , 0 ). Aceasta este o linie, cea care unește punctele ( 0 , 1 , 0 , 0 )
și ( 0 , 0 , 1 , 0 ). Această linie are ecuația:
(0:y:z:0) = μ(1 − λ)(0:1:0:0) + μλ(0:0:1:0)

μ este un factor de scalare. Acest factor poate fi ajustat pentru a normaliza coordonatele
( 0 , y , z , 0 ) și astfel eliminând un grad de libertate. Resultatul este un set de puncte cu un
singur grad de libertate, ceea ce este de așteptat, fiind forba de o linie.

Notații folosite în matematică.

Considerăm spațiul 2-proiectiv: puntele în spațiul proiectiv sunt proiecții a punctelor 3-


dimensionale. Se folosește notația ( x , y , z ) pentru reprezentarea unui punct 3D. Fie un alt
punct ( u , v , w ). Atunci:

( x , y , z ) = ( u , v , w ) ⇔ x = u, y = v și z = w.

Folosim notația [ x , y , z ] pentru proiecția unui punct 3D ( x , y , z ) pe planul de


proiectie. Punctul [ x , y , z ] poate fi considerat ca fiind egal cu o clasă de echivalență a
punctelor tri-dimensionale care aparțin liniei ce trece rpin ( x , y , z ) și ( 0 , 0 , 0 ). Dacă [ u , v , w
] este un alt punct atunci

[ x , y , z ] = [ u , v , w ] ⇔ ∃α ≠ 0, x = α u, y = α v și z = α w.

Două puncte 3D sunt echivalente dacă proiecțile lor pe planul de proiecție sunt egale:

( x , y , z ) ≡ ( u , v , w ) ⇔ ∃α ≠ 0, x = α u, y = α v și z = α w.

Deci ( x , y , z ) ≡ ( u , v , w ) ⇔ [ x , y , z ] = [ u , v , w ].

-8-
De asemenea un alt concept de care se folosește OpenGL-ul este utilizarea matricelor de
transformare. Aceste matrici permit operațiuni de transformare liniară să fie reprezentate întru-
un format consistent. De asemenea permite concatenarea a mai multor operațiuni foarte ușor,
prin înmulțirea matricelor de transformare asociate acestora.

Transformările liniare nu sunt singurele ce se pot reprezenta ca și matrice. Folosind


coordonate omogene atât transformările afine cât și proiecțiile de perspectivă pe Rn pot fi
reprezentate ca transformări liniare pe RPn+1 (spațiu proiectiv real de dimensiune n+1). În
OpenGL sunt folosite matrice de dimensiune 4x4.

Găsirea matricei unei transformări

Fiind dată o funcție de transformare T(x), este ușor de determinat matricea de


transformare A prin aplicarea funcției de transformare fiecărui vector al bazei canonice:

De exemplu, funcția T(x) = 5x este o transformare liniară. Considerăm n = 2 și aplicăm


procedeul de mai sus:

Cele mai des întâlnite transformări ce păstrează originea fixatăsunt liniare: rotație,
scalare, shearing, reflexie, proiecție ortogonală. Dacă o transformare afină nu este o translație
pură atunci păstrează cel puțin un punct fix, iar acesta poate fi ales ca origine pentru a face
transformarea liniară.

Exemplificând într-un spațiu bi-dimensional, folosim matrice 2x2.

• Rotația de un unghi θ în sensul acelor de ceas în jurul originii are formulele: x' = x cos θ +
y sin θ și y' = - x sin θ + y cos θ
• Scalarea se realizează prin x' = sx ∙ x și y' = sy ∙ y

• Shear – această operație poate fi executată în două moduri. Paralela cu axa Ox avem
formulele x' = x + ky și y' = y

iar pe aca Oy avem x' = x și y' = y + kx

Principalul avantaj al folosirii acestor matrici este facptul că se realizează ușor


compunerea lor, prin înmulțirea de matrici. Pentru două matrici de transformrare liniară A și B,
efectul aplicării mai întai a transformării A si apoi a transformării B unui vector x este dat de:

Se observă totuși diferența că înmulțirea se face în ordine inversă, B ∙ A.

Pentru transformările afine se folosește coordonate omogene, astfel o translație se obține

x' = x + tx și y' = y + ty

-10-
Toate transformările liniare sunt incluse în transformările afine și pot fi descrise ca o
transformare afină simplificată prin simpla adăugare a unei linii și a unei coloane de zero la
matricea corespunzătoare transformării liniare, cu excepția elementului din stânga jos care
trebuie să fie 1. Astfel pentru rotație se obține:

Folosing matrice de transformare conținând coordonate omogene, translațiile pot fi


amestecate cu ușurință cu alte tipuri de transformări. Motivul e ca planul real este mapat pe
planul w = 1 din spațiul real proiectiv și deci translațiile din spațiul real Euclidian pot fi
reprezentate ca un shear în spațiul real proiectiv. Deși o translație este o transformare non-liniară
într-un spațiu Euclidian bi-dimensional sau tri-dimensional descris de coordonate Carteziene,
devine, întru-un spațiu proiectiv 3D sau 4D descris de coordonate omogene, o transformare
liniară simplă ( shear ).

Concepte din domeniul fizicii

În general conceptul mișcării în fizică este centrat asupra accelerației. Dacă ne-am afla în
spațiu și am împinge un obiect acesta nu s-ar opri niciodată, decât la impactul cu un alt obiect.
În realitate însă dacă împingem un obiect pe orizontală acesta s-ar opri datorită forțelor de
frecare. În schimb dacă lăsăm un obiect să cadă și nu luăm în considerare gravitația acesta acesta
își va păstra viteza. Deci dacă păstrăm viteza constantă, aceasta poate fi scrisă astfel:

v(t) = v0

Viteza poate fi considerată ca fiind diferența instantanee a distanței supra timp. Astfel
dacă integrăm această formulă o obținem ca fiind o funcție de poziția x și poziția inițială:
x(t) = ∫v(t) = v0(t) + x0

De aici deducem că dacă avem un obiect la x = 0 cu o viteză v0 = 1, pentru fiecare valoare


întreagă a lui t distanța se mărește cu 1. Această funcție ne dă poziția obiectului știind timpul,
poziția inițială și viteza.

În același mod am putea considera și mișcarea pe axa Oy însă pe aceasta apare și


gravitația. În cel mai simplist model accelerația gravitațională este considerată o constantă , 9.81
m/s2. Considerând această accelerație ca fiind constantă are mai multe implicații. În primul rând
am putea integra ecuația pentru a obține ecuația vitezei funcție de timp, iar dacă mai aplicăm
integrala încă odată obținem ecuația poziției ca funcție de timp.

a(t) = a0

v(t) = ∫a(t) = v0 + a0t

y(t) = ∫v(t) = y0 + v0t + (a0t2)/2

Mai convenabil este să organizăm totul într-o matrice:

Restricționându-ne la două dimensiuni, să presupunem ca avem un obiect ce are o


traiectorie balistcă, este mult mai ușor să descriem mișcarea folosind o viteză și un unghi. Acest
lucru înseamnă să folosim coordonate polare, în trei dimensiuni ne-ar trebui două unghiuri deci
vor fi coordonate sferice. Pentru simplificare luăm cazul 2D, accelerația are o valoare fixă 10,
punctul inițial (0,0), viteza inițială 5, unchil 450 și calculăm pentru timpul t = 2.

-12-
Presupunem că avem nevoie de punctul de înălțime maximă la care ajunge obiectul. Acest
lucru este ușor deoarece pentru funcția de înălțime maximul este exelași cu maximul funcției y,
iar această valoare este obținută pentru punctul în care viteza este nulă.
Se observă că valoarea timpului este negativă, ceea ce este incorect din punctul de vedere
al fizicii. Acest lucru este rezultatul neglijării definirii axelor de coordonate. Acesta e primul
lucru care trebuie specificat atunci când se propune rezolvarea unei probleme de fizică. Pentru a
corecta greșeala este nevoie doar să schimbăm semnul lui t în ecuație.

Graficul unui obiect cu traiectorie balistică

Descrierea forțelor în fizică este simplă. O forță F a unui obiect de masa m și accelerație a
poate fi scrisă astfel:

F=m∙a

Acest model presupune că obiectul este un singur punct în spațiu și se analizează


diferitele forțe ce acționează asupra acestuia. Datorită acestei ipoteze nu se poate rezolva toate
problemele folosind formula dată, dar chiar și așa este simplu de înțeles și pentru modele mai
complexe.

Folosind acest model se poate deduce că asupra unui obiect acționează două forțe

-14-
• Forța gravitațională – ceea ce atrage obiectul spre Pământ și este de fapt
imprimarea accelerației g asupra obiectului de masă m

F=m∙g

• Forța normală – ceea ce acționează asupra obiectului și îl împiedică să


înainteze. Altfel spus aceasta este forța cu care Pământul acționează asupra
obiectului împotriva gravitației. Înlăturarea acestei forțe (înlăturarea
pământului de sub obiect) îi permite obiectului să înainteze spre centrul
Pământului.

Un alt factor în deplasarea obiectelor este acțiunea forțelor de frecare. Spre exemplu un
obiect ce se mișcă prin aer ar trebui sa poată să aibă o viteză mai mare decât dacă ar călători prin
apă. Acesta depinde de două lucruri:

• materialul cu care intră încontact obiectul

• obiectul în sine

În general modelele fizice iau în considerare doar primul factor.

În plus în calcularea acestei forțe intră în calcul și greutatea obiectului.Pentru frecarea


cauzată de deplasarea de-a lungul unei suprafețe, spre exemplu obținem forța de frecare Fk având
coeficientul de frecare μ, masa obiectului m și accelerația gravitațională g astfel:

Fk = μ ∙ m ∙ g

Acest tip de forță însă nu apare decât atunci când obiectul este în mișcare, dar o
componentă a sa există în orice moment, astfel avem următoarele concepte:

• Frecare statică – este limita inferioară a unei forțe necesare pentru a pune în mișcare un
obiect. Un obiect staționar necesită o forță mai mare pentru a-l face mobil decât forța
necesară menținerii în mișcare a aceluiași obiect.

• Frecare cinetică sau dinamică (non-statică) – reprezintă coeficientul de frecare din


timpul mișcării. Aceasta este forța risipită prin frecare în timp ce obiectul este mobil.
Fracțiunea de forță ce rămâne este folosit pentru a accelera obiectul.

Ceea ce am descris mai sus presupunea ca forțele să fie aplicate constant în timp asupra
unui obiect. Impulsul este conceptul fizic care presupune că pentru o perioadă definită t o forță
constantă a fost aplicată. Ecuația de calcul având masa obiectului, viteza finală și cei doi timpi
între care s-a aplicat forța este:

Impuls = F ∙ (t2 – t1 ) = m ∙ v

Inerția este conceptul ce permite definirea de coliziuni elastice și este definit ca fiind masa
transportată cu o viteză dată:

p=m∙v

De aici se deduce că un obiect de masa mare are multă inerție dar și faptulu ca un obiect
ușor dar cu o viteză foarte mare poate genera acceași forță.

Coliziunea elastică este interacțiunea, lovirea, a două obiecte având ca rezultat


modificarea vitezei fiecărui obiect. Folosind legea de conservare a energiei și știind masa

-16-
obiectelor m1 și m2 precum si vitezele în momentul coliziunii v1 și v2 obținem:

Rezolvând sistemul pentru necunoscutele v1f și v2f ,vitezele finale ale obiecteleor avem:
3 Realizarea aplicatiei

3.1 Tehnologii folosite

Am realizat aplicaţia utilizând mediul integrat de dezvoltare Visual Studio şi limbajul


propietar al Microsoft-ului, managed C++. Pentru realizarea lumii tridimensionale am folosit
OpenGL, mai specific librăria open source „freeglut” care este o încapsulare a bibliotecii
OpenGL, oferind o adiţie de metode ce înlesnesc utilizarea. Interfeţa utilizatorului am creat-o
folosit Windows Forms, succesorul bine cunoscutului MFC (Microsoft Foundation Classes). În
ceea ce priveşte persistenţă datelor, folosirea limbajului XML este uşor de înţeles, acesta oferind
posibilitatea de a-mi crea singur un limbaj extins cu restricţii lexicale şi de parsare stricte.

3.1.1 Descriere C++

Limbajul de programare C++ a fost iniţial derivat din C. Totuşi, nu absolut orice program
scris în C este valid în C++. Deoarece C şi C++ au evoluat independent, au apărut, din nefericire,
o serie de incompatibilităţi între cele două limbaje de programare. Cea mai amplă revizie a
limbajui C, C99, a creat un număr suplimentar de conflicte. Diferenţele fac să fie greu de scris
programe şi biblioteci care să fie compilate şi să ruleze corect în calitate de cod C sau C++, şi
produce confuzii celor care programează în ambele limbaje. Diferenţele fac că fiecare din cele
două limbaje de programare să împrumute din caracteristicile celuilalt limbaj de programare.

Bjarne Stroustrup, creatorul limbajului C++, a sugerat de nenumărate ori să se reducă


incompatibilităţile pe cât de mult posibil pentru a maximiza interoperabilitatea dintre cele două
limbaje de programare. Unii au argumentat că C şi C++ sunt două limbaje de programare
distincte, compatibilitatea dintre ele fiind utilă dar nu vitală; potrivit acestei opinii, eforturile de
a reduce incompatibilitatea nu trebuie să reducă eforturile de a aduce elemente noi în mod
independent celor două limbaje de programare.

Cele mai importante diferențe sunt:

-18-
• inline —funcţiile inline apar în secţiunea de declarare a variabilelor globale în C++, iar în
C acestea apăr în aşa zisele „fisiere statice€œ”.
• Cuvântul cheie bool are în C99 propriul sau header, <stdbool.h>. În variantele anterioare
de C tipul de date boolean nu era definit, în schimb erau folosite o serie de metode
(incompatibile) pentru a simulă acest tip de date.
• Constantele caracter (cuprinse între apostrofuri) au dimensiunea unui int in C si char in
C++. Cu alte cuvinte, in C, sizeof('a') == sizeof(int); in C++, sizeof('a') == sizeof(char).
Chiar și în aceste condiții, valoarea acestui tip de constante nu va depași valoarea maximă
ce poata fi păstrată de char, deci o conversie de genul (char)'a' este sigură.
• Cuvinte cheie suplimentare au fost introduse in C++, deci acestea nu pot fi folosite ca
identificatori așa cum ar putea fi folosite in C. (de exemplu try, catch, template, new,
delete, ...)
• în C++, compilatorul creează automat o „eticheta“ pentru orice structura (struct), uniune
(union) sau enumeratie (enum), astfel încât struct S {}; în C++ este echivalent cu typedef
struct S {} S; în C.

C99 a adoptat unele funcţionalităţi ce au apărut initial in C++. Printre acestea se enumeră:

• Declararea obligatorie a prototipului funcțiilor


• Cuvântul cheie inline
• Eliminarea variabilei implicite int ca valoare de întoarcere.

3.1.2 Descriere Managed C++

Managed Extensions pentru C++, sau simplu Managed C++, este o implementare
proprietară de C++ de catre Microsoft care include extensii gramaticale și sintactice, cuvinte
cheie și atribute pentru a aduce limbajul C++ pe platforma .Net. Aceste extensii permit codul C+
+ sa fie adus pe Common Language Runtime (CLR), sub forma de managed code, dar pastrând
totodată interoperabilitatea cu codul nativ. Managed C++ nu este de sine stătător un limbaj de
programare ci doar o extensie.

Aceste extensii au fost introduse odaca cu lansarea Visual C++ .Net dar nu au fost
adoptate de mulți dezvoltatori până la revizuirea extensivă care a avut loc in 2005 cu scopul de a
clarifica și a simplifica sintaxa și pentru a adăuga funcționalitate precum folosirea de generice
managed. „Managed” se referă la faptul că este rulat, gestionat, de către mașina virtuală .Net care
funcționează ca un mediu de protecție pentru o securitate sporită, având mai multe verificări la
rulare, precum verificări de buffer overrun. În plus, aplicațiile scrise in Managed C++ se
compilează în CIL, Common Intermediate Language, și nu direct în instrucțiuni native de
procesor, așa cum se întamplă cu aplicațiile scrise în C++ clasic.

Codul scris în Managed C++ poate să interopereze cu orice alt limbaj ce poate fi gestionat
de mașina virtuală .Net, cum ar fi C# sau Visual Basic .Net. De asemenea poate să foloseasca și
garbage collector-ul și alte trăsături ale CLR. Aceasta înseamnă că Managed C++ ocupă un loc
unic printre limbajele .Net deoarece este singurul ce poate comunica direct cu aceste limbaje
precum și cu C++ nativ. Celelalte limbaje .Net pot comunica cu cod C++ doar prin PInvoke sau
COM, de aceea Managed C++ este folosit adesea ca un „pod” de comunicare între acestea.

Funcționalitate adițională adusă de Managed C++

Cum am amintit mai sus unul din avantajele rulării pe maşina virtuală a platformei .Net
este folosirea garbage collector-ului care eliberează programatorul de povara gestionării manuale
a memoriei, însă este important de ştiut că există şi pentru clasic C++ garbage collector. Deşi
această formă de gestionare a memoriei este destul de rapidă ca viteză de acces, pentru aplicaţii a
căror performanţă este critică, cel mai probabil se va opta pentru utilizarea codului unmanaged,
nativ.

Însă această uşurare a gestiunii memoriei vine cu un preţ: în C++ există moştenire
multiplă, o clasă poate avea mai multe clase de bază, în Managed C++, datorită unei limitări a
CLR-ului acest lucru nu este posibil.

-20-
Avantaje in comparație cu codul unmanaged:

• Cod managed si unmanaged pot fi combinate foarte ușor în același assambly .Net.
Aceasta permite programatorului să păstreze codul unmanaged ce nu poate fi portat
pe platforma .Net fără a rescrie tot proiectul.

• Managed C++ este singurul limbaj care e capabil sa comunice nativ și cu toate
limbajele .Net și cu cod unmanaged C++. Deci este o soluție ideală pentru
interoperabilitate între toate aceste limbaje.

Dezavantaje in comparație cu codul unmanaged:

• Managed C++ introduce multe cuvinte cheie si convenții sintactice ce pot afecta
lizibilitatea codului managed, mai ales dacă este inclus cod unmanaged cu care
interactionează direct.

• Managed C++ nu este compatibil cu aplicatii web ASP.Net, care este o capabilitate a
tuturor limbajelor .Net, inclusiv cele ale unor dezvoltatori independenți.

• Managed C++ nu are suport pentru programare generica, cu template-uri. Succesorul


acestuia, C++/CLI va avea această capabilitate.

Dezavantaje in comparație cu alte limbaje .Net (C#, Visual Basic, etc.)

• Aplicațiilor in Managed C++ necesita un timp de dezvoltare mai lung decat a altor
limbaje ce pot fi aplicate în același caz și care ar avea același rezultat, datorita
necesității folosirii pointer-ilor, chiar și în cod Managed C++.
În comparație cu Java, Managed C++ are avantajul de a putea comunica cu sistemul la un
nivel jos și mai apropiat de hardware mult mai eficient, pe când programatorul java trebuie să
folosească JNI (Java Native Interface) pentru a accesa servicii de nivel jos al sistemului. În schimb
Java realizează și documentația codului sursă precum și existența unei game mai largă de
utilitare și medii de dezvoltare integrate ce folosesc acest limbaj, Managed C++ este acceptat doar
de Visual Studio, deși pentru programatorii dispuși să lucreze mai mult cu linia de comandă
există un Visual C++ Toolkit ce poate fi descărcat separat.

Un alt limbaj din platforma .Net este C#, mai asemănător cu java, fiind de asemenea mai
simplu de utilizat, poate duce la aceleași rezultate când este aplicat aceleași probleme rezolvate
cu Managed C++ având convențiile structurale și sintactice asemănătoare. De asemenea are
avantajul de a fi un limbaj interpretat pur (MSIL) pe cand Managed C++ poate duce la confuzii și
erori dacă se interpatrunde cu C++ nativ. În schimb portarea aplicațiilor din C sau C++ se
realizează mai ușor cu Managed C++ și deși compilatorul Microsoft Visual C++ produce tot cod
interpretat, acesta este unul cu un set de intrucțiuni mai matur, sporind performanța și în
general este mai rapid decat cel produs de compilatorul C#.

C++ nativ este mai rapid la rulare şi nu e nevoie să se instaleze un compiler special sau o
maşină virtuală, de asemenea suportă cuvântul cheie const, avantaje ce nu sunt împărtăşite şi de
limbajele de nivel înalt. De aseamenea în codul unmanaged se poate moşteni din mai multe
clase, un lucru important ce în multe situaţii poate crea probleme şi de aceea nu e văzut neapărat
că un avantaj, dar folosit cum trebuie poate aduce rezultate superioare şi poate reduce
complexitatea codului, pe când ocolirea acestei soluţii poate crea un cod mai complex decât este
necesar.

Pe de altă parte Managed C++ suportă un nivel mai ridicat al reflexiei, ceea ce în cele mai
multe cazuri este bine, luând în calcul bineînţeles şi socpul şi utilizarea codului. De asemenea
interoperabilitatea cu celelalte limbaje .Net oferă o versatilitatea rar întâlnită, iar prin
managementul automat al memoriei dezvoltarea aplicaţiilor este mai facilă.

-22-
3.1.3 Descriere Visual Studio

Visual Studio este un mediu de dezvoltare integrat, IDE, de la Microsoft și este singurul
disponibil care poate fi folosit pentru crearea de aplicații folosing Managed C++.

Acesta prezintă avantajul de a pune la îndemâna utilizatorului un set de unelte


indispensabile pentru un programator. Pe lângă un editor de text, acesta suport IntelliSense ce
ajută la scrierea mai rapidă a codului prin afișarea de informații utile și completarea automată a
cuvintelor, fie acestea cuvinte cheie, fie nume de variabile sau funcții.

De asemenea debugger-ul care este pus la dispoziție este unul complex și funcționează ca
un debugger la nivel de cod sursă dar și la nivel de cod mașină putându-se vizualiza instrucțiunile
procesor în cod assembler un lucru important când se lucrează cu librării proprietare dar și
pentru optimizarea codului.

Pentru a facilita crearea de interfețe grafice, în pachet este inclus si un designer pentru
Windows Forms ce suportă vizualizarea în timp real a modificărilor aduse ferestrei curente
precum și adăugarea de controale din toolbox, generându-se codul necesar în mod automat.

Cel mai important aspect este construcția acestui, fiind un program modular, fiecare
componentă fiind separată poate fi înlocuită sau extinsă de orice utilizator. Acest sistem de
pachete facilitează adăugarea de noi capabilități de către terțe persoane în scopul dezvoltării mai
rapide a unor aplicații. Deși această aplicație este closed source există pachete ce se pot folosi
pentru dezvoltarea aplicațiilor Python, Ruby și altele ce sunt open source.

Acest lucru este posibil deoarece Visual Studio nu suportă nici un limbaj de programare,
soluție sau unealtă ci pune la dispoziție sub formă de Service toate pachetele ce sunt instalate.
IDE-ul pune la dispoziție trei servicii: SVsSolution, care oferă posibilitatea de a enumera proiecte
și soluții; SVsUIShell, oferă funcționalitate pentru ferestre si alte elemente de interfață cu
utilizatorul; SVsShell ce se ocupă cu înregistrarea pachetelor VSPackeges. De asemenea Visual
Studio se ocupă de coordonarea comunicației dintre aceste servicii, înlesnind munca
programatorului.

-24-
3.1.4 Descriere Windows Forms

Când Windows a fost lansat pentru prima dată, exista cu adevărat o singură posibilitate de
a scrie aplicații pentru Windows, iar aceasta presuputea folosirea limbajului de programare C
pentru a accede la interfața de programare a aplicațiilor Windows (API). Deși era posibil accesul
la Windows API și utilizând Microsoft Pascal, această abordare era foarte rar utilizată.

Pe parcursul anilor, multe alte limbaje au fost adaptate pentru a realiza programe pentru
Windows. Printre aceastea se numără Visual Basic si C++. Atât C++, cât si C# sunt limbaje
orientate spre obiecte care recunosc majoritatea tipurilor, operatorilor, expresiilor și
instrucțiunilor din limbajul de programare C. Din acest motiv, C++ si C# (precum si Java) sunt
numite uneori limbaje bazate pe C, sau limbaje care aparțin familiei C.

După introducerea mediului .Net, Microsoft pune la dispoziție trei abordări pentru
scrierea aplicațiilor Windows, utilizând un limbaj bazat pe C:

Anul lansării Limbaj Interfa


1985 C Interfața de programare a
aplicațiilor Windows (API)
1992 C++ Biblioteca Microsoft
Foundation Class (MFC)
2001 C# sau C++ Windows Forms (face parte din
.Net Framework)

Din punctul de vedere al programării, ambele interfețe, MFC și Windows Forms,


funcționează prin apeluri la Windows API. Din punctul de vere al arhitecturii, se poate spune că
aceastea se află deasuprea lui API. Aceste interfețe de nivel mai înalt sunt concepute pentru a
simplifica programarea sub Windows. De obicei se pot efectua multe activități în MFC sau
Windows Forms utilizând mai puține instrucțiuni decât atunci când s-ar utiliza direct Windows
API.

Deși aceste interfețe de nivel înalt adesea cresc productivitatea programatorului, faptul ca
acestea se bazeaza pe alte interfețe crează dezavantajul de a fi mai puțin flexibile. Folosind direct
Windows API se pot face mai multe lucruri decât dacă dacă se folosește Windows Forms. Totuși
pentru a ameliora acest fapt, s-au introdus capabilitați, care cu puțin efort în plus, permit
efectuarea de apeluri Windows API dintr-un program Windows Forms.

La lansarea produsului Windows 1.0, întreaga intergață API a fost implementată în trei
biblioteci cu legare dinamică, numite KERNEL, USER si GDI. Deși bibliotecile cu legare
dinamică asociate cu Windows au ajuns să fie mult mai voluminoase, este în continuare util să se
împartă apelurile la funcțiile Windows (sau la clase ale cadrului de lucru) în aceste trei categorii:
apelurile la nucleu sunt cele implementate în arhitectura sistemului de operare și privesc de
obicei lucrul cu task-uri, gestionarea memoriei și operații de intrare/ ieșire pentru fișiere.
Termenul user se referă la interfața cu utilizatorul. Acestea sunt funcții pentru crearea ferestrelor,
utilizarea meniurilor și a casetelor de dialog și afișarea elemetelor de control, cum ar fi butoane și
bare de derulare. GDI este Graphics Device Interface, acea parte din Windows care răspunde de
afișarea ieșirii grafice (inclusiv a textului) pe ecran și la imprimantă.

-26-
3.1.5 Descriere OpenGL

• Ce este OpenGL?

OpenGL este un set standard de functii grafice 3D.

Acest standard îşi are originile în bibliotecă grafica IRIS GL a lui Silicon Graphics
Incorporated, fiind un format proprietar şi suportat doar de propriile platforme hardware. În
urmă numeroaselor solicitări venite din partea marilor dezvoltatori de software de a face publică
specificaţia GL, SGI a trebuit să rescrie specificaţia deoarece în forma originală era prea
dependentă de platforma hardware SGI. A rezultat un format nou, de data aceasta fiind asigurată
portabilitatea şi standardizarea. Noul nume: OpenGL.

Specificația, respectarea specificației și dezvoltarea OpenGL este controlată de un comitet


numit OpenGL ARB (architectural review board) care cuprinde DEC, Evans&Sutherland, IBM,
Intel, Intergraph, Microsoft și SGI.

La elaborarea specificației OpenGL au stat la bază următoarele două principii:

1. independența față de platforma hardware;

2. independența față de sistemul de operare.

În plus, orice implementare a OpenGL trebuie să fie conformă cu standardul de bază, ceea
ce asigură programatorii că funcţiile de bază vor fi disponibile pe orice platformă. Fiecare
implementator este nevoit să parcurgă un set de teste de conformitate care să certifice
implementarea corectă şi compatibilitatea OpenGL.
Ce nu este OpenGL?

• nu este un mediu de programare;


• nu este o interfață grafică;
• nu este orientat obiect.

Ce ofera OpenGL:

• primitive geometrice: puncte, linii si poligoane;


• primitive rastru;
• mod de lucru RGBA;
• modelarea și vizualizarea transformărilor de geometrie;
• eliminarea muchiilor ascunse (invizibile);
• antialiasing - tehnica netezirii muchiilor crestate prin modificarea culorii și
intensității pixelilor pentru ca muchiile să apară netede, continue;
• maparea texturilor - aplicarea de texturi 2D pe obiect 3D;
• efecte speciale - fum, ceață și dizolvări;
• evaluatori polinomiali - pentru reprezentări NURBS;
• operații cu pixeli;
• stencil planes - lucrul cu porțiuni de ecran;
• double-buffering - lucrul simultan cu doua rânduri de imagini, una care este
afișată și una care este pregatită pentru afișare.

După cum se poate observa din descrierea de mai sus, OpenGL este proiectat pentru
utilizarea în aplicații tehnice 3D cum ar fi CAD-ul (aplicații precum Solid Edge, Pro Engineer sau
I-DEAS), animații de calitate (cum ofera Softimage) sau în aplicații de simulare vizuală (Design
Review, GVS, ExoDIS).

Implementările OpenGL pot fi implementări hardware totale (de exemplu Intergraph,


SGI) caz în care se obțin cele mai mari performanțe, implementări software (de exemplu Sony)

-28-
sau implementări hardware parțiale (de exemplu 3Dlabs/GLiNT) caz în care se obțin
acceleratoare grafice ieftine din cauza rabatului de performantă. Cum OpenGL este independent
de interfața grafică a sistemului de operare, nu există o legatură strânsă între acestea două, fiind
suficiente doar cateva funcții de legătură, nucleul de baza OpenGL rămânând același indiferent
de implementare.

• Cum se măsoară performanța OpenGL?

În momentul in care dorim sa achizitionam un accelerator OpenGL sau un sistem


complet integrat care sa aiba implementat OpenGL, in mod normal prospectam piata,
comparam performante, preturi si servicii. Daca in ceea ce priveste pretul si serviciile totul este
clar, stim cum sa facem comparatia, in privinta performantei OpenGL lucrurile nu sunt tocmai
simple. Si asta tocmai din pricina furnizorilor si a datelor pe care le ofera. In general se dau cifre
care se refera la viteza de afisare a liniilor 2D sau 3D, a triunghiurilor, poligoanelor, suprafetelor
etc., dar nu se specifica si conditiile in care au fost facute aceste masuratori. Si ca o ironie, din
performantele de afisare a primitivelor nu rezulta performantele care vor fi obtinute in
exploatarea reala cu aplicatii si date concrete.

Cateva dintre cele mai frecvent intalnite metrici sunt:

• 3D vectors - in general se aleg vectori cu lungimea de 10 pixeli, iar punctele de la


capete au coordonate X, Y si Z;
• 3D line strings - serii de vectori 3D conectati la capete;
• 3D triangles - triunghiurile utilizate in teste au suprafetele de 25 pixeli sau 50
pixeli. Este greu de comparat performantele diferitelor acceleratoare grafice pentru ca
exista mai multe modalitati de desenare a triunghiurilor 3D. Aceste triunghiuri pot fi
iluminate sau nu, pot fi in modul Gouraud-shaded, sau flat-shaded, reprezentate cu 24-
bit color sau 16-bit color (uneori chiar 8-bit color). Fiecare din acesti factori influenteaza
puternic numarul de triunghiuri afisate intr-o secunda. De exemplu un triunghi flat-
shaded este desenat mai rapid comparativ cu unul Gouraud-shaded, sunt necesare mai
multe calcule pentru desenarea unui triunghi iluminat comparativ cu unul neiluminat.
Multi producatori nu specifica in rapoarte ce tip de triunghiuri au folosit, ceea ce face
imposibila o comparatie corecta. Recomandarile Intergraph sunt ca rapoartele sa fie
intocmite pentru triunghiuri iluminate, Gouraud-shaded, 24-bit color, Z-buffer, marimi
de 25 si 50 pixeli.
• T-mesh - triunghiuri care pot fi desenate independent in asa fel incat oricare doua
triunghiuri sa nu aiba laturi comune, sau suprafete alcatuite din triunghiuri astfel incat
doua triunghiuri sa partajeze o latura. Datele reale din aplicatii contin de obicei mai multe
elemente de tip 3D-triangles, T-mesh si quads;
• Quads - poligoane cu patru laturi (patrulatere).

Pentru a veni in intampinarea acestor inadvertente cu care se confrunta consumatorii, a


fost elaborat in 1994 un program de test numit Viewperf de catre subcomisia OpenGL
Performance Characterization (OPC) care apartine de comisia Graphics Performance
Characterization (GPC). OPC este parte componenta a Systems Performance Evaluation
Corporation (SPEC) - aceeasi companie care produce larg utilizatele programe de testare a
performantelor procesoarelor. Scopul OPC este de a realiza o metoda de comparare a
performantelor OpenGL, metoda care sa nu depinda de platforma hardware, sistem de operare,
sau interfata grafica. Sistemele de operare includ, dar nu sunt limitate la, OS/2, UNIX si
Windows NT. Interfetele grafice includ, dar nu sunt limitate la, Presentation Manager, X si
Windows. Intentia OPC este de a testa performantele grafice ale intregului sistem ruland
aplicatii si nu doar performantele grafice in sine, dat fiind faptul ca din performantele de afisare a
primitivelor nu rezulta performantele care vor fi obtinute in exploatarea reala cu aplicatii si date
concrete.

OPC si-a propus urmatoarele obiective:

• standardizarea masuratorilor performantei OpenGL prin crearea de unitati de


masura care sa nu depinda de o anumita platforma;
• sa ofere mecanisme care sa permita oricarui producator sau utilizator sa-si

-30-
efectueze propriile evaluari;
• sa faca publice versiunile beta si finale ale programelor;
• sa genereze o lista a celor afectati direct, sau material de specificatiile de evaluare,
sa ofere spre consultare publica aceste specificatii;
• sa contribuie la coerenta masuratorilor si evaluarilor performantei OpenGL astfel
incat producatorii sa fie capabili de a prezenta masuratori bine executate, iar cumparatorii
sa poata compara si evalua produsele.

Viewperf

Primul program de evaluare elaborat de OPC se numeste Viewperf si masoara


performantele de rendering 3D ale sistemelor bazate pe OpenGL. Viewperf nu este o aplicatie
concreta, in acceptiunea curenta, ci reprezinta o suita de teste bazate pe date reale.

Cateva din caracteristicile Viewperf:

• ofera un singur cod sursa pentru a efectua comparatii tip "mere cu mere, pere cu
pere" intre diverse platforme;
• ruleaza pe diferite procesoare incluzand Alpha, Intel, MIPS si PowerPC;
• cuprinde o mare varietate de caracteristici OpenGL si tipuri de rendering;
• foloseste seturi de date create pentru si utilizate de aplicatii reale;
• foloseste modele si parametri de rendering de la producatori diferiti;
• rezultatele sunt numere bazate pe cadre/secunda, ceea ce duce la o
interpretabilitate facila a rezultatelor;
• furnizeaza un singur numar pentru fiecare tip de rendering si pentru fiecare set de
date.

Parametrii masurati de Viewperf:

• primitive 3D incluzand puncte, linii, retele de linii, contururi liniare, triunghiuri


3D, retele de triunghiuri 3D, patrulatere si poligoane;
• atributele per vertex, per primitiva si per cadru;
• iluminarea;
• maparea texturilor;
• variatiile alpha;
• efectele speciale;
• eliminarea pixelilor clipitori (anti-aliasing);
• z-buffering-ul.

Ca orice program de test, Viewperf are si el unele limitari. Cele mai importante sunt ca nu
poate rula singur fiind nevoie de interventia utilizatorului, nu tine cont de efectele cauzate de
schimbarea primitivelor, de modificarile aparute in cadrul unui ciclu, de miscari complexe ale
modelelor multiple, de incarcarea CPU in timpul testului, de efectele multi-fereastra si de
calitatea vizuala.

Suita de teste

Viewperf consta dintr-o suita de 5 teste diferite: Awadvs-01 pentru animatii 3D, CDRS-03
pentru proiectarea industriala, DX-03 pentru vizualizari stiintifice, DRV-04 pentru explorarea
machetelor 3D virtuale si Light-01 pentru alte tipuri de vizualizare. Fiecare dintre teste include o
serie de sub-teste. Rezultatul final al unui test este o valoare medie a rezultatelor obtinute pentru
fiecare sub-test al testului respectiv. Trebuie mentionat ca rezultatele sub-testelor au ponderi

-32-
diferite in valoarea finala, ponderi care sunt direct proportionale cu gradul de dificultate al sub-
testului.

Awads-01

Este un test bazat pe aplicatia Alias|Wawefront Advanced Visualizer pentru animatii 3D.
Este o aplicatie high-end folosita in general de profesionisti. Este important de mentionat ca
aceasta aplicatie nu este disponibila sub Windows NT, deci acest test nu poate fi folosit pentru
comparatia intre diferite platforme. Modelul utilizat in aceasta aplicatie este sistemul muscular
uman. Aplicatia nu suporta multithreading, deci rezultatele vor fi aceleasi indiferent de numarul
de procesoare. Sunt 10 sub-teste, dintre care primul are un grad de dificultate de 41.8% (ponderea
in cadrul rezultatului final pe test) si foloseste interpolari triliniare, ceea ce duce la o mare
calitate a imaginii obtinute. Acceleratoarele grafice care sunt suplimentate cu procesoare
geometrice si cu memorie pentru texturi dau rezultate excelente la acest test.

CDRS-03

Aceasta aplicatie, facuta initial de Evans&Sutherland si apoi cumparata de Parametric


Technologies, este utilizata in proiectarea industriala, mai ales in industria de automobile la
proiectarea de interioare si exterioare. Aplicatia nu suporta multithreading, iar setul de date
include si o mica textura (860K). Sporul cel mai mare de performanta la acest test este dat de
acceleratorul geometric.

DX-03

IBM Visualization Data Explorer este o aplicatie de vizualizare si analiza stiintifica. In


cadrul testului sunt vizualizate traiectoriile particulelor care strabat un jet de fluid. Date de tipul
acesta pot proveni din simularea curgerii unor fluide sub anumite constrangeri. Setul de date este
compus in majoritate din primitive de tip retele triunghiulare. Aplicatia nu suporta
multithreading, nu include texturi, dar contine o sursa de lumina.

DRV-04

Aplicatia Design Review dezvoltata de Intergraph este folosita la explorarea machetelor


3D virtuale, utilizate in proiectarea obiectivelor industriale (instalatii cu tubulaturi, structuri
metalice etc.). Setul de date utilizat reprezinta o parte din modelul 3D al unei platforme de foraj
marin construite in Marea Nordului. Testul inseamna explorarea virtuala a platformei utilizand
imagini realistice. Aplicatia este multithreading, deci mai multe procesoare inseamna un plus de
performanta. Textura folosita este aceeasi cu cea de la testul CDRS, deci memoria pentru texturi
(cat mai mare) este foarte binevenita.

Light-01

Aplicatia se numeste LightScape Visualization System si este dezvoltata de LightScape


Technologies. Aplicatia combina algoritmi proprietari de difuzivitate cu diverse procedee de
iluminare. Utilizatorii au posibilitatea de a modifica rapid tipul iluminarii si a texturilor pentru a
obtine efectul vizual dorit. Setul de date utilizat la test reprezinta un interior dintr-un spatiu
arhitectural. Aplicatia nu suporta multithreading si nici nu utilizeaza texturi.

Producatorii care si-au evaluat produsele cu ajutorul lui Viewperf prezinta de obicei
valoarea finala la fiecare test. Este posibil ca un utilizator anume sa se confrunte cu o serie de
date al caror specific sa nu fie acoperit de cele 5 teste si sa considere ca un subtest se potriveste
cel mai bine cu cerintele sale.

-34-
• Glosar de termeni întâlniți în literatura de specialitate

24-bit color: sau "true-color", fiecare pixel de pe ecran are culoarea definita cu ajutorul a
24 biti (8 biti pentru rosu, 8 biti pentru verde si 8 biti pentru albastru). 24 biti ofera 16,7 milioane
de combinatii posibile de rosu (R - red), verde (G - green) si albastru (B - blue). Desi ochiul
uman nu poate distinge 16,7 milioane de culori diferite, numarul mare de culori permite
obtinerea de imagini 3D shaded foarte apropiate de realitate. Unele placi video suporta doar
culori pe 16 biti, adica 64K combinatii. Utilizarea unei game de culori mai reduse duce la
pierderea efectului realistic al modelului afisat pe ecran. Pe de alta parte, cresterea numarului de
culori duce la necesitatea cresterii latimii de banda de memorie a subsistemului grafic. De
exemplu, afisarea pe 16 biti presupune o latime de banda dubla fata de afisarea pe 8 biti, pentru a
afisa la aceeasi viteza. Adancimea culorii, sau coordonata Z, este o alta informatie critica care
trebuie luata in considerare in momentul in care sunt comparate performantele diferitelor
acceleratoare grafice.

32-bit color: o alta descriere a lui "true-color" care, in aditie la cei 24 biti descrisi anterior,
mai adauga inca 8 biti utilizati la definirea gradului de transparenta al pixelilor.

bit-planes: defineste numarul de biti care descriu fiecare pixel de pe ecran. De exemplu,
128 bit planes inseamna ca 128 biti controleaza modul de afisare al fiecarui pixel (pot fi 32 biti
pentru controlul culorii, 32 biti pentru adancime etc.). Memoria video este divizata in planuri de
biti (mai multi biti presupun mai multa memorie).

double-buffering: majoritatea placilor grafice OpenGL lucreaza cu doua randuri de


imagini, una care este afisata si una care nu. Acestea doua sunt denumite uzual "front-buffer" si
"back-buffer". Redarea fara fragmentari a unei animatii 3D presupune utilizarea unui card cu
"double-buffering". in timpul in care un cadru aflat in "front buffer" este afisat pe ecran, in "back
buffer" este pregatit cadrul urmator, dupa care continutul lui "back buffer" este transferat in
"front buffer", concomitent cu aducerea cadrului urmator in "back buffer". Din cauza ca acest
procedeu presupune multa memorie video, multe placi OpenGL nu suporta double buffering
si/sau 24-bit color. intrucat double-buffering este indispensabil pentru redarea continua a
imaginilor 3D, la aceste placi grafice trebuie sa se faca rabat fie la numarul de culori (trecerea pe
16-bit color), fie la rezolutie (micsorarea acesteia), ambele variante ducand la scaderea calitatii
imaginii.

frame-buffer: memoria video disponibila pe card pentru stocarea atat a informatiei


afisabile, cat si a celei neafisabile (cum ar fi coordonata Z). Furnizorii cu pretentii utilizeaza un
bloc contiguu de memorie pentru stocarea tuturor informatiilor, altii utilizeaza memorii VRAM
pentru stocarea informatiei afisabile si memorii DRAM pentru informatia neafisabila.

Mflops: milioane de operatii in virgula mobila. Algoritmii OpenGL presupun un intens


calcul in virgula mobila. Cu cat cardul poate efectua un numar mai mare de operatii in virgula
mobila, cu atat mai rapid va fi redering-ul.

overlay-planes: multe aplicatii presupun afisarea de vectori peste o imagine rastru, cum
sunt aplicatiile GIS (de exemplu desenarea unei linii reprezentand o sosea pe deasupra unei
imagini scanate). Utilizarea de planuri suprapuse permite desenarea de vectori fara coruperea
imaginii de pe fundal (a rastrului). Aceste planuri suprapuse mai sunt numite si planuri
nedistructive si presupun existenta in memoria video a unor biti de control separati de planurile
de imagini. Unele placi grafice ofera planuri de suprapunere pentru ambele randuri de imagini,
front buffer si back buffer, asa-numitul "double-buffered overlay planes".

stencil planes: mascarea anumitor portiuni din ecran (utilizarea sabloanelor). De


exemplu un simulator de tanc poate folosi un stencil-plane pentru definirea unei ferestre care sa
reprezinte peisajul exterior care se schimba odata cu deplasarea tancului. Imaginea din fereastra
poate fi rapid actualizata, fara a fi nevoie de modificarea intregului ecran, care in cazul de fata
reprezinta interiorul tancului. 8 asemenea planuri ofera posibilitatea definirii a 8 ferestre pe

-36-
ecran.

Z-buffer: numarul de biti alocati fiecarui pixel pentru definirea adancimii (coordonatei
Z). Un numar mai mare de biti pentru z-buffer inseamna o mai mare acuratete in determinarea
coordonatei z. Majoritate placilor grafice 3D suporta z-buffer doar de 16 biti, uneori de 24 biti.
Pentru o calitate minima a imaginii sunt suficienti 16 biti, dar recomandarea este 24 sau 32 biti.
in cazul reprezentarii unei instalatii care are o lungime de 500 m, dar care are tevi distantate la
doar 5 cm, un z-buffer de 24 biti nu ofera suficienta acuratete pentru a afla care teava este
deasupra celeilalte. Cardul video va incerca sa afiseze ambele tevi simultan, ceea ce duce la
palpairi deranjante pentru ochi (efect cunoscut sub numele de transpunerea triunghiurilor). Un
z-buffer de 32 biti elimina aceste neajunsuri.

texture mapping: procesul de aplicare de texturi 2D pe obiecte 3D pentru marirea


gradului de realism al obiectului. Fiecare texel (unitatea elementara a unei texturi) este aplicat pe
pixelul corespunzator al obiectului.

texture fill rate: viteza cu care texelii sunt aplicati peste pixelii obiectului 3D. De
exemplu o rata de 38 milioane reprezinta tot atatia pixeli care au fost acoperiti de textura intr-o
secunda. Sunt mai multi factori care afecteaza viteza de mapare, dar cei mai importanti sunt
modul de filtrare (sau interpolare) si adancimea culorii texturii (care poate fi de 4, 8, 16 sau 32
biti per texel). Marirea numarului de biti de culoare per texel duce la o crestere semnificativa a
calitatii imaginii, dar presupune si o latime de banda mai mare in accesarea memoriei video.
Modul de filtrare afecteaza in aceeasi masura calitatea imaginii, dar presupune in plus si un
volum de calcul mai mare. De exemplu maparea unei texturi pe 32 biti cu interpolare triliniara
presupune, comparativ cu o textura pe 16 biti si interpolare biliniara, o latime de banda de 4 ori
mai mare si un volum de calcul de 2 1/3 ori mai mare, in ipoteza ca dorim sa pastram aceeasi
viteza de mapare. Atat timp cat nu se cunosc acesti 2 parametri, nu se poate face o comparatie
corecta intre vitezele de mapare ale diferitelor acceleratoare grafice.

texture map interpolation: cand texturile sunt aplicate pe un obiect, procesorul grafic
trebuie sa determine care texel va fi aplicat pe care pixel. Cum texturile sunt 2D, iar obiectele sunt
3D, nu va exista o corespondenta de 1:1 intre texeli si pixeli. Exista 3 tipuri principale de
interpolare sau filtrare: metoda celui mai apropiat vecin, interpolare biliniara si interpolare
triliniara.

• Metoda celui mai apropiat vecin - pixelul primeste valoarea texelului care il acopera
in cea mai mare masura, deci valoarea unuia dintre cei 4 texeli vecini. Aceasta metoda este
folosita cel mai des in jocurile 3D din cauza vitezei mari la resurse mici, dar calitatea
imaginii rezultante este de slaba calitate.

• Interpolarea biliniara - valoarea pixelului este calculata pe baza celor 4 texeli vecini
si foloseste 3 valori medii astfel: prima medie se calculeaza pe baza celor 2 texeli de sus, a
doua medie pe baza celor 2 texeli de jos, iar a treia medie pe baza celor doua medii
anterioare. Ultima valoare medie este cea care se atribuie pixelului. Interpolarea biliniara
este potrivita pentru imagini statice, nu ofera imagini de mare calitate si este inca
nepotrivita pentru obiecte in miscare, cum este cazul simularilor.

• Interpolarea triliniara - foloseste mai multe texturi de rezolutii diferite derivate din
textura de baza, fiecare reprezentand exact 1/4 din suprafata celeilalte. Astfel, daca o
textura are 512x512 texeli, a doua va avea 256x256, a treia 128x128, ... iar ultima 1x1. Folosind
mai multe texturi de rezolutii diferite obtinem imagini de calitate excelenta mai ales cand
lucram cu apropieri/departari ale obiectelor, cum este cazul in majoritatea animatiilor si
simularilor. Valoarea aplicata pixelului va fi o medie de 8 texeli - 4 din fiecare textura.
Interpolarea triliniara inseamna calculul a 7 valori medii, comparativ cu 3 valori medii in
cazul interpolarii biliniare. Necesita in plus o latime de banda dubla, fiind cititi 8 texeli,
comparativ cu 4 texeli in cazul precedent. Modalitatea de calcul elimina posibilitatea de
aparitie a pixelilor clipitori, asa-numitul fenomen de "texture aliasing". Pentru aplicatii
care necesita obiecte in miscare, doar interpolarea liniara ofera calitate acceptabila.

-38-
3.1.6 Alternative OpenGL

Pentru crearea de aplicații grafice un programator nu are la dispoziție decât două variante:

• Direct3D – un API proprietar ce oferă funcții de randare a elementelor de grafică tri-


dimensionale și folosește accelerare hardware dacă este prezentă pe placa video. A fost
creat de Microsoft pentru a fi folosit pe platforma Windows.

• OpenGL – un API open standard ce cuprinde funcții de randare a elementelor 2D și 3D și


este disponibil pe majoritatea sistemelor de operare. Dacă placa video suportă accelerare
hardware, OpenGL o va folosi.

În general, Direct3D este conceput ca o interfață hardware 3D. Capabilitățile Direct3D-


ului sunt derivate din capabilitățile ce sunt puse la dispoziție de către suportul hardware. Spre
deosebire de acesta, OpenGL este conceput ca un sistem de randare 3D ce poate fi accelerat de
hardware. Aceste două API-uri sunt construite în două moduri fundamental diferite. Luând în
considerare acest lucru, faptul că au ajuns sa fie similare în funcționalitate arată ca nevoile
utilizatorului au împins dezvoltarea părții de hardware.

Chiar și așa există diferențe fundamentale între acestea. Direct3D obligă aplicația să
gestioneze resursele hardware pe când OpenGL implemetarea (driver-ul) să fac acest lucru.
Aceasta înseamnă că OpenGL facilitează dezvoltarea pentru API dar în același timp sporește
complexitatea creării unei implementări. Abordarea Direct3D permite dezvoltatorilor să aloce
independent resursele necesare cu puțin mai mult efort, dar implementarea este mai simplă și
dezvoltatorii pot aloca resursele în modul cel mai eficient pentru aplicația lor.

Din punctul de vedere al performanței diferența cea mai importantă constă în modul de
gestionare a schimbării modului de lucru. Această diferență apare datorită structurii
implementării hardware de către dezvoltatorii hardware.Sub DirectX implementarea este în
modul kernel, driver-e ce sunt instalate pe sistemul de operare. Modul utilizator este gestionat de
aplicația DirectX. Implementările pentru OpenGL sunt împărțite in două: partea modului
utilizator ce implementează API-ul OpenGL și partea modului kernel ce este apelată de partea
modului utilizator.

Motivul pentru care acest lucru este o problemă este faptul că apelarea de operații a
modului kernel din modul utilizator necesită crearea unui apel de sistem. Acest apel este foarte
încet și necesită microsecunde pentru a se executa, iar în acest timp procesorul nu poate executa
alte instrucțiuni. Din acest punct de vedere o metodă de optimizare ar fi reducerea numarului de
astfel de apeluri de schimbare de mod. Acest lucru se poate realiza prin stocarea informațiilor de
procesat într-un buffer și să se trimită la procesor un set de comenzi și nu numai una.

Datorită faptului că implementările DirectX sunt numai în modul kernel iar codul din
modul user se află în afara driver-ului, nu există posibilitatea realizării acestei optimizări. Efectul
acestui fapt este că fiecare apel Direct3D ce trimite comenzi către hardware trebuie sa realizeze o
schimbare de mod.

Deoarece implementarea OpenGL conține și modul utilizator, acesta poate realiza


optimizarea, iar numărul maxim teoretic de apeluri de schimbare de mod este același cu cel al
comportamentului standard al Direct3D-ului.

Există doar două tipuri de utilizări ale acestor API-uri: utilizarea profesională și utilizarea
pentru jocuri.

Datorită începutului OpenGL care a fost creat sa lucreze pe stații de lucru, acesta este
preferat de către utilizatorii profesioniști. Acest API conține aproximativ 250 de apeluri dar
pentru dezvoltarea de jocuri mai puțin de 100 din aceste apeluri sunt relevante.

-40-
Alegerea de către profesioniști a acestei platforme este parțială din motive istorice,
datorită faptului că la început plăcile video profesioniste suportau doar OpenGL, acest lucru s-a
schimbat dar utilizatorii au rămas. De asemenea existența acelor apeluri inutilizabile pentru
dezvoltarea de jocuri dar facile în alte contexte a contrubuit la această alegere. Un alt factor a fost
modul de prezentare, chiar de la început DirectX s-a vrut a fi un API de nivel jos, cu performanțe
ridicate pentru acces rapid la hardware pentru dezvoltarea de jocuri, pe când OpenGL s-a
remarcat prin aplicații profesioniste utilizate în diferite domenii.
3.1.7 Descriere XML

● Despre XML

XML – (eXtensible Markup Language) este un limbaj de adnotare/structurare a datelor.


Istoria aparitiei sale porneste de la SGML (Standard Generalized Markup Language) aparut in
anii 80. Acest limbaj isi propunea la aparitie sa creeze documente ce pot fi analizate de catre
masini prin introducerea de marcaje (sau taguri). SGML nu a fost un succes deoarece era foarte
complex si astfel crearea de programe care sa-l analizeze.

In anii 90 la CERN a aparut HTML-ul (HyperText Markup Language). La baza acestui


limbaj a fost SGML-ul si scopul sau a fost marcarea documentelor astfel incat sa poata fi
transmise prin retea. Una din ideile acestui document este ca browserele trebuie sa ignore
marcajele si atributele pe care nu le inteleg. Aceasta idee a avut ca efect aparitia unui limbaj mai
simplu care sa poata fi parsat rapid de catre browsere. Si astfel s-a dezvoltat HTML-ul.

Succesul avut de Web a cauzat o dezvoltare rapida a browserelor care analizau marcajele
HTML. Astfel au aparut o gama larga de marcaje si atribute care puteau fi scrise fara prea multe
constrangeri. Browserele au trebuit sa tina cont de aceste constrangeri si au devenit foarte
complexe. Pe de alta parte s-a sesizat utilizarea HTML-ului pentru adnotarea documentelor si o
slabiciune de-a sa, faptul ca nu se pot adauga marcaje noi.

In acest context in decembrie 1997 W3C (World Wide Web Consortium) a lansat ca
recomandare propusa versiunea 1.0 de XML. In acest document se afirma ca XML este un subset
al SGML care pastreaza caracteristici cum ar fi posibilitatea crearii de marcaje, posibilitatea de
validare, posibilitatea de a fi citit si inteles de catre oameni. Totodata se afirma ca XML este creat
pentru a fi folosit pentru adnotari, schimb de date, publicare documente si prelucreare automata

-42-
de catre clienti (agenti) inteligenti. Pastrand un subset al SGML impreuna cu un set de
constrangeri documentele XML vor putea fi prelucrate foarte rapid de catre parsere neavand
limitele date de complexitatea SGML. Vom vedea care sunt cazurile de utilizare actuale pentru
XML dupa ce ii vom intelege sintaxa – dupa care ii vom intelege mai clar si avantajele si
slabiciunile.

● Sintaxa

Un marcaj este un text care descrie sensul sau structura unor date. Acest text este inserat
intre semnele „<” si „>”. Marcajele pot avea inceput si sfarsit ca de exemplu:

<nume>Popescu</nume>
sau pot fi vide (fara text in interiorul marcajului)
<casatorit />

Marcajele sunt case-sensitive. La intalnirea unui marcaj de tipul


<nume>Popescu</NUME> parserul va da o eroare.

Un element este tot ceea ce se afla intre marcajul de inceput si marcajul de sfarsit. In cazul
de mai sus numele elementului este „nume”. Aceste nume trebuie sa indeplineasca cateva
conditii.

• Pot sa contina litere, cifre si alte caractere


• Nu pot incepe cu cifre si cu semne de punctuatie
• Nu pot incepe cu „xml”
• Nu pot contine spatii

Un element poate contine mai multe elemente. Acest lucru determina aparitia unor relatii
de rudenie intre elemente si a unor constrangeri suplimentare. Cea mai importanta dintre aceste
constrangeri este aceea ca intr-un fisier XML trebuie sa existe un element radacina care sa le
contina pe toate celelalte. O a doua constrangere este ca elementele nu pot fi incrucisate. Astfel
urmatoarea constructie este incorecta <tranzactie><data>2005-11-05</tranzactie></data>. Cu
alte cuvinte marcajele trebuie inchise invers fata de cum sunt deschise.

Relatiile de rudenie pot fi parinte-copil sau frate-frate. Un exemplu de relatie parinte-


copil in cadrul unui element este urmatoarea.

<tranzactie>
<data>20-07-2005</data>
<ora>13:00:00</ora>
</tranzactie>

In acest exemplu elementul <tranzactie> este parinte al elementelor <data> si <ora> care
sunt “frati”.

Un element poate sa contina unul sau mai multe atribute. Atributele se specifica in cadrul
marcajului de inceput al elementului si sunt de tip nume_atribut=”valoare”. Un exemplu: <suma
moneda=”RON”> 1000 </suma>. Atributul in acest caz este moneda iar valoarea atributului este
RON. Valorile atributelor se pun intotdeauna intre ghilimele.

Ar mai fi de mentionat ca intotdeauna un document XML incepe cu un rand in care se


mentioneaza versiunea limbajului si codificarea folosita. De exemplul se poate specifica faptul ca
se foloseste versiunea 1.0 si ca se foloseste codificarea ISO-8859-2, care este codificarea folosita
pentru limba romana.

Respectand aceste simple reguli de sintaxa vom putea obtine ceea ce se numeste un
document XML bine format. Acest document se valideaza la randul lui cu ajutorul unui alt fisier
in care se definesc tagurile folosite. Acest alt fisier poate fi de tip DTD sau Xschema.

-44-
● Cazuri de utilizare

XML-ul este un limbaj care permite structurarea si adnotarea datelor intr-un mod lizibil
atat de catre oameni cat si de catre calculatoare. Avand aceste calitati putem oarecum deduce
unde se poate folosi in mod practic si unde este mai putin recomandat.

Poate cel mai evident caz de utilizare este cel al fisierelor de configurare. In momentul de
fata foarte multe aplicatii isi pastreaza fisierele de configurare in XML. Motivele sunt cele
enuntate mai sus – parsare rapida pentru calculatoare, usor de citit de catre oameni, structura
logica a datelor.

Un alt caz in care se foloseste XML si in care se pare ca va deveni un standard este cel al
stocarii informatiilor din fisiere tip office. Dezvoltatorii de solutii office open-source au
standardizat un format numit Open Document. Acest format presupune salvarea oricarui
document de tip office – document, foaie de calcul (spreadsheet), prezentare – intr-un format
XML. Informatia este stocata in mai multe fisiere care sunt arhivate si astfel utilizatorul poate
vedea numai un singur fisier de tip *.sxw sau *.odt, etc. De ce s-a alex XML pentru un astfel de
format? Pentru ca ofera avantajele structurarii informatiei si mai ales pentru ca s-au dezvoltat
deja foarte multe alte limbaje si standarde pe baza lui. Aceste limbaje (XHTML, SVG, XSL, SMIL,
XLink, XForms, MathML, Dublin Core) sunt folosite si ele in acest format si deoarece toate au la
baza XML interoperabilitatea este garantata. XML are si un dezavantaj care este dat de faptul ca
introduce informatie redundanta (overhead). Informatia redundanta este reprezentata de
numele marcajelor care se repeta in document. Aceasta problema a fost rezolvata de cei de la
Open Office prin arhivarea fisierelor XML intr-o arhiva zip. Astfel s-a rezolvat problema spatiului
suplimentar aparut prin introducerea unei mici pierderi in viteza. Mai recent (incepand cu
Microsoft Office 2007) si Microsoft a adoptat formatul OOXML care dupa cum ii spune si
numele este tot bazat pe XML si care este in acest moment in curs de standardizare.

Un alt caz de utilizare este in stocarea efectiva a datelor – mai precis baze de date. In
momentul de fata XML poate fi folosit cu succes pentru baze de date mici. In momentul in care
bazele de date cresc ca dimensiune overheadul devine inacceptabil. Din cauza spatiului mare
ocupat si a necesitatii accesului foarte rapid la date arhivarea fisierelor XML cu date nu poate fi o
solutie si in acest caz. Oricum, multe interfete pentru baze de date permit exportarea bazei de
date in format XML – atat definitia tabelelor si a relatiilor intre ele cat si datele propriu zise.
Doua exemple de aplicatii care au aceasta facilitate sunt MS Access si PHPMyAdmin. Un alt
exemplu de caz in care XML-ul nu a avut succes este legat tot de stocarea unor cantitati mari de
date si de acces rapid la acestea – mai precis pastrarea fisierelor jurnal ale serverelor. In acest
domeniu este folosit printre altele un standard numit CLF – Common Logfile Format – care are
avantajul ca nu introduce informatie suplimentara.

XML sta la baza multor tehnologii si limbaje noi. Astfel pentru prezentare de continut pe
web exista XHTML si WML (pentru dispozitive mobile), pentru descrierea unor fisiere XML
exista XSchema, pentru transformarea fisierelor XML pentru a fi reprezentate exista XSL, pentru
realizarea unor prezentari exista SMIL, pentru descrierea obiectelor grafice exista SVG, pentru
reprezentarea semanticii unor domenii exista RDF si/sau OWL, pentru schimb de informatii
intre aplicatii exista SOAP si asa mai departe, lista aceasta fiind departe de a cuprinde toate
tehnologiile/limbajele existente bazate pe XML. De ce au aparut atatea limbaje bazate pe XML?
Pentru ca are o structura simpla si totusi stricta, pentru ca este foarte usor de analizat si foarte
usor de definit si dezvoltat.

● Tool-uri

Exista o larga varietate de instrumente pentru editarea fisierelor XML. Din seria celor
comerciale cele mai cunoscute sunt XMLSpy si StylusStudio. Ambele ofera versiuni de „trial”
pentru a vedea ce facilitati ofera.

Datorita simplitatii sintaxei o gama larga de editoare au facilitati pentru crearea fisierelor

-46-
XML: Notepad++, Context din gama editoarelor mai simple si Eclipse sau Netbeans din gama
editoarelor mai complexe

● Sabloane de proiectare a fisierelor XML

Folosirea sabloane permite crearea unor documente mai usor de citit, folosit si prelucrat,
permite gestionarea mai facila a informatiilor oferite.

In aceasta sectiune vom rezuma aabloanele cele mai importante.

• Sabloane pentru folosirea Metadatelor (date despre date). Cand exista metadate
intr-un document pot fi folosite mai multe solutii pentru integrarea lor:
o Head+Body – varianta folosita si in HTML – datele despre date se pun intr-o
secţiune speciala a documentului numita head si datele efective se vor plasa in sectiunea
body.
o Metadatele se pun inaintea datelor in document. Motivul este destul de
simplu si anume in conditiile in care procesarea XML-ului se face secvential s-ar putea ca
un proces, dupa ce interpreteaza meta-datele sa nu mai doreasca sa prelucreze si restul
documentului si implicit sa nu-l mai incarce sau parseze
o In cazul in care exista un mare numar de metadate, poate fi util ca acestea sa
fie plasate intr-un fisier separat. Acest lucru este recomandabil mai ales in cazul in care
este vorba de metadate comune mai multor fisiere (vezi ontologii şi RDF)

• Abstractizare. Cum se pot alege si respectiv grupa elementele astfel incat structura
XML-ului format sa fie cat mai inteligibila.
o Containere – in containere se pot pune mai multe elemente diferite dar care
caracterizeaza un „parinte” comun dintr-un anumit punct de vedere. De exemplu pentru
un om putem pune intr-un container „date de identificare” elementele „nume”,
„prenume”, „CNP”
o Colectii – cand in cadrul unui element pot aparea ca si copii mai multe
elemente de acelasi tip acestea este recomandabil sa se grupeze ca si copii al unui element
separat. Exemplu un om are mai mulţi copii ceea ce putem exprima in mai multe feluri:
<om>
<date_identificare>…</date_identificare>
<copil></copil>
<copil></copil>...
..
</om>
Sau
<om>
<date_identificare>…</date_identificare>
<copii>
<copil></copil>
<copil></copil>...
</copii>
..
</om>
A doua varianta presupune adaugarea elementului „copii” care reprezinta o colectie
de elemente de tip „copil”
o Elementele este bine sa aiba o corespondenţa in cadrul domeniului descris

• Organizarea datelor
o Declararea elementelor inainte de a fi referite. Cu ajutorul atributelor de tip
IDREF elemente pot fi referite in cadrul altor elemente. Este recomandabil ca intai sa
apara in document elementul si apoi referinta (tot pentru usurinta procesarii)
o Referirea datelor si nu repetarea lor. Datele pot fi declarate folosind
declaratii de tip Entity sau pot fi identificate in mod unic folosind atribute de tip ID şi
referite prin atribute de tip IDREF
o Clasificare folosind atribute – cand pot clasifica anumite elemente in mai

-48-
multe feluri se pot introduce atribute pentru a nu complica ierarhia. In exemplul de mai
sus elementului copil i se poate introduce atributul „sex” care practic introduce o
clasificare suplimentara fara a adauga elemente suplimentare.

• Altele
o Reutilizare atribute – daca mai multe elemente au aceleasi atribute nu
trebuie definite atributele de mai multe ori
o Nume scurte dar inteligibile – „loc_de_munca” este preferat elementului
“serv”.

● Concluzii

XML-ul este un limbaj cu o sintaxa simpla si care permite doar structurarea datelor intr-o
maniera proprie prin definirea propriilor taguri. Aceasta facilitate de structurare a datelor a
permis folosirea sa pentru a dezvolta limbaje noi precum si pentru a fi folosit in noi standarde de
stocare a datelor. Nu in ultimul rand XML-ul poate fi folosit pentru a schimba date intre
aplicatiile care au nevoie de a comunica intr-un limbaj comun.

Chiar si in ciuda dezavantajelor pe care le are (overhead) calitatile XML mai sus
mentionate ii permit sa fie folosit cu succes in multe domenii si sa fie piatra de temelie pentru si
mai multe domenii.

Pentru a usura manuirea aplicatiei am realizat un sistem de salvare si incarcare a unei stari
catre si dintr-un fisier in format XML. Avantajele pe care le prezinta acest limbaj au usurat foarte
mult acest task. Formatul fisierului este simplu si usor de inteles, atat de un utilizator cat si de
calculator:

<Objects>
...
<Object Type="SolidCube" Id="1" Name="Cubul" Selected="False">
<Center X="0" Y="16" Z="0" />
<Size X="2" Y="2" Z="2" />
<Rotation X="0" Y="0" Z="0" />
<Color X="240" Y="50" Z="140" />
<BoxMin X="-2" Y="14" Z="-2" />
<BoxMax X="2" Y="18" Z="2" />
<Movement X="0" Y="0" Z="0" />
<ResistanceAir X="0.1" Y="0.1" Z="0.1" />
<ResistanceFloor X="0.5" Y="0.5" Z="0.5" />
<Forces>
...
<Force Name="Gravity" Id="1" Persistant="True">
<Direction X="0" Y="-0.2" Z="0" />
</Force>
...
</Forces>
</Object>
...
</Objects>

Radacina documentului este tag-ul <Objects></Objects> intre care se afla descrierea


obiectelor din scena. Fiecare obiect are atribute: Type=”SolidCube”, Id=”2”; dar si copii care
descriu proprietati: Size, Rotation, Color. De asemeanea contine si elementul <Forces></Forces>
care poate contine mai multi copii de tipul <Force></Force> fiecare descriind o forta care este
exercitata asupra obiectului parinte.

Folosind capabilitatile platformei .Net la care am acces datorita utilizarii Managed C++
pentru scrierea codului, nu a fost greu sa creez clasa XMLFileTranzaction care are rolul de a scrie
si a citi dintr-un fisier scena curenta vizibila.

-50-
Header-ul acestei clase este urmatorul:

using namespace System;


using namespace System::Xml;

ref class XMLFileTranzaction


{
String^ Path;
XmlDocument^ doc;

public:
XMLFileTranzaction(String^ path);

array<oglObject^>^ LoadFromXML(int &l);


oglObject^ BuildObject(XmlNode^ o);
Punct^ BuildProperty(XmlNode^ o, String^ name);
void BuildForces(XmlNode^ o,oglObject^ obj);

void SaveToXML(array<oglObject^>^ objs,int l);


XmlNode^ CreateObjectNode(oglObject^ o);
XmlNode^ CreateInnerPropertyNode(String^ nume, Punct^ p);
XmlNode^ CreateForcesNode(oglObject^ o);
};

si se poate observa importurile din .Net pentru lucru cu fisiere si cu XML din namespace-
urile System si System::Xml. Se poate observa ca este o clasa ref ceea ce inseamna ca alocarea
memoriei se realizeaza automat si este gestionata de garbage collector si deci nu este neboie de
un destructor. Cele mai importante metode ale acestei clase sunt: cea de incarcarre dintr-un
fisier LoadFromXML() si cea de salvare intr-un fisier XML SaveToXML(). Celelalte metode sunt
doar functii ajutatoare.
3.2 Diagrama claselor

-52-
3.3 Realizarea legaturii intre Windows Forms si OpenGL

Crearea unei ferestre OpenGL într-un view MFC era o chestiune simplă și directă. Odată
cu trecerea la Windows Forms acest lucru s-a complicat, fiind nevoie rezolvarea unor probleme.
Conceptul de Device Context al ferestrei ne mai fiind prezent in Windows Forms. Există
implementări de OpenGL pe Windows Forms, dar acestea se bazează în mare parte pe DLL-uri
sau pe componente ActiveX ce conțin apeluri MFC sau de Windows API. De asemenea acestea
presupun folosirea limbajului C#, ceea ce nu e neaparat un lucru rău, dar obligă dezvoltatorul sa
rescrie intreaga aplicație in C# și uneori nu este avantajos să se facă aceasta numai pentru
avantajele lucrului cu Windows Forms. De aceea am ales cea mai „curată” variantă și anume
folosirea numai a codului Managed C++ si al platformei .Net.

În primul rând este nevoie de o clasă ce va realiza, efectiv, redarea contextului OpenGL pe
ecran și care va funcționa ca o fereastra OpenGL. Pentru a avea acces la pointer-ii ferestrei în care
se va face desenarea trebui ca această clasă să moșteneasca din
System::Windows::Forms::NativeWindow.

ref class GLWindow:public System::Windows::Forms::NativeWindow


{
private:
HDC hDC;
HGLRC hglrc;
int Width;
int Height;
public:
static GLWindow ^oglWindow; //this static

//env
float LastX;
float LastY;
float PosX;
float PosY;
float Zoom;
float RotX;
float RotY;
bool IsMaximized;
public:
GLWindow(System::Windows::Forms::Panel ^ parent,GLint iWidth, GLint
iHeight);
virtual ~GLWindow(void);

//OGL
void SetPerspective();
void InitScene();
void Render(GLenum mode);
void SwapOpenGLBuffers();
GLint MySetPixelFormat(HDC hdc);
bool InitGL();
void ReSizeGLScene(GLsizei width, GLsizei height);
};

Accesul la Device Context se realizează prin pointer-ii hDC și hglrc care sunt inițializați in
constructorul clasei:

m_hDC = GetDC((HWND)parent->Handle.ToPointer());
m_hglrc = wglCreateContext(m_hDC));

Trebuie menționat parametrul constructorului care este container-ul unde se realizeaza


afișarea, acesta poate fi: fereastra in sine, un PictureBox sau un simplu Panel. Se poate observa ca
GLWindow are parametru la constructor un pointer managed System::Windows::Forms::Panel^
parent. De asemenea se observa prezența funcției Render care efectueaza redarea conținutului în
fereastră, mai exact pe acel Panel.

Bineînțeles este nevoie de un Form care sa conțină toate elementele de interfața cu


utilizatorul ce vor fi afișate. Aceasta va conține un membru de tip GLWindow si un Panel pentru a
putea afișa contextul OpenGL utilizatorului.

public ref class FormMain : public System::Windows::Forms::Form


{
public:
int SelectedObject;
int SelectedForce;
String^ CurrentFile;

-54-
GLWindow ^ OpenGL;
...
private:
System::Windows::Forms::Panel^ OGLPanel;
...
FormMain(void)
{
InitializeComponent();

OpenGL = gcnew GLWindow(this->OGLPanel,OGLPanel-


>Width,OGLPanel->Height);

}
...
}

În constructorul ferestrei se observa inițializarea clasei mai sus menționata și parametrul


dat, care este de tipul Panel.
4 Instalarea si utilizarea aplicatiei, interfața utilizatorului

Această aplicație constă intr-un singur executabil și nu necesită nici un fel de instalare
specială. În schimb pentru a putea rula acest program este nevoie ca user-ul să aibă instalat
anumite elemente esențiale.

Pentru că a fost scrisă itilizând Managed C++ e nevoie sa fie prezentă mașina vrituală .Net.
Aceasta se găsește în pachetul Microsoft .Net Framework 3.5 care se găseste de descărcat gratis de
pe site-ul Microsoft. Este important ca versiunea sa fie minim 3.5 doarece aceasta este versiunea
în care a fost scrisă, iar orice versiune nou aparută pentru această mașină virutală prezintă
compatibilitate înapoi, asigurând că orice verisune nouă poate rula toate aplicațiile scrise pentru
versiunea precedentă.

De asemenea pentru a vedea spațiul virtual pe calculatorul ținta trebuie instalat librăria
open-source freeGLUT. Acest lucru este mai dificil, neavând la dispoziție un installer, dar
urmărind instrucțiunile care vin cu librăria este ușor de trecut peste acest obstacol.

La pornirea aplicației se disting cu ușurința două zone de lucru. În partea stângă se află
afișata lumea virtuală într-un spațiu tri-dimensional. Această zonă acupă 75% din suprafața
ferestrei.

-56-
Folosind mouse-ul se poate naviga prin spațiul virtual astfel:

• Acționând click dreapta se realizează operațiunea de pan, mutarea spațiului de vizualizare


spre stânga, dreapta, mai sus sau mai jos.

• Dacă se realizează click 3, cunoscut si sub numele de click mijloc, și se menține apăsat se
realizeaza o rotire a spațiului de vizualizare mișcând mouse-ul în direcțiile
corespunzătoare.

• Folosind mouse scroll se realizează zoom-ul, permițând apropierea de un anumit obiect


sau observarea scenei în ansamblu, astfel navigarea în lumea virtuală este completă,
putânduse realiza o vizualizare a fiecărui punct din spațiul creat.

Dacă se acționează click stânga atunci când cursorul mouse-ului este deasupra unui
obiect, se realizează selectarea obiectului, iar dacă sunt mai multe obiecte unul deasupra altui, se
selecrează doar cel care este mai aproape de fereastra de vizualizare.

Pentru aceasta operațiune există două abordări standard: picking și ray tracing.

Operațiunea de ray tracing constă în calcularea direcțieie unui vector în cadrul spațiului
virtual astfel încât acesta să reprezinte direcția pe care utilizatorul a intenționat să selecteze. În
OpenGL acest lucru se poate realiza folosind funcțiile de mouse puse la dispoziție de către aceste
librării, astfel că dacă se apelează funcția de mouse pentru planul apropiat utilizatorului, asociat
trunchiului de piramidă al portului de vizualizare, și se realizează un al doilea apel pentru planul
departat al portului de vizualizare, atunci se poate calcula direcția vectorului director al selecției.

Deși aceasta abordare nu e dificilă, prezintă dezavantaje datorate limitării calculatorului


și anume precizia calculelor. Acest lucru nu pare atât de grav la prima vedere, calculatorul fiind
considerat un instrument precis, însă realitatea este mai dură și de aceea si o eroare de o sutime
crează o eroare remarcabilă cu ochiul liber, ceea ce distruge imersia în lumea virtuală.

De aceea folosirea mecanismului de picking implementat în motorul intern al OpenGL-

-58-
ului este de preferat. Acest mecanism constă în redarea scenei pe buffer-ul plăcii video, într-un
mod puțin diferit dând nume fiecărui obiect. În mod normal acest buffer ar fi folosit pentru
crearea imaginii ce ar urma sa fie prezentată utilizatorului, dar în acest caz este folosit pentru
realizarea unor calcule foarte precise. Când utilizatorul acționează modul select în loc de obiecte
propriu-zise se desenează contururi și se utilizează o stivă de nume pentru fiecare. Acest lucru
asigură o precizie îmbunatățită deoarece, pe masură ce conturul este desenat se verifică locația
unde s-a realizat click iar în program se returnează o listă de nume cu obiectele care au fost
„lovite” și de asemenea adâncimea minimă și maximă la care acel specific obiect se găsește.
Datorită acestor informații suplimentare și preciziei îmbunătățite am ales această metodă.

Există și o a treia metoda care nu este mult diferită de precedentă și folosește culoarea
pixel-ului de sub mouse ca indicator al selecției. Pentru această metoda trebuie ca toate obiectele
să aibă culori diferite, acest lucru nu e practic pentru acplicatie și deci se folosește aceeași
metodă de redare a conținutului în buffer și nu pe ecran. Deși se pot crea multe culori într-o
scenă complexă, folosirea de culori dinstincte pentru toate obiectele este imposibil. Pentru
remedierea acestui fapt se realizare o divizare a scenei astfel încât la un pas procesul de selecție să
micșoreze câmpul de vizualizare. Însă acest proces este mai complicat, realizarea în mai mulți
pași irosește cicluri de procesor și de asemenea este mai greu de implementat.
Panoul de proprietăți

• Objects Tab

Acest panou este împarțit în două grupuri de controale. Primul grup este intitulat objects
și este folosit pentru a adauga obiecte în scenă sau pentru a modifica un obiect existent. Mai întâi
trebuie selectat unul din butoanele radio pentru a activa una din listele în cascadă ce iti permit
selecția diferitelor proprietăți. Dacă se selectează crearea unui obiect nou în lista din dreapta va
apărea opțiuni pentru tipul noului obiect. După selectarea tipului trebuie completate toate
câmpurile ce se găsesc mai jos:

-60-
• Center – poziția centrului obiectului nou creat
• Size – dimensiunea obiectului, în funcție de tipul obiectului trebuie completat
diferit
• Rotation – unghiul de rotație față de fiecare axă de coordonate
• Color – apăsarea acestui buton va deschide un dialog de tipul color chooser
pentru a alege culoarea obiectului; în dreapta butonului se afla un preview al
culorii ce a fost aleasă
• Has Mass – Aceasta căsuță de bifare specifică dacă la obiectul nou creat se va
adăuga implicit forța ce reprezintă gravitația
• Name – acest câmp nu este obligatoriu dar este de preferat să se completeze
pentru a face mai ușor căutarea obiectului în lista obiectelor existente

Pentru a continua cu adăugarea obiectului trebuie acționat butonul de adăugare, add


object.

În cazul în care se selectează modificarea unui obiect existent, în dreapta butonului radio
corespunzător lista se populează cu numele obiectelor existente la care se adaugă id-ul intern
pentru a nu avea elemente duplicate și pentru a putea identifica fiecare obiect în parte. După
selectarea obiectului dorit, toate câmpurile se încarcă cu valorile aferente obiectului. După
efectuarea modificărilor dorite folosind tot butonul add object se realizează salvarea obiectului și
modificarea scenei pentru a reflecta modificările aduse. De asemenea în acest caz avem acces la
butonul delete object pentru a șterge obiectul selectat.

Cel de-al doilea grup este denumit Forces și nu este activ, nu se poate modifica nici un
câmp, decât după selectarea unui obiect existent și deci salvat. În cazul în care avem selectat un
obiect existent din scena lista de selecție este încărcată cu toate forțele ce se aplică acelui obiect la
momentul respectiv.

Imediat după aceea se află câmpuri ce descriu o forță. Pentru a adăuga o forță trebuie
completate:
• Direction – direcția pe care noua forță va acționa
• Is Persistent – acest check box specidică dacă forța va fi luată în considerare la
fiecare pas sau numai ca un impuls inițial
• Name – un nume pentru a face căutarea mai facilă între forțele existente

După completarea acestor date pentru salvarea si adăugarea la obiectul selectat a noii
forțe trebuie acționat butonul Add Force.

Dacă se acționează selecția unei forțe deja existente în câmpurile mai sus menționatesunt
încărcate caracteristicile acelei forțe. Prin apăsarea butonului Add Force se realizează salvarea
modificărilor. De asemenea în acest caz avem acces și la butonul de ștergere a forței selectate.

• Actions Tab

-62-
Elementul central al acestui tab este TextBox-ul ce reține calea către fișierul unde se
salvează spațiul virtual sau de unde se încarcă acesta. Acesta poate fi editat manual, dacă
utilizatorului îi este mai la îndemână și dacă știe calea unde se află fișierul sau unde ar dori să se
salveze. Însă există grupul de controale File Operation care pune la dispoziția utilizatorului un
mod grafic de a realiza aceste operațiuni.

• Pentru a salva în fișier


Dacă nu este completat controlul ce arată calea de salvare se apasă butonul de Browse care
deschide un dialog de selectare a fișierului dorit. Acesta filtrează implicit informațiile afișate
astfel încât să fie vizibile doar fișierele de tip XML, dar există si posibilitatea de a modifica filtru
pentru a se afișa toate fișierele

saveFileDialog->DefaultExt = "xml";
saveFileDialog->AddExtension = true;
saveFileDialog->Filter = "Xml files (*.xml)|*.xml|All files (*.*)|*.*";

De asemenea la introducerea unui nume de fișier nu este nevoie introducerea și a


extensiei, aceasta fiind adăugată automat, deși pentru utilizatorii neîncrezători, introducerea
manuală a extensiei nu va modifica în nici un fel rezultatul.

-64-
După selectarea unui fișier corespunzător și apăsarea butonului Save se poate observa
completarea automata a câmpului de cale. Pentru a efectua salvarea propriu-zisă trebuie sa se
acționeze și butonul Save to File. În acest moment dacă fișierul exista, acesta va fi suprascris, în
caz contrar va fi creat.

În cazul în care această operațiune a mai fost efectuată, pentru salvări ulterioare în același
fișier se poate folosi doar butonul de Save to File facându-se suprascrierii informațiilor
precedente.

• Pentru a încărca din fișier

Înainte de a se putea încărca din fișier trebuie asigurat că în controlul de cale spre fișier
este introdusă o cale validă spre un fișier XML. Pentru a face acest lucru se apasă butonul Browse
corespunzător operațiunii de încărcare. La acționarea acestuia utilizatorului îi este prezentat un
dialog de selectare a fișierului dorit. De asemenea informația din acesta este filtrată dipă tipul de
fișier dorit, în cazul acesta, fișierele cu extensia .xml.

openFileDialog->DefaultExt = "xml";

openFileDialog->Filter = "Xml files (*.xml)|*.xml|All files (*.*)|*.*";

După acționarea butonului Open controlul de cale spre fișier este modificat astfel încât sa
conțină calea către fișierul nou selectat.

Pentru efectuarea încărcării trebuie acționat butonul Load from File după care se va
observa modificarea spațiului virtual corespunzător cu informațiile conținute în fișierul din care
s-a efectuat încărcarea.
În partea inferioară a panoului se afla un grup de butoane ce afectează scena virtulă și de
aceea sunt grupate sub numele de Scene Control. Butoanele sunt:

• Play – acționarea acestui buton produce efectual de a pune în mișcare obiectele conform
forțelor ce acționează asupra acestora.

• Stop – în orice moment acest buton poate fi acționat pentru a opri obiectele din scenă,
pentru a fi analizate mai de aproape ori pentru că s-a ajuns la un momentul dorit și
acțiunea dorită a fost deja observată.

-66-
• Reset – acționarea acestui buton este singura modalitate de a relua un experiment și de a
se întoarce la scena inițială.

• Properties Tab

Acest panou conține în partea superioară un grup de controale grupate sub denumirea de
Resistance. Aici se pot redefini două constante ce acționează asupra scenei:
• Air - forța de frecare cu aerul, insemnând valoarea care se scade din forța care
acționează asupra fiecărui obiect, implicit aceasta este de 1 pe toate cele trei axe
de coordonate.

• Floor – forța de frecare a suprafeței scenei, reprezentând valoarea care se scade


din forțele care acționează asupra fiecărui obiect atunci când este pe baza
scenei, implicit aceasta are valoarea de 3 pe toate axele de coordonate, deși pe
axa OY nu este necesară.

După completarea cămpurilor, pentru a se efectua modificările astfel încât sa se observe în


scenă trebuie acționat butonul de Update.

Sub acest grup se găsește un control glisant pentru viteza de deplasare în interiorul scenei.
Acesta este de fapt factorul cu care toate forțele ce se aplică în scena sunt înmulțite pentru a
obține efectul de încetinitor, sau de accelerator. Acest slider are un pas 0.2 și poate lua valori între
0.00001 și 2. Motivul pentru care nu se începe de la 0 este evident, factorul 0 însemnând anularea
tuturor forțelor, iar pentru aceasta este mai facilă folosirea butonului Stop.

Sub panoul de proprietăți se află o bară de status ce are rolul de a prezenta diverse
informații utilizatorului. De exemplu cel mai în stânga se găsește scris statusul scenei, dacă este
oprită mișcarea sau dacă modul este Playing.

Imediat după această informație este afișat un număr. Acest reprezintă valoarea
multiplicatorului de viteză.

-68-
5 Concluzii

Prin descrierea lumii în care trăim într-un mod riguros putem să cream cu ajutorul
calculatorului o lume virtuală care să ne ajute să înțelegem mai bine ceea ce se petrece în jurul
nostru. OpenGL folosește pentru afișarea punctelor un spațiu proiectiv pentru ca trebuie să redea
pe o suprafață plană o lume tri-dimensională. Doar datorită matematicii s-a putut realiza această
iluzie. Deci folosind un suport matematic s-a creat o lume virtuală și folosind aplicații ale
matematicii în lumea reală, din domeniul fizicii, putem simula realitatea noastră.

Acest lucru este complex și de aceea aplicația este realizată astfel încât să fie ușor de
extins, separând partea funțională de cea a interfeței utilizatorului. Principalul avantaj este
existența unui prototip de obiect, acesta putându-se extinde pentru a simula orice obiect foarte
ușor, datorită funcționalității incluse în acesta. Dezvoltatorul ce extinde această clasă nu este
scutit însă de anumite calcule și de implementare de funcționalități, însă munca acestuia este
înlesnită.
6 Bibliografie

1. Stupariu Sorin - Curs de Geometrie, Facultatea de Matematică și Informatică


Universitatea din București

2. Stupariu Sorin – Concepte geometrice în grafica pe calculator, Facultatea de


Matematică și Informatică Universitatea din București

3. OpenGL Architecture Review Board, Dave Shreiner, Mason Woo, Jackie Neider,
Tom Davis - OpenGL Programming Guide: The Official Guide to Learning OpenGL, Version 2.1
(cunoscută și sub numele de OpenGL Red Book)

4. Christopher Tremblay - Mathematics for Game Developers

5. David M Bourg - Physics for Game Developers

6. Eric Lengyel - Mathematics for 3D Game Programming and Computer Graphics

7. nehe.gamedev.net – turoriale OpenGL

8. http://www.codeproject.com/KB/miscctrl/OpenGLViewWinForms.aspx – tutorial
de îmbinare a OpenGL-ului cu Windows Forms

9. msdn.microsoft.com – informatii despre Visual Studio si Managed C++

-70-