Sunteți pe pagina 1din 197

UNIVERSITATEA DIN BACU

FACULTATEA DE INGINERIE









Culea George Gbureanu Ctlin







PRELUCRARE GRAFIC
Note de curs - laborator
























Editura Alma Mater Bacu
2007


































3






1 ELEMENTE INTRODUCTIVE


1.1 Sistemul grafic OpenGL


Grafica cu calculatorul (n special grafica 3D i n particular grafica interactiv
3D) i caut propriul drum ntr-un numr n cretere de aplicaii, de la programe de
grafic simple pentru calculatoare personale pn la software de modelare i vizualizare
sofisticat pentru staii grafice i supercalculatoare. Deoarece a crescut interesul pentru
grafica cu calculatorul, a crescut de asemenea i dorina de a fi capabil s scrii aplicaii
care pot rula pe o varietate de platforme cu un domeniu de capaciti grafice. Un
standard grafic uureaz aceast sarcin prin eliminarea nevoii de a scrie un driver
grafic distinct pentru fiecare platform pe care ruleaz aplicaia.
Pentru a fi viabil, un standard grafic propus pentru aplicaii interactive 3D trebuie
s satisfac cteva criterii. El trebuie s fie implementabil pe platforme cu capaciti
grafice diferite fr compromiterea performanelor grafice. El trebuie s asigure o
interfa natural care permite unui programator s descrie operaiile de redare ntr-un
mod concis. n final, interfaa trebuie s fie suficient de flexibil pentru a gzdui extensii
astfel nct dac noi operaii grafice devin semnificative sau disponibile n noile
subsisteme grafice, aceste operaii s poat fi asigurate fr fragmentarea interfeei.
OpenGL (Open Graphics Library) ndeplinete aceste criterii prin asigurarea unei
interfee simple, directe pentru operaiile fundamentale de redare grafic 3D. El permite
primitive grafice de baz cum ar fi punctele, segmentele de dreapt, poligoanele i
imaginile, precum i operaii de redare de baz cum ar fi transformrile afine i proiective i
calculele de iluminare. El permite de asemenea operaii de redare avansat cum ar fi
maparea texturilor i redarea cu antialiasing.
OpenGL este o interfa software pentru plcile grafice. OpenGL se bazeaz pe
IrisGL dezvoltat de Silicon Graphics (SGI). Scopul iniial al dezvoltrii IrisGL a fost de a
dezvolta o interfa programabil pentru staiile grafice SGI. Aceast interfa
programabil s-a intenionat iniial a fi independent de hardware i a ndeplini cerinele
speciale ale programrii grafice 3D. Ulterior IrisGL a devenit interesant i pentru alte
staii.
n 1992 a luat fiin OpenGL Architecture Review Board (ARB) printre ai crui
membrii se afl principalii productori de staii grafice cum ar fi SGI, Sun, Hewlett-
Packard, Microsoft, Evans&Sutherland, IBM, Intergraph. Site-ul ARB OpenGL poate fi
gsit la www.opengl.org. OpenGL a devenit un standard industrial, disponibil din anul
1992, pe baza specificaiilor realizate de acest consoriu independent. Scopul ARB este
de a controla dezvoltarea OpenGL, i de a introduce noi funcionaliti n versiunile
urmtoare. OpenGL evolueaz n mod continuu permind ca inovaiile la nivelul
hardware-ului s fie accesibile dezvoltatorilor de aplicaii prin mecanismul de extensii
4
OpenGL Adugrile la specificaii (prin extensii) sunt bine controlate de consoriul ARE
i actualizrile propuse sunt anunate din timp pentru a permite dezvoltatorilor s adopte
modificrile. Atunci cnd extensiile sunt larg acceptate, ele sunt luate n considerare
pentru includerea n nucleul de baz OpenGL. Este asigurat compatibilitatea cu
dezvoltrile anterioare ale bibliotecii astfel c aplicaiile mai vechi vor rula pe
acceleratoarele hardware cu drivere OpenGL mai noi.
Utilizatorii finali ai OpenGL, furnizorii independeni de software i ali realizatori
de aplicaii bazate pe APLuI OpenGL pot utiliza biblioteca fr cerine de licen.
OpenGL Performance Characterisation Committee, o alt organizaie independent,
creeaz i menine benchmark-urile OpenGL i public rezultatele acestor benchmark-uri pe
site-ul www.specbenc.org/gpc/opc.static/index.htinl.
OpenGL este portabil, fiind disponibil pe o varietate de sisteme cum ar fi PC,
Macintosh, Silicon Graphics, UNIX, Linux, Irix, Solaris, HP-UX OpenGL ruleaz pe
fiecare din principalele sisteme de operare incluznd MacOS, OS/2, UNIX, Windows95,
Windows NT, Linux, OPENStep, Python i BeOS. Lucreaz de asemenea cu fiecare
sistem de ferestre principal, incluznd Presentation Manager, Win32 i X/Window
System. OpenGL este practic disponibil pe aproape orice calculator care suport un
monitor grafic, o implementare OpenGL poate fi n mod eficient gzduit la aproape
orice nivel al hardware-ului grafic, de la memoria video de baz la cele mai sofisticate
subsisteme grafice. OpenGL poate fi apelat din limbajele de programare C, C++, Java,
FORTRAN i Ada i ofer independen complet fa de topologiile i protocoalele de
reea.
OpenGL este de asemenea scalabil deoarece poate rula pe o varietate de
calculatoare, de la cele personale pn la staii de lucru i supercalculatoare Aceasta se
realizeaz prin mecanismul OpenGL de cerere a capacitilor hardware.
OpenGL este bine structurat avnd o arhitectur intuitiv i comenzi logice (n
numr de cteva sute). Utiliznd comenzile OpenGL se pot scrie aplicaii avnd cteva
linii de cod spre deosebire de programele realizate utiliznd alte biblioteci. Una din
caracteristicile forte ale interfeei OpenGL este c interfaa sa este uor de utilizat de
ctre nceptori fiind n acelai timp suficient de puternic pentru a satisface cerinele
unor aplicaii profesioniste indiferent c acestea sunt simulatoare de zbor, animaii,
aplicaii de proiectare asistat sau vizualizri tiinifice. Driverele OpenGL ncapsuleaz
informaii despre substratul hardware, elibernd dezvoltatorul aplicaiei de necesitatea
de a scrie aplicaiile pentru anumite caracteristici hardware.



1.2 Sisteme grafice pentru grafica 3D


Pentru grafica 3D sunt disponibile cteva sisteme. Un sistem relativ bine cunoscut
este PHIGS (Programmer's Hierarchical Interactive Graphics System). Bazat pe GKS
(Graphics Kernal Systems), PHIGS este standard ANSI. PHIGS asigur modalitatea de a
manipula i a desena obiecte 3D prin ncapsularea descrierii obiectelor i a atributelor ntr-
o list de display care este apoi referit cnd obiectul este afiat sau manipulat. Un avantaj al
listei de display este c un obiect complex este descris doar o dat chiar dac este afiat de
mai multe ori. Aceasta este important n special dac obiectul de afiat trebuie transmis de-
5
a lungul unui canal de band joas (cum ar fi reeaua). Un dezavantaj al listei de display este
c poate cere un efort considerabil pentru respecificarea obiectului dac el este modificat
continuu ca rezultat al interaciunii cu utilizatorul. O alt dificultate cu PHIGS este lipsa
suportului caracteristic de redare avansat cum ar fi suportul pentru maparea texturilor.
PEX extinde sistemul de ferestre X (standard pentru staiile UNIX) pentru a
include posibilitatea de a manipula i desena obiecte 3D (PEXlib este API care asigur
protocolul PEX). Original bazat pe PHIGS, PEX permite redarea n mod imediat, ceea
ce nseamn c obiectele pot fi afiate dup ce sunt descrise, fr a fi necesar ca mai
nti s se complecteze o list de display. PEX de obicei nu permite caracteristici
avansate de redare, i este disponibil doar pentru utilizatorii X. n linii mari, metodele de
descriere a obiectelor grafice, pentru a fi redate utiliznd PEX sunt similare celor
OpenGL.
Ca OpenGL i PEXlib, RenderMan este o API care asigur o modalitate de redare
a obiectelor geometrice. Spre deosebire de aceste interfee, oricum, RenderMan asigur un
limbaj de programare (denumit shading language) pentru descrierea felului cum aceste
obiecte trebuie s apar Ia desenare. Aceast programabilitate permite generarea imaginilor
care arat foarte real, dar este de nepracticat pentru implementarea celor mai multe
acceleratoare grafice, fcnd din RenderMan o alegere slab pentru grafica interactiv
3D.
n final, exist API-uri care asigur accesul la redarea 3D ca un rezultat al
metodelor pentru descrierea obiectelor grafice de nivel ridicat. Liderii acestora sunt
HOOPS i IRIS Inventor. Obiectele asigurate de aceste interfee sunt de obicei mai
complexe dect primitivele geometrice simple descrise cu API-uri cum ar fi PEXlib sau
OpenGL; ele pot comprima nu doar geometria dar de asemenea i informaii despre cum
sunt ele desenate i cum reacioneaz la intrrile utilizatorului. HOOPS i Inventor
elibereaz programatorul de descrierea plicticoas a operaiilor de desenare individuale,
dar accesul simplu la obiecte complexe n general nsemnnd pierderea controlului fin
asupra redrii (sau cel puin fcnd un asemenea control dificil). n orice caz, OpenGL
poate asigura o baz bun pe care s se construiasc asemenea API-uri de nivel ridicat.
Caracteristicile de standardizare, stabilitate, fiabilitate, portabilitate, uurin n
utilizare i buna documentare fac din OpenGL un produs preferat naintea altor biblioteci
pentru realizarea vizualizrilor tiinifice, a mediilor virtuale, aplicaiilor
CAD/CAM/CAE, imagistic medical, jocuri, etc.
Cei mai renumii dezvoltatori de software utilizeaz OpenGL ca suport pentru
realizarea unor API de nivel mai nalt. Spre exemplu, Openlnventor asigur o interfa
cu utilizatorul care permite uurina realizrii aplicaiilor OpenGL. Iris Performer
extinde funcionalitatea OpenGL i permite caracteristici suplimentare create pentru
cerinele unei rate de remprosptare a imaginii mai mari necesare n simulri vizuale i
realitatea virtual. OpenGL Optimizer este un toolkit pentru interaciunea, modificarea
n timp real i redarea unor modele complexe cum ar fi cele din aplicaiile CAD/CAM.
Lista aplicaiilor realizate avnd la baz OpenGL este mare i ea cuprinde
aplicaii de modelare i animaie 3D (Maya, truSpace, 3D Studio Max, etc.), aplicaii
CAD/CAM (CATIA, 3D Studio Viz, Pro/ENGINEER, I-DEAS, etc), simulri vizuale i
realitate virtual (Visualisation Data Explorer, WorldToolKit, Designer, Workbranch,
etc.), playere VRML {Cosmo World, RenderSoft VRML Editor, etc.), jocuri (Quake2,
X-Plane, Unreal, etc.).
6
Pentru a ine pasul cu inovrile la nivelul hardware-ului, fr ns a fora
programatorii s lucreze n limbaj de asamblare, soluia oferit de firmele din domeniul
grafic este un limbaj de nivel nalt pentru OpenGL - OpenGL Shading Language (sau
GLslang), independent de hardware, uor de utilizat, suficient de puternic pentru a trece
testul timpului i care va reduce drastic nevoia de extensii. Continund tradiia de
compatibilitate "backwards", pe care au avut-o toate cele patru versiuni OpenGL,
OpenGL 2.0 va fi un superset al lui OpenGL 1.4, astfel c aplicaiile mai vechi vor rula
pe acceleratoarele hardware cu drivere OpenGL 2.0 fr modificri.




1.3 Caracteristici OpenGL


Dei specificaia OpenGL definete un anumit flux de procesare grafic,
furnizorii de platforme au libertatea de a realiza o implementare OpenGL particular
pentru a ndeplini obiective de performan i de cost al sistemului unice. Apelurile
individuale OpenGL pot fie executate de hardware dedicat, pot rula ca rutine software
pe sisteme standard CPU, sau pot fi imlementate ca o combinaie de rutine hardware i
software. Dezvoltatorii de aplicaii au garania unor rezultate de afiare consistente
indiferent de implementarea OpenGL.
OpenGL permite dezvoltatorilor de software accesul la primitive geometrice i
imagine, liste de display, transformri de modelare, iluminare i texturare, antialiasing,
blending i multe alte faciliti.
Din punctul de vedere al programatorului, OpenGL reprezint un set de comenzi
care permit specificarea obiectelor geometrice n dou sau trei dimensiuni, mpreun cu
comenzi care controleaz felul n care aceste obiecte sunt rasterizate n buffer-ul cadru
(framebuffer). Pentru cele mai multe din aceste comenzi, OpenGL asigur o interfa cu
efect imediat, n sensul c specificarea unui obiect determin desenarea sa.
OpenGL conine o mare cantitate de informaii de stare. Aceast stare controleaz
modul n care sunt desenate obiectele n framebuffer. OpenGL se afl totdeauna ntr-o stare
definit, setat prin variabile de condiie; aceasta nseamn c OpenGL este o maina de
stare. Un exemplu de variabil de condiie este culoarea curent cu care sunt redate
(desenate) primitivele individuale. Aceasta este setat utiliznd comanda glcolor() i apoi
culoarea setat se aplic tuturor obiectelor care se deseneaz, pn cnd este utilizat o
nou comand de modificare a culorii. La un anumit moment, o parte din aceast stare -
chiar i coninutul unei texturi i al memoriei video - este disponibil n mod direct
utilizatorului, care poate utiliza comenzi pentru a obine valori asociate cu diferite informaii
de stare. O parte a informaiilor de stare sunt vizibile, ns, doar prin efectul pe care l au
asupra a ceea ce se deseneaz.
OpenGL permite de asemenea aplicaii de vizualizare cu imagini 2D tratate ca
tipuri de primitive care pot fi manipulate la fel ca i obiectele geometrice 3D. OpenGL
dispune de unmai 10 primitive geometrice, i orice obiect care se deseneaz n OpenGL
este compus din aceste primitive. Setul de instruciuni din bibliotec conine cteva sute
de comenzi, toate fiind prefixate de gl. OpenGL asigur controlul direct asupra
operaiilor fundamentale de grafic 3D i 2D. Aceste operaii includ specificarea unor
7
parametrii cum ar fi matricele transformrilor, coeficienii ecuaiilor de iluminare,
operatori pentru actualizarea pixelilor. El nu asigur o modalitate pentru descrierea sau
modelarea obiectelor geometrice complexe (cum ar fi cilindrul, cubul, sfera, etc.). Altfel
spus, OpenGL asigur mecanismele pentru a descrie cum sunt redate obiectele
geometrice complexe i nu mecanismele de a descrie obiectele complexe nsele.
Toate corpurile complexe trebuie s fie construite de dezvoltatorul aplicaiei 3D
pe baza primitivelor simple - puncte, linii, poligoane. Pentru a simplifica puin lucrurile
pentru dezvoltatorii de aplicaii, experii n grafica 3D au dezvoltat cteva biblioteci dintre
care cele mai importante sunt GLU (OpenGL Utility Library), GLUT (OpenGL Utility
Toolkit) sau echivalentul su Microsoft -GLAUX. GLU simplific lucrurile pentru crearea
calculelor de proiecie i pentru construirea suprafeelor complexe, reprezentnd printre
altele curbe i suprafee NURBS (Non-uniform-rational-B-splines). GLUT este un utilitar
independent de sistem pentru manevrarea n mod simplu a ferestrelor OpenGL i pentru
furnizarea dezvoltatorului de aplicaii de rutine pentru controlarea evenimentelor externe
provenite de la utilizator prin mouse sau tastatur.
Oricine dorete s devin expert n grafica 3D trebuie s se familiarizeze cu
cteva noiuni fundamentale de algebr i geometrie analitic. Altfel utilizarea
comenzilor OpenGL se face mecanic fr o profund nelegere a mecanismelor interne.
Aceste noiuni sunt calculul vectorial (produs scalar, produs vectorial), calcul matricial
(nmulirea matricelor, matrice identitate), transformri geometrice. Sunt de asemenea
necesare cteva cunotine din domeniul opticii. Cei interesai pot s i remprospteze
aceste cunotine i din cri care prezint fundamentele graficii cu calculatorul.
Un program tipic care utilizeaz OpenGL ncepe cu deschiderea unei ferestre n
framebuffer-ul n care programul va desena. Apoi, se apeleaz funcii pentru alocarea
unui context GL i asocierea sa cu fereastra. Odat ce contextul OpenGL este alocat,
programatorul este liber s dea comenzi OpenGL. Unele comenzi sunt utilizate pentru
desenarea obiectelor geometrice simple (cum ar fi puncte, segmente de dreapt i
poligoane), n timp ce altele au efect asupra redrii acestor primitive inclusiv a felului
cum sunt iluminate, colorate i a modului n care spaiul modelului utilizatorului este
mapat la ecranul bidimensional. Sunt i comenzi care controleaz efectiv framebuffer-ul,
cum ar fi citirea i scrierea pixelilor.
Din punctul de vedere al implementatorului, OpenGL este un set de comenzi
care au efect asupra felului n care opereaz hardware-ul grafic. Dac hardware-ul const
doar dintr-un framebuffer adresabil, atunci comenzile OpenGL trebuie s fie
implementate n ntregime software, de CPU-ul calculatorului gazd. Tipice pentru acest
moment sunt ns plcile grafice care conin acceleratoare grafice variind de la cele cu un
subsistem de redare capabil s redea linii i poligoane 2D pn la procesoare n virgul
mobil sofisticate capabile de transformri i calcule asupra datelor geometrice. Sarcina
implementatorului este de a asigura interfaa software CPU astfel nct pentru fiecare
comand OpenGL s se divid sarcinile ntre CPU i placa grafic. Pentru a se obine un
optim al performanei n executarea comenzilor OpenGL, aceast diviziune trebuie s fie
n concordan cu placa grafic disponibil.





8



2 BAZELE PROGRAMRII N OPENGL


2
2.1 Arhitectura OpenGL


OpenGL deseneaz primitive ntr-o memorie video, subiectul a numeroase
moduri selectabile. O primitiv poate fi un punct, segment de dreapt, poligon sau
bitmap. Fiecare mod poate fi modificat independent; setarea unuia nu afecteaz setarea
altora (dei pot interaciona n mai multe moduri pentru a determina ceea ce se produce
n final n memoria video). Modurile sunt setate, primitivele specificate i celelalte
operaii OpenGL sunt descrise prin intermediul comenzilor, n forma apelurilor de
funcii sau proceduri.



















Figura 2.1 Schema fluxului de procesare OpenGL

Figura 2.1 arat schema fluxului de procesare OpenGL. Modelul de interpretare
a comenzilor de ctre OpenGL este client-server. Aceasta nseamn c programul
(client) d comenzile i aceste comenzi sunt procesate i interpretate de OpenGL
(server). Server-ul poate sau nu s opereze pe acelai calculator cu client-ul.
Multe dintre comenzi pot fi acumulate n liste de display pentru o procesare
ulterioar. n cazul n care se lucreaz cu procesare imediat (deci fr liste de display)
comenzile sunt transmise prin fluxul de procesare OpenGL. Comenzile nu sunt altceva
dect apeluri de funcii i proceduri OpenGL.
D
a
t
e

v

r
f
u
r
i
D
a
t
e

p
i
x
e
l
i
Liste de
display
Evaluator
polinomial
Operaii
cu pixeli
Operaii pe
vrfuri
Asamblarea
primitivelor
Rasterizare
Memorare
textur
Operaii pe
fragment
Bufferul
de cadru
9
Primul stadiu de procesare asigur o modalitate eficient pentru aproximarea
curbelor i a suprafeelor curbe prin evaluarea funciilor polinomiale ale valorilor de la
intrare. Acest stadiu este parcurs doar de acele comenzi utilizate pentru reprezentarea
curbelor i a suprafeelor Bezier i spline. Urmtorul nivel opereaz asupra primitivelor
geometrice descrise prin coordonatele vrfurilor: puncte, segmente de dreapt i
poligoane. n acest stadiu vrfurile sunt transformate i iluminate, i primitivele sunt
decupate fa de volumul de vizualizare pentru a fi pregtite pentru nivelul urmtor -
rasterizarea.
Rasterizarea convertete o primitiv proiectat, scalat la viewport ntr-o serie de
fragmente. Fiecare fragment comprim pentru o locaie a unui pixel din memoria video -
culoarea, coordonatele de textur i adncimea (z). Rasterizarea produce o serie de
adrese i de valori pentru memoria video utiliznd descrierea 2D a unui punct, segment
de dreapt, sau poligon. Fiecare fragment astfel produs alimenteaz nivelul urmtor care
asigur operaii asupra fragmentelor individuale nainte ca ele s modifice memoria
video. Aceste operaii includ actualizri condiionale n memoria video pe baza noilor
valori sau a valorilor de adncime memorate anterior (pentru efectuarea testului de
ascundere), amestecarea culorilor fragmentelor cu culorile memorate, precum i
mascarea i celelalte operaii logice asupra valorilor din fragment.
Cnd este rasterizat un segment de dreapt sau un poligon, aceste date asociate
sunt interpolate de-a lungul primitivei pentru a obine o valoare pentru fiecare fragment.
Rasterizarea fiecrui tip de primitiv este controlat de un grup corespunztor de
parametrii (atribute de redare a primitivelor). Un atribut de lime afecteaz rasterizarea
punctului i un altul afecteaz rasterizarea segmentelor de dreapt. Suplimentar, se
poate specifica o secven stipple (stilul liniei -linie punctata, ntrerupt, etc.) pentru
segmentele de dreapt, i un model de haur pentru poligoane.
Antialiasing-ul poate fi activat sau dezactivat individual pentru fiecare tip de
primitiv. Cnd este activat, o valoare acoperitoare este calculat pentru fiecare fragment
ce descrie poriunea acelui fragment care este acoperit de primitiva proiectat. Aceast
valoare acoperitoare este utilizat dup ce texturarea a fost terminat pentru modificarea
valorii alfa a fragmentului (n modul RGBA) sau valorii color index (n modul index).
Procesarea pixelilor i a imaginilor trece peste seciunea de procesare a vrfurilor
din flux pentru a transmite un bloc de fragmente n mod direct prin blocul de rasterizare
spre blocul operaiilor pe fragmente individuale, determinnd eventual ca un bloc de
pixeli s fie scris direct n memoria video. Valorile pot fi de asemenea citite din
memoria video sau copiate dintr-o poriune a memoriei video n alta. Aceste transferuri
pot include unele tipuri de decodificri i codificri.
Se poate constata c exist dou fluxuri de date. Fluxul din partea de sus a
schemei este pentru primitivele bazate pe vertex-uri. Fluxul din partea de jos este pentru
primitive bazate pe pixeli - primitive imagine. Se poate spune c texturarea combin
cele dou tipuri de primitive.
Aa cum s-a mai artat, la modul general, sunt dou operaii principale care se pot
face utiliznd OpenGL:
- Se deseneaz ceva;
- Se modific starea (aspectul) a ceea ce se deseneaz.
n ceea ce privete obiectele pe care le putem desena cu OpenGL, i acestea sunt
de dou tipuri:
- Primitive geometrice;
10
- Primitive imagine.
Altfel spus, grafica pe care o putem realiza utiliznd OpenGL este att grafic
vectorial ct i grafic punctual. Primitivele geometrice pe care le poate reda OpenGL
sunt puncte, linii i poligoane. Primitivele imagine sunt bitmap-uri i imagini grafice
(adic pixeli care se pot extrage dintr-o imagine JPEG dup ce s-a citit aceast imagine
n program). Suplimentar, OpenGL prin maparea texturilor unete primitivele
geometrice cu cele imagine.
O alt operaie comun care se face asupra ambelor tipuri de primitive este setarea
strii. Setarea strii este procesul de iniializare al datelor interne, utilizate de OpenGL
pentru redarea primitivelor. Setarea poate fi o operaie simpl cum ar fi stabilirea dimensiunii
i culorii unui punct desenat dar i o operaie mai complicat cum ar fi iniializarea nivelelor
multiple pentru maparea texturilor.
Trebuie subliniat c dei primitivele geometrice pe care le poate reda OpenGL
nu sunt spaiale, n sensul c ele pot fi redate i n plan, totui OpenGL este o bibliotec
de grafic 3D. Ceea ce este deosebit n felul n care se deseneaz un punct ntr-o
bibliotec 2D, i felul n care se deseneaz un punct ntr-o bibliotec 3D sunt
coordonatele acestui punct. Bibliotecii 2D i se furnizeaz coordonate 2D, pe cnd
bibliotecii 3D i se furnizeaz coordonate 3D i prin mecanismele proieciei se face
transformarea din sistemul de coordonate 3D n 2D urmnd ca apoi primitivele s fie
redate pe dispozitivul de afiare.
Efectul comenzilor OpenGL asupra memoriei video este fundamental controlat de
sistemul de ferestre care aloc resurse de memorie video. Sistemul de ferestre este cel care
determin care poriuni ale memoriei video pot fi accesate de OpenGL la un anumit
moment de timp i tot el este cel care i comunic lui OpenGL cum sunt structurate acele
poriuni. n mod similar, afiarea coninutului memoriei video pe un tub CRT nu este
controlat de OpenGL (incluznd transformarea valorilor individuale din memoria video
prin asemenea tehnici, cum ar fi corecia gamma). Configurarea memoriei video are loc n
exteriorul OpenGL, n conjuncie cu sistemul de ferestre; iniializarea unui context OpenGL
are loc cnd sistemul de ferestre aloc o fereastr pentru redare OpenGL. Suplimentar,
OpenGL nu are faciliti de obinere a intrrilor de la utilizator, deoarece este de ateptat ca
sistemul de ferestre sub care ruleaz OpenGL s asigure asemenea faciliti. Aceste
considerente fac de fapt OpenGL independent de sistemul de ferestre.









2.2 Descriere general OpenGL, GLU i GLAUX



2 2. .2 2. .1 1 O Op pe en nG GL L U Ut ti il li it ty y L Li ib br ra ar ry y ( (G GL LU U) )

11
Un principiu de baz n proiectarea interfeei OpenGL a fost de a se asigura
portabilitatea unui program fr a se specifica ct de nalt s fie nivelul la care pot fi
descrise obiectele grafice. Ca rezultat, interfaa de baz OpenGL nu permite redarea
unor obiecte geometrice, care sunt asociate n mod tradiional cu standardele grafice.
Spre exemplu, implementarea OpenGL nu red poligoane concave. Un motiv ar fi c
algoritmii pentru redarea (umplerea) poligoanelor concave sunt mai compleci dect cei
pentru redarea poligoanelor convexe n particular, dac se red un poligon concav mai
mult de o dat este mai eficient s fie mai nti descompus n poligoane convexe (sau
triunghiuri) i apoi s se deseneze poligoanele convexe.
Un algoritm de descompunere a poligoanelor concave este asigurat ca parte a
bibliotecii GLU, care este asigurat pentru fiecare implementare OpenGL. GLU asigur
de asemenea o interfa, care se bazeaz pe evaluatorii polinomiali OpenGL, pentru
descrierea i afiarea curbelor i a suprafeelor NURBS (cu posibilitatea de segmentare
spaial), precum i o modalitate de reprezentare a cvadricelor (sferelor, conurilor, i a
cilindrilor). GLU este util att pentru redarea unor obiecte geometrice utile ct i pentru
exemplificarea modelului de construire a unei biblioteci care se bazeaz pe OpenGL
pentru redarea n memoria video.
Pentru a nu exista o imagine confuz asupra a ceea ce reprezint OpenGL trebuie
subliniat c OpenGL nu este un limbaj de programare ci aa cum s-a mai artat o API
(interfa pentru programarea aplicaiilor). Atunci cnd ne referim la o aplicaie OpenGL,
nelegem c aplicaia respectiv a fost scris ntr-un limbaj de programare (cum ar fi C) i
c apeleaz funcii OpenGL. Nu este obligatoriu ca o aplicaie s utilizeze doar pachetul de
funcii OpenGL pentru desenare. Simultan pot fi utilizate mai multe biblioteci grafice.
Spre exemplu se pot utiliza funciile OpenGL pentru partea de reprezentare 3D iar pentru
partea de grafic ce ine de interfaa aplicaiei s se utilizeze funciile grafice specifice
mediului cu care se lucreaz (spre exemplu interfaa GDI a Windows-ului).
Ca orice API, funciile OpenGL pot fi apelate dup conveniile de apel din C.
Deci apelarea bibliotecii din limbajul C nu constituie o problem. Apelarea din C++ a
funciilor API, se face n acelai mod ca din limbajul C, cu consideraii minore.
Funciile OpenGL pot fi de asemenea apelate din limbaje de tipul Visual Basic - care
pot apela funcii C.
Dei OpenGL este o interfa API puternic ce conine peste 300 funcii ea nu
are nici mcar o singur funcie pentru managementul ferestrelor i a ecranului. De
asemenea nu are funcii pentru manevrarea evenimentelor de la mouse i tastatur.
Motivul este clar - independena de platform. Crearea i deschiderea unei ferestre se
realizeaz n mod diferit n diferitele sisteme de operare.
Pentru a putea lucra, programele OpenGL necesit ns o interfa grafic bazat
pe ferestre. Deoarece OpenGL este independent de platform, este nevoie de o
modalitate de a integra OpenGL n fiecare sistem grafic bazat pe ferestre. Fiecare sistem
grafic bazat pe ferestre care suport OpenGL are funcii suplimentare API pentru
controlarea ferestrelor OpenGL, manevrarea culorilor i a altor caracteristici. Aceste
API-uri suplimentare sunt dependente de platform.



2 2. .2 2. .2 2 B Bi ib bl li io ot te ec ci i d di is sp po on ni ib bi il le e

12
Pentru crearea ferestrelor dar i pentru alte operaii necesare n realizarea
aplicaiilor grafice OpenGL, s-au creat biblioteci suplimentare cum ar fi GLAUX sau
GLUT (OpenGL Utility Toolkit). Trebuie spus c funciile puse la dispoziie de aceste
dou biblioteci sunt similare i c un utilizator care a nvat utilizarea uneia dintre
aceste biblioteci va utiliza cu uurin i cealalt bibliotec.
Pentru simplitatea programelor care exemplific OpenGL, noi vom utiliza
biblioteca GLAUX, care simplific interaciunea cu sistemul de ferestre i cu mouse-ul
sau tastatura. Unul dintre motivele pentru care am ales aceast bibliotec este faptul c
programele sunt implementate n Visual C (versiunea 6.0) i c acest mediu conine
biblioteca GLAUX precum i o serie de aplicaii pentru exemplificarea funciilor
OpenGL care se bazeaz pe biblioteca GLAUX. GLAUX este o bibliotec care face
scrierea programelor OpenGL, n partea legat de sistemul de ferestre mult mai uoar.
OpenGL este independent de sistemul de ferestre i de sistemul de operare. n felul
acesta, partea din aplicaia realizat cu OpenGL, care face redarea este de asemenea
independent de platform. Oricum pentru ca OpenGL s poat face redarea are nevoie
de o fereastr n care s deseneze. n general aceast fereastr este controlat de sistemul
de operare bazat pe ferestre cu care se lucreaz.
Pentru a putea integra OpenGL n diferitele sisteme grafice bazate pe ferestre
sunt utilizate biblioteci suplimentare pentru modificarea unei ferestre native ntr-una
capabil OpenGL. Fiecare sistem de gestionare a ferestrelor are propria sa bibliotec,
unic i funciile care fac acest lucru. Iat cteva astfel de biblioteci:
- GLX pentru sistemul X Windows, obinuit pe platformele Unix;
- AGL pentru Apple Macintosh;
- WGL pentru Miocrosoft Windows.
Pentru a simplifica programarea i dependena de sistemul de ferestre noi vom
utiliza biblioteca GLAUX. GLAUX este un toolkit pentru realizarea simpl a aplicaiilor
OpenGL. Biblioteca GLAUX simplific procesul crerii ferestrelor, al lucrului cu
evenimente n sistemul de ferestre i manevrarea animailor.
n general aplicaiile care necesit mai mult (adic butoane, meniuri, bare de
scroll, etc.) n realizarea interfeei cu utilizatorul, vor utiliza o bibliotec proiectat pentru
a realiza aceste caracteristici cum ar fi Motif sau Win32 API.
Aplicaiile prototip sau cele care nu necesit toate caracteristicile unei interfee
grafice cu utilizatorul complete, pot ns lucra cu GLAUX datorit modelului su de
programare simplificat i datorit independenei de sistemul de ferestre.




2.3 GLAUX


Iniial biblioteca GLAUX a fost creat ca un toolkit pentru a permite nvarea
OpenGL fr a intra n detaliile unui anumit sistem de operare sau de interfa cu
utilizatorul., Pentru aceasta GLAUX conine funcii pentru crearea ferestrelor i pentru
citirea intrrilor de la mouse i de la tastatur. Intern aceste funcii utilizeaz funciile
API ale mediului n care se lucreaz. Modul de apelare al funciilor GLAUX rmne ns
acelai pentru toate platformele. Dei are doar cteva funcii pentru crearea ferestrelor,
13
biblioteca GLAUX scutete utilizatorul de sarcina de a utiliza funciile Windows API
care realizeaz acest lucru. Dei nu face parte din specificaia OpenGL, biblioteca
GLAUX este implementat pentru fiecare platform pentru care se implementeaz
OpenGL. Windows-ul nu face excepie de la acest lucru, i biblioteca GLAUX este
inclus free n Win32 SDK de la Microsoft. Dac mediul de programare n care se
lucreaz nu conine biblioteca GLAUX ea poate fi obinut free de la MicrosoftWin32
SDK.
n afara funciilor pentru ferestre i pentru manevrarea evenimentelor de la
tastatur biblioteca GLAUX conine o serie de funcii pentru desenarea unor obiecte 3D:
sfera, cubul, torul i chiar un ceainic, etc.
Programele scrise cu GLAUX-ul pot fi mutate, prin recompilare pe diverse
medii. Suplimentar acestor funcii principale biblioteca GLAUX implementeaz cteva
funcii pentru a permite operaii specifice sistemului cum ar fi inversarea buffer-elor i
ncrcarea imaginilor. Utilizarea lor poate face ns programele neportabile.
Toate exemplele i aplicaiile din aceast carte sunt scrise n C. Pentru C, exist
cteva elemente necesare pe care trebuie s le fac o aplicaie:
- Fiierele header aa cum se tie, conin prototipurile tuturor funciilor apelate,
parametrii acestora, definirea valorilor constante. Aplicaiile OpenGL trebuie s includ
fiierele header OpenGL, GLU i GLAUX (gl.h, glu.h, glaux.h).
- Proiectele aplicaiei trebuie s includ cele trei biblioteci care vor fi legate (la
linkeditare) de aplicaie (opengl32.1ib, glu32.1ib i glaux.lib).
- Bibliotecile sunt dependente de implementarea OpenGL pentru sistemul de
operare pe care se lucreaz. Fiecare sistem de operare are propriile sale biblioteci.
Pentru sistemul Unix, biblioteca
OpenGL este de obicei denumit libGL.so i pentru Microsoft Windows este
denumit opengl32. lib.
Funciile celor trei biblioteci pot fi recunoscute dup prefixele lor: gl pentru
OpenGL, glu pentru GLU i aux pentru GLAUX. Tipurile enumerare (enumerated
types) sunt definiii OpenGL pentru tipurile de baz (adic float, double, int, etc.)
utilizate de program pentru definirea variabilelor. Pentru a se simplifica independena de
platform a programelor OpenGL, se definete un set complet de tipuri enumerated
types. Este indicat s se utilizeze aceste tipuri pentru a se simplifica transferarea
programelor pe alte sisteme de operare.
n continuare se d structura de baz care va fi utilizat ntr-o aplicaie.
- Se configureaz i se deschide fereastra
- Se iniializeaz starea OpenGL
- Se nregistreaz funciile callback
- Redare
- Redimensionare
- Intrri: tastatur, mouse, etc.
- Bucla de procesare a evenimentelor de intrare.
n general, acetia sunt paii ntr-o aplicaie OpenGL, pai pe care i detaliem n
continuare.
1) Se alege tipul de fereastr necesar pentru aplicaie i se iniializeaz fereastra.
2) Se iniializeaz starea OpenGL care nu este necesar a fi modificat n fiecare
poriune din program. Asemenea operaii pot fi setarea culorii background-ului, poziia
surselor de lumin, setri pentru texturare.
14
3) Se nregistreaz funciile callback utilizate de aplicaii. Funciile callback sunt
rutine scrise de programator pe care GLAUX-ul le apeleaz la apariia anumitor
evenimente, cum ar fi remprosptarea ferestrei, micarea mouse-ului de ctre utilizator.
Cea mai important funcie callback este cea de redare a scenei.
4) Se introduce bucla principal de procesare a evenimentelor. Aici aplicaia
recepioneaz evenimentele, i se programeaz cnd anume sunt apelate funciile
callback.

Exemplu

Structura unui program simplu se exemplific n continuare;
Programul afieaz un ptrat pe care l translateaz pe axa x la apsarea sgeilor
stnga, dreapta.

#include "glos.h"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void myinit(void);
void CALLBACK display(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK MutaStanga(void);
void CALLBACK MutaDreapta(void);
static GLfloat x=0;
void myinit (void) {
glClearColor(1.0, 1.0,1.0, 1.0);
}

void CALLBACK MutaStanga(void)
{
x=x-10;
}
void CALLBACK MutaDreapta(void)
{
x=x+10;
}
void CALLBACK display (void)
{
glClear(GL_COLOR_BUFFER_BIT);

glLoadIdentity ();
glTranslatef(x, 0.0, 0.0);
glBegin(GL_QUADS);
glBegin(GL_QUADS);
glColor3f (1.0, 0.0, 0.0);
glVertex2f(100.0,100.0);
15
glColor3f (0.0, 1.0, 0.0);
glVertex2f(150.0,100.0);
glColor3f (0.0, 0.0, 1.0);
glVertex2f(150.0,150.0);
glColor3f (1.0, 1.0, 0.0);
glVertex2f(100.0,150.0);
glEnd();
glFlush();
}

/*void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho (-160.0, 160.0, -160.0,
160.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}*/

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-160.0, 160.0, -160.0*(GLfloat)h/(GLfloat)w,
160.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-160.0*(GLfloat)w/(GLfloat)h,
160.0*(GLfloat)w/(GLfloat)h, -160.0, 160.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300, 200);
auxInitWindow ("Un patrat care se translateaza pe axa x");
myinit ();
auxKeyFunc (AUX_LEFT, MutaStanga);
auxKeyFunc (AUX_RIGHT, MutaDreapta);
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
16
}

Marea majoritate a programelor din aceast carte se bazeaz pe acest model.
Pentru a obine fiierul executabil plecnd de la aceast surs, n mediul Visual C 6.0,
parcurgei paii urmtori:
- Se editeaz programul.
- Se compileaz programul (Build/ Compile). La compilare se va ntreba dac
se dorete crearea workspace-ului. Se va rspunde cu yes.















Figura 2.2
- Se introduce n proiect bibliotecile opengl32.1ib, glu32.1ib, glaux. lib
(Project / Settings / Link / Project Options)
- Se construiete fiierul executabil i se ruleaz aplicaia (Build/Execute...)
Programul afieaz pe un background alb un ptrat care la apsarea sgeilor
stnga/dreapta poate fi deplasat (figura 2.2).
Se poate remarca n codul aplicaiei utilizarea att a funciilor GLAUX ncep cu
aux) ct i a celor OpenGL (ncep cu gl).
Win32 permite crearea unei ferestre grafice dintr-o aplicaie n mod consol.
Aceste detalii sunt acoperite de biblioteca GLAUX, creat tocmai pentru a ascunde aceste
detalii de platform. Spre exemplu aplicaia urmtoare nu face altceva dect s creeze o
fereastr i s atepte apoi introducerea unei taste.

/* Programul afieaz o fereastr i ateapt introducerea unei taste dup care se
nchide fereastra */
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <conio.h>

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
17
auxInitPosition (50, 50, 200, 200);
auxInitWindow ("Deschiderea unei ferestre intr-o aplicatie consola");
cprintf("Apasati o tasta pentru inchiderea ferestrei\n");
getch();
return(0);
}
Fereastra va fi afiat i la introducerea unei taste n fereastra consol se va
nchide aplicaia (figura 2.3)












Figura 2.3

S vedem cum este scris funcia principal a aplicaiei: main().
Funciile auxlnitDisplayMode(), auxinitPosition() j auxInitWindow() fac parte din pasul
de configurare a ferestrei. Folosind funcia auxinitDisplayMode() se specific diverse
informaii privitoare la buffer-ele utilizate de fereastra aplicaiei - dac se folosete
modelul de culoare RGBA sau index, dac se folosesc unul sau dou buffer-e de
culoare, dac fereastra are sau nu asociate buffer-e de adncime, buffer ablon sau/i
buffer de acumulare.
void auxInitDisplayMode(GLbitfield mask);
Argumentul mask este un SAU la nivel de bit ntre AUX_RGBA (modelul de
culoare RGBA), AUX_INDEX (modelul de culoare index). AUX_SINGLE (un buffer de
culoare), AUX_DOUBLE (dou buffer-e de culoare). AUX_DEPTH (buffer de
adncime), AUX_STENCIL (buffer ablon). AUX_ACCUM (buffer de acumulare).
Valorile implicite sunt pentru modelul de culoare index, cu un singur buffer de culoare.
n exemplul de mai sus, ferestrei i se va asocia un singur buffer de culoare i
modelul de culoare va fi RGB. Poziia ferestrei pe ecran: colul stnga-sus al ferestrei va
fi poziionat la pixelul (0,0) al ecranului. Dimensiunea ferestrei este de 300 pixeli pe
lime i de 200 pixeli pe nlime.
Prototipul funciei care specific aceti parametrii este;
auxInitPosition (GLint x, Glint y, Glsizei width, Glsizei heigth);

Se remarc faptul c poziia colului stnga-sus este specificat n coordonatele
ecranului. Sistemul de coordonate al ecranului este figurat de cele dou axe de
coordonate. Funcia auxInitWindows() creeaz fereastra i specific titlul afiat pe bara
de titlu. Dac aplicaia s-ar rezuma doar la funcia main() care ar include doar funciile
comentate pn n acest moment rezultatul ar fi afiarea pe ecran a unei ferestre de
18
culoare neagr care ar i disprea imediat fr a se mai ntmpla nimic altceva. n
exemplu, se apeleaz n continuare funcia myinit () care conine setrile proprii fiecrei
aplicaii, n general este vorba de acele setri care se fac o singur dat n program. n
cazul programului nostru n funcia myinit() s-a setat culoarea de tergere a ecranului,
tergere care se realizeaz odat cu apelarea funciei
glClear(GL_COLOR_BUFFER_BlT) din funcia display. Urmtoarele 4 funcii
nregistreaz rutinele callback, rutine care se definesc n cadrul programului. Este vorba
de nregistrarea rutinelor MutaStanga(), MutaDreapta(), my/Reshape() i display().
Funcia auxMainLoop() pe lng faptul c nregistreaz funcia callback display() este i
bucla de procesare a evenimentelor, care interpreteaz evenimentele i apeleaz rutinele
callback scrise de programator.


2 2. .3 3. .1 1 F Fu un nc c i ii il le e c ca al ll lb ba ac ck k G GL LA AU UX X

GLAUX-ul utilizeaz mecanismul callback pentru a realiza procesarea
evenimentelor. Utiliznd acest mecanism se simplific procesarea evenimentelor pentru
dezvoltatorul aplicaiei. Comparnd cu programarea tradiional de manevrare a
evenimentelor, n care autorul trebuia s recepioneze i s proceseze fiecare eveniment,
i s apeleze aciunile necesare, mecanismul callback simplific procesul prin definirea
aciunilor care sunt suportate, i manevrarea automat a intrrilor dinspre utilizator. Tot
ce trebuie s fac programatorul este s scrie codul pentru ceea ce se ntmpl cnd are
loc evenimentul.
GLAUX permite mai multe tipuri de funcii callback, incluznd:
- auxMainLoop() - apelat cnd trebuie s fie remprosptai pixelii din
fereastr.
- auxReshapeFunc () - apelat cnd fereastra i modific dimensiunea.
- auxKeyFunc () - apelat cnd se apas o tast la tastatur.
- auxMouseFunc () - apelat cnd utilizatorul apas sau relaxeaz butonul
mouse-ului
- auxidleFunc() - apelat cnd nu se ntmpl nimic altceva. Funcia este foarte
util n animaii.

Funcia callback pentru redare
n rutina principal a exemplului anterior apare urmtorul apel:
auxMainLoop(display);
Tot ceea ce se deseneaz se scrie n funcia display () (n cazul nostru) nregistrat
de funcia auxMainLoop(). Funcia callback display() este una dintre cele mai
importante funcii callback. Funcia display() este apelat atunci cnd este necesar a se
remprospta coninutul ferestrei. Acesta este motivul pentru care tot ceea ce se deseneaz
trebuie programat aici. Pe scurt, funcia display(), din aplicaia noastr, red un ptrat.
Deoarece pentru fiecare vrf al ptratului s-a specificat alt culoare i deoarece n mod
implicit n OpenGL este setat modelul de umbrire Gouraud, care interpoleaz
intensitile vrfurilor, ptratul va fi desenat cu o combinaie a culorilor specificate pentru
fiecare vrf Se va studia fiecare funcie OpenGL detaliat, n capitolele urmtoare.
Funcia glFlush() determin ca orice funcie OpenGL neexecutat pn n acest
moment s fie executat n momentul apelului glFlush. n aceast situaie se afl, n
19
cazul nostru, toate apelurile din display(). Intern OpenGL utilizeaz un flux de redare
care proceseaz comenzile n mod secvenial. Deseori comenzile OpenGL sunt reinute
pn cnd server-ul OpenGL proceseaz mai multe comenzi deodat. Desenarea este
accelerat deoarece hardware-ul grafic lent este deseori accesat mai puin pentru un set
dat de instruciuni de desenare.
Se va exemplifica funcia auxKeyFunc() care n funcia principal a programului
a fost apelat sub forma:
auxKeyFunc (AUX_LEFT, MutaStanga);
Funcia auxKeyFunc() asociaz apsarea tastei - sgeat stnga - cu funcia
MutaStanga(). Funcia MutaStanga() din aceast aplicaie este:
void CALLBACK MutaStanga(void)
{ x=x-10;)
Rezultatul este c la apsarea tastei <, variabila x va fi modificat, n
consecin, se va redesena fereastra iar funcia de translaie glTranslatef() din display()
va determina deplasarea ptratului spre stnga cu 10 uniti.

Exemplul de mai sus arat o modalitate de tratare a evenimentelor de la utilizator.
Cele dou proceduri nregistrate n acest caz trateaz intrrile de la tastatur: sgeat
stnga , sgeat dreapta . GLAUX permite intrri de la utilizator prin mai multe
dispozitive de intrare cum ar fi tastatura, mouse-ul, etc.

Funcia pentru redimensionarea ferestrei
Funcia callback myReshape() este apelat atunci cnd se redimensioneaz
fereastra. Funcia este nregistrat de funcia:
auxReshapeFunc (myReshape);
S presupunem c nu am include n aplicaie aceste funcii. Rezultatul este artat
n figura 2.6. n figura 2.7 s-a redimensionat fereastra. Se poate ns constata c poziiile
n pixeli ale ptratului nu s-au modificat. Trebuie specificat c n fereastra OpenGL
pixelul (0, 0) se afl n colul stnga jos al ferestrei i orientarea axelor este cea din figura
2.4, n cazul n care nu se definete funcia MyReshape().
















Figura 2.4 Un ptrat care se translateaz pe axa x
100
100
(150,150)
20

Rolul funciei myReshape este pentru redimensionarea ferestrei. La aplicarea
funciei coninutul ferestrei este redesenat, lund n considerare noile dimensiuni. Sunt
cazuri n care la redimensionarea ferestrei se dorete ca desenul s nu-i modifice
dimensiunile ci s fie decupat n cazul micorrii ferestrei i afiat la dimensiunea real n
cazul lrgirii acesteia. n alte cazuri, cum este de altfel i cazul aplicaiei noastre ne dorim ca
la micorarea ferestrei s fie proporional modificate i dimensiunile desenului.

Funcia auxIdIeFunc
Biblioteca GLAUX asigur o funcie care permite realizarea animailor. Aceast
funcie, auxidleFunc(ldleFunction) nregistreaz funcia idleFunction() care este apelat
n mod continuu n timp ce programul este n ateptare, mai puin n situaiile n care
fereastra este mutat sau redimensionat. Iat un exemplu de scriere a funciei
idleFunction().
void CALLBACK IdleFunction (void)
{ t+=dt;
display(); }
Funcia actualizeaz o variabil i apoi apeleaz funcia de desenare. Animaia
necesit abilitatea de a desena o secven de imagini. Funcia auxidleFunc() este
mecanismul pentru realizarea animailor. Programatorul nregistreaz prin aceast
funcie o rutin care actualizeaz variabilele de micare (de obicei variabile globale care
controleaz cum se mic obiectele) i apoi cere ca scena s fie actualizat. Funcia
IdleFunction() cere ca funcia nregistrat prin auxMainLoop()-display(), s fie apelat
ct de repede posibil. Aceasta este de preferat apelrii n mod direct a rutinei de redare,
deoarece este posibil ca utilizatorul aplicaiei s fi interacionat cu aplicaia i s fie
necesar ca s fie procesate evenimentele de intrare.
Exemplu:
Exemplul urmtor (figura 2.5) arat un exemplu de utilizare a funciei
auxidleFunc().












Figura 2.5

#include "glos.h"

#include <GL/gl.h>
#include <GL/glu.h>
21
#include <GL/glaux.h>

void myinit(void);
void CALLBACK display(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK IdleFunction(void);

void myinit (void) {
glClearColor(1.0, 1.0,1.0, 1.0);
glColor3f(0.0,0.0,0.0);
}

void CALLBACK display (void)
{
glClear(GL_COLOR_BUFFER_BIT);
auxWireCube(100);
glFlush();
}

void CALLBACK IdleFunction(void)
{
glRotatef(30,1,1,1);
display();
Sleep(300);
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-160.0, 160.0, -160.0*(GLfloat)h/(GLfloat)w,
160.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-160.0*(GLfloat)w/(GLfloat)h,
160.0*(GLfloat)w/(GLfloat)h, -160.0, 160.0, -80.0, 80.0);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300, 200);
auxInitWindow ("Un cub care se roteste");
myinit ();
22
auxReshapeFunc (myReshape);
auxIdleFunc(IdleFunction);
auxMainLoop(display);
return(0);
}

Funcii GLAUX pentru desenarea primitivelor 3D
n exemplul anterior s-a constatat c s-a utilizat o funcie GLAUX pentru
desenarea unui cub wireframe avnd latura de 100 de uniti - auxWireCube(100).
Dimensiunea unei uniti n pixeli fiind cea specificat n funcia myReshape().
Biblioteca GLAUX dispune de funcii pentru desenarea i a altor corpuri 3D. n
continuare vom enumera aceste funcii.
- void auxSolidBox(Gldouble width, Gldouble height, Gldouble depth);
permite desenarea unui paralelipiped, centrat n origine, pentru care se
specific limea, nlimea i adncimea. Paralelipipedul are atribut de
umplere.
- void auxWireBox(Gldouble width, Gldouble height, Gldouble depth);
similar cu auxSolidBox() dar wireframe (doar cu atribut de contur).
- void auxSolidCube(Gldouble width); permite desenarea unui cub, centrat n
origine, pentru care se specific latura. Cubul are atribut de umplere.
- void auxWireCube(Gldouble width); similar cu auxSolidCube() dar
wireframe (doar cu atribut de contur).
- void auxSolidTetrahedron(Gldouble radius); permite desenarea unui
tetraedru (poliedru cu 4 fee, feele sunt triunghiulare), centrat n origine,
pentru care se specific raza. Corpul are atribut de umplere.
- void auxWireTetrahedron(Gldouble radius); similar cu
auxSolidTetrahedron() dar wireframe (doar cu atribut de contur).
- void auxSolidOctahedron(Gldouble radius); permite desenarea unui
octaedru (poliedru cu 8 fee, feele sunt triunghiulare), centrat n origine,
pentru care se specific raza. Corpul are atribut de umplere.
- void auxWireOctahedron (Gldouble radius); similar cu
auxSolidOctahedron() dar wireframe (doar cu atribut de contur).
- void auxSolidDodecahedron(Gldouble radius); permite desenarea unui
dodecaedru (poliedru cu 12 fee, feele sunt pentagonale), centrat n
origine, pentru care se specific raza. Corpul are atribut de umplere.
- void auxWireDodecahedron(Gldouble radius); similar cu
auxSolidDodecahedron() dar wireframe (doar cu atribut de contur).
- void auxSolidDodecahedron (Gldouble radius); permite desenarea unui
icosaedru (poliedru cu 20 fee, feele sunt triunghiulare), centrat n
origine, pentru care se specific raza. Corpul are atribut de umplere.
- void auxWireIcosahedron(Gldouble radius); similar cu
auxSolidicosahedron() dar wireframe (doar cu atribut de contur).
- void auxSolidCylinder{Gldoubble radius, Gldouble height); permite
desenarea unui cilindru, centrat n origine, pentru care se specific raza bazei
i nlimea. Cilindrul are atribut de umplere.
- void auxWireCylinder(Gldouble radius, Gldouble height); similar cu
auxSolidCylinder() dar wireframe (doar cu atribut de contur).
23
- void auxSolidCone(Gldouble radius, Gldouble height); permite desenarea
unui con, centrat n origine, pentru care se specific raza bazei i nlimea.
Conul are atribut de umplere.
- void auxWireCone(Gldouble radius, Gldouble height); similar cu
auxSolidConeOdar wireframe (doar cu atribut de contur).
- void auxSolidSphere(Gldouble radius); permite desenarea unei sfere,
centrat n origine, pentru care se specific raza. Corpul are atribut de
umplere.
- void auxWireSphere(GldoublG radius); similar cu auxSoildSphere() dar
wireframe (doar cu atribut de contur).
- void auxSolidTorus{Gldouble InnerRadius, Gldouble outerRadius);
permite desenarea unui tor (forma colacului), centrat n origine. Parametrul
innerRadius este raza seciunii prin tor, iar outerRadius este raza gurii din
centrul torului. Corpul are atribut de umplere.
- void auxWireTorus(Gldouble innerRadius, Gldouble outerRadius);
similar cu auxSolidTorus() dar wireframe (doar cu atribut de contur).
- void auxSolidTeapot(Gldouble size); permite desenarea unui ceainic,
centrat n origine, pentru care se specific dimensiunea (aproximativ
diametrul). Corpul are atribut de umplere.
- void auxWireTeapot (Gldouble size); similar cu auxSolidTorus() dar
wireframe (doar cu atribut de contur).

Exemplu:


















Figura 2.6 (cub, paralelipiped, tetraedru, octaedru, dodecaedru, icosaedru, tor,
con, sfer, cilindru, ceainic - reprezentate wireframe)

Programul urmtor reprezint wireframe toate primitivele enumerate mai sus
(figura 2.6). Pentru poziionarea corpurilor n cadrul ferestrei, naintea apelrii fiecrei
24
funcii de desenare s-a apelat o funcie de translatare. Iniial s-a aplicat o rotaie care are
efect asupra tuturor corpurilor.

Codul programului este dat n continuare:
/* Programul afieaz primitivele 3D GLAUX */
#include "glos.h"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void myinit(void);
void CALLBACK display(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);

void myinit (void) {
glClearColor(1.0, 1.0,1.0, 1.0);
glColor3f(0.0,0.0,0.0);
}

void CALLBACK display (void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRotatef(30,1,1,1);
glTranslatef(-250,300,0);
auxWireCube(100);
glTranslatef(200,-50,0);
auxWireBox(200, 100, 50);
glTranslatef(200,-100,0);
auxWireTetrahedron(100);
glTranslatef(200,-50,0);
auxWireOctahedron(100);
glTranslatef(-700,0,0);
auxWireDodecahedron(100);
glTranslatef(220,-70,0);
auxWireIcosahedron(100);
glTranslatef(230,-80,0);
auxWireTorus(30, 80);
glTranslatef(220,-100,0);
auxWireCone(75, 150);
glTranslatef(-600,20,0);
auxWireSphere(80);
glTranslatef(250,-50,0);
auxWireCylinder(75, 100);
glTranslatef(230,-120,0);
auxWireTeapot(80);
25
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-300.0, 300.0, -300.0*(GLfloat)h/(GLfloat)w,
300.0*(GLfloat)h/(GLfloat)w, -300.0, 300.0);
else
glOrtho (-300.0*(GLfloat)w/(GLfloat)h,
300.0*(GLfloat)w/(GLfloat)h, -300.0, 300.0, -300.0, 300.0);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 900, 600);
auxInitWindow ("Primitive GLAUX");
myinit ();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}


Funcia auxMouseFunc
Funcia auxMouseFunc() asociaz o funcie callback cu o aciune asupra mouse-
ului. Prototipul funciei este:
void auxMouseFunc (int button, int mode, AUXMOUSEPROC func);
- Funcia func va fi apelat atunci cnd este apsat sau relaxat butonul button
al mouse-ului.
- Parametrul button poate avea una din urmtoarele valori:
AUX_LEFTBUTTON, AUX_MIDDLEBUTTON sau
AUX_RIGHTBUTTON.
- Parametrul mode specific aciunea asociat cu butonul mouse-
ului. Aceasta poate fi AUX_MOUSEDOWN sau AUX_MOUSEUP.


Funcia auxSwapBuffers
Funcia auxSwapBuffers() comut ntre cele dou buffer-e color n timpul
desenrii cu dublu buffer. Prototipul funciei este:
void auxSwapBuffers(void) :
26
Funcia este utilizat n special pentru animaie. Apelul ei va determina afiarea
pe ecran a scenei ascunse. Funcia necesit ca la iniializarea ferestrei cu funcia
auxInitDisplayMode() s fie utilizat flag-ul AUX_DOUBLE, pentru a specifica
folosirea a dou buffere de culoare.

Funcia auxSetOneColor

Funcia auxSetOneColor() seteaz o culoare n paleta de culori n cazul
modelului index de culoare. Prototipul funciei este:
void auxSetOneColor(int index, float red, float green, float blue);
In cazul modelului de culoare index se creeaz o palet de culori. O culoare este
selectat prin specificarea unui index n paleta de culori. Aceast funcie asociaz cu un
anumit index o culoare specificat prin componentele RGB ale culorii.






3 PRIMITIVE GEOMETRICE
3

n acest capitol se va discuta despre primitivele geometrice de care dispune
OpenGL pentru redarea scenelor, precum i modul n care se controleaz starea
OpenGL pentru aspectul acestor primitive. Se va discuta apoi despre modul de
reprezentare a curbelor i a suprafeelor curbe utiliznd evaluatori OpenGL dar i
funciile GLU pentru curbe i suprafee spline. Un subcapitol va fi dedicat pentru
redarea cvadricelor utiliznd funciile GLU. In afara tratrii acestor primitive vectoriale
este inclus un subcapitol special pentru tratarea primitivelor punctuale de care dispune
OpenGL (bitmap-uri, imagini).



3.1 Primitive geometrice OpenGL










Figura 3.1

P(x,y,z)
z
y
x
27
nainte de a ncepe s discutm despre felul n care sunt construite obiectele 3D
pe baza primitivelor geometrice simple, trebuie s explicm n detaliu sistemul de
coordonate utilizat de OpenGL. Acesta este un sistem cartezian. Axele x i y formeaz
un plan, ceva de genul suprafeei vizibile a monitorului. Axa z adaug cea de a treia
dimensiune - adncimea spaial (figura 3.1). Astfel pentru a avea o poziie spaial fix
n acest sistem de coordonate, un punct este necesar s fie specificat prin trei coordonate
(x, y, z).
Primitivele geometrice (puncte, segmente de dreapt, i poligoane) sunt definite
de un grup de unu sau mai multe vrfuri (vertex-uri). Un vrf definete un punct,
punctul terminal al unei muchii, sau colul n care se ntlnesc dou muchii ale unui
poligon. Unui vrf i sunt asociate date (constnd din coordonatele de poziie, culori,
normale, i coordonate de textur) i fiecare vrf este procesat n mod independent i n
acelai fel. Singura excepie de la aceast regul este n cazul n care un grup de vrfuri
trebuie s fie decupate astfel ca primitiva respectiv s fie cuprins n regiunea
specificat prin volumul de vizualizare definit de funcia myReshape(). n acest caz
datele despre un vrf pot fi modificate i sunt create noi vrfuri. Tipul decuprii depinde
de primitiva care este reprezentat de grupul de vrfuri.
















Figura 3.2

Toate primitivele geometrice sunt specificate prin vrfuri (coordonatele
vrfurilor). Intern OpenGL opereaz cu coordonate omogene. Coordonatele omogene
sunt de forma (x, y, z, w). Funciile OpenGL permit specificarea vrfurilor n
coordonate 2D, 3D i n coordonate omogene.
n funcie de parametrul funciei glBegin() (care poate fi unul din cele 10 nume
enumerate n figura 3.2) i de felul cum sunt organizate vrfurile, OpenGL poate reda
oricare din primitivele artate n figura 3.2.

Exemplu
Pentru ca cele spuse s fie mai clare se va exemplifica printr-o funcie de redare
a unui patrulater.
void patrulater( GLfloat color[] ) {
.
.
.
.
.
GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP
GL_TRIANGLES GL_TRIANGLE_FAN GL_TRIANGLE_STRI
GL_QUADS GL_QUAD_STRIP GL_POLYGON
28
2-(x,y)
3- (x,y,z)
4
(x,y,z,w)
b-byte
ub-unsigned byte
s-short
us-unsigned short
i-int
ui-unsigned int
f-float
d-double
Numrul
componentelor
Tipul datei
V se va omite
pentru formele
scalare
Ex:
glVertex2f(x,y)
Vector
glvertex3fv(v)
glBegin( GL_QUADS ) ;
glColor3fv( color );
glVertex2f( 0.0, 0.0 );
glVertex2f( 1.0, 0.0 ) ;
glVertex2f( 1.5, 1.118 );
glVertex2f( 0.5, 1.118 ) ;
glEnd(); }

Funcia patrulater() determin OpenGL s deseneze un patrulater ntr-o singur
culoare. Patrulaterul este planar deoarece, coordonat z este setat automat la 0 de funcia
glvertex2f (). Dac s-ar fi dorit ca patrulaterul s nu se afle n planul x0y, ci ntr-un plan
oarecare, atunci ar fi fost necesar s fie utilizat o funcie glvertex3#(). n felul acesta s-
ar fi furnizat pentru fiecare vrf i cea de a treia coordonat. Trebuie remarcat de
asemenea c numele primitivei geometrice se d ca parametru al funciei glBegin() i
corpul n care sunt furnizate coordonatele primitivei este delimitat de funciile glBegin()
i glEnd().


3 3. .1 1. .1 1 F Fo or rm ma at tu ul l c co om me en nz zi il lo or r O Op pe en nG GL L

Fiecare din comenzile care specific coordonatele vrfului, normalele, culorile
sau coordonatele de textur sunt disponibile n cteva formate pentru a se potrivi
diferitelor formate de date ale aplicaiilor i numrului de coordonate (figura 3.3).
Datele pot fi de asemenea transmise acestor comenzi fie ca o list de argumente sau ca
un pointer la un tablou ce conine date. Variantele se disting prin sufixele mnemonicelor
comenzilor.















Figura 3.3

Interfaa de programare a aplicaiilor OpenGL (OpenGL API) are astfel
proiectate apelurile nct s fie acceptate aproape orice tipuri de date de baz, al cror
nume este reflectat n numele funciei. Cunoscnd felul n care sunt formate numele
apelurilor este uor de determinat care apel va fi utilizat pentru un format particular de
29
date i pentru o anume dimensiune. Spre exemplu, coordonatele vrfurilor pentru
aproape toate modelele comerciale sunt reprezentate de un vector cu trei componente n
virgul mobil. n felul acesta, cea mai potrivit comand este glvertex3fv(coord). n
acest caz coord este un vector cu trei componente de tip float. Dac cele trei
componente s-ar furniza ca parametri ai funciei glVertex# atunci forma apelului ar fi
givertex3f (x, y, z); unde x, y, z sunt elemente de tip float.
Fiecare vrf poate fi specificat cu dou, trei sau patru coordonate (patru
coordonate indic coordonate omogene 3D). Dup cum s-a artat mai nainte, intern,
OpenGL utilizeaz coordonate omogene 3D pentru specificarea vrfurilor. Pentru acele
forme de apel glvertex#() care nu specific toate coordonatele (adic glvertex2f()),
OpenGL va fixa implicit z=0.0 i w=1.0.


3 3. .1 1. .2 2 S Sp pe ec ci if fi ic ca ar re ea a p pr ri im mi it ti iv ve el lo or r g ge eo om me et tr ri ic ce e O Op pe en nG GL L

n OpenGL cele mai multe obiecte geometrice sunt desenate prin includerea unei
mulimi de coordonate care specific vrfurile i opional normalele, coordonatele de
textur i culorile ntre perechea de comenzi glBegin()/glEnd():
glBegin(tipul_primitivei) ;
//se specific coordonatele vrfurilor, normalele,
//culorile, coordonatele de texturare
glEnd();
unde tipul_primitivei determin felul cum sunt combinate vrfurile din blocul
respectiv.
Spre exemplu, pentru specificarea unui patrulater cu vrfurile avnd
coordonatele (0,1,0), (1,3,0), (3,4,0),(0,4,0) se poate scrie:
glBegin(GL_QUADS)
glVertex3i(0,1,0) ;
glVertex3i(1,3,0) ;
glVertex3i(3,4,0) ;
glVertex3i(0,4, 0) ;
glEnd();

Cele zece primitive geometrice care pot fi astfel desenate sunt descrise n figura
3.2. Acest grup particular de primitive permite ca fiecare obiect s poat fi descris
printr-o list de vrfuri, i permite satisfacerea necesitilor fiecrei aplicaii grafice.
Exemplu:

Glfloat red, greed, blue;
Glfloat coords[3];
glBegin(tipul_primitivei);
for (i=0; i< nvertex; ++i){
glColor3f( red, green, blue );
glVertex3fv( coords);
}
glEnd() ;

30
Normala
curent
Coordonate
de vrfuri
transformate
Transformare
vrfuri
normale
Iluminare
Coordonatele
de texturi
curente
Culoare
curent
Funcia de
generare a
coordonatelor
de texturare
Coordonatele
de texturare
coordonate de
vrfuri
Matricea de
texturare
culoare
procesat
n acest exemplu, nvertex este numrul vrfurilor care se specific. Acestea sunt
grupate dup tipul primitivei, specificat ca parametru al funciei glBegin(). Spre
exemplu dac tipul primitivei este GL_QUADS i nvertex este 12 se vor desena 3
patrulatere. Tipurile posibile pentru tipul primitivei sunt:
GL_POINTS
GL_LINE_STRIP
GL_LINES
GL_LINE_LOOP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUADS
GL_QUAD_STRIP
GL_POLYGON
n esen sunt doar 5 tipuri de primitive (punct, linie, triunghi, patrulater i
poligon) restul de 5 chiar dac nu introduc primitive suplimentare prezint avantajul ca
n cazul n care dou vrfuri aparinnd la dou primitive distincte, se suprapun, s fie
memorate o singur dat. n felul acesta se ctig att timp de procesare ct i spaiu de
memorie.


















Figura 3.4 Asocierea valorilor curente cu vrfurile

Pentru procesarea unui vrf mai pot fi, suplimentar, utilizate normala curent,
coordonatele texturii curente i culoarea curent. OpenGL utilizeaz normalele pentru
calculele de iluminare. Normala curent este un vector 3D care se poate seta prin
specificarea celor trei coordonate. Culoarea poate fi format din valorile pentru rou,
verde, albastru i alfa (atunci cnd se utilizeaz modelul de culoare RGBA) sau o
singur valoare index (atunci cnd la iniializare se specific modul index). Una dou
trei sau patru coordonate de textur determin felul cum imaginea unei texturi se
mapeaz pe o primitiv.
31
Atunci cnd este specificat un vrf, culoarea curent, normala, coordonatele
texturii sunt utilizate pentru a obine valori care sunt apoi asociate cu vrful (figura 3.4).
nsui vrful este transformat de matricea de modelare-vizualizare, care este o matrice
de 4x4. Aceast transformare are loc intern prin nmulirea matricei de modelare
vizualizare cu coordonatele vrfului obinndu-se coordonatele acestuia n sistemul de
vizualizare. Culoarea asociat vrfului se obine fie pe baza calculelor de iluminare, fie
dac iluminarea este dezactivat, pe baza culorii curente. Coordonatele de texturare sunt
transmise n mod similar unei funcii de generare a coordonatele de texturare (care poate
fi identitate). Coordonatele de texturare rezultate sunt transformate de matricea de
texturare (aceast matrice poate fi utilizat pentru scalarea sau rotirea unei texturi ce se
aplic unei primitive).

Reguli pentru construirea poligoanelor

Nu ne referim aici la triunghiuri dei fac i ele parte din categoria poligoanelor.
Motivele sunt simple: triunghiurile aparin ntotdeauna unui singur plan, triunghiurile
sunt ntotdeauna convexe.
Regula 1
Poligoanele trebuie s fie totdeauna planare. Aceasta nseamn c toate vrfurile
unui poligon trebuie s aparin aceluiai plan. n figura 3.5 se poate vedea un poligon
planar i altul neplanar (rsucit).








Figura 3.5





Figura 3.6
Regula 2
Poligoanele trebuie s fie convexe. Pentru a verifica dac un poligon este convex
se face testul urmtor: dac oricare linie care traverseaz poligonul este intersectat n
mai mult de dou puncte de laturile poligonului acesta nu este convex (figura 3.6).
Regula 3
Muchiile poligoanelor nu se pot intersecta. Spre exemplu poligonul din figura
3.7 nu este un poligon corect n concepia OpenGL.



Figura 3.7
32


Orientarea poligoanelor

n OpenGL ordinea specificrii vrfurilor este cea dat de ordinea apelurilor
givertex# () n blocul glBegin() /glEnd().







Figura 3.8
Ordinea stabilit a vrfurilor este implicit n sens invers rotirii acelor de
ceasornic. Ordinea vrfurilor se specific n OpenGL prin funcia glFrontFace() care are
ca parametrii (figura 3.8):
- GL_CCW pentru sensul trigonometric (invers acelor de ceasornic
"counterclockwise") - care este valoarea implicit
- GL_CW pentru sensul rotirii acelor de ceasornic ("clockwise")
O primitiv geometric are orientare directa ("frontface") daca ordinea
specificrii vrfurilor coincide cu ordinea stabilit a vrfurilor. Dac ordinea specificrii
vrfurilor nu coincide cu ordinea stabilit a vrfurilor atunci primitiva are orientare
inversa ("backface")


Ordinea corect pentru specificarea vrfurilor primitivelor OpenGL
In figura 3.9 este artat ordinea n care trebuie specificate vrfurile primitivelor
OpenGL pentru ca orientarea acestora s fie n sens invers rotirii acelor de ceasornic -
adic ordinea direct n OpenGL.














Figura 3.9


33

Eliminarea poligoanelor n funcie de orientare
n OpenGL se poate realiza eliminarea anumitor suprafee n funcie de
orientarea acestora.
- Validarea eliminrii primitivelor geometrice n funcie de orientare:
- glEnable(GL_CULL_FACE);
- Selectarea suprafeelor eliminate:
- glCullFace(GLenum type);
unde type poate fi: GL_BACK - sunt eliminate poligoanele avnd orientare
invers, GL_FRONT - sunt eliminate poligoanele avnd orientare direct.


Utilitatea orientrii poligoanelor
La construirea unui corp solid toate poligoanele care-1 mrginesc trebuie s aib
aceeai orientare. Dac spre exemplu toate poligoanele au orientare trigonometric,
toate poligoanele vor fi poligoane fa i vor fi vizibile. Se poate stabili ca feele spate
s fie eliminate n situaia n care corpul este vizualizat din exterior. Dac ns corpul
este vizualizat dinspre interior atunci se va stabili s fie vizibile doar feele spate i s
fie eliminate feele fa.
S presupunem acum c un anumit corp solid a fost consistent construit, deci
cu toate poligoanele avnd aceeai orientare. Orientarea
specificat ns nu este aceeai cu cea stabilit pentru feele fa. Atunci se poate
interveni i se schimb orientarea stabilit pentru feele fa.

3 3. .1 1. .3 3 A At tr ri ib bu ut te e a al le e p pr ri im mi it ti iv ve el lo or r d de e i ie e i ir re e

n acest subcapitol ne vom referi la atribute primitivelor de ieire: dimensiunea
punctului, grosimea sau stilul liniei, modelul de umplere pentru primitivele cu atribut de
umplere, etc.

Atributul de culoare
Modelele de culoare OpenGL sunt RGBA sau Color Index. Fiecare
implementare OpenGL trebuie s permit redarea att n modelul de culoare RGBA
(denumit uneori ca modelul TrueColor) ct i n modelul index (sau colormap).
Pentru redarea cu modelul RGBA, culorile vrfurilor sunt specificate utiliznd
apelul glColor#(). Pentru modelul index, indexul culorii fiecrui vrf este specificat cu
apelul gllndex# ().
Sistemul de ferestre cere specificarea modelului de culoare al ferestrei. Dac se
utilizeaz GLUT, atunci modelul de culoare al ferestrei se specific folosind apelul
glutlnitDisplayMode(), cu flag-urile GLUT_RGBA (pentru modelul RGBA) sau
GLUT_INDEX (pentru modelul index). Dac se utilizeaz biblioteca GLAUX, modelul
de culoare se specific folosind funcia auxinitDisplayMode() cu flag-urile
AUX_RGBA sau AUX_INDEX.
Setrile de culoare pentru primitive pot fi specificate utiliznd fie modelul
RGBA fie modelul index. Odat specificat o anumit culoare, va afecta toate
primitivele care urmeaz pn la o modificare a culorii. Noua culoare va afecta apoi
doar primitivele specificate dup modificarea culorii.
34
n modelul RGB se vor specifica componentele rou, verde i albastru ale
culorii. Se poate folosi i varianta RGBA n care se specific i o a patra component -
valoarea alfa. Aceast a patra component este utilizat pentru amestecarea culorilor
pentru obiectele care se suprapun. O aplicaie important a amestecrii culorilor este
simularea efectului de transparen. Pentru aceste calcule valoarea alfa corespunde
coeficientului de transparen.
Pentru a folosi modelul RGB (sau RGBA), se seteaz simplu culoarea cu funcia
glColor#() dnd celor patru parametrii ai culorii valori cuprinse ntre 0.0 i 1.0. Pentru
specificarea componentelor culorii pot fi utilizate valori ntregi, n virgul mobil sau
alte formate numerice. Ca i n cazul funciei giVertex se vor utiliza ca sufix coduri ca
3, 4, d, f i i pentru a indica numrul parametrilor i formatul acestora. De pild, funcia
urmtoare specific componentele de culoare RGB n virgul mobil i seteaz culoarea
curent ca albastru de intensitate maxim:
glColor3f(0.0, 0.0, 1.0);
Valoarea implicit a culorii este alb (1, 1, 1) i valoarea implicit pentru alfa este
1. n mod opional, se pot seta valorile de culoare utiliznd tablourile. n acest caz se va
aduga funciei un al treilea sufix - v - i se va furniza un singur argument - pointer-ul la
tabloul ce conine componentele culorii. Utiliznd un tablou colorArray care conine
spre exemplu valorile anterioare, se va seta culoarea utiliznd apelul:
glColor3fv(colorArray);
Cellalt model pentru setarea culorii, disponibil n OpenGL este modelul index
care face referine la tabele de culoare. Acest model este utilizat n cazul n care spaiul
de memorare este limitat. n acest model se seteaz ca i culoare curent o culoare din
tabelul de culori utiliznd funcia:
gllndex#(index);
unde index specific o poziie n tabloul cu culori. Funcia necesit de asemenea
un sufix (d, f, i) care specific tipul datelor. Un tablou de culori poate fi setat cu funcia:
glIndexPointer(type, offset, ptr);
unde parametrul type d tipul datei, parametrul offset, d spaierea ntre valori
consecutive de culoare i parametrul ptr este un pointer spre primul element al tabloului
de culori.

A patra component de culoare
Componenta alfa pentru o culoare este o msur a opacitii fragmentului. Ca i
cu celelalte componente de culoare, domeniul valorilor sale este ntre 0.0 (care
reprezint complet transparent) i 1.0 (complet opac). Valorile alfa sunt importante
pentru o mulime de utilizri despre care se va discuta pe larg n capitolul 8 (Efecte
vizuale: transparena, ceaa, antialiasing).




Atributele punctului
Pentru punct pot fi setate dou atribute: culoare i dimensiune. Culoarea este
controlat de setarea curent a culorii, iar dimensiunea punctului se seteaz cu funcia:
void glPointSize(Glfloat size);
35
Parametrul size poate fi specificat ca orice valoare pozitiv n virgul mobil.
Dac valoarea specificat nu este un ntreg, ea va fi rotunjit la cea mai apropiat
valoare ntreag (presupunnd c antialiasing-ul este dezactivat). Valoarea implicit
pentru size este 1.


Atributele liniei
Atributele de baz pentru segmentul de linie dreapt sunt tipul liniei, grosimea
liniei i culoarea liniei. Alte efecte posibile, cum ar fi tipul peni sau tipul pensul, pot
fi implementate cu adaptri ale funciilor pentru tipul i grosimea liniei.
Pentru afiarea unui segment de dreapt ntr-o singur culoare este folosit
setarea curent a culorii. O alt posibilitate ar fi ca linia s fie afiat cu culoarea variind
de-a lungul liniei. O modalitate de a face acest lucru este de a atribui culori diferite
fiecrei extremiti a unei linii, n loc de a se seta o culoare curent pentru ntreaga linie.
De pild, poriunea de cod urmtoare seteaz o extremitate a liniei verde iar cealalt
galben. Rezultatul va fi afiarea unei linii continue n culori care interpoleaz culorile
extremitilor.
glShadeModel(GL_SMOOTH);
glBegin (GL_LINES);
glColor3f (0.0, 1.0, 0.0);
glVertex2i (-5,-5);
glColor3f (1.0, 1.0, 0.0);
glVertex2i (5,5);
glEnd ();

n ceea ce privete cellalt atribut al linie - tipul - n mod implicit acesta este
tipul continuu. n afara liniilor continue se pot utiliza linii ntrerupte, punctate sau n
diverse combinaii linie-punct. Spaiile dintre liniue sau puncte, dimensiunea liniuelor
pot fi de asemenea modificate. Stilul liniei este definit de programator - nu exist un set
de stiluri din care programatorul s-i aleag un anume stil.
ablonul se stabilete ntr-un cuvnt de 16 bii n care fiecare bit are semnificaia
de un pixel. Modelul astfel stabilit se repet de-a lungul liniei. Dac se dorete ca
semnificaia fiecrui bit s fie de 2, 3, ... pixeli se poate realiza o multiplicare cu un
factor. Pentru a se putea afia linii de diferite stiluri trebuie realizat activarea acestui
atribut cu funcia glEnable():
glEnable(GL_LINE_STIPPLE);
Altfel toate liniile vor fi afiate ca linii continue. Revenirea la linie continu se
face, evident, cu funcia glDisable().
Un anumit tip de linie este specificat cu funcia:
void glLineStipple(GLint repeatFactor, GLushort pattern);
care specific ablonul dup care sunt distribuii pixelii la desenarea liniei.
Parametrul pattern d un model, n binar, pe 16 bii (l=pixel on, 0=pixel off) i
parametrul ntreg repeatFactor specific de cte ori se repet fiecare bit din model.
Modelul este aplicat pixelilor de-a lungul liniei ncepnd cu biii mai puin
semnificativi. Spre exemplu, apelul:
glLineStipple(1, 0x00ff);
36
specific o linie ntrerupt n care liniuele ocup 8 pixeli iar spaiul dintre liniue
este tot de 8 pixeli. Deoarece biii mai puin semnificativi sunt pe on fiecare segment de
dreapt care se deseneaz va ncepe cu liniu i modelul se va repeta pn se ajunge la
cealalt extremitate a segmentului de dreapt. n cazul n care se deseneaz o linie frnt
modelul nu va fi restartat dup fiecare segment de dreapt, ci va fi aplicat continuu.
Iat spre exemplu cum se poate specifica o linie ntrerupt cu intervale egale
pentru ntrerupere i linie.
Exemplu:
GLint factor=l;
GLushort pattern=0x00ff;
glEnable(GL_LINE_STIPPLE);
glLineStipple(factor, pattern);
glBegin(GL_LINES);
glVertex2f(20, 30);

glVertex2f(100, 30);
glEnd(
);






0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0





Figura 3.10

Din figura 3.10 se poate constata care este corespondena dintre modelul liniei i
cuvntul pattern utilizat.
Ultimul atribut al liniei - grosimea - se seteaz cu funcia:
void glLineWidth(Glfloat width);
Valoarea implicit a parametrului width este 1. Valorile n virgul mobil sunt
rotunjite la ntregul cel mai apropiat atunci cnd nu este activat antialiasing-ul.



Atributele poligoanelor
Pentru poligoane, atributul de baz este stilul de umplere. Poligoanele pot fi
umplute ntr-o singur culoare, cu un anumit model de umplere, sau fr atribut de
umplere ("hollow") atunci cnd se reprezint doar conturul. Aa cum s-a artat un
poligon are dou fee: fa i spate care pot fi diferit reprezentate. Aceasta permite
reprezentarea seciunilor prin corpuri. Se pot selecta atribute diferite pentru poligoanele
modelul liniei
biii cuvntului pattern
pixelii corespunztori
37
"fa" i pentru cele "spate", se poate inversa definirea poligoanelor "fa" sau "spate" i
se poate elimina afiarea poligoanelor "fa" sau "spate".
n mod implicit ambele fee sunt desenate la fel. Pentru a schimba acest lucru se
utilizeaz funcia glPolygonMode(),
glPolygonMode(GLenum face, GLenum mode)
care stabilete modul de desenare al poligoanelor (mode: GL_POINT,
GL_LINE, GL_FILL) i tipul feelor care sunt afectate (face: direct -GL_FRONT,
invers - GL_BACK, ambele - GL_FRONT_AND_BACK).
n mod implicit ambele fee sunt desenate cu atribut de umplere. Se poate spre
exemplu, stabili ca partea fa s fie desenat plin iar cea spate s fie desenat cu
wireframe (fr atribut de umplere).
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);

Culoarea primitivelor cu atribut de umplere
Triunghiurile, patrulaterele i poligoanele sunt primitivele care au atribut de
umplere. Acestea pot fi colorate cu o anumit culoare sau pot fi umplute cu un anumit
model de umplere. n ceea ce privete culoarea, aceasta se poate stabili pentru fiecare
vrf n parte sau se utilizeaz culoarea curent de desenare. Funcia utilizat este
glColor3f(). n funcie de modelul de umbrire, poligoanele sunt umplute cu o culoare
compact sau cu o interpolare a culorii vrfurilor. Modelul de umbrire se stabilete cu
funcia glShadeModel().
void glShadeModel (Glenum mode);
Dac se stabilete o umbrire poligonal constant (parametrul GL_FLAT) atunci
culoarea de umplere a poligoanelor va fi culoarea curent sau culoarea stabilit pentru
ultimul vrf al poligonului. Dac se stabilete modelul de umbrire Gouroud
(GL_SMOOTH) atunci se vor interpola culorile vrfurilor (ca la ptratul reprezentat
pentru exemplificare funciilor glaux).

Utilizarea abloanelor de umplere
Aa cum liniile pot fi desenate avnd anumite stiluri i poligoanele pot fi
umplute cu anumite modele de umplere. Pentru aceasta programatorul stabilete
ablonul, care se va repeta apoi pe suprafaa ntregului poligon. Pentru activarea
umplerii cu ablon se folosete funcia glEnable().
glEnable(GL_POLYGON_STIPPLE);
Modelul de umplere se specific folosind funcia glPolygonStipple avnd ca
parametru un pointer spre un tablou care conine ablonul.
glPolygonStipple(fillPattern);
Parametrul fillPattern este un pointer la o masc de 32X32 bii. Tabloul
fillPattern conine elemente de tip GLubyte. O valoare 1 n masc arat c pixelul
corespunztor va fi pe on, i 0 indic un pixel pe of f. Intensitatea pixelilor este setat n
funcie de setarea culorii curente. Spre exemplu
GLubyte fillPattern[]={Oxff, 0x00, Oxff, 0x00, ...};
Biii trebuie s fie specificai ncepnd cu rndul de jos al modelului, i
continund pn la rndul cel mai de sus (al-32-lea). Modelul este apoi aplicat de-a
lungul ferestrei curente, umplnd poligonul specificat acolo unde modelul se suprapune
38
cu interiorul poligonului. Odat specificat modelul i activat umplerea cu ablon se
poate trece la desenarea poligonului.
O alt modalitate de umplere a poligoanelor este utiliznd texturile. De
asemenea, poligoanele pot fi umplute cu culoarea curent setat. Ca i n cazul liniilor
se pot specifica culori diferite pentru fiecare vrf al unui poligon i n acest caz culoare
interiorului poligonului va fi interpolarea culorilor vrfurilor poligonului. Aa cum s-a
mai artat poligoanele pot fi desenate n modul wireframe sau doar marcnd vrfurile
poligonului, depinde de ce parametrii sunt folosii pentru funcia glPolygonMode():
GL_FILL - cu atribut de umplere
GL_LINE - fr atribut de umplere(wireframe)
GL_POINTS - marcate vrfurile
n OpenGL, funciile de redare a poligoanelor pot fi aplicate doar poligoanelor
convexe. Pentru un poligon concav, trebuie mai nti desprit ntr-o mulime de
poligoane convexe, de obicei triunghiuri. Pentru a afia apoi doar poligoanele originale
trebuie s putem specifica care linii fac parte din poligoanele originale. Pentru aceasta
se folosete funcia glEdgeFlag, care arat dac un vrf este sau nu primul punct al unei
laturi din poligonul original. Funcia glEdgeFlag() este utilizat n interiorul perechii
glBegin/glEnd.
glEdgeFlag(GL_FALSE);
Aceast comand arat c vrful care urmeaz nu precede o latur a unui poligon
original. De asemenea, comanda se aplic tuturor vrfurilor care urmeaz pn la un
nou apel al funciei glEdgeFlag. Argumentul GL_TRUE arat c vrful urmtor iniiaz
o latur a poligonului original.

Antialiasing
Pentru activarea procedurilor pentru antialiasing se folosete apelul:
glEnable();
avnd ca parametru una din valorile GL_POINT_SMOOTH,
GL_LINESMOOTH sau GL_POLYGON_SMOOTH.

Funcii de interogare
Se pot obine valorile pentru setrile curente ale atributelor i pentru diveri ali
parametrii utiliznd funciile corespunztoare "Get" cum ar fi glGetlntegerv(),
glGetFloatv(), glGetPolygonStipple(). Spre exemplu, se poate afla setarea curent a
culorii cu
glGetFloatv(GL_CURRENT_COLOR, colorArray);
Tabloul colorArray va fi setat n urma acestui apel cu culoarea curent. Similar
se poate afla dimensiunea curent a punctului (GL_POINT_SIZE) sau a liniei
(GL_LINE_WIDTH_RANGE). De asemenea se poate afla dac anumite proceduri,
cum ar fi antialiasing-ul, sunt activate sau dezactivate.

Exemple

n continuare vor fi date cteva exemple ilustrative pentru utilizarea primitivelor
geometrice i a atributelor acestora.

Exemplul 1
39
/*Un cerc din puncte de dimensiune un pixel */
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <math.h>

void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);

void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}

void CALLBACK display(void)
{
int i;
double PI = 3.1415926535;
double raza =2.0;

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);

glBegin(GL_POINTS);
for (i = 0; i < 360; i+=5)
glVertex2f(raza*cos(PI*i/180.0), raza*sin(PI*i/180.0));
glEnd();
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
40
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("Un cerc din puncte");
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Observaii:

Ceea ce se obine la rularea acestui program este afiat n figura 3.11. Ce trebuie
remarcat n acest exemplu este felul cum s-au furnizat coordonatele punctelor n corpul
glBegin/glEnd. ntr-un ciclu for s-a apelat funcia glVertex() de 360/5 ori. Coordonatele
punctelor de pe cerc s-au dat n coordonate polare. Mai trebuie remarcat c n funcia
myReshape() s-au stabilit 10 uniti pe fiecare ax i s-a urmrit ca raza cercului(2) s
se ncadreze n aceste dimensiuni.












Figura 3.11













41
Figura 3.12

Exemplul 2
S modificm acum acest exemplu astfel nct punctele de pe cerc s aib
dimensiuni cresctoare. Ceea ce se modific este funcia display(). Rezultatul rulrii
este artat n figura 3.12.

void CALLBACK display(void) {
int i ;
double PI = 3.1415926535;
double raza =2.0;
GLfloat size=0.5;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
for (i = 0; i < 360; i+=10)
{ glBegin(GL_POINTS);
glVertex2f(raza*cos(PI*i/180.0), raza*sin(PI*i/180.0));
glEnd() ;
size+=0.125; //incrementeaz dimensiunea punctului
glPointSize(size); }
glFlush() ; }

Observaii:
Ceea ce trebuie remarcat aici este faptul c n corpul glBegin/glEnd nu au efect
dect instruciunile pentru caracteristicile vrfurilor. Astfel c urmtorul cod nu ar fi
condus la rezultatul ateptat, dei nu ar fi aprut eroare la compilare.
glBegin(GL_POINTS);
for (i = 0; i < 360; i+=5)
glVertex2f(raza*cos(PI*i/180.0), raza*sin(PI*i/180.0));
size+=0 .125; //incrementeaz dimensiunea punctului
glPointSize(size);
glEnd() ;

Exemplul 3

Exemplul 1 se poate modifica pentru desenarea unui cerc cu linie continu, prin
simpla modificare a parametrului funciei glBegin() n GL_LINE_LOOP (figura 3.13).
Dac se folosete parametrul GL_LINE_STRIP atunci nu este unit primul punct cu
ultimul punct al liniei frnte din care s-a construit cercul. Acesta este un exemplu despre
cum se construiete o curb dintr-o linie frnt. Pentru ca linia care formeaz cercul s
fie mai neted, vrfurile vor fi alese i mai apropiate. Cu toate c cercul este format
dintr-un contur nchis, el nu are atribut de umplere. Pentru aceasta este suficient s se
nlocuiasc parametrul GL_LINE_LOOP, al funciei glBegin() cu parametrul
GL_POLYGON. Rezultatul obinut n acest caz este artat n figura 3.14.



42









Figura 3.13












Figura 3.14


Exemplul 4
Se reia acum exemplul anterior dar cercul va fi umplut cu un model (figura
3.15). n continuare se poate vedea felul n care a fost declarat tabloul care conine
modelul de umplere.














Figura 3.15

Codul programului este urmtorul:

43
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <math.h>
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);

void CALLBACK display(void)
{
int i;
double PI = 3.1415926535;
double raza =3.0;

GLubyte model[] = { 0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFc, 0x3F, 0xFF,
0xFF, 0xF8, 0x1F, 0xFF,
0xFF, 0xF1, 0x8F, 0xFF,
0xFF, 0xe3, 0xc7, 0xFF,
0xFF, 0xc7, 0xe3, 0xFF,
0xFF, 0x8e, 0x71, 0xFF,
0xFF, 0x1c, 0x38, 0xFF,
0xFe, 0x39, 0x9c, 0x7F,
0xFc, 0x73, 0xce, 0x3f,
0xF8, 0xe7, 0xe7, 0x1f,
0x01, 0xce, 0x73, 0x80,
0x01, 0xce, 0x73, 0x80,
0xF8, 0xe7, 0xe7, 0x1f,
0xFc, 0x73, 0xce, 0x3f,
0xFe, 0x39, 0x9c, 0x7F,
0xFF, 0x1c, 0x38, 0xFF,
0xFF, 0x8e, 0x71, 0xFF,
0xFF, 0xc7, 0xe3, 0xFF,
0xFF, 0xe3, 0xc7, 0xFF,
0xFF, 0xF1, 0x8F, 0xFF,
0xFF, 0xF8, 0x1F, 0xFF,
0xFF, 0xFc, 0x3F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,
0xFF, 0xFe, 0x7F, 0xFF,

44
};

glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);

glEnable (GL_POLYGON_STIPPLE);
glPolygonStipple (model);

glBegin(GL_POLYGON);
for (i = 0; i < 360; i+=5)
glVertex2f(raza*cos(PI*i/180.0), raza*sin(PI*i/180.0));
glEnd();
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("Un cerc cu model");
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Exemplul 5
Exemplul urmtor construiete un cub din patrulatere. Cubul este animat (rotit),
utilizndu-se funcia IdleFunctionO. Indiferent de poziia cubului n timpul rotaiei,
muchiile spate sunt reprezentate cu linie punctat iar muchiile fa cu linie continu.
/*Un cub care se rotete i care are muchiile spate desenate cu linie punctat */
45

#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <math.h>
void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK IdleFunction(void);
void CALLBACK display(void);
void cub(GLfloat latura);

void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}

void CALLBACK IdleFunction(void)
{
glRotatef(30,1,1,1);
display();
Sleep(300);
}

void CALLBACK display(void)
{
GLint factor=10;
GLushort pattern=0x255;

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLineStipple(factor, pattern);

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glEnable(GL_LINE_STIPPLE);
cub(0.5);

glCullFace(GL_BACK);
glDisable(GL_LINE_STIPPLE);
cub(0.5);

glFlush();
}
46
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.0, 1.0, -1.0*(GLfloat)h/(GLfloat)w,
1.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0);
else
glOrtho(-1.0*(GLfloat)w/(GLfloat)h,
1.0*(GLfloat)w/(GLfloat)h, -1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("Un cub");
myinit();
auxReshapeFunc (myReshape);
auxIdleFunc(IdleFunction);
auxMainLoop(display);
return(0);
}

void cub(GLfloat latura) //funcia care n cubul
//cu latura de 2Xlatura i centrat n origine
//ordinea specificrii vrfurilor este invers rotirii acelor de ceasornic
{ glBegin(GL_QUAD_STRIP);
glVertex3f(-latura, latura, latura);
glVertex3f(-latura, -latura, latura);
glVertex3f(latura, latura, latura);
glVertex3f(latura, -latura, latura);
glVertex3f(latura, latura, -latura);
glVertex3f(latura, -latura, -latura);
glVertex3f(-latura, latura, -latura);
glVertex3f(-latura, -latura, -latura);
glVertex3f(-latura, latura, latura);
glVertex3f(-latura, -latura, latura);
glEnd();
glBegin(GL_QUADS);
glVertex3f(-latura, latura, latura);
glVertex3f(latura, latura, latura);
glVertex3f(latura, latura, -latura);
47
glVertex3f(-latura, latura, -latura);
glEnd();
glBegin(GL_QUADS);
glVertex3f(-latura, -latura, latura);
glVertex3f(-latura, -latura, -latura);
glVertex3f(latura, -latura, -latura);
glVertex3f(latura, -latura, latura);
glEnd();
}

Observaii:
In figura 3.16 sunt capturate dou poziii diferite n timpul rotaiei. Se constat
c acele muchii care intervin i n poligoanele fa i n cele spate sunt desenate cu
ambele tipuri de linii. Pentru a se masca acest lucru s-ar putea alege o grosime mai mare
pentru linia continu.
S analizm codul aplicaiei. n primul rnd s constatm c funcia cub ()
pstreaz orientarea trigonometric pentru toate patrulaterele. Dac se schimb
orientarea direct (funcia glFrontFace () care este comentat n aplicaie) atunci
poligoanele spate vor fi desenate cu linie continu i cele fa cu linie ntrerupt.
Deoarece funcia glPoligonMode() nu ne permite specificarea de tipuri diferite de linii
pentru poligoanele fa i cele spate, s-a desenat cubul de dou ori.












Figura 3.16

Prima dat s-au eliminat poligoanele fa i s-a activat linia punctat pentru
desenarea poligoanelor spate. A doua oar s-au eliminat poligoanele spate i s-a
dezactivat linia punctat. In ceea ce privete linia punctat, ea apare neuniform,
deoarece fiecare muchie cu linie punctat intervine n desenarea a dou poligoane.




3.2 Reprezentarea curbelor i a suprafeelor curbe


48
Deoarece curbele nu pot fi descrise cu exactitate prin ecuaii lineare, n OpenGL
nu exist funcii simple pentru desenarea curbelor, aa cum exist pentru puncte sau
pentru drepte. O modalitate de a desena o curb este de a o aproxima prin puncte sau
prin segmente de dreapt, cum s-a putut de altfel vedea ntr-unui din exemplele
anterioare care reprezenta cercul cu linie continu. Reprezentarea cercului este ns o
problem simpl avnd n vedere c se cunoate ecuaia sa. O soluie pentru modelarea
curbelor ar fi deci de a se memora un set de puncte de pe curb. Reprezentarea s-ar
putea face prin unirea punctelor prin linii n cazul n care acestea sunt suficient de
apropiate. Soluia este costisitoare avnd n vedere numrul mare al punctelor ce ar
trebui memorate pentru o curb. Pentru un set de puncte prin care ar trebui s treac
curba se poate realiza o interpolare utiliznd pentru aceasta polinomul Newton. i
aceast soluie este costisitoare avnd n vedere gradul mare al polinomului care rezult.
O alt metod este de a genera curbele utiliznd funciile polinomiale Bezier pentru care
OpenGL dispune de evaluatori. In acest caz sunt suficiente cteva puncte de control care
aproximeaz forma curbei i evaluatorii determin puncte succesive pentru curba Bezier
respectiv. Reprezentarea se face prin linii. Biblioteca GLU dispune chiar de o interfa
pentru reprezentarea curbelor, folosind pentru aceasta ecuaiile NURBS (Non-Uniform
Raional B-Spline). In acest subcapitol se va discuta despre reprezentarea curbelor
Bezier i spline (NURBS). Utilitatea lor n realizarea aplicaiilor grafice este cu att mai
mare cu ct permit programarea interactiv n reprezentarea curbelor. Mutnd punctele
de control utilizatorul unei aplicaii poate modifica forma curbei.
n ceea ce privete reprezentarea suprafeelor, problemele i soluionarea lor sunt
asemntoare cu cele ale curbelor. Pentru reprezentarea unei suprafee curbe la care nu
se cunoate o ecuaie presupune determinarea unui set de puncte pe suprafa i
aproximarea reprezentrii prin triunghiuri. Soluia presupune mult memorie pentru
salvarea coordonatelor triunghiurilor i nu este interactiv. Inginerul francez Pierre
Bezier a fost primul care a venit cu o soluie care permite realizarea ntr-o manier
necostisitoare a unor aplicaii interactive, prin inventarea ecuaiilor care-i poart
numele. Interfaa OpenGL dispune de posibilitatea de evaluare a polinoamelor Bezier,
prin evaluatori. Pentru reprezentarea unei suprafee Bezier de ordinul 3 este necesar o
matrice de 16 puncte care aproximeaz forma suprafeei. Pe baza acestei matrice de
puncte se determin ecuaiile Bezier i apoi, funcie de gradul de precizie, mai multe sau
mai puine puncte de pe suprafa. Ca i n cazul curbelor, interfaa NURBS a bibliotecii
GLU pune la dispoziie o metod de reprezentare a suprafeelor care generalizeaz
curbele spline. Despre aceste metode se va discuta n continuare.
n sfrit, biblioteca GLU are de asemenea funcii pentru generarea
reprezentrilor poligonale ale obiectelor cvadrice. Aceste funcii pot genera de
asemenea normalele pentru iluminare i coordonatele de texturare pentru obiectele
cvadrice.
Pentru a se nelege fundamentul matematic pentru reprezentarea curbelor i a
suprafeelor curbe se recomand studierea capitolului respectiv din cartea "Sisteme de
prelucrare grafic".


3 3. .2 2. .1 1 E Ev va al lu ua at to or ri i


49
Evaluatorii asigur o modalitate de a specifica puncte de pe o curb sau de pe o
suprafa, utiliznd doar punctele de control. Curba sau suprafaa pot fi redate apoi cu
precizia dorit. Suplimentar, pot fi determinate i normalele la suprafa. Punctele
determinate de evaluatori pot fi utilizate pentru reprezentare n mai multe moduri a unei
suprafee - reprezentarea unui set de puncte de pe suprafa, reprezentarea unei
suprafee wireframe, reprezentarea unei suprafee cu iluminare i umbrire. Evaluatorii
pot fi utilizai pentru a descrie orice curb sau suprafa polinomial de orice grad.
Interfaa GLU care asigur o interfa de nivel ridicat NURBS are la baz tot
evaluatorii. Ea conine o mulime de proceduri complicate, dar redarea final se
realizeaz tot cu evaluatorii.
Evaluatorii permit specificarea funciilor polinomiale de una sau dou variabile
ale cror valori determin coordonatele vrfurilor primitivelor, coordonatele normalelor,
coordonatele texturilor. Pentru oricare din aceste grupuri de valori, poate fi dat o hart
polinomial specificat n termenii de baz Bezier. Odat definite i activate, hrile
sunt invocate n unul din dou moduri posibile. Prima modalitate este de a determina o
singur evaluare a fiecrei hri activate prin specificarea unui punct n domeniul hrii
utiliznd funcia glEvalCoord(). Aceast comand se d ntre apelurile glBegin() i
glEnd() astfel c se folosesc primitivele individuale pentru construirea unei poriuni
dintr-o curb sau o suprafa. A doua metod este de a specifica o matrice de puncte n
spaiu utiliznd funcia glEvalMesh(). Fiecare vrf din matricea evaluat este o funcie
de polinoamele definite. Funcia glEvalMesh() i genereaz propriile sale primitive i
de aceea nu poate fi plasat ntre funciile glBegin () i glEnd ().
Interfaa pentru evaluatori asigur o baz pentru construirea unui pachet mai
general pentru curbe i suprafee. Un avantaj al asigurrii evaluatorilor n OpenGL n
locul unei interfee NURBS mai complexe este acela c aplicaiile care reprezint curbe
i suprafee altele dect NURBS sau care utilizeaz proprieti speciale de suprafa au
totui acces la evaluatori polinomiali eficieni (care pot fi implementai n hardware-ul
grafic) fr a fi nevoie s fie convertii la reprezentri NURBS.
n continuare se va descrie pe scurt suportul teoretic pentru curbele i suprafeele
Bezier, pentru a nelege mai bine semnificaia evaluatorilor.

Evaluatori uni-dimensionali
O curb parametric polinomial este descris printr-un vector cu trei elemente:
P(u) = [x(u) y(u) z(u)]
Parametrul u ia valori de la 0 la 1. Pentru fiecare valoare a lui u se obine un
punct P(u) aparinnd curbei.
Utiliznd un set de puncte de control se poate obine o curb aproximativ
folosind un set de funcii polinomiale obinute pe baza coordonatelor acestor puncte de
control. Vom considera cazul general al curbelor Bezier de orice grad.
Pentru un set de (n+1) puncte de control care definesc vectorii:
Pk = (xk yk zk) k=0, 1, 2, ...n
se poate aproxima polinomul vectorial P(u), care reprezint trei ecuaii
parametrice (x(u), y(u), z(u)) pentru curba care trece prin punctele de control pk

=
=
n
k
n k
u B pk u P
0
,
) ( ) (
k=0
Fiecare polinom B
k,n
este o funcie polinomial definit ca
50
1
,
) 1 ( ) , ( ) (

=
k k
n k
u u k n C n B
iar C(n, k) reprezint coeficienii binomiali
)! ( !
!
) , (
k n k
n
k n C

=
Relaiile coordonatelor pot fi scrise n form explicit ca un set de ecuaii
parametrice pentru coordonatele curbelor:

=
=
n
i
n k k
u B x u x
0
,
) ( ) (

=
=
n
i
n k k
u B y u y
0
,
) ( ) (

=
=
n
i
n k k
u B z u z
0
,
) ( ) (

Evaluatori bi-dimensionali

Ecuaiile parametrice pentru suprafee sunt date folosind doi parametrii, u i v.
Poziia coordonatelor unui punct de pe suprafa este reprezentat printr-un vector:
S(u, v)=[x(u, v) y(u, v) z(u,v)] (3.9)
Pentru reprezentarea unor suprafee specificate prin punctele de control se
folosesc dou seturi de curbe Bezier. Funciile pentru vectorii parametrici care definesc
suprafaa Bezier se obin ca produs cartezian al funciilor de amestec al celor dou seturi
de curbe.

= =
=
m
i
n
k
v n k u m i k i
B B p v u S
0 0
) ( , ) ( , ,
) , (
unde pi,k specific un punct de control din cele (m+l)x(n+l) puncte de control
care definesc suprafaa.


3 3. .2 2. .2 2 C Cu ur rb be e B Be ez zi ie er r

Exemplul 1
In exemplul urmtor se arat modul de utilizare al evaluatorilor pentru
reprezentarea unei curbe Bezier.
/* curbe_Bezier.c
Programul utilizeaz evaluatorii pentru determinarea punctelor de pe curba
Bezier */
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
51
GLfloat ctrlpoints[4][3] = {
{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
{2.0, 4.0, 0.0}, {4.0, -4.0, 0.0}};

void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
glShadeModel(GL_FLAT);
glLineStipple (1, 0x0F0F);
}

void CALLBACK display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();
glPointSize(5.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glEnable(GL_LINE_STIPPLE);
glColor3f(1.0, 0.0, 1.0);
glBegin (GL_LINE_LOOP);
for (i=0; i<4; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();

glFlush();
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
52
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300, 300);
auxInitWindow ("Curbe Bezier");
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Observaii:
In figura 3.17 se poate vedea rezultatul rulrii programului. Din program se
poate vedea c funcia glMaplf() descrie caracteristicile curbei (puncte de control,
gradul polinoamelor de amestec, intervalul pentru parametrul w), cu funcia
glEnable(GL_MAPl_VERTEX_3) se activeaz un anumit tip de evaluatori, iar apoi se
obin puncte pe curb cu funcia glEvalCoordlf().














Figura 3.17










53




Figura 3.18

Exemplul 2
O problem care se pune atunci cnd se lucreaz cu curbe Bezier, este realizarea
unor curbe care sunt aproximate de mai mult de patru puncte de control. Ecuaiile curbei
permit n acest caz specificarea mai multor puncte de control. Dar implicit n cazul
acesta crete i gradul curbei. Dac se mrete doar numrul punctelor de control i nu
se actualizeaz i gradul curbei n funcia glMaplf(), rezultatul va fi c se va reprezenta
curba doar pentru primele patru puncte de control din tabloul punctelor de control.
Exemplul anterior este modificat pentru reprezentarea unei curbe aproximat de 6
puncte de control, (figura 3.18). Se vor da doar funciile myinit() i display() n care s-
au fcut modificri fa de exemplul anterior.
GLfloat ctrlpoints[6][3] = {
{ -4.0, 0.0, 0.0}, { -3.0, 4.0, 0.0}, { -1.0, 4.0, 0.0},
{1.0, -4.0, 0.0}, {3.0, -4.0, 0.0}, {4.0, 0.0, 0.0}};
void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 6, &ctrlpoints[0][0]);
/*funcia definete caracteristicile curbei:
- tipul punctelor de control date in vectorul ctrlpoints, si al
- datelor de ieire generate de funcia de evaluare glEvalCoordlf
- valorile extreme luate de parametrul u (0 si 1 in acest caz)
- numrul coordonatelor date pentru fiecare punct de control, in tabloul
ctrlpoints
- numrul punctelor de control pe baza crora se va determina ordinul curbei
(numr puncte-1) -vectorul punctelor de control
*/
glEnable (GL_MAP1_VERTEX_3) ; //se valideaz un anumit tip de
evaluare
gl ShadeModel (GL_FLAT) ; //umbrire constanta pe poligoane
glLineStipple (1, 0x0F0F);
}
void CALLBACK display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();
glPointSize(5.0);
54
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 6; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glEnable(GL_LINE_STIPPLE);
glColor3f(1.0, 0.0, 1.0);
glBegin (GL_LINE_STRIP);
for (i=0; i<6; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();

glFlush();
}

Exemplul 3
n exemplul urmtor se deseneaz o curb (figura 3.19) care trece prin aceleai
puncte de control ca i curba din exemplul anterior. De data aceasta ns se folosesc
dou curbe Bezier de gardul 3 cu continuitate geometric (G
1
) de ordinul 1 n punctul de
contact. Punctul de contact al celor dou curbe este un punct de control introdus
suplimentar fa de exemplul anterior. El este punct terminal pentru prima curb i
punct iniial pentru cea de a doua curb. Pentru a se obine continuitate geometric de
ordinul 0 (G) n punctul de contact este necesar ca ultimul punct de control al primei
curbe s coincid cu primul punct de control al celei de a doua curbe (punctul (0, 0, 0)
n exemplul nostru). Pentru a avea continuitate geometric de ordinul 1 este necesar ca
n punctul de contact tangentele la cele dou curbe s fie coliniare. O caracteristic a
curbelor Bezier este c primele dou puncte de control i ultimele dou puncte de
control sunt extremitile unor drepte care sunt tangente la curba Bezier. Condiia de
continuitate geometric de ordinul 1 revine la condiia ca penultimul punct de control al
primei curbe, punctul comun i al doilea punct de control al celei de a doua curbe s fie
puncte coliniare. In cazul nostru aceste puncte sunt: {-1.0, 4.0, 0.0}, {0.0, 0.0, 0.0}, {l.0,
-4.0, 0.0}. Toate aceste puncte sunt puncte coliniare i se afl pe dreapta de ecuaie y = -
4x.














55
Figura 3.19

i pentru acest exemplu se furnizeaz doar partea de cod modificat fa de
exemplu anterior.
GLfloat ctrlpointsl[4][3] = {
//sunt date coordonatele celor 4 puncte de control pentru prima curb
{-4.0, 0.0, 0.0},{-3.0, 4.0, 0.0},{-1.0, 4.0, 0.0},{0.0, 0.0, 0.0}};
GLfloat ctrlpoints2[4][3] = {
//sunt date coordonatele celor 4 puncte de control pentru a doua curb
{0.0, 0.0, 0.0}, {1.0, -4.0, 0.0}, {3.0, -4.0, 0.0},{4.0, 0.0, 0.0}};
void myinit(void) {
glClearColor (1.0, 1.0, 1.0, 1.0); //culoarea background-ului
glShadeModel (GL_FLAT) ; //umbrire constanta pe poligoane
glLineStipple (1, 0x0F0F) ; //stilul liniei punctate }
void CALLBACK display(void) {
int i ;
glClear(GL_COLOR_BUFFER_BIT);
glColor3 f (0 . 0, 0.0, 0.0); //culoarea curenta de desenare
glMaplf(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpointsl[0][0]);
glEnable (GL_MAP1_VERTEX_3) ; //se valideaz un anumit tip de
evaluare
glBegin (GL_LINE_STRIP) ; //se deseneaz curba prin segmente de
dreapta
for (i = 0; i <^= 30; i++)
glEvalCoordlf ( (GLfloat) i/30 . 0) ; //pentru cele 30 vrfuri determinate de
// funcia glEvalCoordlf glEnd() ;
glMaplf (GL_MAP1_VERTEX__3, 0.0, 1.0, 3, 4, &ctrlpoints2[0][0]);
glBegin (GL_LINE_STRIP) ; //se deseneaz curba prin segmente de
dreapta
for (i = 0; i <= 30; i++)
glEvalCoordlf ( (GLf loat) i/30.0) ; //pentru cele 30 vrfuri determinate de
//funcia glEvalCoordlf glEnd() ;
/*Se afieaz punctele de control. */
glPointSize (5 . 0) ; //de dimensiune 5
glColor3f (1.0, 0.0, 0.0); //culoare roie
glBegin (GL_POINTS) ; //pentru prima curba
for (i = 0; i < 4; i + +)
glVertex3fv(&ctrlpointsl[i][0]);
glEnd() ;
glBegin (GL_POINTS) ; //pentru a doua curba
for (i = 0; i < 4; i++)
glVertex3fv(&ctrlpoints2[i] [0] ) ;
glEnd() ;
//se unesc punctele de control
glEnable (GL_LINE_STIPPLE) ; //linie punctat
glColor3f(0.0, 1.0, 0.0);
glBegin (GL_LINE_STRIP) ; //pentru prima curba
56
for (i=0; i<4; i++)
glVertex3fv(&ctrlpointsl[i][0]);
glEnd() ;
glBegin (GL_LINE_STRIP) ; //pentru a doua curba
for (i=0; i<4; i++)
glVertex3fv(&ctrlpoints2[i][0]); glEnd();
glFlush() ;
}




3 3. .2 2. .3 3 S Su up pr ra af fe e e e B Be ez zi ie er r

Urmtoarele dou exemple arat modul de utilizare al evaluatorilor
bidimensionali pentru reprezentarea suprafeelor.
Exemplul 1
In figura 3.20 se poate vedea rezultatul rulrii acestui exemplu.













Figura 3.20

/* Wire_Bezier.c
Programul realizeaz o reprezentare Wireframe
pentru o suprafaa Bezier, utiliznd evaluatorul bidimensional EvalCoord2f
*/

#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
GLfloat ctrlpoints[4][4][3] = {
57
{{-1.5, -1.5, -4.0}, {-0.5, -1.5, -4.0},
{0.5, -1.5, -4.0}, {1.5, -1.5, -4.0}},
{{-1.5, -0.5, -4.0}, {-0.5, -0.5, -2.0},
{0.5, -0.5, -2.0}, {1.5, -0.5, -4.0}},
{{-1.5, 0.5, -4.0}, {-0.5, 0.5, -2.0},
{0.5, 0.5, -2.0}, {1.5, 0.5, -4.0}},
{{-1.5, 1.5, -4.0}, {-0.5, 1.5, -4.0},
{0.5, 1.5, -4.0}, {1.5, 1.5, -4.0}}
};

void myinit(void)
{
glClearColor (1.0, 1.0, 1.0, 1.0); // culoarea background-ului
/* funcia glMap2f definete caracteristicile suprafeei Bezier:
- tipul punctelor determinate de funcia glEvalCoord2f
- intervalul de variaie al parametrului u (0 -l in acest caz)
- intervalul valorilor in tabloul ctrlpoints intre doua puncte de control
pe direcia u
- numrul punctelor de control pe direcia u
- intervalul de variaie al parametrului v (0 -l in acest caz)
- intervalul valorilor in tabloul ctrlpoints intre doua puncte de control
pe direcia v
- numrul punctelor de control pe direcia v
- tabloul punctelor de control
*/

glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
0, 1, 12, 4, &ctrlpoints[0][0][0]);
glEnable (GL_MAP2_VERTEX_3 ) ; // validarea tipului de evaluare
// GL_MAP2_VERTEX_3 glMapGrid2 f(20, 0.0, 1.0, 20, 0.0, 1.0);
// intervalele de eantionare
// a suprafeei pentru parametrii u si v. Fiecare parametru variaz ntre 0 i 1 i
sunt // 20 de intervale de eantionare. Deci valorile pentru care se calculeaz puncte
pe //suprafa sunt pentru u i v variind cu un pas de 1/20. }
void CALLBACK display(void) {
int i, j; glClear(GL_COLOR_BUFFER_BIT);
// se folosete si buffer de refresh si buffer de adncime
glColor3f (1.0, 0.0, 0.0); //culoarea curenta
glLoadldentity() ; // pentru a nu aplica transformri geometrice
// la fiecare redesenare a ferestrei glRotatef (-85.0, 1.0, 1.0, 1.0);
//rotaie in jurul axei (1, 1, 1) glTranslatef (0, 0, 4) ;
// urmeaz desenarea wireframe a suprafeei
//fiecare patch (8X8 patch-uri) este desenat //dintr-o linie frnt n 30 de
segmente //de dreapta for (j = 0; j <= 8; j++) {
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
58
// evalueaz un punct pe suprafaa pentru valorile u si v ale ale parametrilor
glEnd();
glBegin(GL_LINE_STRIP); for (i = 0; i <= 30; i++)
glEvalCoord2f((GLfloat)j/8.0, (GLfloat)i/30.0);
glEnd(); }
glFlush() ; }

void CALLBACK myReshape(GLsizei w# GLsizei h) {
if (!h) return;
glViewport(0, 0, w, h) ;
glMatrixMode(GL_PROJECTION);
glLoadldentity(); if (w <= h)
glOrtho(-4.0/4.0,-4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
else
glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
glMatrixMode(GL_MODELVIEW);
glLoadldentity(); }
int main(int argc, char** argv) {
auxInitDlsplayMode(AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300,300); auxInitwindow ("Suprafaa Bezier
wireframe");
myinit();
auxReshapeFunc (myReshape) ;
auxMainLoop(display);
return(0);
}

Observaii:

n exemplul de mai sus se poate remarca asemnarea n utilizarea evaluatorilor
unidimensionali i bidimensionali. Pentru a fi mai clar felul n care se declar tabloul
punctelor de control se recomand afiarea acestei suprafee fr a se aplica cele dou
transformri geometrice (glRotatef, glTranslatef). De asemenea pentru a se obine
rezultate mai bune la reprezentare se recomand ncercarea de a reprezenta suprafaa cu
mai mult de 8X8 patch-uri.

Exemplul 2

n exemplul urmtor se reia reprezentarea suprafeei cu punctele de control
specificate anterior dar utiliznd cellalt tip de evaluator bidimensional glEvalMesh2.
Se poate constata, c dac n exemplul anterior evaluatorul era folosit n corpul
glBegin/glEnd, n acest caz nu mai este necesar acest lucru. Motivul este urmtorul: n
primul exemplu evaluatorul furnizeaz coordonate de vrfuri, iar n al doilea caz se i
genereaz poligoanele care formeaz suprafaa. Deoarece modul de reprezentare al
poligoanelor permite reprezentarea n puncte, linii sau cu umplere (GL_POINT,
59
GL__LINE, GL_FILL) n acest caz suprafaa poate fi reprezentat n toate aceste
modaliti (figura 3.21).
























Figura 3.21

/* Solid_Bezier.c
Programul afieaz o suprafaa Bezier folosind
evaluatori bidimensionali
*/
#include "glos.h"
#include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h>
void myinit(void);
void initlights(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
// tabloul ctrlpoints definete cele 16 puncte de control ale suprafeei
GLfloat ctrlpoints[4][4][3] = {
{{-1.5, -1.5, -4.0}, {-0.5, -1.5, -4.0},
{0.5, -1.5, -4.0}, {1.5, -1.5, -4.0}},
{{-1.5, -0.5, -4.0}, {-0.5, -0.5, -2.0},
{0.5, -0.5, -2.0}, {1.5, -0.5, -4.0}},
{{-1.5, 0.5, -4.0}, {-0.5, 0.5, -2.0},
{0.5, 0.5, -2.0}, {1.5, 0.5, -4.0}},
{{-1.5, 1.5, -4.0}, {-0.5, 1.5, -4.0},
60
{0.5, 1.5, -4.0}, {1.5, 1.5, -4.0}}
};
// setri pentru iluminarea suprafeei
void initlights(void)
{
GLfloat ambient[] = { 1.0, 0.6, 0.0, 1.0 };
GLfloat position[] = { 2.0, 2.0, 2.0, 1.0 };
GLfloat mat_diffuse[] = { 1.0, 0.6, 0.0, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix(); //salvare n stiv matrice curent de modelare
//trei transformri de modelare
//rotaia i translaia poziioneaz suprafaa n fereastra de
vizualizare // iar scalarea mrete dimensiunea suprafeei de 1,7 ori
glRotatef(-85.0, 1.0, 1.0, 1.0);
glTranslatef(0, 0, 6);
glScalef(1.7,1.7,1.7);
glEvalMesh2(GL_POINT, 0, 20, 0, 20); //specifica modul
// de redare al poligoanelor (GL_FILL, GL_POINT, GL_LINE,
// si intervalele de eantionare a suprafeei pentru u si v
glPopMatrix() ;//scoate din stiv matricea de modelare
glFlush() ; }
void myinit(void)
{
glClearColor (1.0, 1.0, 1.0, 1.0); //culoarea background-ului
glEnable (GL_DEPTH_TEST) ; //se activeaz ascunderea
suprafeelor
/* funcia glMap2f definete caracteristicile suprafeei Bezier
- tipul punctelor determinate de funcia glEvalCoord2f
- intervalul de variaie al parametrului u (0 -l in acest caz)
- intervalul valorilor in tabloul ctrlpoints intre doua puncte de control
pe direcia u
- numrul punctelor de control pe direcia u
- intervalul de variaie al parametrului v (0 -l in acest caz)
- intervalul valorilor in tabloul ctrlpoints intre doua puncte de control
61
pe direcia v
- numrul punctelor de control pe direcia v
- tabloul punctelor de control
*/

glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
0, 1, 12, 4, &ctrlpoints[0][0][0]);
glEnable (GL_MAP2_VERTEX_3 ) ; // validarea tipului de evaluare
//GL_MAP2_VERTEX_3 glEnable(GL_AUTO_NORMAL);
glEnable (GL_NORMALIZE) ; // pentru iluminare
glMapGrid2f (20, 0.0, 1.0, 20, 0.0, 1. 0); //intervalele de eantionare
// a suprafeei pentru parametrii u si v
//20 de intervale pentru fiecare parametru.
//fiecare parametru variaz ntre 0 i 1 initlights () ;
/* doar daca se dorete reprezentarea cu iluminare */ }

void CALLBACK myReshape(GLsizei w, GLsizei h) {
if (!h) return;
glViewport(0, 0, w, h) ;
glMatrixMode (GL_PROJECTION) ;
glLoadldentity();
if (w <= h)
glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0) ;
else
glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
glMatrixMode(GL_MODELVIEW);
glLoadldentity(); }
int main(int argc, char** argv) {
auxInitDisplayMode (AUX_SINGLE | AUX_RGB | AUX_DEPTH16);
auxInitPosition (0, 0, 300, 300);
auxInitWindow ("Suprafaa Bezier cu iluminare si atribut de umplere pe
poligoane"); myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0); }

Observaii:
Ca o concluzie, n primul exemplu suprafaa wireframe este reprezentat prin
evaluarea unor puncte pe curbe i prin reprezentarea acestor curbe. In al doilea exemplu
evaluatorii determin vertex-urile unor poligoane i reprezint aceste poligoane n
oricare din modurile posibile pentru poligoane.




62
3 3. .2 2. .4 4 I In nt te er rf fa a a a N NU UR RB BS S

Aa cum am artat, n cazul curbelor Bezier pentru forme mai complicate de
curbe sunt necesare mai multe puncte de control. Pentru a aproxima forma unei curbe pe
baza acestor puncte, n exemplele anterioare fie am crescut gradul polinoamelor de
amestec, fie am asamblat curba din mai multe buci. O soluie pentru construirea
curbelor, care ofer o mai mare flexibilitate n modelare este utilizarea interfeei
NURBS (Non-Uniform Raional B-Spline) din biblioteca GLU. Curbele NURBS sunt
de fapt o metod generalizat care permite descrierea matematic att a curbelor Bezier
ct i a altor curbe. Un alt avantaj al acestor curbe este tipul de continuitate n punctele
de control. Aa cum s-a vzut, n cazul curbelor Bezier ordinul polinoamelor de amestec
crete odat cu numrul punctelor de control. Pentru asamblarea mai multor curbe
programatorul este cel care trebuie s aleag astfel punctele de control ca s se obin
continuitate de ordinul 1 n punctele de control. In cazul curbelor spline, creterea
numrului punctelor de control nu conduce la creterea gradului polinoamelor de
amestec. Gradul polinoamelor este controlat de un alt parametru. Indiferent de numrul
punctelor de control, n cazul curbelor spline se asigur continuitate de ordinul 2 n
noduri (aceasta nseamn c n noduri att derivatele de ordin nti ct i derivatele de
ordin 2 sunt egale).
Curbele B-spline sunt o clas de curbe spline foarte utile n aplicaiile grafice.
Pentru un set de (n+1) puncte de control ph (k variaz de la 0 la n) se pot determina
punctele care aparin unei curbe B-spline aproximat prin punctele de control date,
utiliznd ecuaia parametric urmtoare:

=
=
n
i
u t Nk pk y P
0
) ( , * ) (
Se observ c gradul polinoamelor de amestec (care este t-1) este independent de
numrul punctelor de control (n), ceea ce reprezint un avantaj al curbelor spline.
Funciile de amestec A^, sunt polinoame de gradul (t-l). O metod pentru
definirea polinomului folosit pentru funciile de amestec este de a le defini recursiv fa
de diferitele subintervale din domeniul de variaie al parametrului u. Domeniul de
variaie al parametrului u nu mai este n intervalul [0, 1] ci el este dependent de numrul
punctelor de control i de alegerea fcut pentru t. Astfel u variaz n intervalul:
0 - (n-t+2)
Numrul total al segmentelor de curb va fi deci de (n-t+2). Fiecare din aceste
curbe va fi controlat (ca i form) de t puncte de control din cele (n+l) puncte de
control.
Dac se consider (n+t) subintervale, se definesc funciile de amestec n mod
recursiv:


=
+
altfel
r u r
u N
k k
k
, 0
, 1
) (
1
1 ,
p

) ( ) ( ) (
1 , 1
1 1
1
1 ,
1
1 ,
u N
r r
u r
u N
r r
r u
u N
t k
k k
k
n t
k t k
k
k +
+ +
+

=

Se observ c polinomul de amestec corespunztor unui punct de control se
calculeaz folosind polinoamele de amestec corespunztoare acestui punct i celui
63
urmtor dar de grad mai mic cu 1. Deci pentru fiecare punct de control k, se calculeaz
funciile de amestec plecnd de la t=l. Cu ct t este mai mic se fac mai puine calcule.
Deoarece numitorii, n calculele recursive pot avea valoarea 0, aceast formulare
consider c se evalueaz prin 0 rapoartele 0/0.
Poziiile definite de xj- pentru subintervalele lui u sunt referite ca valori nodale,
iar punctele corespunztoare lor pe o curb B-spline sunt numite noduri. Cele (n-t+2)
segmente de curb vor fi cuprinse ntre aceste noduri. In noduri exist continuitate de
ordinul 2, asigurat de modul n care sunt definite curbele B-spline.
Spre exemplu, pentru n=6 i t=4 curbele B-spline uniforme pot fi caracterizate n
felul urmtor:

Tabelul 3.1
numrul punctelor de control: n+1=7
gradul polinoamelor de amestec t -1 = 3
numrul segmentelor de curb n-t + 2 = 4
intervalul de variaie al lui u [0,4]
numrul nodurilor 5
valorile nodale 0,1,2,3,4
numrul subintervalelor n + t= 10

Valorile nodale pot fi definite n diverse feluri. O distanare uniform a valorilor
nodale se obine prin setarea lui rd egal cu j. Trebuie spus .c n cazul n care valorile
nodale sunt distanate uniform curbele B-spline se numesc curbe B-spline uniforme. O
alt metod de definire uniform a intervalelor este de a seta valorile nodale astfel:

> +
+
<
=
n j pentru t n
n j t pentru t j
t j pentru
rj
2
1
0


Pentru grad 2 (t=3) folosind cinci puncte de control (n4), subintervalele definite
ca n relaiile (3.14), parametrul u variaz n intervalul de la 0 la 3, cu valori nodale de
la r0 la r7 avnd valorile:
r0 = 0
ri = 0
r2 = 0
r3 = 1
r4 = 2
r5 = 3
r6 = 3
r7 = 3
n = 4, t = 3, j [0,7], u[0,3]
r0 = 0; ri = 0; r2 = 0; r3 = 1; r4 = 2; r5 = 3; r6 = 3; r7 = 3;

64
Numrul segmentelor de curb n acest caz va fi 3: Q1, Q2, Q3. Curba Q1 va fi
controlat de punctele P0, P1, P2 . Curba Q2 va fi controlat de punctele P1, P2, P3.
Curba Q3 va fi controlat de punctele P2, P3, P4.
Primul punct de control are influen asupra formei curbei spline doar pentru
valorile lui u cuprinse n intervalul (0,1). n felul acesta se pot localiza uor punctele n
care apar modificri. Dac utilizatorul modific poziia primului punct de control, forma
curbei se va modifica n apropierea acestui punct fr a afecta celelalte poriuni ale
curbei. Pentru valorile date pentru n i t se poate deci realiza urmtoare schem:

Tabelul 3.2
u [0,1] [1, 2] [2,3]
Curba Q1 Q2 Q3
Polinoam
ele care
controleaz
N0, 3
N1,3
N2,3
N1, 3
N2,3
N3,3
N2,3
N3,3
N4.3
Punctele
care controleaz
forma curbei
P0
P1
P2
P1
P2
P3
P2
P3
P4

Folosirea curbelor B-spline prezint avantajul c utilizatorul poate specifica
orice numr de puncte de control fr a fi nevoie pentru aceasta s creasc gradul
curbei. O funcie de grad 3 (funcie cubic n care t=4) poate fi folosit pentru diferite
forme de curbe, fr a fi nevoie pentru aceasta de a compune curba din segmente de
curb ca n cazul curbelor Bezier. Pentru a modifica forma curbei poate fi adugat orice
numr de puncte de control. Nu se aleg valori mai mici pentru t deoarece n cazul n
care, spre exemplu, t=l (funcii de amestec de grad 0) curbele spline sunt discontinue pe
intervalele de variaie ale lui u. n cazul n care t=2 (funcii de amestec de grad 1) se
obine continuitate de ordinul 0 n noduri (curba nu este neted ). In cazul n care t=3
(funcii de amestec de ordin 2) se obine continuitate de ordinul 1 n punctele de
jonciune. Pentru t=4 (funcii de amestec de grad 3) se obine continuitate de ordinul 2
n noduri.
La fel ca i n cazul curbelor Bezier, specificarea mai multor puncte de control,
n poziii apropiate, va conduce la "atragerea" curbei spre poziia respectiv. De
asemenea, pentru obinerea unei curbe nchise trebuie s se specifice primul i ultimul
punct de control avnd aceleai coordonate. De asemenea, curbele spline se aeaz n
interiorul poligonului convex definit de punctele de control.








3 3. .2 2. .5 5 C Cu ur rb be e N NU UR RB BS S

65

Exemplul 1
n acest exemplu se vor utiliza aceleai puncte de control care s-au utilizat n
exemplul 2 de la curbe Bezier. Ceea ce trebuie pus n vederea programatorilor este felul
n care se calculeaz numrul nodurilor i valorile acestora. De asemenea este important
felul n care se stabilesc caracteristicile curbei B-spline. n acest exemplu s-au utilizat 6
puncte de control deci n=5. Deoarece s-a dorit continuitate de ordinul 2 s-au utilizat
polinoame de gradul 3 deci t=4. Ca urmare a relaiilor 3.14 numrul intervalelor nodale
este n+t=9 (deci 10 noduri de la r0 la r9). Valorile nodurilor calculate conform relaiilor
3.14 sunt:
r0=0; ri=0; r2=0; r3=0; r4=l; r5=2; r6=3; r7=3; r8=3; r9=3
Trebuie subliniat c dac valorile nodale i numrul acestora sunt alese aleator,
rezultatele nu sunt controlabile. Forma curbei pentru valorile nodale alese ca mai sus, va
fi asemntoare cu cea a curbei Bezier pentru aceleai puncte de control (figura 3.22).












Figura 3.22

/* Curba_spline.c
Programul utilizeaz biblioteca GLUT
pentru redarea unei curbe spline */

#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
GLUnurbsObj *theNurb; // curba este un obiect de tipul GLUnurbsObj
void myinit(void)
{
glShadeModel (GL_FLAT);
glLineStipple (1, 0x0F0F); //stilul liniei ntrerupte
theNurb = gluNewNurbsRenderer(); // obiectul de tip GLUnurbsObj
gluNurbsProperty (theNurb, GLU_SAMPLING_TOLERANCE, 10.0);
66
}
/* Funcia afieaz o curba B-spline.
*/
void CALLBACK display(void)
{ int i;
GLfloat ctrlpoints[6][3] =
{{ -4.0, 0.0, 0.0}, { -3.0, 4.0, 0.0}, { -1.0, 4.0, 0.0},
{1.0, -4.0, 0.0}, {3.0, -4.0, 0.0}, {4.0, 0.0, 0.0}};
GLfloat knots[10] = {0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0};
glClearColor (1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (0.0, 0.0, 0.0);
gluBeginCurve(theNurb);
gluNurbsCurve(theNurb,
10, knots,
3,
&ctrlpoints[0][0],
4,
GL_MAP1_VERTEX_3);
gluEndCurve(theNurb);
glPointSize(5.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 6; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glEnable(GL_LINE_STIPPLE);
glColor3f(1.0, 0.0, 1.0);
glBegin (GL_LINE_STRIP);
for (i=0; i<6; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
67
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300, 300);
auxInitWindow ("Curba B-spline");
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Exemplul 2
Pentru a exemplifica faptul c interfaa NURBS permite obinerea de curbe de
forme complicate, fr a fi nevoie pentru aceasta s se creasc gradul polinoamelor de
amestec sau s se calculeze poziia punctelor de control pentru a asigura continuitatea
dorit n punctele de contact, vom mai prezenta un exemplu. Se vor da doar funciile
care au suferit modificri fa de exemplul anterior. n figura 3.23 se poate vedea
rezultatul rulrii programului.













Figura 3.23

/* Funcia afieaz o curba B-spline. */
void CALLBACK display(void)
{ int i;
// 6 puncte de control n=5
GLfloat ctrlpoints[17][3] =
GLfloat ctrlpoints[17][3] =
{{ 1.0, 0.0, 0.0}, { 2.0, 1.0, 0.0}, { 1.0, 3.0, 0.0},
{ -1.0, 2.0, 0.0}, { -2.0, 0.0, 0.0}, { -1.0, -2.0, 0.0},
{ 1.0, -3.0, 0.0}, { 3.0, -1.0, 0.0}, { 4.0, 1.0, 0.0},
{ 5.0, 3.0, 0.0}, { 0.0, 5.0, 0.0}, { -3.0, 3.0, 0.0},
68
{ -4.0, -1.0, 0.0}, { -2.0, -5.0, 0.0}, { 2.0, -6.0, 0.0},
{ 4.0, -3.0, 0.0}, { 6.0, 0.0, 0.0}};
// 21 noduri, n+t=20subintervale, valorile sunt calculate dup relaia de mai sus
GLfloat knots[21] = {0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 14.0, 14.0, 14.0};
glClearColor(1.0,1.0,1.0, 1.0); //culoarea background-ului
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (0.0, 0.0, 0.0); //culoarea curenta de desenare
// ncepe corpul de redare al curbei Spline gluBeginCurve(theNurb);
gluNurbsCurve (theNurb, // pointer obiect NURBS
21, knots, //numr noduri, tablou noduri
3 , // intervalul de valori dintre doua puncte de control consecutive
&ctrlpoints [ 0 ] [ 0 ] , // vector puncte de control
4, // ordinul curbei, t=4
GL_MAP1_VERTEX_3 ) ; // tip evaluator
gluEndCurve(theNurb);
/* Se afieaz punctele de control. */
glPointSize(5. 0) ; //de dimensiune 5
glColor3f (1.0, 0.0, 0.0); //culoare roie
glBegin(GL_POINTS) ;
for (i = 0; i < 17; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd() ;
//se unesc punctele de control
glEnable(GL_LINE_STIPPLE) ;
glColor3f(1.0, 0.0, 1.0);
glBegin (GL_LINE_STRIP);
for (i=0; i<17; i + +)
glVertex3fv(&ctrlpoints[i][0]);
glEnd() ;
glFlush() ; }
void CALLBACK myReshape(GLsizei w, GLsizei h) {
if (!h) return;
glViewport(0, 0, w, h) ;
glMatrixMode(GL_PROJECTION);
glLoadldentity();
if (w <= h)
glOrtho(-7.0, 7.0, -7.0*(GLfloat)h/(GLfloat)w,
7.0*(GLfloat)h/(GLfloat)w, -7.0, 7.0) ;
else
glOrtho(-7.0*(GLfloat)w/(GLfloat)h,
7.0*(GLfloat)w/(GLfloat)h, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadldentity();

Suprafee NURBS
69
Vom relua redarea suprafeei definit prin punctele de control din exemplul de la
"Suprafee Bezier". Modul de utilizare al interfeei NURBS pentru reprezentarea
suprafeelor NURBS este foarte asemntor cu cel pentru redarea curbelor NURBS.
Trebuie creat un obiect de tipul GLUnurbsObj, utiliznd funcia gluNewNurbsRenderer.
Apoi se definesc caracteristicile pentru obiectul creat folosind funcia gluNUrbsProperty
pentru fiecare atribut definit. Desenarea suprafeei se face n corpul gluBeginSurf ace
(theNurb) / gluEndSurface (theNurb) utiliznd funcia gluNurbsSurface (gluNurbsCurve
pentru curbe NURBS). Ca i n cazul curbelor trebuie definit tabloul punctelor de
control i tabloul nodurilor. In funcie de numrul punctelor de control (n+1, m+1) i al
ordinului (s sau t) pe fiecare direcie se va stabili i numrul nodurilor (n+s+l sau
m+t+l) pentru fiecare direcie. n cazul exemplului urmtor valorile sunt urmtoarele:

Tabelul 3.3
Parametrul Valoare
n 3
Numrul punctelor de control pe direcia u 4
m 3
Numrul punctelor de control pe direcia v 4
Ordinul s pe direcia u 4
Ordinul t pe direcia v 4
Gradul polinoamelor de amestec pe direcia u (s-1) 3
Gradul polinoamelor de amestec pe direcia v (t-1) 3
Numrul subintervalelor pe direcia u (n+s) 7
Numrul subintervalelor pe direcia v (m+s) 7
Numrul nodurilor pe direcia u
(puncte control+ordin=n+s+l)
8
Numrul nodurilor pe direcia v
(puncte control+ordin=m+t+l)
8

Pentru calcularea valorilor nodurilor se folosesc aceleai relaii ca i n cazul
curbelor (3.14). Desigur c se pot reprezenta i suprafee de forme mult mai complicate.
Exemplul 1
/* Supf_spline_solid2.c
Afieaz o suprafaa spline
folosind biblioteca GLUT */

#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void myinit(void);
70
void CALLBACK display(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);

// tabloul ctrlpoints definete cele 16 puncte de control ale suprafeei

GLfloat ctrlpoints[4][4][3] = {
{{-1.5, -1.5, -4.0}, {-0.5, -1.5, -4.0},
{0.5, -1.5, -4.0}, {1.5, -1.5, -4.0}},
{{-1.5, -0.5, -4.0}, {-0.5, -0.5, -2.0},
{0.5, -0.5, -2.0}, {1.5, -0.5, -4.0}},
{{-1.5, 0.5, -4.0}, {-0.5, 0.5, -2.0},
{0.5, 0.5, -2.0}, {1.5, 0.5, -4.0}},
{{-1.5, 1.5, -4.0}, {-0.5, 1.5, -4.0},
{0.5, 1.5, -4.0}, {1.5, 1.5, -4.0}}
};
GLUnurbsObj *theNurb;
/* Iniializarea buffer-ului de adncime si a atributelor materialului si sursei de
lumina
Iniializarea suprafeei NURBS */

void myinit(void)
{
GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_diffuse[] = { 1.0, 0.2, 1.0, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light0_position[] = { 1.0, 0.0, -1.0, 0.0 };
GLfloat light1_position[] = { -1.0, 0.1, 0.0, 0.0 };
GLfloat lmodel_ambient[] = { 0.3, 0.3, 0.3, 1.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_AUTO_NORMAL);
theNurb = gluNewNurbsRenderer();
gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
//sau GLU_OUTLINE_POLYGON
}
71

void CALLBACK display(void)
{
GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(-85.0, 1.0, 1.0, 1.0);
glTranslatef(0, 0, 6);
glScalef(1.7,1.7,1.7);
gluBeginSurface(theNurb);
gluNurbsSurface(theNurb,
8, //numrul nodurilor n direcia u
knots, // tabloul nodurilor n direcia u
8, //numrul nodurilor n direcia v
knots,
4 * 3, // offsetul ntre puncte de control succesive n direcia u n tabloul
//ctrlpoints
3, // offsetul ntre puncte de control succesive n direcia v n tabloul
ctrlpoints
&ctrlpoints[0][0][0], // tabloul punctelor de control
4, // ordinul curbei s n direcia u, gradul polinoamelor de amestec este s-1
4, // ordinul curbei t n direcia v, gradul polinoamelor de amestec este t-1
GL_MAP2_VERTEX_3);
gluEndSurface(theNurb);
glPopMatrix();
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
else
glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
72
auxInitPosition (0, 0, 300, 300);
auxInitWindow ("Suprafaa B-Spline");
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Observaii:
Se poate observa c forma suprafeei obinute este aceeai cu a suprafeei Bezier
(figura 3.24). n figura 3.24 se poate vedea i reprezentarea wireframe n cazul n care se
folosete constanta GLU_OUTLINE_POLYGON n locul constantei GLU_FILL n
funcia gluNurbsProperty pentru parametrul GLU_DISPLAY_MODE.













Figura 3.24

Exemplul 2
Se va exemplifica i o form mai complicat. Se vor da doar acele funcii care au
suferit modificri fa de exemplul anterior. Reprezentarea suprafeei se poate vedea n
figura 3.25.














Figura 3.25
73

GLfloat ctrlpoints[4][8][3] = {
{{-4.5, -1.5, -4.0}, {-3.0, -1.5, -2.0},
{-1.5, -1.5, -0.0}, {0.0, -1.5, -2.0},
{1.5, -1.5, -4.0}, {3.0, -1.5, -2.0},
{4.5, -1.5, -0.0}, {6.0, -1.5, -2.0}},
{{-4.5, 0.0, -4.0}, {-3.0, 0.0, -2.0},
{-1.5, 0.0, -0.0}, {0.0, 0.0, -2.0},
{1.5, 0.0, -4.0}, {3.0, 0.0, -2.0},
{4.5, 0.0, -0.0}, {6.0, 0.0, -2.0}},
{{-4.5, 1.5, -4.0}, {-3.0, 1.5, -2.0},
{-1.5, 1.5, -0.0}, {0.0, 1.5, -2.0},
{1.5, 1.5, -4.0}, {3.0, 1.5, -2.0},
{4.5, 1.5, -0.0}, {6.0, 1.5, -2.0}},
{{-4.5, 3.0, -4.0}, {-3.0, 3.0, -2.0},
{-1.5, 3.0, -0.0}, {0.0, 3.0, -2.0},
{1.5, 3.0, -4.0}, {3.0, 3.0, -2.0},
{4.5, 3.0, -0.0}, {6.0, 3.0, -2.0}},
};
GLUnurbsObj *theNurb;

void CALLBACK display(void)
{ // punctele de control
GLfloat s_knots[12] = {0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0 };
GLfloat t_knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
glClearColor(1.0, 1.0, 1.0, 1.0); //culoarea background-ului
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
// transformri geometrice pentru poziionarea i
// dimensionarea suprafeei
glRotatef(-85.0, 1.0, 1.0, 1.0);
glTranslatef(0, 0, 6);
glScalef(1.7,1.7,1.7);
gluBeginSurface(theNurb) ; // ncepe redarea suprafeei
gluNurbsSurface (theNurb, //obiectul NURBS
12 , //numrul nodurilor n direcia u
s_knots, // tabloul nodurilor n direcia u
8, //numrul nodurilor n direcia v
t_knots, // tabloul nodurilor n direcia u
4 * 3, // offsetul ntre puncte de control succesive n direcia u n tabloul
ctrlpoints
3, // offsetul ntre puncte de control succesive n direcia v n tabloul ctrlpoints
&ctrlpoints [0] [0] [0] , //tabloul punctelor de control
4, // ordinul curbei s n direcia u, gradul polinoamelor de amestec este s-1
4 , // ordinul curbei t n direcia v, gradul polinoamelor de amestec este t-1
GL_MAP2_VERTEX_3 ); // GL_MAP2_VERTEX_3 sau
GL_MAP2_COLOR_4
74
gluEndSurf ace (theNurb) ; // se termin redarea suprafeei
glPopMatrix();
glFlush() ; * }
void CALLBACK myReshape(GLsizei w, GLsizei h) {
if (!h) return;
glViewport(O, 0, w, h);
glPopMatrix();
glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-7.0, 7.0, -7.0*(GLfloat)h/(GLfloat)w,
7.0*(GLfloat)h/(GLfloat)w, -7.0, 7.0);
else
glOrtho(-7.0*(GLfloat)w/(GLfloat)h,
7.0*(GLfloat)w/(GLfloat)h, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 300, 300);
auxInitWindow ("Suprafaa B-Spline");
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}




3.3 Suprafee cvadrice



Suprafeele cvadrice sunt suprafee definite printr-o ecuaie de gradul al doilea.
Biblioteca GLU dispune de funcii pentru reprezentarea acestui tip de suprafee (sfere,
cilindrii, discuri i poriuni de discuri).
75
Pentru a crea un obiect de tip cvadric, se utilizeaz funcia gluNewQuadric().
Pentru distrugerea obiectului creat, atunci cnd acesta nu mai este necesar, se folosete
funcia gluDeleteQuadric(). Pentru a specifica alte valori dect cele implicite, n
legtur cu stilul de redare al acestor suprafee se utilizeaz anumite funcii:
- gluQuadricNormals() : dac se vor genera normale la suprafee, iar dac da,
se specific dac vor fi specificate relativ la vrfuri sau la suprafee.
- gluQuadricTexture(): dac se genereaz coordonate pentru texturare.
- gluQuadricOrientation(): care fee vor fi considerate exterioare i care
interioare.
- gluQuadricDrawStyle() : stilul de desenare al cvadricelor - cu puncte, linii
sau poligoane.
Dup ce s-a specificat stilul de redare, se apeleaz funciile corespunztoare
tipului de cvadric ce se reprezint: gluSphere(), gluCylinder(), gluDisk() sau
gluPartialDisk(). Dac se dorete mrirea sau micorarea obiectului, este recomandat s
se specifice noile dimensiuni dect s se foloseasc funcia de scalare glScalef().
Motivul este creterea vitezei de reprezentare, avnd n vedere, c dac se utilizeaz
funcia de scalare are loc o renormailzare a normalelor la suprafee. Pentru o redare a
iluminrii ct mai precis se recomand valori ridicate pentru parametrii loops i stacks.
n continuare se vor da prototipurile tuturor acestor funcii.

Funcii pentru controlarea obiectelor
GLUquadricObj* gluNewQuadric (void);
- Funcia permite crearea unei cvadrice.
void gluDeleteQuadric (GLUquadricObj *state);
- Funcia permite tergerea unei cvadrice.
Funcii pentru modificarea felului n care sunt desenate cvadricele
void gluQuadricNormals (GLUquadricObj *quadObject, Glenum normals) ;
- Parametrul normals poate lua urmtoarele valori:

Tabelul 3.4

GLU_NONE Nu se genereaz normale pentru iluminare
GLU_FLAT Normalele sunt generate pentru fiecare fa, rezultnd o iluminare
poligonal constant pe poligoane
GLU_SMOOTH Normalele sunt generate pentru fiecare vrf, rezultnd o iluminare
GOURAUD.

- voidgluQuadricTexture(GLUquadricObj*quadObject,
GLboolean textureCoords);
- Funcia activeaz (GL_TRUE) sau dezactiveaz (GL_FALSE) generarea
coordonatelor de texturare.
- void gluQuadricOrientation (GLUquadric *quadObject, GLenum
orientation);
- Funcia controleaz direcia normalelor pentru iluminare. Acestea pot
avea orientarea spre exteriorul obiectelor (GLU_OUTSIDE) sau spre
interiorul acestora (GLU_INSIDE).
- void gluQuadricDrawStyle (GLUquadricObj *quadObject, GLenum
76
drawStyle);
- Funcia specific tipul primitivelor OpenGL utilizate pentru
reprezentarea cvadricelor. Parametrul drawStyle poate lua urmtoarele
valori:


Tabelul 3.5

GLU__FILL Cvadricele au atribut de umplere i pentru generarea lor sunt
utilizate poligoane.
GLU__LINE Cvadricele sunt reprezentate wireframe utiliznd primitivele
pentru reprezentarea liniilor
GLU__SILHOUETTE Cvadricele sunt reprezentate utiliznd primitivele pentru linii;
sunt desenate doar muchiile exterioare.
GLU POINT Cvadricele sunt reprezentate utiliznd ca primitiv punctul

Funcii pentru specificarea tipului cvadricei
void gluCylinder(GLUquadricObj *qobj, GLdouble baseRadius, GLdouble
topRadius,GLdouble height, GLint slices, GLint stacks);
- Funcia genereaz un cilindru avnd centrul bazei n originea sistemului
de axe. Funcia poate fi utilizat i pentru generarea conurilor, prin
specificarea uneia dintre cele dou raze ca fiind 0.
- Slices reprezint numrul poligoanelor care se genereaz n jurul
cilindrului.
- stacks reprezint numrul poligoanelor generate n lungul cilindrului (figura
3.26). Aceast valoare va crete atunci cnd se dorete o iluminare mai bun.













Figura 3.26







77


Figura 3.27

void gluDisk(GLUquadricObj *qobj, GLdouble innerRadius, GLdouble
outerRadius, GLint slices, GLint loops);
- Discurile (figura 3.27) sunt forme plane care au forma unui CD (sau
dischet). Funcia poate fi utilizat i pentru generarea cercurilor.
- innerRadius reprezint raza interioar;
- outerRadius reprezint raza exterioar.
- slices reprezint numrul sectoarelor generate.
- loops reprezint numrul cercurilor concentrice generate la reprezentarea
discurilor.
void gluPartialDisk(GLUquadricObj *qobj, GLdouble innerRadius, GLdouble
outerRadius, Glint slices, GLint loops, GLdouble startAngle, GLdouble sweepAngle);
- Funcia este utilizat pentru reprezentarea unui sector dintr-un disc. Pentru
aceasta se specific valorile unghiurilor ntre care se ncadreaz sectorul.
Funcia poate fi utilizat i pentru generarea unui sector dintr-un cerc.
void gluSphere(GLUquadricObj *qobj, Gldouble radius, GLint slices, GLint
stacks);
- Funcia reprezint o sfer.
- slices determin numrul longitudinilor generate,
- stacks pe cel al latitudinilor generate Ia reprezentarea sferei.

Exemplu:
n exemplul urmtor se arat felul n care se pot utiliza funciile GLU pentru
redarea cvadricelor. n figura 3.28 se pot vedea obiectele pe care le deseneaz
programul urmtor.









Figura 3.28

/* cvadrice.c
Programul arat modul de utilizare al cvadricelor din GLU pentru desenare de
cilindri, conuri, sfere, disk-uri, cercuri, arce de cerc, sectoare de disk. */
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void initlights(void);
78
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
GLUquadricObj * quadObj ; //obiect de tip cvadric
// setri pentru iluminarea suprafeei
void initlights(void) {
GLfloat ambient[] = { 1.0, 0.6, 0.0, 1.0 };
GLfloat position0[] = { -3.0, 0.0, 2.0, 0.0 };
GLfloat position1[] = { 1.0, 0.0, 1.0, 0.0 };
GLfloat mat_diffuse[] = { 1.0, 0.6, 0.0, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT1, GL_POSITION, position1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}
void CALLBACK display(void) {//terge ecranul
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear (GL_COLOR_BUFFER_BIT);
//Stabilete atributele, comune pentru toate cvadricele.
quadObj = gluNewQuadric () ; //genereaz cvadric
gluQuadricDrawStyle (quadObj, GLU_FILL) ; //atribut de umplere
gluQuadricNormals (quadObj ,GLU_SMOOTH) ; //iluminare GOURAUD
//reprezint sfera
glPushMatrix();
glTranslatef (-15.0, 0.0, 0.0);
gluSphere(quadObj, 2.5, 20.0, 20);
glPopMatrix(); //reprezint cilindru
glPushMatrix () ;
glRotatef(30, 1, 1, 0);
glTranslatef (-11.0, 1.5, 0.0);
gluCylinder(quadObj, 2.0, 2.0, 4.0, 20.0, 20);
glPopMatrix(); //reprezint conul
glPushMatrix();
glRotatef(30, 1, 1, 0);
glTranslatef (-5.0, 0.8, 0.0);
gluCylinder(quadObj, 2.0, 0.0, 5.0, 20.0, 20);
glPopMatrix(); //reprezint disk-ul
glPushMatrix();
glTranslatef (1.0, 0.0, 0.0);
gluDisk (quadObj, 1.0, 2.5, 20, 20);
79
glPopMatrix(); //reprezint cercul
glPushMatrix();
glTranslatef (7.0, 0.0, 0.0);
gluDisk (quadObj, 0.0, 2.5, 20, 20);
glPopMatrix(); //reprezint sectorul de disk
glPushMatrix();
glTranslatef (11.0, 0.0, 0.0);
gluPartialDisk (quadObj, 1.0, 2.5, 20, 20, 10.0, 90.0);
glPopMatrix(); //reprezint sectorul de cerc
glPushMatrix();
glTranslatef (15.0, 0.0, 0.0);
gluPartialDisk (quadObj, 0.0, 2.5, 20, 20, 10.0, 90.0);
glPopMatrix(); glFlush() ; }
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-8.0, 8.0, -8.0*(GLfloat)h/(GLfloat)w,
8.0*(GLfloat)h/(GLfloat)w, -8.0, 8.0);
else
glOrtho(-8.0*(GLfloat)w/(GLfloat)h,
8.0*(GLfloat)w/(GLfloat)h, -8.0, 8.0, -8.0, 8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (10, 10, 750, 300);
auxInitWindow ("Cvadrice");
initlights();
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}



3.4 Primitive raster



80
D
a
t
e

v

r
f
u
r
i
D
a
t
e

p
i
x
e
l
i
Liste de
display
Evaluator
polinomial
Operaii
cu pixeli
Operaii
pe vrfuri
Rasterizare
Memorare
textur
Operaii pe
fragment
Bufferul
de cadru
OpenGL nu este doar o interfa complet pentru aplicaiile de grafic vectorial
3D ci este, de asemenea, un foarte bun motor de procesare a imaginilor (utilizate n
aplicaiile de grafic punctual sau raster).
Primitivele conin explicit informaii de culoare pentru fiecare pixel pe care-1
conin. In Windows se utilizeaz denumirea de bitmap att pentru bitmap-urile
monocrome ct i pentru cele color. n OpenGL, spre deosebire de Windows, se face
distincie ntre bitmap-uri i pixelmap-uri. OpenGL lucreaz deci cu dou tipuri de
primitive raster:
- Bitmap-urile care utilizeaz un singur bit (0 sau 1) pentru fiecare pixel. Ele sunt
utilizate, n principal, ca tablouri 2D de mti la nivel de bit pentru a determina
care pixeli s fie actualizai. Culoarea curent, setat cu funcia glColor() este
utilizat pentru a determina noua culoare a pixelilor corespunztori valorii 1 din
bitmap, n timp ce pixelii corespunztori biilor 0 sunt transpareni.
- Pixelmap-urile (imagini) sunt blocuri de pixeli (tablouri 2D) cu informaii
complete de culoare pentru fiecare pixel.

n ceea ce privete fiierele de imagini se subliniaz c OpenGL nu nelege
formatele de imagini, cum ar fi JPEG, PNG, sau GIF-uri. Pentru ca OpenGL s poat
utiliza informaiile coninute n aceste formate de fiiere, fiierul trebuie s fie citit i
decodificat pentru a obine informaia de culoare, i plecnd de aici OpenGL poate
rasteriza valorile culorilor.

Fluxul de procesare al pixelilor















Figura 3.29

n figura 3.29 se d procesarea n cascad a primitivelor geometrice i de
asemenea a pixelilor. Pixelii sunt citii din memoria principal, sunt procesai pentru a
se obine formatul intern pe care-1 utilizeaz OpenGL, care poate include modificri de
culoare sau nlocuiri de octei. Dup aceasta, este procesat fiecare pixel din imagine prin
operaiile pe fragment din ultima seciune a fluxului de procesare, i n final rasterizate
n buffer-ul de cadru.
81
Modul de
pstrare al
pixelilor
glBitmap()
Operaii de
transfer pixel
Pixel Map
Rasterizare
Pixel Zoom
Memorie
textur
Operaii pe
fragment
Buffer de
cadru
glReadPixel(), glCopyPixel()
glCopyText*Image()
glDrawPixels()
CPU
Suplimentar redrii n buffer-ul de cadru, pixelii pot fi copiai din buffer-ul de
cadru napoi n memoria gazd, sau transferai n memoria de mapare a texturii.
Pentru performane mai bune, reprezentarea intern a tabloului de pixeli va fi n
concordan cu hardware-ul. Spre exemplu, pentru un buffer de cadru de 24 bii, RGB
8-8-8 va fi probabil o potrivire bun, dar RGB 10-10-10 ar fi o potrivire rea.
Atenie:
Pentru valori neimplicite, memorarea i transferul pixelilor se face foarte ncet.
n figura 3.30, pe lng fluxul de procesarea pixelilor sunt specificate i funciile
OpenGL utilizate n fiecare etap.









Figura 3.30
Bitmap-urile i pixmap-urile sunt cele dou primitive care nu sunt afectate de
operaiile geometrice care au loc n fluxul operaiilor anterior rasterizrii.



3 3. .4 4. .1 1 R Re ep pr re ez ze en nt ta ar re ea a i im ma ag gi in ni il lo or r b bi it tm ma ap p


Un bitmap specific un dreptunghi complectat cu 0 i 1, i este mult utilizat
pentru descrierea caracterelor care pot fi plasate la o locaie proiectat 3D (prin poziia
raster curent). Fiecare 1 din bitmap produce un fragment ale crui valori asociate sunt
cele ale poziiei raster curente, n timp ce pentru fiecare 0 nu se produce nici un
fragment. Comanda glBitmap() specific de asemenea offset-urile care controleaz cum
este plasat bitmap-ul n funcie de poziia raster curent i cum poziia raster curent
este modificat dup ce se deseneaz bitmap-ul (astfel determinnd poziiile relative ale
bitmap-uilor succesive).


Poziionarea primitivelor raster

glRasterPos3f( x, y, z)
- poziia raster (figura 3.31) este afectat de transformri ca i poziia geometric;
- primitiva bitmap nu se afieaz dac poziia raster este n exteriorul viewport-
ului.
Imaginile sunt poziionate prin specificarea poziiei raster, care mapeaz colul
stnga jos al unei primitive imagine la un punct din spaiu. Poziiile raster sunt
transformate i decupate la fel ca vrfurile. Dac o poziie raster se pierde prin
decuparea fa de viewport, nu mai este rasterizat nici un fragment din primitiva bitmap.
82







Figura 3.31 Poziia raster


Redarea Bitmap-urilor

glBitmap (width, height, xorig, zorig, xmove, zmove, bitmap) ;
- funcia red bitmap-ul n culoarea curent;
- dup redarea primitivei, poziia raster curent este actualizat.
Bitmap-urile sunt utilizate ca o masc pentru a determina care pixeli s fie
actualizai. Un bitmap este specificat ca un tablou mpachetat de bii ntr-un tablou de
tip byte. Pentru fiecare valoare de 1 dintr-un bitmap, este generat un fragment n
culoarea curent i apoi este procesat de operaiile pe fragment.
Bitmap-urile pot avea propria lor origine, care asigur o poziie relativ fa de
poziia raster curent. Suplimentar, dup ce se red bitmap-ul, poziia raster este
actualizat n mod automat prin offset-ul furnizat n (xmove, ymove). Dac originea
bitmap-ului este (0,0) atunci colul stnga jos al bitmap-ului va fi plasat n poziia raster
curent. Dac originea bitmap-ului este diferit de (0,0) atunci poziia raster curent va
fi utilizat pentru plasarea originii bitmap-ului. Dac poziia raster curent este n
exteriorul viewport-ului, chiar dac pentru aceast poziie s-ar putea reprezenta parial
bitmap-ul, totui el nu este redat deloc. Deci, din acest punct de vedere, primitivele
raster nu se comport la fel cu primitivele vectoriale, care sunt decupate fa de
viewport.
















Figura 3.32

Poziie raster
width
yorig
xorig
height
83
Coordonatele originii bitmap-ului se stabilesc relativ la colul stnga-jos al
bitmap-ului. Pentru figura 3.32 coordonatele originii sunt (xorig=2, yorig=2).
Dimensiunea bitmap-ului este height=32, width=32.
Bitmap-urile sunt utile n mod particular pentru redarea font-urilor de tip bitmap,
despre care se va discuta n continuare. n acest caz facilitatea de actualizare a poziiei
raster curente este utilizat din plin.

Exemplul 1
Exemplul urmtor red bitmap-ul din figura 3.33, succesiv n fereastra aplicaiei.
Dimensiunea ferestrei iniial este de 200X200 pixeli. Pentru viewport-ul
aplicaiei, de 10X10 uniti, va rezulta c fiecare unitate are 20 de pixeli. Bitmap-ul
fiind de 32X32 pixeli, vom stabili prin program o repetare a bitmap-ului din 2 n 2
uniti, adic un bitmap la 40 de pixeli. Distana dintre dou bitmap-uri succesive va fi
de 8 pixeli. n figura 3.34 se poate vedea cum va arta fereastra aplicaiei.












Figura 3.33

Mai trebuie subliniat felul n care se specific un bitmap. Bitul 7 din primul octet
al tabloului care descrie bitmap-ul corespunde pixelului stnga jos al bitmap-ului. Deci
descrierea bitmap-ului ncepe cu primul rnd din partea de jos a bitmap-ului.











Figura 3.34
n continuare, se d codul aplicaiei.
/*utilizarea bitmap-urilor n OpenGL*/
#include "glos.h"
#include <GL/gl.h>
84
#include <GL/glu.h>
#include <GL/glaux.h>
#include <math.h>

void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
void CALLBACK display(void)
{ int i, j;
GLubyte model[] = {
0x03, 0xc0, 0, 0,
0x0f, 0xf0, 0, 0,
0x1e, 0x78, 0, 0,
0x39, 0x9c, 0, 0,
0x77, 0xee, 0, 0,
0x6f, 0xf6, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0x73, 0xce, 0, 0,
0x73, 0xce, 0, 0,
0x3f, 0xfc, 0, 0,
0x1f, 0xf8, 0, 0,
0x0f, 0xf0, 0, 0,
0x03, 0xc0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
for(i=-5; i<5; i+=2)
for(j=-5; j<5; j+=2)
85
{
glRasterPos2i(i,j);
glBitmap(32, 32, 0.0, 0.0, 0.0, 0.0, model);
}
glFlush();
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("O fereastr cu bitmap-uri");
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}



3 3. .4 4. .2 2 R Re ep pr re ez ze en nt ta ar re ea a f fo on nt tu ur ri il lo or r p pr ri in n b bi it tm ma ap p- -u ur ri i

n OpenGL, pentru redarea caracterelor, se pot utiliza fonturi vectoriale sau
fonturi bitmap. Fonturile vectoriale sunt construite din segmente de dreapt i se
preteaz pentru dispozitivele vectoriale (plotere spre exemplu). Fonturile bitmap
construiesc fiecare caracter ca un bitmap. Pentru a se facilita utilizarea fonturilor, n
OpenGL se utilizeaz listele de display. Fiecare list de display conine doar un apel
glBitmap(), pentru redarea caracterului corespunztor. Listelor de display le sunt
asociate n mod unic, identificatori (numere) care pentru caracterele fontului pot fi alese
ca valori succesive. n felul acesta pentru redarea unui text trebuie apelate listele de
display corespunztoare caracterelor din textul respectiv. Pentru construirea bitmap-
urilor corespunztoare fiecrui caracter dintr-un font exist dou posibiliti:
Se declar tabloul de tip unsigned byte (tipul GLubyte n OpenGL) care conine
caracterele respective.
86
Se construiesc bitmap-urile corespunztoare fiecrui caracter pe baza fontului
curent din sistemul de ferestre cu care se lucreaz. Sistemele de ferestre au pentru
aceasta funcii proprii. Windows-ul, spre exemplu, dispune de funcia
wglUseFontBitmaps(). i n acest caz, se utilizeaz pentru manevrarea fontului tot
listele de display. Fiecare caracter este memorat ntr-o list de display care este parte a
unui set creat la procesarea fontului.
n continuare, se vor exemplifica ambele modaliti.




Construirea unui caracter i afiarea sa

Vom ncepe cu exemplificarea modului n care primitivele bitmap sunt utilizate
n OpenGL pentru construirea i afiarea unui caracter. n acest caz nu apar modificri
fa de afiarea obinuit a unui bitmap. Se construiete tabloul care conine caracterul.
Se ine seama de faptul c limea bitmap-ului trebuie s fie un numr par de octei.
Pentru caracterul "E" afiat de exemplul nostru (figura 3.35), utilizm un bitmap de
10X12. Avem nevoie de un tablou de octei, cte doi octei pentru fiecare linie a bitmap-
ului. Din acest tablou, pentru construirea bitmap-ului vor fi utilizai doar primii 10 bii
din fiecare rnd. Originea bitmap-ului se va considera colul stnga jos al bitmap-ului.
Ce mai trebuie remarcat, este faptul c funcia glRasterPos2i () utilizeaz coordonate
logice iar offset-ul pentru actualizarea poziiei curente, din funcia glBitmap() este dat n
pixeli. n cazul acestui exemplu, fereastra are 200X200 pixeli (uniti fizice). Funcia
myReshape () stabilete cte 10 uniti logice pe fiecare ax, n intervalul [-5, 5]. Deci
fiecrei uniti logice i corespund 20 uniti fizice (pixeli). Pentru a deplasa cu o unitate
fiecare caracter, n funcia glBitmap, actualizarea poziiei curente s-a fcut cu 20 pixeli
pe axa x i cu 0 pixeli pe axa y.









Figura 3.35

Exemplu:
/* Programul este un exemplu de utilizare a primitivei bitmap * in OpenGL,
pentru desenarea fonturilor. */
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

87
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
// tabloul care conine litera E, 2 octei X 12 rnduri
GLubyte litera_E[24] = {
0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xff, 0x00, 0xff, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xff, 0xc0, 0xff, 0xc0};

void CALLBACK display(void)
{
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glClearColor (1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (0.0, 0.0, 0.0);
glRasterPos2i (-2.0, 0.0);
//poziia curent pentru primul bitmap
// dat n uniti logice (sunt 10 uniti pe axa x n intervalul(-5, 5))
glBitmap (10, 12, 0.0, 0.0, 20.0, 0.0, litera_E);
// deplasarea poziiei curente este dat n pixeli - 20 de pixeli pe axa x
glBitmap (10, 12, 0.0, 0.0, 20.0, 0.0, litera_E);
glBitmap (10, 12, 0.0, 0.0, 20.0, 0.0, litera_E);
glBitmap (10, 12, 0.0, 0.0, 20.0, 0.0, litera_E);
glFlush();
}
// proiecie ortogonal
//se mapeaz 10 uniti pe fiecare ax, o unitate are 20 pixeli

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho (-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("Bitmap_E");
auxReshapeFunc (myReshape);
88
auxMainLoop(display);
return(0);
}













Figura 3.36

n figura 3.36 este dat fereastra afiat de aceast aplicaie.

Funcii pentru manevrarea listelor de display utilizate pentru fonturile bitmap.

Pentru utilizarea fonturilor bitmap n OpenGL, anumite funcii pentru listele de
display au o relevan deosebit. Trebuie subliniat c aceste funcii se utilizeaz la fel i
pentru fonturile vectoriale. Acestea sunt:
- void glNewList( GLuint list, GLenum mode );
- void glEndList(void);
Funciile glNewListO i glEndListO creeaz lista de display cu identificatorul
list. Parametrul mode stabilete modul de compilare al listei de display.
- GLuint glGenLists( GLsizei range );
Funcia creeaz un set de liste de display, cu identificatori succesivi i care sunt
goale (nu conin nici o comand). Funcia returneaz identificatorul primei liste
de display n, iar celelalte liste vor avea identificatorii n+J, n+2,..., n+range-1.
Parametrul range este numrul listelor de display create.
- void glListBase( GLuint base );
Funcia glListBase() seteaz baza listelor de display, pentru funcia glCallLists.
- void glCallLists( GLsizei n, GLenum type, const GLvoid *lists );
Funcia execut o list de liste de display. Parametrul n este numrul listelor de
display care vor fi executate. Parametrul type este tipul elementelor din lists.
Parametrul lists este adresa unui tablou cu numele ofseturilor n listele de
display.
- void glCallList( GLuint list );
Funcia execut lista de display al crui identificator (ntreg) este dat ca
parametru.
- void glDeleteLists( GLuint list, GLsizei range );
Funcia terge un grup de liste de display ("range" liste de display) avnd
identificatori succesivi, ncepnd cu identificatorul list.
89
Un font, aa cum probabil se tie, este un ir de caractere, fiecare caracter avnd
asociat un numr de identificare, de obicei acesta fiind codul ASCII al
caracterului. Fiecare caracter are i o anumit form grafic, aceasta fiind
coninut n bitmap-ul asociat caracterului respectiv. Spre exemplu, caracterul 'A'
are codul ASCII 65 (41H), caracterul 'B' are codul ASCII 66 (42H), caracterul
'C are codul ASCII 67 (43H), .a.m.d. La modul cel mai simplu, listele de display
asociate cu afiarea caracterelor pot avea ca identificatori chiar codurile ASCII
ale caracterelor. n acest caz, pentru afiarea irului "ABC" se vor executa listele de
display avnd identificatorii 65, 66, 67. Pentru aceasta se poate apela funcia
glCallLists(). Parametrul n va conine lungimea irului de caractere, 3 n cazul
nostru, iar tabloul lists va conine codurile ASCII ale caracterelor.
- glCallLists(3, GL_UNSIGNED_BYTE, "ABC");
Avnd acum n vedere faptul c exist mai multe tipuri de fonturi, avnd corpuri
de caractere diferite, utilizarea codurilor ASCII nu mai pare a fi o soluie
convenabil. Se poate ns proceda n felul urmtor: pentru fiecare font se
adaug un offset, fa de care se stabilesc identificatorii fiecrei liste de display.
Deoarece numrul maxim al caracterelor dintr-un font nu depete 255, un
offset de 1000, spre exemplu, este o soluie convenabil. In felul acesta un font
va utiliza liste de display cu identificatorii cuprini ntre 1000 i 1255, urmtorul
font va utiliza liste cu identificatorii cuprini ntre 2000 i 2255, .a.m.d. Pentru
stabilirea offset-ului se poate utiliza comanda glListBase().
Deoarece este necesar ca listele de display corespunztoare caracterelor dintr-un
font s aib identificatori succesivi se va utiliza pentru aceasta comanda
glGenLists(). Spre exemplu, dac se dorete un font cu toate cele 255 de
caractere apelul va fi:
- glGenLists(255);
Funcia va stabili identificatori unici pentru fiecare list de display. Dac funcia
nu gsete un bloc de 255 de identificatori succesivi, va returna 0. Pentru a
terge o parte din listele de display se poate utiliza funcia glDeleteLists().
Cum se utilizeaz aceste funcii pentru fonturile bitmap, se va vedea n cele dou
exemple care vor urma.


Construirea intern a unui font

nainte de toate, trebuie spus c exemplul urmtor se bazeaz pe exemplul din
fiierul font.c, care face parte din exemplele pentru utilizarea bibliotecii OpenGL,
existente n nucleul de instalare pentru Visual C 6.0, preluate din OpenGL Programming
Guide. n acest exemplu, tabloul rasters[] conine toate cele 95 de caractere ASCII
tipribile (coduri ASCII cuprinse ntre 32 i 127), inclusiv spaiul. Fiecare caracter este
construit n tabloul rasters, aa cum s-a construit i caracterul E din exemplul anterior.
Listele de display sunt construite n funcia makeRasterFont(). Fiecare list de display
are asociat ca identificator codul ASCII al caracterului la care se adaug un offset
obinut de funcia glGenLists() (apelat n funcia makeRasterFont()), i conine ca i
comand funcia glBitmap(). Dup afiarea fiecrui caracter, poziia curent este
actualizat prin adugarea unui offset pe axa x, de 10 pixeli. n figura 3.7 se poate vedea
fereastra aplicaiei.
90
















Figura 3.37

Exemplu:
/*
Aplicaia afieaz texte n OpenGL, utiliznd un font bitmap.
Pentru construirea caracterelor fontului utilizeaz glBitmap() i alte funcii
pentru primitive raster. Aplicaia utilizeaz de asemenea listele de display. */

#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

void makeRasterFont(void);
void printString(char *s);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00},
//caracterul spaiu
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18},
//caracterul !
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36,
0x36},
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00,
0x00},
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8,
0x70},
91
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c,
0x38},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c,
0x0e},
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18,
0x0c},
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18,
0x30},
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00,
0x00},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00,
0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03,
0x03},
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66,
0x3c},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38,
0x18},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7,
0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7,
0x7e},
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03,
0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7,
0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7,
0x7e},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c,
0x06},
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30,
0x60},
92
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3,
0x7e},
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7,
0x7e},
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x7e},
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7,
0x7e},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66,
0x3c},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7,
0x7e},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
0xc3},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
0xc3},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66,
0xc3},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66,
0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x3c},
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60,
0x60},
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x3c},
93
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c,
0x18},
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30,
0x70},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03,
0x03},
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33,
0x1e},
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18,
0x00},
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c,
0x00},
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x78},
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00},
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30,
0x00},
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00,
0x00},
94
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00,
0x00},
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00,
0x00},
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18,
0x0f},
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18},
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18,
0xf0},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00,
0x00}
};

GLuint fontOffset;
void makeRasterFont(void)
{
GLuint i;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
fontOffset = glGenLists (128);
for (i = 32; i < 127; i++) {
glNewList(i+fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, rasters[i-32]);
glEndList();
}
}
void printString(char *s)
{
glPushAttrib (GL_LIST_BIT);
glListBase(fontOffset);
glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);
glPopAttrib ();
}

void CALLBACK display(void)
{
int i, j;
char teststring[33];
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
makeRasterFont();
95
for (i = 32; i < 127; i += 32)
{
glRasterPos2i(20, 200 - 18*i/32);
for (j = 0; j < 32; j++)
teststring[j] = (char) (i+j);
teststring[32] = 0;
printString(teststring);
}
glRasterPos2i(20, 100);
printString("Aceasta este o aplicate pentru");
glRasterPos2i(20, 82);
printString("ilustrarea afirii irurilor.");
glRasterPos2i(20, 64);
printString("de caractere dintr-un font bitmap.");
glRasterPos2i(20, 46);
printString("Sunt utilizate listele de display.");
glFlush ();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho (0.0, w, 0.0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 400, 200);
auxInitWindow ("Font bitmap");
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}


Crearea textelor n OpenGL cu fonturi Windows

Aa dup cum s-a artat, aplicaiile Windows beneficiaz de funcii suplimentare
(aparinnd sistemului) pentru utilizarea fonturilor sistemului. Funcia
wglUseFontBitmaps() creeaz un set de liste de display pentru a fi utilizate ntr-un
context de redare OpenGL. Fontul obinut se bazeaz pe fontul curent selectat n
contextul de dispozitiv.
BOOL wglUseFontBitmaps ( HDC hdc,
96
//contextul de dispozitiv al crui font se va utiliza
DWORD first, // caracterul corespunztor primei liste de display
DWORD count, // numrul caracterelor ce vor fi plasate n listele de display
DWORD 1istBase // specific identificatorul listei de display a
// primului caracter din font
) ;


Exemplu:

n exemplul urmtor se arat cum se pot afia caractere n OpenGL utiliznd un
font bitmap construit pe baza fontului curent din contextul de dispozitiv curent. Pentru
aceasta s-a utilizat funcia wglUseFontBitmaps(), care construiete cte o list de
display pentru fiecare caracter al fontului. Fiecare list de display nu conine altceva
dect o funcie glBitmap care construiete bitmap-ul corespunztor caracterului
respectiv. Spre deosebire de aplicaia anterioar, funcia makeRasterFont este nlocuit
de funcia CreazaFontBitmap(), cu acelai rol. Funcia printstring() este nlocuit de
funcia AfiseazaSirBitmap(), cu acelai rol. Rezultatul rulrii programului este afiat n
figura 3-38. Codul aplicaiei este dat n continuare.














Figura 3.38

/* Aplicaia arat felul n care sunt redate fonturile
* n aplicaii OpenGL care utilizeaz ferestrele Windows */

#include <windows.h>
#include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void CALLBACK myReshape(GLsizei w, GLsizei h);
void SetDCPixelFormat(HDC hdc);
97
GLuint CreazaFontBitmap(HGLRC hdc, HFONT font, char *typface, int height,
int weight, DWORD italic);
void StergeFontBitmap(GLuint font);
void AfiseazaSirBitmap(GLuint font, char *s);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Fonturi" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;
hwnd = CreateWindow (szAppName, "Fonturi bitmap",

WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
50, 50,
300, 300,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM
wParam, LPARAM lParam)
{
static HDC hDC ;
static HGLRC hRC;
static GLuint base;
HFONT font;
switch (iMsg)
98
{
case WM_SIZE:
myReshape(LOWORD(lParam), HIWORD(lParam));
break;
case WM_CREATE:
hDC=GetDC(hwnd);
SetDCPixelFormat(hDC);
hRC=wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);
break;
case WM_PAINT:
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
base=CreazaFontBitmap(hDC, font, "Ariel", 0, 0, FALSE);
glRasterPos2i(-4, 0);
AfiseazaSirBitmap(base, "123456789!%&'()*+,-");
glRasterPos2i(-4,-1);
AfiseazaSirBitmap(base, "OpenGl");
glRasterPos2i(-4,-2);
AfiseazaSirBitmap(base, "Prelucrare grafica- Tehnologia Informatiei");
glFlush();
ValidateRect(hwnd, NULL);
}
break;
case WM_DESTROY:
StergeFontBitmap(base);
DeleteObject(font);
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho (-5.0*(GLfloat)w/(GLfloat)h,
99
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
}
void SetDCPixelFormat(HDC hdc)
{
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,0,
0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0};
nPixelFormat=ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, nPixelFormat, &pfd);
}
GLuint CreazaFontBitmap(HDC hdc, HFONT font, char *typface, int height, int
weight, DWORD italic)
{
GLuint base;
if((base=glGenLists(255))==0)
return(0);
if(stricmp(typface, "symbol")==0)
font=CreateFont(height, 0, 0, 0, weight, italic, FALSE,
FALSE,SYMBOL_CHARSET, OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
DEFAULT_PITCH, typface);
else
font=CreateFont(height, 0, 0, 0, weight, italic, FALSE, FALSE,
ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
DRAFT_QUALITY,
DEFAULT_PITCH, typface);
SelectObject(hdc, font);
wglUseFontBitmaps(hdc, 0, 255, base);
return(base);
}
void StergeFontBitmap(GLuint base)
{
100
if (base==0)
return;
glDeleteLists(base, 255);
}
void AfiseazaSirBitmap(GLuint base, char *s)
{
if(base==0)
return;
if(s==NULL)
return;
glPushAttrib(GL_LIST_BIT);
glListBase(base);
glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);
glPopAttrib();
}




3 3. .4 4. .3 3 R Re ed da ar re ea a p pi ix xm ma ap p- -u ur ri il lo or r


Imaginile care folosesc mai mult de dou culori sunt numite pixmap-uri
(prescurtarea de la "pixel map" din limba englez). Pixmap-urile sunt utilizate n
principal, n OpenGL, ca imagini de fundal sau ca texturi. Un pixmap este un grup de
valori destinat memoriei video. Un pixmap (dreptunghi de pixeli) este similar cu un
bitmap, cu excepia faptului c, de obicei, valorile reprezint culori, dei este alocat
spaiu i pentru alte tipuri de date cum ar fi valori ale adncimii. n OpenGL, pixmap-
urile sunt, n general, fie imagini n index de culoare (8 bii/pixel) fie imagini RGB (24
bii/pixel).

Funcia de redare a pixmap-urilor

Pentru redarea pixmap-urilor, OpenGL dispune de o singur funcie, i anume
glDrawPixels(). Spre deosebire de funcia pentru desenarea bitmap-urilor glBitmap(),
aceast funcie nu permite specificarea unei originii a pixmap-ului i nici a unui offset
pentru poziia raster curent.
Utiliznd glDrawPixels valorile memorate ca un bloc de date n memoria gazd
sunt transmise spre memoria video.
void glDrawPixels (GLsizei width, //dimensiunea dreptunghiului de pixeli
GLsizei height, //care se va nscrie n memoria video
GLenum format, // formatul datelor pentru un pixel
GLenum type, // tipul datelor pentru pixeli
const GLvoid *pixels) ; //un pointer spre tabloul de pixeli
Funcia glDrawPixels red pixelii avnd colul stnga jos al imaginii n poziia
raster curent. Un bloc de pixeli din memoria gazd CPU este transmis spre OpenGL cu
un format i un tip de date specificat. Pentru fiecare pixel din imagine, se genereaz un
101
fragment utiliznd culoarea restabilit din imagine, i n continuare este procesat. Odat
obinute, valorile rezultate produc un dreptunghi de fragmente. Localizarea acestui
dreptunghi este controlat de poziia raster curent, care este tratat ca un punct
(incluznd culoarea i coordonatele texturii), cu excepia faptului c este setat cu o
comand separat (glRasterPos) care nu apare ntre glBegin() i glEnd(). Dimensiunea
dreptunghiului este determinat de limea i nlimea specificat precum i de setarea
parametrilor de zoom ai dreptunghiului de pixeli (setai cu glPixelZoom).
Exist numeroase formate i tipuri de date pentru specificarea depozitrii n
memorie a pixmap-urilor. Cele mai bune performane se obin prin utilizarea formatului
i a tipului care se potrivete hardware-ului.
OpenGL permite formate diferite pentru imagini incluznd:
- Imagini RGB sau RGBA coninnd un triplet RGB pentru fiecare pixel.
Parametrul format este GL_RGB sau GL_RGBA, i specific valorile exacte
pentru rou, verde i albastru pentru fiecare pixel din imagine.
- Imagini color. Parametrul format este GL_COLOR_INDEX i arat c fiecare
valoare din pixmap este un index n paleta de culori curent a Windows-ului.
- Imagini intensitate care conin doar intensitatea pentru fiecare pixel. Aceste
imagini sunt convertite intern n imagini RGB n tonuri de gri. Parametrul
format este GL_LUMINANCE sau GL_LUMINANCE_ALPHA. In acest
format, fiecare valoare este mapat la o valoare de intensitate, valoarea maxim
corespunznd albului iar valoarea minim corespunznd negrului, iar valorile
intermediare diferitelor tonuri de gri.
- Imagini adncime (format este GL_DEPTH_COMPONENT) care conin
valoarea adncimii (coordonata z) pentru fiecare pixel, valoare nscris i n
buffer-ul de adncime, corespunztor buffer-ului de cadru care conine culoarea
corespunztoare fiecrui pixel. Acesta este util n ncrcarea buffer-ului de
adncime cu valori i apoi redarea imaginilor color corespunztoare cu activarea
testului de adncime.
- Imagini stencil (format este GL_STENCIL_INDEX) care copiaz mti ablon
n buffer-ul stencil. Aceasta permite o modalitate uoar pentru a ncrca o
masc per pixel complicat.
Parametrul type descrie datele pentru tabloul pixels. Acestea ar putea fi valori
ca: GL_FLOAT, GL_INT, GL_BYTE (valori cu semn ntre -128 i 127), GL_BITMAP
(dou valori 0 i 1) GL_UNSIGNED_BYTE (valori fr semn ntre 0 i 255) sau pixeli
cu toate componentele de culoare mpachetate ntr-un tip ca
GL_UNSIGNED_SHORT_5_6_5.
Parametrul pixels indic adresa de memorie a datelor.

Citirea pixelilor

Aa cum se pot transmite pixeli spre framebuffer (buffer-ul de cadru), se pot i
citi valorile pixelilor napoi din framebuffer n memoria gazd pentru realizarea
memorrii sau procesrii imaginilor. O aplicaie evident a acestei funcii este salvarea
imaginilor create n fiiere. O alt aplicaie ar putea fi realizarea unor efecte speciale cu
maparea texturilor. Funcia care realizeaz citirea pixelilor de pe ecran este
glReadPixels().
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei
102
height, GLenum format, GLenum type, GLvoid *pixels);
Funcia citete din framebuffer un dreptunghi de pixeli al crui col stnga-jos
are poziia specificat prin (x, y). Dimensiunea dreptunghiului este dat de parametrii
width i height. Pixelii se convertesc n mod automat din formatul framebuffer n
formatul i tipul cerut i sunt plasai n memoria intern la adresa pixels. Pixelii citii din
framebuffer sunt procesai prin modurile de transfer i depozitare.


Copierea pixelilor n buffer-ul de cadru

Suplimentar, pixelii pot fi copiai dintr-o locaie n alta a buffer-ului de cadru
utiliznd funcia glCopyPixels(). De o asemenea funcie este nevoie, spre exemplu,
atunci cnd sunt mrite anumite poriuni din imagine. Pixelii sunt procesai de modurile
de transfer i depozitare nainte de a fi returnai n buffer-ul de cadru.
void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei
height, GLenum type);
Parametrii (x, y) reprezint poziia colului stnga jos a dreptunghiului de pixeli
care se copiaz. Dimensiunile acestui dreptunghi sunt date de parametrii width i height.
Datele sunt copiate ntr-o nou poziie din buffer-ul de cadru, care este poziia raster
curent. Parametrul type este fie GL_COLOR, GL_STENCIL sau GLJDEPTH i
specific ce valori se copiaz. Spre exemplu dac type este GL_COLOR se vor copia
valori RGB sau indeci de culoare.

Scalarea pixmap-urilor

In afara ajustrii culorilor unei imagini, folosind funciile de mapare a culorilor,
un alt atribut care poate fi modificat este dimensiunea unei imagini. Pentru aceasta se
utilizeaz funcia glPixelZoom(). n mod normal fiecare pixel al imaginii este redat pe
un pixel al dispozitivului de ieire. Funcia accept doi parametrii n virgul mobil,
care specific factorii de scalare ai imaginii pe axele x i y.
void glPixelZoom(Glfloat zoomx, Glfloat zoomy);
Pentru valori egale ale factorilor de scalare imaginea este scalat pstrnd
proporiile pe cele dou axe. Valori supraunitare ale factorilor de scalare conduc la o
mrire a imaginii iar valori subunitare conduc la o micorare a imaginii. Dac se
utilizeaz valori negative se va realiza n plus i o oglindire a imaginii dup axa
respectiv n jurul poziiei raster curente.
Exemplu 1:
glPixelZoomd(1.0, 1.0); //nu scaleaz imaginea
glPixelZoom( -l .0, 1.0); //oglindete imaginea pe orizontal
glPixelZoom (1.0, -2.0); //oglindete imaginea pe vertical, i dubleaz
//dimensiunea pe vertical
glPixelZoom(0 .33, 0.33);
//red imaginea la 1/3 din dimensiune

Exemplu 2:
n exemplul urmtor o imagine de 16 X 16 pixeli va fi copiat n colul stnga
jos al ferestrei i scalat la 32 x 32 pixeli.
103
int pozx, pozy;
glPixelZoom(2.0, 2.0);
glRasterPos2i(0, 0);
glCopyPixels(pozx-8, pozy-8, 16, 16, GL_COLOR);

Remaparea culorilor

Atunci cnd o imagine este transferat din memorie n buffer-ul de cadru sau
invers din buffer-ul de cadru n memorie, OpenGL poate realiza unele operaii asupra ei.
Spre exemplu, domeniile componentelor de culoare pot fi alterate. n mod obinuit,
componenta rou este cuprins ntre 0.0 i 1.0, dar este posibil s dorii memorarea ei n
alte domenii, sau este posibil ca datele utilizate de la diferite sisteme grafice s utilizeze
alte domenii de valori. Se pot crea mapri pentru a asigura conversii arbitrare ale
indecilor de culoare sau ale componentelor de culoare n timpul transferrii pixelilor.
Conversiile asemntoare celor asigurate n timpul transferrii pixelilor la i de la
buffer-ul de cadru sunt numite moduri de transfer a pixelilor (pixel-transfer modes).
Aceste conversii sunt controlate de funciile glPixelTransfer#() i glPixelMap#().
Alte moduri de conversie ce pot fi controlate includ buffer-ul de cadru din care
se citesc pixelii, i orice mrire ce se face asupra pixelilor la scrierea lor n buffer-ul de
cadru.
Buffer-ele de culoare, adncime i stencil dei au multe similitudini, nu se
comport identic i cteva moduri au cazuri speciale pentru buffer-e speciale.
Dac se utilizeaz formatul GL_COLOR_INDEX, se pot remapa culorile din
pixmap sau bitmap utiliznd funciile glPixelMap() sau glPixelTransfer(). Funcia
glPixelTransfer() permite specificarea scalarii i a offset-urilor pentru valori RGB sau
color index. Spre exemplu codul urmtor arat modul de cretere a luminozitii unei
imagini cu 10%.
glPixelTransferf(GL_RED_SCALE, 1.1);
glPixelTransferf(GL_GREEN_SCALE, 1.1);
glPixelTransferf(GL_BLUE_SCALE, 1.1);

n mod similar, pentru a deplasa indecii de culoare ai unui bitmap la intrri
definite special pentru bitmap-ul respectiv, se folosete apelul urmtor:
glPixelTransferi(GL_INDEX_OFFSET, bitmap_entry);

Exemplu:
Exemplul urmtor reia aplicaia de la redarea bitmap-urilor. Aceeai imagine
este redat acum ca pixmap, utiliznd funcia glDrawPixels(). n continuare sunt date
doar funciile display() i main(), care au suferit modificri fa de aplicaia anterioar.
Cele dou culori ale bitmap-ului sunt remapate la diferii indeci. Pentru valori diferite
ale offset-ului, cele dou culori cu care sunt redate bitmap-ul se vor modifica.
void CALLBACK display(void) { int i, j;
//urmeaz tabloul cu bitmap-ul 32X32 bii
void CALLBACK display(void)
{ int i, j;

GLubyte model[] = {
104
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0x03, 0xc0, 0,
0, 0x0f, 0xf0, 0,
0, 0x1e, 0x78, 0,
0, 0x39, 0x9c, 0,
0, 0x77, 0xee, 0,
0, 0x6f, 0xf6, 0,
0, 0xff, 0xff, 0,
0, 0xff, 0xff, 0,
0, 0xff, 0xff, 0,
0, 0xff, 0xff, 0,
0, 0x73, 0xce, 0,
0, 0x73, 0xce, 0,
0, 0x3f, 0xfc, 0,
0, 0x1f, 0xf8, 0,
0, 0x0f, 0xf0, 0,
0, 0x03, 0xc0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
glClearIndex(10.0);
glClear(GL_COLOR_BUFFER_BIT);
glPixelTransferi(GL_UNPACK_ALIGNMENT, 10);
glPixelTransferi(GL_INDEX_OFFSET, 16);
for(i=-5; i<5; i+=2)
for(j=-5; j<5; j+=2)
{
glRasterPos2i(j,i);
glDrawPixels(32, 32, GL_COLOR_INDEX, GL_BITMAP,
model);
}
glFlush();
}
int main(int argc, char** argv)
105
{
auxInitDisplayMode (AUX_SINGLE | AUX_INDEX);
auxInitPosition (0, 0, 200, 200);
auxInitWindow ("O fereastr cu bitmap-uri");
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}

Observaii:
Pentru valorile din aplicaie ale culorilor, fundalul este gri foarte deschis,
bitmap-ul este redat n combinaia de culori galben i albastru (figura 3.39). Trebuie
remarcat c funcia auxInitDisplayMode() s-a modificat pentru a lucra cu modelul de
culoare index (AUX_INDEX). De asemenea pentru stabilirea culorii background-ului s-
a folosit funcia glClearIndex(). Bitmap-ul s-a redat cu funcia glDrawPixels() dar
utiliznd tipul de date GL_BITMAP, i formatul GL_COLOR_INDEX.










Figura 3.39

Tabele de mapare a culorilor

Uneori este necesar s se aplice corecii ale culorilor care sunt mai complicate
dect simpla scalare liniar sau offset-ul. O aplicaie este corecia gamma, n care
intensitatea fiecrei valori de culoare este ajustat pentru a compensa iregularitile de
pe monitor sau imprimant. Funcia glPixelMap() permite realizarea acestui lucru.
void glPixelMap (GL_enum map, GL_int mapsize, const TYPE *values) /
Funcia realizeaz o mapare al crui nume simbolic este indicat de map.
Valoarea simbolic map poate lua 10 valori:
GL_PIXEL_MAP_I_TO_I - se realizeaz o mapare a indecilor de culoare la
indeci de culoare;
GL_PIXEL__MAP_S_TO_S - se realizeaz o mapare a indecilor ablon
(stencil) la indeci stencil;
GL_PIXEL_MAP_I_TO_R - se realizeaz o mapare a indecilor de culoare la
componente rou;
GL_PIXEL_MAP_I_TO_G - se realizeaz o mapare a indecilor de culoare la
componente verde;
GL_PIXEL_MAP_I_TO_B - se realizeaz o mapare a indecilor de culoare la
componente albastru;
106
GL_PIXEL_MAP_I_TO_A - se realizeaz o mapare a indecilor de culoare la
componente alfa;
GL_PIXEL_MAP_R_TO_R - se realizeaz o mapare a componentelor rou la
componente rou;
GL_PIXEL_MAP_G_TO_G - se realizeaz o mapare a componentelor verde la
componente verde;
GL_PIXEL_MAP_B__TO_B - se realizeaz o mapare a componentelor albastru
la componente albastru;
GL_PIXEL_MAP_A_TO_A - se realizeaz o mapare a componentelor alfa la
componente alfa;
Parametrul mapsize arat dimensiunea maprii care se va realiza. Parametrul
values este un pointer spre tabloul care conine valorile pentru mapare.
Exemplu:
In exemplul urmtor se arat felul cum se poate realiza o corecie gamma.
GLfloatl 1ut[256];
GLf loat gamma_value;
int i ;
gamma_value=l. 7; //Pentru monitoare video NTSC
//se ncarc tabela de cutare cu valori corespunztoare
// monitorului cu care se lucreaz
for(i=0; i<256; i++)
lut[i]=pow (i/255.0, 1.0/gamma_value); //se activeaz maparea
glPixelTransferi(GL_MAPCOLOR, GL_ TRUE);
//se realizeaz maparea
glPixelMap(GL_PIXEL_MAP_R_TO_R/ 256, lut);
glPixelMap(GL_PIXEL_MAP_G_TO_G/ 256, lut);
glPixelMap(GL_PIXEL_MAP_B_TO_B/ 256, lut);

Moduri de memorare sau de transfer a pixelilor

n aceast seciune se arat detalii ale modurilor de memorare i de transferare.
O imagine depozitat n memorie conine pentru fiecare pixel ntre unul i patru
elemente. Aceste elemente pot fi indexul de culoare sau intensitatea luminoas dar pot fi
i componentele rou, verde, albastru i alfa. Aranjamentele posibile pentru datele
corespunztoare pixelilor, sau formatele, determin numrul elementelor memorate
pentru fiecare pixel i ordinea lor.
Unele elemente sunt valori ntregi iar altele sunt valori n virgul mobil
cuprinse ntre 0 i 1. Numrul exact de bii utilizat pentru reprezentarea comp0nentelor
difer de la un hardware la altul. De aceea uneori este o risip s se memoreze fiecare
component ca un numr n virgul mobil pe 32 de bii, mai ales c imaginile pot, uor,
conine un milion de pixeli.
Elementele pot fi memorate ca diferite tipuri de date, de la octei la ntrebi sau
numere n virgul mobil pe 32 de bii. OpenGL definete explicit conversia fiecrei
componente, n fiecare format, pentru fiecare din tipurile posibile de date. Trebuie
reinut c se pierde din rezoluie atunci cnd se ncearc memorarea pe un numr mai
mic de bii.
107
Datele corespunztoare unei imagini sunt memorate n memoria procesorului ca
tablouri cu dou sau trei dimensiuni. Deseori, este nevoie s se afieze sau sa se
memoreze o subimagine care corespunde unui sudreptunghi dintr-un tablou.
Suplimentar, este nevoie s se ia n considerare diferite maini care au diferite convenii
de ordonare a octeilor. n sfrit, unele maini au astfel hardware-ul nct este mai
eficient s se mute datele nspre i dinspre buffer-ul de cadru dac datele sunt aliniate pe
doi octei, patru octei sau opt octei n memoria procesorului. n asemenea cazuri poate
fi necesar s se controleze alinierea octeilor. Toate aceste lucruri, descrise n acest
subcapitol, sunt controlate de modurile de stocare al pixelilor. Aceste moduri se
specific utiliznd comanda glPixelStore#(). De obicei trebuie fcute cteva apeluri
succesive ale acestei comenzi pentru a seta valorile ctorva parametrii.
void glPixelStore{if}(Glenum pname, TYPE param) ;
Funcia afecteaz modurile de depozitare, care intervin n operaiile realizate de
funciile: glDrawPixels, glReadPixels, glBitmap, glPolygonStippla, glTexImage i
glGetTexImage.
Parametrul pname poate lua 12 valori. Dintre acestea, 6 valori intervin n felul n
care datele sunt scrise n memorie i deci afecteaz doar comenzile glReadPixels() i
glTexImage().
GL_PACK_SWAP_BYTES
GL_PACK_LSB_FIRST
GL_PACK_ROWLENGTH
GL_PACK_SKIP_ROWS
GL_PACK_SKIP_PIXELS
GL_PACK_ALIGNMENT

Celelalte 6 tipuri de valori ale parametrului pname intervin n felul n care sunt
citii pixelii din memorie i afecteaz funciile glDrawPixels, glBitmap,
glPolygonStipple, glTexImage.
GL_UNPACK_SWAP_BYTES
GL_UNPACK_LSB_FIRST
GL_UNPACK_ROW_LENGTH
GL_UNPACK_SKIP_ROWS
GL_UNPACK_SKIP_PIXELS
GL_UNPACK_ALIGNMENT

Valorile #SWAP_BYTES controleaz ordinea octeilor n memorie care poate
sau nu s fie inversat dup cum parametrul este true sau false. Acest parametru poate fi
ignorat dac nu se lucreaz cu imagini create pe procesoare diferite.
Valoarea #LSB_FIRST (low significant bit) este util atunci cnd se lucreaz cu
pixmap-uri de un bit sau cu bitmap-uri. Dac parametrul este false, biii sunt preluai din
octet ncepnd cu bitul cel mai semnificativ.
Atunci cnd dorim s desenm sau s citim un subdreptunghi dintr-un
dreptunghi al unui pixmap memorat n memorie, se utilizeaz celelalte valori
enumerate. Dac dreptunghiul din memorie este mai mare dect subdreptunghiul care se
va desena, trebuie s se specifice lungimea dreptunghiului mai mare cu
#ROW_LENGTH. Dac parametrul #ROW_LENGTH este 0 (implicit), atunci se sub
nelege c lungimea este valoarea parametrului width specificat n funciile
108
glReadPixels(), glDrawPixels(), glCopyPixels(). Trebuie s se specifice de asemenea
numrul rndurilor i al pixelilor care se sar nainte de a se ncepe copierea datelor din
subdreptunghi. Aceste numere sunt setate utiliznd parametrii

Exemplu:
Spre exemplu, pentru a afia o imagine de 200 x 200 pixeli, aflat n centrul unei
imagini de 500 x 300 se va utiliza urmtorul cod:
glPixelStorei(GL_UNPACK_ROW_LENGTH, 500);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, (500-200)/2);
glPixelStorei(GL_UNPACK_SKIP_ROWS, (300-200)12);
glDrawPixels(200, 200, GL_RGB, GL_UNSIGNED_BYTE, model);


3.5 Utilizarea atributelor de redare n OpenGL


Un obiect poate fi redat cu diferite atribute:
a) reprezentare wireframe
b) reprezentare wireframe cu poligoanele avnd atribut de umplere;
c) reprezentare cu iluminare folosind un model de iluminare constant pe
poligoane;
d) reprezentare cu iluminare Phong;
e) reprezentare cu texturare;
f) reprezentare cu texturare.

OpenGL poate reda obiectele de la modul wireframe pn la texturarea acestora
sau la utilizarea unor modele complexe de iluminare cum ar fi modelul Gouraud. Aa
cum s-a mai artat n capitolul introductiv, OpenGL se comport ca o maina de stare.
Toate atributele de redare sunt ncapsulate n starea OpenGL:
- Stiluri de redare
- Umbrire
- Iluminare
- Maparea texturii
De fiecare dat cnd OpenGL proceseaz un vrf, utilizeaz datele memorate n
tabelele sale interne de stare pentru a determina cum se va transforma vrful, cum se va
lumina, textura, etc.



3 3. .5 5. .1 1 C Co on nt tr ro ol la ar re ea a s st t r ri ii i O Op pe en nG GL L

Aspectul obiectelor desenate de aplicaiile OpenGL este controlat de starea
curent. Fluxul general al oricrei redri OpenGL este de a se seta starea curent, apoi
de a se transmite primitiva de redat, i de a se repeta aceti pai pentru fiecare primitiv.
pentru fiecare (primitiv de reprezentat) {
- se actualizeaz starea OpenGL
- se red primitiva }
109
n general, metoda cea mai obinuit de a controla starea OpenGL este de a seta
atributele vrfurilor, care includ culoarea, normalele pentru iluminare, coordonatele de
texturare.
glColor#() / glIndex()
glNormal#()
glTexCoord#()


3 3. .5 5. .2 2 S Se et ta ar re ea a s st t r ri ii i c cu ur re en nt te e

Setarea strii OpenGL de obicei include modificarea atributelor de redare, cum
ar fi ncrcarea unei texturi sau setarea grosimii unei linii. Alte atribute necesit ns
activarea lor. Aceasta se face prin utilizarea funciei glEnable(), i transmiterea numelui
strii respective, cum ar fi GL_LIGHTO (pentru activarea sursei de lumin 0) sau
GL_POLYGON_STRIP (pentru activarea abloanelor de umplere ale poligoanelor).
Exemple:
Setarea strii
glPointSize(size) ; //stabilete grosimea liniei
glLineStipple (repeat, pattern) ; //stabilete stilul liniei
glShadeModel (GL_SMOOTH) ; //umbrire Gouraud

Activarea atributelor
glEnable (GL_LIGHTING) ; //se activeaz reprezentarea cu iluminare
glDisable (GL_TEXTURE_2D) ; //se dezactiveaz reprezentarea cu texturare
//2D

3 3. .5 5. .3 3 I In nt te er ro og ga ar re ea a s st t r ri ii i i i s st ti iv va a d de e p pa ar ra am me et tr ri ii i

Aa cum s-a mai spus, OpenGL este o main de stare. Ea poate fi pus n
diferite stri (sau moduri) care au efect pn cnd sunt schimbate. Fiecare variabil de
stare sau mod are o valoare implicit, i n orice punct al programului se poate interoga
sistemul cu privire la fiecare din valorile curente ale variabilelor. n mod obinuit, se va
folosi una din urmtoarele patru comenzi pentru a afla aceste valori: glGetBooleanv(),
glGetDoublev(), glGetFloatv(), glGetIntegerv(). Care dintre aceste comenzi se va alege
depinde de tipul datelor care se doresc a fi obinute. Unele variabile de stare au comenzi
de interogarea strii mult mai specifice (cum ar fi glGetLight(), glGetError(),
glGetPolygonStipple()). Exist de asemenea o stiv pentru valorile parametrilor care pot
fi salvai sau restaurai din stiv. Comenzile pentru salvarea respectiv restaurarea din
stiva de atribute de stare sunt: glPushAttrib() i glPopAttrib(). Comenzile get i stivele
de parametrii fac posibil implementarea diferitelor biblioteci, fiecare fr a interfera cu
alt utilizare OpenGL.






110




4 INDRUMAR DE LABORATOR

Programare Grafic OpenGL

4.1 Lucrare de laborator 1.

4 4. .1 1. .1 1 I In nt tr ro od du uc ce er re e n n O Op pe en nG GL L

OpenGL (Open Graphic Library) nu este cum s-ar putea crede un limbaj de
programare ci un standard de programare al aplicaiilor 3D. A fost primul standard care
s-a impus pe pia fiind inclus deja la primele versiuni de Windows95 i
WindowsNT4.0. Practic odat cu biblioteca de funcii Win32 a aprut i suportul
pentru OpenGL (separat desigur).
OpenGL este independent de mediul de programare, fiind definite aceleai tipuri
de date i aceleai funcii indiferent dac se programeaz n Visual C, Visual Basic,
Delphi, CBuilder .a. Totui se poate observa o oarecare nrudire ntre OpenGL i C pe
msur ce se avanseaz n programare i se capt o oarecare experien i familiaritate
cu OpenGL. Nu se pot nega nici oarecare asemnri cu Delphi, dar mai puine ca numr
i mai subtile.
Astfel chiar dac vei nva OpenGL utiliznd Vizual C, vei putea trece relativ
rapid i fr dificultai la alt mediu de programare mai familiar, dar care are biblioteci
OpenGL. Saltul mai mare se va face dac se va aborda alt standard de programare 3D,
Direct 3D spre exemplu, dar avnd concepte comune se va nsui mult mai uor. Ca fapt
divers n versiunile Visual C, s-a renunat la un moment dat la actualizare bibliotecii
OpenGL, aceasta rmnnd la versiune 1.1, n schimb s-a introdus suport pentru Direct
3D. Alte medii de programare continu nc s includ i s actualizeze bibliotecile
OpenGL, i aceasta cu att mai mult cu ct marea parte a distribuiilor de Linux se
bazeaz pe acest standard. n Linux s-a impus deja GLUT (OpenGL Utility Toolkit) i
mai nou freeGLUT.
Deci dac dorii implementare n medii freeware de aplicaii 3D aceasta este
soluia.

Linkuri utile:
- http://freeglut.sourceforge.net/
- www.opengl.org


4 4. .1 1. .2 2 C Cr re ea ar re ea a u un ne ei i a ap pl li ic ca a i ii i O Op pe en nG GL L

Pentru a crea o aplicaie OpenGL vom folosi n principal 4 biblioteci :
- gl.h bibliotec exclusiv dup standardul OpenGL;
111
- glu.h bibliotec auxiliar pentru integrarea OpenGL n mediul de programare i
nu numai;
- glaux.h bibliotec auxiliar pentru crearea i testarea rapid de aplicaii OpenGL;
- glos.h microbibliotec pentru corecia unui mic bug din bibliotecile OpenGL din
Visual C.

Alturi de acestea mai avem nevoie de 3 librrii:
- glu32.lib
- glaux.lib
- opengl32.lib
Ce se gsesc n directorul LIB al Visual C.
n plus sistemul de operare trebuie s includ neaprat n directorul system32
opengl32.dll.
Vom utiliza pentru aceste laboratoare Visual C++ 6.0. Programele putnd
funciona i n Visual C++ 5.0 , ca de altfel i n Visual Studio Net, i ultima versiune
de Visual Studio 2008.
Iniial vom lucra n modul consol.
Vom proceda astfel:
1. Rulm Visual C++;
2. Din File alegem New;
3. Trecem pe primul tab Files;
4. Alegem i selectm C++ source file;
5. Denumim fiierul xxxx;
6. Scriem programul.
7. Apsam F7 pentru a compila programul.
8. Apsm Yes pentru a crea un spaiu de lucru pentru program.
9. Urmtorul meniu Yes ,salvm modificrile;
10. Din meniul Project alegem Settings ;
11. Alegem tabul Link din fereastra Project Settings ce s-a deschis;
12. La project options scriem librriile folosite de OpenGL glu32.lib, glaux.lib,
opengl32.lib cu spaii ntre ele i fr virgul i la sfrit apsm OK.
13. Rulm programul cu F5.


Exemplu de program:

#include <glos.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include <conio.h>
void main()
{
//initializare modului de afisare
//un singur buffer afisare direct pe ecran
//culori dup standardul RGBA
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
112
//poziia si dimensiunile ferestrei de afisare
auxInitPosition(100,100,250,250);
//initializam fereastra precizand titlul acesteia
auxInitWindow("My first OpenGL Program");

// aici se scrie codul OpenGL pentru afiare
//stergem fereastra folosind culoarea albastru
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glFlush();
// Nu inchide! Asteapta apasarea unei taste
getch();

}

Observai c avem o secven de iniializare a mediului OpenGL:

auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
auxInitPosition(100,100,250,250);
auxInitWindow("My first OpenGL Program");

i o secven de sfrit care poate lipsi. ntre aceste putnd scrie instruciuni
OpenGL de
afiare.

Avem instruciunea glClearColor() care stabilete culoare de tergere a
ferestrei sau a buferului avnd prototipul:

void glClearColor(GLclampf rosu, GLclampf verde,
GLclampf albastru,GLclampf alpha);

GLclampf este un tip de date numeric asemntor cu float din C.
Culoare se specific prin componenii ei rosu, verde i albastru, i o component
de transparen alpha care dac nu este folosit este setat pe 1, adic complet opac.
1.0f este intensitatea maxim a componentei 0.0f cea minim. Observai c dup
fiecare constant numeric de tip float se pune litera f, pentru a se evita ambiguitile i
n special mesajele de avertizare (warning) de la compilare.

Instruciunea glClear () stabilete buferul care va fi ters prin culoare
specificat n glClearColor, ea are prototipul:

void glClear(GLbitfield mask);

unde mask poate lua valorile:
- GL_COLOR_BUFFER_BIT;
- GL_DEPTH_BUFFER_BIT;
113
- GL_ACCUM_BUFFER_BIT;
- GL_STENCIL_BUFFER_BIT.
Pentru primele aplicaii o vom folosi doar cu masca
GL_COLOR_BUFFER_BIT.

Pentru a desena un dreptunghi folosim funcia glRect cu urmtoarele
prototipuri:

void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
void glRecti(GLint x1, GLint y1, GLint x2, GLint y2);
void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
Se observ c OpenGL lucreaz att cu date specificate prin tipuri ntregi ct i
prin date cu virgul. Rezultatul va fi desenarea unui dreptunghi ce are colul din stnga
sus descris de x1,y1 i cel din dreapta jos descris de x2,y2.
n OpenGL sistemul de coordonate nu mai este ca cel definit n Windows sau
BGI, axa Oy este ndreptat n sus i nu n jos ca n cazul acesta. Axa Oz iese din ecran,
Ox este de la stnga spre dreapta.

Exerciiu 1. Modificai programul anterior pentru a desena cte patru
dreptunghiuri, unul verde, unul rou, unul albastru i unul galben pe un fond negru.
Pentru a modifica culoare dreptunghiului se folosete funcia glColor3f() care are
prototipul:

void glColor3f(GLfloat red, GLfloat green, GLfloat blue);















114
Programare Grafic OpenGL

4.2 Lucrare de laborator 2.

4 4. .2 2. .1 1 U Ut ti il li iz za ar re ea a f fu un nc c i ii il lo or r b bi ib bl li io ot te ec ci ii i g gl la au ux x

Biblioteca glaux este o bibliotec auxiliar, care dei compatibil cu standardul
OpenGL nu este prevzut de acesta. Ea fost implementat n special pentru Visual
C++, celelalte medii de obicei avnd doar bibliotecile glu i gl, sub acest nume sau altul.
Biblioteca glaux ofer funcii de integrare a aplicaiei 3D n mediul de programare.
Aplicaiile vor rula iniial o aplicaie de tip consol, aceasta la rndul ei deschiznd o
alt fereastr n care va fi afiat grafica OpenGL. Pentru nceput se va dovedi destul de
util, codul OpenGL putnd fi testat rapid, dar dac se va dori o aplicaie mai serioas se
va renuna la glaux i se vor folosi opiunile de integrare a graficii OpenGL ntr-o
aplicaie gen Win32 sau MFC (aceasta prin funciile bibliotecii glu).
Funciile disponibile n biblioteca glaux sunt prefixate ntotdeauna de cuvntul
aux.
Aceste funcii pot fi mprite n trei categorii:
- funcii de iniializare care definesc bufferele folosite, poziia ferestrei de
afiare, genereaz fereastra;
- funcii de interfa cu utilizatorul pentru mouse i tastatura;
- funcii pentru desenarea de primitive 3D - se pot desena primitive ca model din
srme (wire frame), sau cu suprafa continu (solids).

4 4. .2 2. .2 2 F Fu un nc c i ii i d de e i in ni i i ia al li iz za ar re e: :

Funcia auxInitDisplayMode realizeaz iniializarea modului grafic folosit de
OpenGL ea avnd urmtorul prototip:

void auxInitDisplayMode(GLbitfield mask);

unde mask este o masc cu diferite opiuni de configurare aceste opiuni sunt:

- AUX_SINGLE imaginea se va afia prin intermediul unui singur buffer direct
legat de ecran;
- AUX_DOUBLE imaginea va fi desenat mai nti ntr-un buffer auxiliar, fiind
afiat apoi pe ecran prin intermediul bufferului principal ;
- AUX_RGBA culoare va fi specificat prin cele trei componente de culoare
rou, verde, albastru i o component de transparen alfa;
- AUX_INDEX culoare va fi specificat prin index i nu direct;
- AUX_DEPTH specific c bufferul de adncime folosit va fi pe 32 de bii;
AUX_DEPTH16 specific c bufferul de adncime folosit va fi pe 16 de bii;
- AUX_STENCIL specific c va fi folosit un buffer ablon;
- AUX_ACCUM specific c va fi folosit un buffer de acumulare;
- AUX_ALPHA specific c va fi folosit un buffer pentru parametrul de
transparen alfa ;
- AUX_FIXED_332_PAL specific o palet de culoare 3-3-2 pentru fereastr ;
115

n mod obinuit vom folosi aceast funcie astfel :

auxInitDisplayMode(AUX_DOUBLE | AUX_RGBA) ;

,pentru a lucra cu dou buffere, evitnd astfel efectul de plpire la animaii sau
compoziii complexe ;

sau mai simplu :

auxInitDisplayMode(AUX_SINGLE | AUX_RGBA) ;

, grafica va fi afiat direct pe ecran, relativ nepretenios pentru nceput ;

Pentru a specifica poziia ferestrei de afiare se va folosi funcia
auxInitPosition cu
urmtorul prototip :

void auxInitPosition(GLint x, GLint y, GLsizei lungime, GLsizei inaltime);

n care sunt specificate coordonatele colului stnga sus i dimensiunile
ferestrei.

Exemplu:

auxInitPosition(10,10,200,200);

Pentru a genera efectiv fereastr, inclusiv pentru a preciza titlul acesteia
se va folosi funcia auxInitWindow cu urmtorul prototip:

void auxInitWindow(GLBYTE *titlul ferestrei);

Exemplu:

auxInitWindow( Primul program n OpenGL);



4 4. .2 2. .3 3 F Fu un nc c i ii i d de e i in nt te er rf fa a i i d de e c ci ic cl la ar re e

Pn acum pentru a putea vedea grafica desenat n fereastr, evitnd nchidere
imediat a ferestrei am folosit funcia getch() din biblioteca conio.h. Acelai lucru se
poate realiza ns prin folosirea unor funcii de ciclare. Acestea au prototipul :

void auxIdleFunc(AUXIDLEPROC NumeleFunctiei);
void auxMainLoop(AUXMAINPROC NumeleFunctiei);

116
Funcia auxIdleFunc este apelat atunci cnd programul a terminat de desenat o
scen i ateapt alte comenzi, o putem folosi fr probleme pentru afiarea aceleai
scene sau pentru generarea de animaii.
auxMainLoop este utilizat exclusive pentru ciclri, odat terminat ciclul, acest
ciclu este reapelat, totul terminndu-se la nchiderea ferestrei.

Variabila NumeleFunctiei este o numele unei funcii definit astfel:

voi d CALLBACK Numel eFunct i ei ( voi d)
{
/ / codul OpenGL pr i n car e desenamceva n mod r epet at

}
n program putem apela doar odat ori una ori alta din funciile de ciclare.
NumeleFunctiei o putem denumi fie Desenare, fie RandareScena, cum
anume ni se pare mai sugestiv.

Exerciiu 1. Creai un program n care un dreptunghi s se mite de la stnga la
dreapta n fereastr. Cnd a ajuns la marginea din dreapta s se opreasc. Odat realizat
programul ncercai ca odat ajuns la margine s se ntoarc napoi, repetnd indefinit
aceast micare.

4 4. .2 2. .4 4 F Fu un nc c i ii il le e d de e l lu uc cr ru ul l c cu u m mo ou us se e

Avem o funcie de asociere a unei funcii unui eveniment de mouse aceasta are
prototipul :


void auxMouseFunc(int button, int mode, AUXMOUSEPROC func);

, unde button este definit prin urmtoarele constante:
- AUX_LEFTBUTTON se refer la butonul stng al mouse-ului;
- AUX_MIDDLEBUTTON- se refer la butonul din mijloc al mouse-ului;
- AUX_RIGHTBUTTON se refer la butonul drept al mouse-ului;
, mode specific evenimentul n care este implicat butonul precizat anterior :
- AUX_MOUSEDOWN butonul a fost apsat i este inut apsat;
- AUX_MOUSEUP butonul a fost eliberat;

n ceea ce privete func aceasta este numele unei funcii i are urmtorul mod de
declarare :

void CALLBACK MouseFunc(AUX_EVENTREC *event)
{
// operatii legate de mouse, desenarietc.
}

Unde event este o variabil de tip structur prin care se transmit informaii
despre starea mouse-ului.
117

t ypedef st r uct _AUX_EVENTREC {
GLi nt event ;
GLi nt dat a[ 4] ;
}

Event specific evenimentul definit prin constantele AUX_MOUSEUP /
AUX_MOUSEDOWN ;
Data este apelat cu urmtoarele secvene :

- data[AUX_MOUSEX] coordonata x a pointerului de mouse;
- data[AUX_MOUSEY] - coordonata y a pointerului de mouse;
- data[MOUSE_STATUS] starea butoanelor de mouse;

Exemplu:
void CALLBACK MouseFunc(AUX_EVENTREC *event)
{
int mousex,mousey;
mousex = data[AUX_MOUSEX] ;
mousey = data[AUX_MOUSEY] ;

}

.
void main(void)
{

auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEDOWN, MouseFunc);

}

Exerciiu 2. Creai un program pe baza secvenei de mai sus, care la apsarea
primului buton al mouse-ului s deseneze un dreptunghi pe ecran cu centrul exact la
poziia pointerului de mouse. La fiecare apsare a butonului, la diverse poziii
dreptunghiul va fi redesenat.



4 4. .2 2. .5 5 F Fu un nc c i ii il le e d de e l lu uc cr ru u c cu u t ta as st ta at tu ur ra a

Pentru a se lucra cu tastatura se folosete funcia cu urmtorul prototip:

void auxKeyFunc(GLint key, void(*function(void));

,la care key este codul tastei crei i se asociaz funcia function.

O list de coduri de taste este urmtoarea:

118
- AUX_ESCAPE pentru tasta Escape;
- AUX_SPACE pentru bara de spaiu;
- AUX_RETURN pentru tasta Enter;
- AUX_LEFT The pentru tasta spre stnga;
- AUX_RIGHT pentru tasta spre dreapta;
- AUX_UP The pentru tasta n sus;
- AUX_DOWN pentru tasta n jos;
- AUX_A AUX_Z pentru tastele crora le corespund litere;
- AUX_0 AUX_9 pentru tastele crora le corespund cifre;

Funcia asociat tastei are codul general valabil:

void CALLBACK NumeFunctie(void)
{

}

Exerciiu 3. Scriei un program pentru a deplasa cu tastele sgei un dreptunchi
n fereastr.

Funciile grafice propriu-zise :

Pentru a desena obiecte grafice 3D predefinite se folosesc funciile ce au
urmtoarele prototipuri :

void auxSolidBox(GLdouble lungime, GLdouble inaltime, GLdouble adancime
);
void auxSolidCone(GLdouble raza, GLdouble inaltime);
void auxSolidCube(GLdouble lungimeLatura);
void auxSolidCylinder(GLdouble raza, GLdouble inaltime);
void auxSolidDodecahedron(GLdouble raza);
void auxSolidIcosahedron(GLdouble raza);
void auxSolidOctahedron(GLdouble raza);
void auxSolidSphere(GLdouble raza);
void auxSolidTeapot(GLdouble dimensiune);
void auxSolidTetrahedron(GLdouble raza);
void auxSolidTorus(GLdouble RazaInterioara, GLdouble RazaExterioara);

Observai c toate aceste funcii au un anumit mod de contrucie al numelui :

aux + ModDeDesenare + TipulCorpuluiGeometric

ModDeDesenare poate fi Solid- adic cu suprafa continu sau Wire cu
suprafa reprezentat prin linii interconectate.
Pentru tipul geometric avem urmtoarele cazuri :
- Box - un paralelipiped dreptunghic definit prin lungime, nlime, adncime ;
- Cone un cod definit prin raza bazei i nlimea ;
119
- Cube un cub definit prin mrimea laturii ;
- Cylinder un cilindru definit prin raz i nlime;
- Dodecahedron un dodecaedru definit prin raz sferei cel circumscrie;
- Icosahedron un icosaedru definit prin raz sferei cel circumscrie;
- Octahedron un octaedru definit prin raz sferei cel circumscrie;
- Sphere o sfer definit prin raz;
- Teapot un ceanic definit de o mrime specific dup care se scaleaz;
- Tetrahedron un tetraedru definit prin raz sferei cel circumscrie;
- Torus un tor (un corp de forma unei gogoi) definit prin raz zonei umplute i
raza exterioar.

Se observ c la aceste corpuri nu li s-a precizat poziie. Ele vor desenate la
poziia actual a centrului sistemului de coordinate. Pentru a modifica poziia se
folosete funcia
glTranslatef cu prototipul :

void glTranslatef(GLfloat x, GLfloat y, GLfloat z );

Unde x, y, z semnific deplasri pe ox, oy, oz ale centrului de referin.


Exerciiu 4. Desenai pe ecran n modul Wire toate corpurile 3D precizate mai
sus, ncercai s le afiai pe toate n fereastr pentru a acoperi toat fereastra folosii
translaii cu ajutorul funciei glTranslate(). Sunt nevoie doar de translaii de ox i oy.

Duble buffering

Pentru a nltura plpirea ecranului la animaii vei folosi urmtoarele secvene
de cod:

auxInitDisplayMode(AUX_DOUBLE | AUX_RGBA) ;

,pentru iniializare, iar pentru a afia bufferul secundar se va apela funcia
urmtoare, aceasta dup ce s-a desenat tot ce se dorea :

auxSwapBuffers();








120
Programare Grafic OpenGL

4.3 Lucrare de laborator 3.

4 4. .3 3. .1 1 A Ap pl li ic ca a i ii i O Op pe en nG GL L n n W Wi in n3 32 2

n laboratorul anterior s-a spus c pentru aplicaii serioase ale OpenGL se va
lucra cu aplicaii Win32 sau MFC. n continuare vom prezenta paii ce trebuie urmai
pentru a crea o astfel de aplicaie. Este relativ simplu de a crea o aplicaie Win32
necompletat, mai greu ns este crearea codului de baz ce va iniializa grafic OpenGL
i mai ales fereastra de aplicaie. Pentru astfel de tipuri de aplicaii nu vom scrie pentru
fiecare aplicaie nou codul de la zero, ar fi contraproductiv, vom crea n schimb o
aplicaie ablon n care s avem definite elementele generale pe care le dorim a le folosi
n orice aplicaie viitoare, urmnd s copiem codul acestei aplicaii ori de cte ori dorim
s realizm o aplicaie OpenGL n stilul Win32.

4 4. .3 3. .2 2 C Cr re ea ar re ea a u un ne ei i a ap pl li ic ca a i ii i W Wi in n3 32 2 n ne ec co om mp pl le et ta at te e

Vom folosi pentru aceasta meniurile de creare de proiect specifice Visual C.
Vom parcurge urmtorii pai:
1. Din meniul File apsm New;
2. Alegem din tabul Projects Win32 Application;
3. Denumim proiectul n caseta de editare etichetat Project Name;
4. Apsm OK.
5. n fereastra urmtoare alegem - An empty project- i apsm Finish;
6. Mai apare o fereastr de confirmare n care apsm OK Am creat proiectul;
7. Din fereastra de vizualizare din partea stng selectm modul FileView ce
specific c se dorete a se vizualiza fiiere;
8. Din meniul File apasm New;
9. Din fereastr selectm tabul files- i de aici alegem -C++ source file-;
10. Denumim fiierul i apsm OK, va aprea o fereastr goal n care vom scrie
codul programului.

Acesta va conine n primul rnd includerea bibliotecilor:

#include <windows.h> //pentru lucrul cu ferestre i funcii Win32
#include "glos.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include <stdio.h> //facultativa
#include <string.h>//pentru lucrul cu sirurile de caractere
#include <math.h>// pentru lucrul cu funcii matematice

Apoi o definire a constantelor i variabilelor globale.

const char titlulferestrei[]="OpenGL Afisarea texturarii unui cilindru";
121
static HGLRC hRC; // dispozitivul de randare - obligatoriu
static HDC hDC; // dispozitivul de context suprafaa ferestrei adic -
obligatoriu

Aceste sunt recomandabile a fi definite sau chiar obligatorii.
Corpuri de funcii utilizate.
Funcia principala de desenare a graficii OpenGL:

void CALLBACK deseneaza(void)
{
// comenzi functii opengl
}

Funcia de setare modului grafic, esenial pentru crearea unei ferestre
compatibile cu OpenGL:

void SetDCPixelFormat(HDC hDC)
{
int nPixelFormat;

static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // dimensiunea structurii
1, // Versiunea structurii
PFD_DRAW_TO_WINDOW | // deseneaz n ferestre
PFD_SUPPORT_OPENGL | // suport grafica OpenGL
PFD_DOUBLEBUFFER, // se suporta duble - buffering
PFD_TYPE_RGBA, // culoare respecta standardul RGBA
24, // culoare pe 24 de biti
0,0,0,0,0,0, // nefolositi
0,0, // nefolositi
0,0,0,0,0, // nefolositi
32, // Buffer de adncime pe 32 de bii
0, // nefolosit
0, // nefolosit
PFD_MAIN_PLANE, // deseneaza in planul principal
0, // nefolosit
0,0,0 }; // nefolositi

// Alege un mod ct mai apropiat de cel solicitat in structura
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
// Stabileste modul grafic asociat contextului de dispozitiv hDC
SetPixelFormat(hDC, nPixelFormat, &pfd);
}



Funcia de rspuns la redimensionarea ferestrei:
122


void CALLBACK resizefunc(GLsizei w,GLsizei h)
{
if (w==0) w=1;
if (h==0) h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLsizei w2,h2;
if (w>h){
w2=nRange*w/h;
h2=nRange;
}else
{
w2=nRange;
h2=nRange*h/w;
}
glOrtho(-w2,w2,-h2,h2,-nRange,nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

Funcia repetat prin intermediul unui timer:

Exemplu:
void CALLBACK Repeta(void)
{
if (roteste_on)
{
a=(a+4)%360;
b=(b+4)%360;
deseneaza();
}
}

i cel mai important funcia de gestionare a mesajelor, practic nucleul unei
aplicaii Win32:
Exemplu:

LRESULT CALLBACK WndProc( HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{

123
switch (message)
{
// Apelata la crearea ferestrei
case WM_CREATE:
// extragem contextul de dispozitiv
hDC = GetDC(hWnd);

// selectam modul grafic compatibil OpenGL asociat ferestrei
SetDCPixelFormat(hDC);

//creem contextul de randare al graficii OpenGL
hRC = wglCreateContext(hDC);
// asociam contextului de dispozitiv curent contextul de randare
//facandu-l pe acesta activ
wglMakeCurrent(hDC, hRC);

// creem un timer ciclat la un interval de o milisecunda
SetTimer(hWnd,10000,1,NULL);
break;

// La inchiderea ferestrei
case WM_DESTROY:
// dezactivam timerul
KillTimer(hWnd,101);

//deselectam contextul de randare din contextul de dispozitiv
wglMakeCurrent(hDC,NULL);
// stergem contextul de randare
wglDeleteContext(hRC);
// va iesi din aplicatie odata ce fereastra de aplicatia a disparut
PostQuitMessage(0);
break;

// Apelat la redimensionarea ferestrei
case WM_SIZE:
//apelam functia de redimensionare a ferestrei
resizefunc(LOWORD(lParam), HIWORD(lParam));
break;

// apelat prin intermediul timerului o dat la fiecare milisecunda
case WM_TIMER:
{
//functie care se repeta o data la o milisecunda
Repeta();
}
break;

124
// Apelat la desenarea sau redesenarea ferestrei
case WM_PAINT:
{
// desenam grafica OpenGL propriu-zisa
deseneaza();

// afisam buferul secundar in fereastra pe ecran
SwapBuffers(hDC);
// validam suprafata de desenare
ValidateRect(hWnd,NULL);
}
break;
//apelata la apasarea unei taste
case WM_KEYDOWN:
{
switch (keydata)
{
case 75://executa ramura la apasarea tastei spre stanga
ScadeUnghiA();
break;
case 77:// executa ramura la apasarea tastei spre dreapta
CresteUnghiA();
break;
case 72:// executa ramura la apasarea tastei in sus
ScadeUnghiB();
break;
case 80:// executa ramura la apasarea tastei in jos
CresteUnghiB();
break;
case 57:// executa ramura la apasarea barei de spatiu
AltCorp();
break;
}
}
break
// apelata la micare cursorului mouselui
case WM_MOUSEMOVE:
//Roteste Corpul pe 2 axe cat timp butonul stang este tinut apasat
{
int mx,my;
mx=LOWORD(lParam);
my=HIWORD(lParam);
if (wParam==MK_LBUTTON)
{
a=a_+(mmy-my)*2;
b=b_+(mmx-mx)*2;
deseneaza();
125
}
}break;
//apelata la apsarea butonului stang al mouse-lui
case WM_LBUTTONDOWN://Activeaza rotatia prin mouse
//fixand punctul de referinta
{
int mx,my;
mx=LOWORD(lParam);
my=HIWORD(lParam);
a_=a;
b_=b;
mmx=mx;
mmy=my;
}
break;
//apelata la apasarea butonului drept al mouse-ului
case WM_RBUTTONDOWN://Schimba corpul prin clic dreapta
mouse
{
AltCorp();
}
break;
//apelata la apasarea butonului din mijloc al mouselui
case WM_MBUTTONDOWN:
//Roteste automat si in mod continuu corpul
//activarea dezactivarea facandu-se prin butonul
//de mijloc al mouse-ului
{
roteste_on=!roteste_on;
}
break;


default: // daca nu s-a apelat nici o alta ramura
// apelam functia de procesare implicita a mesajelor
return (DefWindowProc(hWnd, message, wParam, lParam));

}
return (0L);
}



n locul funciei main() din C, C++ vom avea urmtoare secven, care rmne
aproape indentic pentru orice aplicaie Win32 vom crea de acum ncolo:

int APIENTRY WinMain( HINSTANCE hInstance,
126
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg; // mesaj window
WNDCLASS wc; // clasa fereastr.
HWND hWnd; // pointer - indice la o fereastr
// initializam parametrii ferestrei:
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = windowtitle;

// Inregistram clasa fereastra
if(RegisterClass(&wc) == 0)
return FALSE;

// Creem fereastra aplicatiei
hWnd = CreateWindow(
windowtitle,
windowtitle,
// OpenGL requires WS_CLIPCHILDREN and
WS_CLIPSIBLINGS |
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
100, 100,
width0, height0,
NULL,
NULL,
hInstance,
NULL);
// daca fereastra nu s-a creat functia WinMain va returna FALSE
if(hWnd == NULL)
return FALSE;

// Afisam fereastra aplicatiei
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);

// Procesam mesajele spre aplicatie prin intermediul unei bucle
while( GetMessage(&msg, NULL, 0, 0))
127
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;// inchidem ciclul returnand un parametru al mesajului
}


Exerciiu. Pe baza unei aplicaii ablon disponibile pe calculatorul pe care
lucrai. Construii un program care la inerea apsat a butonului stng al mouselui s
deplaseze un dreptunghi care s fie afiat tot timpul cu centrul sub pointerul mouseului.
























128
Programare Grafic OpenGL

4.4 Lucrare de laborator 4.

4 4. .4 4. .1 1 P Pr ri im mi it ti iv ve e g gr ra af fi ic ce e O Op pe en nG GL L

n momentul de fa din laboratoarele precedente stpnim iniializarea i crearea unui
mediu pentru OpenGL att folosind biblioteca glaux ct i Win32. Cu toate aceste nu
prea se tie s se deseneze prea mult n OpenGL cu excepia ctorva elemente de baz.
Pentru a desena orice corp n OpenGL indiferent de ct de complex este, este nevoie de
utilizarea unui set de primitive. Acestea sunt elemente grafice de baz.

4 4. .4 4. .2 2 D De es se en na ar re ea a d de e p pu un nc ct te e

Pentru a se desena un punct se folosete urmtoarea secven:

glBegin(GL_POINTS);
// va desena un punct la coordonatele (50,50,50)
glVertex3f(50.0f, 50.0f, 50.0f);
glEnd();

Se observ folosirea unei funcii de nceput de desenare glBegin la care specificm ce
anume se va desena. O funcie de finalizare a secvenei de desenare glEnd().
ntotdeauna aceste funcii vor lucra n pereche, iar ntre ele nu vor fi permise dect
anumite operaii de desenare. Una dintre acestea este specificare unui vrf ce se face cu
funcia glVertex3f care are urmtorul prototip:

void glVertex3f(GLfloat x, GLfloat y, GLfloat z);

Unde x,y,z sunt coordonatele punctului sau vrfului. Aceast funcie are o multitudine
de alte abordri, aceasta fiind cea mai folosit.
Alt funcie este specificare culorii glColorf3f avnd prototipul:

void glColor3f(GLfloat rosu, GLfloat verde,GLfloat albastru);

Aceasta precede un vrf, sau vrfuri crora le specific culoarea putnd tot la fel de bine
sta i n afara perechii glBegin glEnd.


4 4. .4 4. .3 3 D De es se en na ar re ea a d de e l li in ni ii i

Pentru a desena o linie folosim secventa:

glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);//primul capat al liniei
glVertex3f(50.0f, 50.0f, 50.0f);//al doilea capat al liniei
glEnd();
129

Se observ c i de aceast dat s-a specificat n glBegin tipul de primitiv dorit.
Fcnd aceast practic i precizm secvenei cum va interpreta vrfurile ce se afl n
interiorul perechii glBegin glEnd. Oricare dou perechi de vrfuri luate n ordine vor
specifica o nou linie.
Exemplu :
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);//primul capat al liniei 1
glVertex3f(50.0f, 50.0f, 50.0f);//al doilea capat al liniei 1
glVertex3f(0.0f, 20.0f, 0.0f);//primul capat al liniei 2
glVertex3f(50.0f, 40.0f, 50.0f);//al doilea capat al liniei 2
glVertex3f(20.0f, 0.0f, 0.0f);//primul capat al liniei 3
glVertex3f(10.0f, 30.0f, 50.0f);//al doilea capat al liniei 3
glEnd();

Dac este un vrf necuplat acesta va fi ignorat.


Pentru desenarea unor linii la care ultimul capt este nceput pentru o nou linie se
folosete constanta GL_LINE_LOOP specificat n glBegin().
Pentru a desena un mnunchi de linii n care un punct s fie originea unui grup de linii
se folosete constanta GL_LINE_STRIP.
La GL_LINE_LOOP primul vertex este nceputul nlnuirii de linii i ultimul sfritul.
La GL_LINE_STRIP primul vertex(vrf) este originea mnunchiului de linii i celelalte
vertexuri capete de linie.

Exercitiu 1. Desenai din linii un hexagon centrat pe ecran.
Exerciiu 2. Desenai folosind GL_LINE_STRIP un mnunchi de linii care s semene
cu razele de lumin emise de o stea.( De acum ncolo vom folosi abordare desenai cnd
ne vom referi la crearea unui program care s deseneze un anume lucru, sau ori de cte
ori ne referim la construcia unei scene 3D.)

4 4. .4 4. .4 4 D De es se en na ar re ea a u un nu ui i t tr ri iu un ng gh hi i

Pentru a desena un triunghi avem la dispoziie trei constante:

GL_TRIANGLES deseneaz triungiuri independente grupuri de trei vrfuri luate n
ordine constituie un triunghi;
GL_TRIANGLE_STRIP deseneaz triunghiuri interconectate ultimele dou vrfuri
al oricrui triughi sunt vrfuri de generare ale urmtorului;
GL_TRIANGLE_FAN deseneaz triunghiuri interconectate sub forma unui evantai
la care primul vrf al primului triunghi este comun tuturor celorlalte triunghiuri ;

Dei sunt disponibile o varietate de alte poligoane pe care le poate genera OpenGL, din
punct de vedere hardware triunghiurile sunt procesate cel mai rapid. De aceea la creare
unui obiect din elemente este indicat ca acestea s fie triunghiuri, sau o alt abordare ar
fi descompunerea poligoanelor complexe n triunghiuri.
130


Exerciiu 3. Desenai o piramid folosind evantaiul de triunghiuri, fr de desena i
baza. Fiecare fa desenata va avea alt culoare.


4 4. .4 4. .5 5 D De es se en na ar re ea a u un nu ui i p pa at tr ru ul la at te er r

Pentru a desena un patrulater se folosesc constantele :

GL_QUADS deseneaz un patrulater independent;
GL_QUAD_STRIP deseneaz nite patrulatere interconectate, ultimele dou vrfuri
fiind primele dou ale urmtorului patrulater;

4 4. .4 4. .6 6 D De es se en na ar re ea a u un nu ui i p po ol li ig go on n

Pentru a desena un poligon se folosete constanta GL_POLYGON, fiecare vrf va fi
cte un col al poligonului ultimul vrf fiind automat unit cu primul pentru crearea unui
contur nchis. Aceasta este valabil i pentru patrulatere.


4 4. .4 4. .7 7 F Fu un nc c i ii i g gr ra af fi ic ce e a au ux xi il li ia ar re e

n acest moment au fost expuse toate primitivele grafice de baz i cu toate acestea mai
rmn de precizat elemente tipice pentru primitive : mrimea punctului, grosimea liniei,
model de linie, model de poligon, renunarea la desenarea unei fee,desenarea umplut
sau doar conturat a unei primitive nchise. Aceste lucruri i altele vor fi expuse n
continuare.


4 4. .4 4. .8 8 M Mo od di if fi ic ca ar re e m m r ri im mi ii i p pu un nc ct tu ul lu ui i

Spre deosebire de puncte afiate pe un ecran punctele din OpenGL au dimensiuni.
Punctele au o forma de ptrat cnd sunt mrite i nu de cerc cum s-ar putea crede.
Pentru a modifica mrimea unui punct se folosete secvena urmtoare :

GLfloat sizes[2]; // pastreaza limitele intre care
//variaza marimea punctului
GLfloat step; // pastreaz pasul de incrementare al marimii

// se citesc valorile stocate implicit
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);

De obicei limitele mrimii variaz ntre 0.5 i 10.0, iar pasul de incrementare al mrimii
este de 0.125.
131



Pentru a seta mrimea punctului se folosete aceast apelare :

glPointSize(MarimeaPunctului);

4 4. .4 4. .9 9 M Mo od di if fi ic ca ar re e p pa ar ra am me et tr ri il lo or r l li in ni ie ei i

Pentru a afla limitele ntre care variaz grosimea liniei, precum i pasul de incrementare
al grosimii se folosete o secven asemntoare ca la punct:

GLfloat sizes[2];// intervalul de valori
GLfloat step; //pasul
// Get supported line width range and step size
glGetFloatv(GL_LINE_WIDTH_RANGE,sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&step);

Pentru a seta grosimea liniei vom apela funcia:

glLineWidth(GrosimeLinie);

, naintea desenrii liniilor ce vor avea grosimea precizat.

Pentru a modifica modelul liniei spre exemplu pentru a trasa o linie segmentat sau
compus din puncte, sau alt model. Folosim secvena :

GLushort model = 0x5555;
GLint factor = 4;

glEnable(GL_LINE_STIPPLE);

glLineStipple(factor,model);


La care model semnific o secven de 16 bii fiecare bit semnificnd absena sau
prezen unui segment din linie, segment de lungime specificat de factor-.


4 4. .4 4. .1 10 0 M Mo od di if fi ic ca ar re e p pa ar ra am me et tr ri il lo or r f fi ig gu ur ri il lo or r n nc ch hi is se e

Pentru a specifica faptul c tranziiile de culoare de pe suprafaa poligonului se fac liniar
sau fin se va folosi funcia cu prototipul :

void glShadeModel( GLenum mod);

Unde mod poate fi una dintre constantele:
132

GL_FLAT aspect mai necizelat al tranziiei de culoare;
GL_SMOOTH aspect lin, fin al tranziiei de culoare;

Pentru a specifica c poligoanele (prin acest termen se face referire la toate figurile
nchise fie ele triunghiuri, patrulater) vor fi desenate astfel nct cele din spate s fie
acoperite de cele din fa se va folosi urmtoarele secvene :

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

, pentru tergerea ecranului. Se observ c se terge i bufferul de adncime n care sunt
pstrate poziiile punctelor desenate n raport cu axa oz.

glEnable(GL_DEPTH_TEST);

, pentru a activa opiunea de folosire a buferului de adncime.

Uneori pentru a crete viteza de procesare dorim s nu mai fie desenate suprafeele
interioare ale corpurilor. n acest sens se va folosi o funcie care s specifice care
poligoane vor constitui faa poligonului i care spatele. Esenial n acest proces este
ordinea n care sunt definite vrfurile unui polygon. Ea poate fi n sensul acelor de ceas
sau invers.

Secvena care specific c spatele poligoanelor nu va fi desenat este:

glEnable(GL_CULL_FACE);

glFrontFace(GL_CW);// fata poligonului este cea n care vrfurile
// sunt definite n sensul acelor
//definim poligoane conform acestei reguli
glFrontFace(GL_CCW); // fata poligonului este cea n care vrfurile
// sunt definite contrar sensului acelor
//definim poligoane conform acestei reguli


Pentru a specifica modul n care este desenat poligonul vom folosi secvenele:

glPolygonMode(GL_BACK,GL_LINE);// spatele este desenat numai conturat

glPolygonMode(GL_FRONT,GL_LINE);// faa este desenat numai conturat

glPolygonMode(GL_FRONT,GL_FILL);// faa este desenata umpluta

Primul parametru poate lua valorile :
GL_FRONT se refera doar la faa poligonului
GL_BACK se refera la spatele poligonului
GL_FRONT_AND_BACK se refera la ambele suprafee ale poligonului
133

Al doilea parametru poate lua valorile :
GL_POINT - se deseneaz numai vrfurile;
GL_LINE - se deseneaz numai conturul;
GL_FILL se deseneaz suprafaa umplut;




Pentru a specifica c se va folosi un efect de umplere vom folosi secvenele de
iniializare :

glEnable(GL_POLYGON_STIPPLE);

glPolygonStipple(model);

Unde model este o matrice 32x32 de bii. Fiecare bit reprezentnd un punct din model.
Acest model este repetat pe verticala i pe orizontala suprafeei poligonale la care se
aplic acoperind-o n ntregime.

GLubyte model[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc0,
0x00, 0x00, 0x01, 0xf0,
0x00, 0x00, 0x07, 0xf0,
0x0f, 0x00, 0x1f, 0xe0,
0x1f, 0x80, 0x1f, 0xc0,
0x0f, 0xc0, 0x3f, 0x80,
0x07, 0xe0, 0x7e, 0x00,
0x03, 0xf0, 0xff, 0x80,
0x03, 0xf5, 0xff, 0xe0,
0x07, 0xfd, 0xff, 0xf8,
0x1f, 0xfc, 0xff, 0xe8,
0xff, 0xe3, 0xbf, 0x70,
0xde, 0x80, 0xb7, 0x00,
0x71, 0x10, 0x4a, 0x80,
0x03, 0x10, 0x4e, 0x40,
0x02, 0x88, 0x8c, 0x20,
0x05, 0x05, 0x04, 0x40,
0x02, 0x82, 0x14, 0x40,
0x02, 0x40, 0x10, 0x80,
0x02, 0x64, 0x1a, 0x80,
0x00, 0x92, 0x29, 0x00,
134
0x00, 0xb0, 0x48, 0x00,
0x00, 0xc8, 0x90, 0x00,
0x00, 0x85, 0x10, 0x00,
0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00};
Un exemplu de definire de model.

Pentru construcia unui poligon se aplic o serie de reguli. nclcarea acestor reguli crea
probleme pe plcile video mai vechi dar pentru cele noi aceste restricii nu mai sunt
valabile. n orice caz este bine s fie respectate pentru o mai bun portabilitate a codului
OpenGL. Astfel :
Laturile poligonului nu trebuie s se intersecteze.
Poligonul trebuie s fie convex.
Vrfurile poligonului trebuie s se afle n acelai plan.

4 Exerciiu 4. Creai un poligon hexagonal care s fie umplut cu un model,
care s reprezinte o fa zmbitoare (smiley).






























135

Programare Grafic OpenGL

4.5 Lucrare de laborator 5.

4 4. .5 5. .1 1 T Tr ra an ns sf fo or rm m r ri i g ge eo om me et tr ri ic ce e n n O Op pe en nG GL L

n OpenGL transformrile geometrice pe care le suport un set de puncte,
respectiv un corp 3D format din acestea, sunt mediate de o matrice de transformri cu
patru coloane i patru linii. nmulind vectorul de patru elemente ce specific punctul cu
o astfel de matrice se obine un nou vector care reprezint punctul ce a suferit
transformrile.
Am spus patru elemente i nu trei pentru c primele trei sunt coordonatele x, y, z
ale punctului i a patra valoare este un coeficient de scalare w. Prin nmulirea unei
matrice corespunztoare de transformri cu un punct se pot face rotaii, translaii,
scalri. Acestea sunt transformri clasice realizate prin funciile OpenGL, dar lucrnd
direct cu matricea se pot realiza transformri personalizate ca de exemplu crearea de
umbre. Nu exist un acces direct la matrice dar n schimb exist unul mediat, matricea
poate fi ncrcat, descrcat, ncrcat ntr-o stiv, descrcat dintr-o stiv, iniializat
cu matricea unitate, i n plus o mediere de gradul doi n care modificam matricea prin
nmuliri cu matrice ce specific translaii, rotaii, etc. Orice transformare de coordonate
n OpenGL se realizeaz prin nmulirea matricei de lucru cu o matrice ce specific o
transformare.

4 4. .5 5. .2 2 n nc c r rc ca ar re ea a i i d de es sc c r rc ca ar re ea a d di in n s st ti iv v a a u un ne ei i m ma at tr ri ic ce e

Matricea de lucru poate fi salvat ntr-o stiv, ca mai apoi cnd se dorete
revenirea la starea iniial s fie descrcat din stiv n matricea de lucru curent.
Aceasta este util pentru a pstra o stare a sistemului la un moment pentru ca mai apoi
s se revin la ea.
De exemplu am fcut nite transformri i acestea vor fi comune unui grup de
obiecte ce urmeaz, dar pentru aceste obiecte se mai dorete nc o transformare pentru
orientare de exemplu, nainte de a face rotaia vom salva starea matricei ca dup afiarea
obiectului s se revin la starea iniial.
Pentru a salva matricea de transformare prin ncrcarea ei n stiv se folosete
funcia:

glPushMatrix( );

, care nu are parametri.

Iar pentru a descrca matricea de transformare salvat din stiv se folosete o
funcie asemntoare:

glPopMatrix( );

136
De obicei acestea vor lucra mpreun. O apelare glPushMatrix fiind urmat mai
jos n program de glPopMatrix.

Pentru a ncrca matricea unitate se folosete funcia:

glLoadIdentity( );

,care anuleaz orice transformare anterioar.

Mai exist o funcie care specific la care tip de matrice se refer:

void glMatrixMode(GLenum mode);

unde mode poate fi definit de una din constantele:

GL_MODELVIEW se refer la matricea ce afecteaz modul de vizualizare a
obiectului ;
GL_PROJECTION se refer la matricea de proiecie;
GL_TEXTURE - se refer la matricea prin care se realizeaz texturarea :


Exemplu :
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glTranslatef(0.0f, 0.0f, -300.0f);
glColor3f(1, 1, 0);
auxSolidSphere(30.0f);

glRotatef(a, 0.0f, 1.0f, 0.0f);

glColor3f(0,0,1.0);
glTranslatef(105.0f,0.0f,0.0f);
auxSolidSphere(15.0f);

glColor3f(0.7,0.6,0.8);
glRotatef(b,0.0f, 1.0f, 0.0f);
glTranslatef(30.0f, 0.0f, 0.0f);
auxSolidSphere(6.0f);

glPopMatrix();//

glFlush();




137
4 4. .5 5. .3 3 T Tr ra an ns sf fo or rm m r ri i e el le em me en nt ta ar re e d de e c co oo or rd do on na at te e

OpenGL pune la dispoziie trei tipuri de transformri prin intermediul
urmtoarelor funcii:

glRotatef pentru rotaii;
glTranslatef pentru translaii;
glScalef pentru scalri;

glRotatef are urmtorul prototip:

void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

,unde angle reprezint valoarea unghiului de rotaie exprimat n grade, unghi ce
semnific o rotaie invers acelor de ceas ;
x, y, z reprezint unul din punctele ce definesc axa de rotaie, cellalt fiind
poziia curent a centrului sistemului de referin ;

glTranslatef are urmtorul prototip :

void glTranslatef(GLfloat x, GLfloat y, GLfloat z );

,unde x, y, z sunt valori ale tranlaiei pe cele trei axe de coordonate.

glScalef are urmtorul prototip :

void glScalef(GLfloat x, GLfloat y, GLfloat z);

,unde x, y, z sunt valori ale factorilor de contracie respectiv dilatare a corpului
pe cele trei axe de coordonate .

Trebuie reinut faptul c orice transformare este aditiv i se perpetueaz dac nu
se folosesc funciile glPushMatrix, glPopMatrix sau glLoadIdentity.

Pentru funciile de rotaii pentru a nu aprea confuzii este bine s se fac rotaii
numai cte pe o axa odat astfel :

Pentru a roti pe axa Ox cu un unghi de 45 de grade vom avea secvena :

glRotatef (45.0f, 1.0f, 0.0f, 0.0f) ;

,pentru oy avem ceva asemntor :

glRotatef( 45.0f, 0.0f, 1.0f, 0.0f).

138
Exerciiu 1. Creai un program care folosind glaux, s afieze un cub
(auxWireCube) i apoi apsnd tastele sgei pentru stnga dreapta s se fac o rotaie
pe ox, sus-jos pe oy, si a z pe oz.

Exerciiu 2. Creai un program pentru simularea sistemului Soare, Lun, Pmnt.
Acest sistem se va afla n rotaie, Luna se va nvrti de dou ori mai repede n jurul
Pmntului dect Pmntul n jurul Soarelui. Soarele va fi o sfer galben, Luna o sfer
cenuie iar Pmntul o sfer albastr.

Exerciiu 3. Creai un atom cu electroni nucleul va fi compus din 2 sfere
albastre i dou sfere roii. Vor fi 4 electroni ce se vor roti fiecare pe o orbit proprie,
fiecare cu raze diferite. Electronii vor fi sfere galbene.

Exerciiu 4. Creai o compoziie format dintr-un cub, iar n fiecare col al su va
fi desenat o sfer.

4 4. .5 5. .4 4 C Co on nf fi ig gu ur ra ar re ea a m me ed di iu ul lu ui i v vi iz zu ua al l

Dac vei crea programe n Win32, de OpenGL, vei avea nevoie s cunoatei o
serie de funcii de configurare a mediului vizual. Mai nti se vor expune o serie de
secvene de cod n care sunt implicate astfel de funcii:


glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(60.0f,(GLfloat)w/(GLfloat)h, 1.0, 400.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

n aceast secven avem urmtoarele funcii:

glViewport stabilete parametrii ferestrei software de desenare(Viewport)
specificai prin poziia colului stnga - sus , i lungimea w, i nlimea h a ferestrei.
glMatrixMode(GL_PROJECTION) stabilete c se va lucra cu matricea de
proiecie;
glLoadIdentity() stabilete c matricea de proiecie va fi resetat la starea
iniial;
gluPerspective face modificri asupra matricei de proiecie stabilind unghiul
percepiei 60.0 de grade, aspectul proieciei adic raportul dintre nlimea i lungimea
imaginii, cel mai apropiat i cel mai ndeprtat punct pe oz pe baza crora se stabilete
planurile de decupare a scenei, astfel c ce este nafara acestor limite nu este afiat ;
glMatrixMode(GL_MODELVIEW) se stabilete c se va lucra cu matricea
modelelor 3D ;
glLoadIdentity() se seteaz mediul 3D la starea iniial;
139

De obicei o astfel de secven este apelat la fiecare redimensionare a ferestrei,
sau nainte de prima afiare a ferestrei aplicaiei.

O alt funcie de configurare ar fi urmtoarea:

void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble
centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
GLdouble upz );

, unde eyex, eyey, eyez este poziia observatorului sau mai bine spus a ochiului
acestuia;
, centerx, centerzy, center z este centrul scenei spre care privete.
, upx, upy, upz specfic direcia privirii observatorului.

Exemplu:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(locX, locY, locZ, dirX, dirY, dirZ, 0.0f, 1.0f, 0.0f);

n acest exemplu matricea de vizualizare este resetat, i apoi setat n raport cu
ochiul observatorului.

Folosind aceast funcie putem crea un program prin care s explorm o anumit
scen.

Exerciiu 5. Modificnd exemplul 4, scriei o secven de program n care la
apsarea tastelor sus jos ochiul observatorului s se deplaseze pe oz, iar stnga
dreapta pe ox. Vei folosi desigur funcia gluLookAt prezentat mai sus. Mai putei
modifica programul astfel nct la apsarea tastelor a z s se modifice upx, s x upy, d
- c upz, modificnd astfel i orientarea privirii observatorului.












140


Programare Grafic OpenGL

4.6 Lucrare de laborator 6.

4 4. .6 6. .1 1 I Il lu um mi in na ar re e, , l lu um mi in ni i i i m ma at te er ri ia al le e. .

Pn acum s-a lucrat n medii n care nu s-a pus problema iluminrii scenelor,
obiectele solide, triunghiurile erau toate uniform colorate, nu conta distana, orientarea
acestora. Corpurile care aveau suprafa opac, sferele spre exemplu erau simple pete de
culoare mai mult discuri, dect corpuri cu volum. Scopul acestui laborator este chiar
rezolvarea acestei probleme. Se vor prezenta att moduri de iluminare, poziionri de
spoturi, efecte de iluminare ct i un aspect complementar materialul din care este fcut
corpul. La material vor conta proprietile reflexive ale acestuia adic modul cum acesta
rspunde la lumin.

4 4. .6 6. .2 2 C Co on nf fi ig gu ur ra ar re ea a i il lu um mi in n r ri ii i

Iluminarea natural are trei componente principale :
componenta ambiental n care lumina nu pare a avea o surs anume ea
emannd din toate punctele din spaiu i din nici unul n mod particular, obiectele sunt
luminate uniform;
componenta difuz la care lumina are o surs anume, dar nu apar suprafee
lucioase;
componenta de luciu la care lumina este direcional i mai apare i un luciu
al suprafeelor;

Pentru a configura aceste trei componente se folosete funcia cu urmtorul
prototip:

void glLightfv( GLenum sursa, GLenum mod, const GLfloat *parametri);

,in care sursa este o constanta de forma GLLightx. Unde x poate lua valori de la
0 la o valoare maxim precizat de constanta GL_MAX_LIGHTS.
, mod este tipul componentei de iluminare aceasta poate fi :

GL_AMBIENT - pentru specificare componentei ambientale;
GL_DIFFUSE - pentru specificare componentei difuze;
GL_SPECULAR pentru specificare componentei de luciu;
GL_POSITION pentru specificare poziiei sursei de lumin.

ar mai i alte moduri dar pentru moment acestea sunt suficiente,


141
, parametri este un vector de patru componente care pentru modurile de
iluminare reprezint elementele RGBA adic intensitatea culorii roii, a celei verzi i a
celei albastre plus intensitatea componentei alfa toata date prin valori de la 0.0 la 1.0.
Pentru poziii parametri specific exact coordonatele x, y i z ale sursei plus o
component de scalare care trebuie setat ntotdeauna la 1.0.

Exemplu :


GLfloat ambient[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat specular[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { 0.0f, 200.0f, 200.0f, 0.0f };

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);

Se observ modul cum sunt declarai vectorii. Se mai observ folosirea unor
funcii de activare a iluminrii pentru iluminarea generala a scenei
glEnable(GL_LIGHTING) - iar pentru activarea exclusiv a unei surse
glEnable(GL_LIGHT0).

n cazul iluminrii ambientale nu se pune problema orientrii suprafeei fa de
sursa de lumin. Pentru iluminrii direcionale n schimb orientarea suprafeei devine
esenial. n matematic pentru a defini orientare unei suprafee se specific vectorul
normal pe acea suprafa, practic o perpendicular care iese din suprafa. Cnd se
construiete o suprafa nainte de specifica vrfurile pentru aceea suprafa
(glVertex)
se va specifica n interiorul secvenei glBegin . glEnd normala la acea
suprafa folosind funcia cu prototipul :

void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);

, unde nx, ny, nz sunt coordonatele vrfului normalei.

Dei OpenGL ofer o modalitate de precizare a normalei unei suprafee nu ofer
i o funcie care dnd o serie de vrfuri s calculeze normala pentru suprafaa definite de
ele. Din aceasta cauza va trebui definit o funcie de calcul a normalei. Un exemplu de
astfel de funcie este :



142

void ReduceToUnit(float vector[3])
{
float lungime;

// se calculeaz lungimea vectorului
lungime = (float)sqrt((vector[0]*vector[0]) +
(vector[1]*vector[1]) +
(vector[2]*vector[2]));

// evitarea impartirii la zero
if(lungime == 0.0f)
lungime = 1.0f;

// se impart toate componentele vectorului la lungime
// normalizandu-le
vector[0] /= lungime;
vector[1] /= lungime;
vector[2] /= lungime;
}
void calcNormal(float vv0[3],float vv1[3],float vv2[3], float out[3])
{
float v1[3],v2[3];
static const int x = 0;
static const int y = 1;
static const int z = 2;

// determin doi vectori pe baza a trei puncte
v1[x] = vv0[x] - vv1[x];
v1[y] = vv0[y] - vv1[y];
v1[z] = vv0[z] - vv1[z];

v2[x] = vv1[x] - vv2[x];
v2[y] = vv1[y] - vv2[y];
v2[z] = vv1[z] - vv2[z];

// se face produsul vectorial al celor doi vectori
// obinndu-se varful normalei
out[x] = v1[y]*v2[z] - v1[z]*v2[y];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];
//se normalizeaza vectorul
ReduceToUnit(out);
}



143
Funcia care calculeaz normala este calcNormal, se mai folosete i o funcie de
normalizare a vectorilor ReduceToUnit. vv0, vv1, vv3 constituie vrfurile, iar out
vrful vectorului normal.

Exemplu de folosire:
glFrontFace(GL_CW);
glColor3f(1,0,0);
calcNormal(triunghi[2],triunghi[1],triunghi[0],mynormal);
glBegin(GL_TRIANGLES);
glNormal3fv(mynormal);
glVertex3fv(triunghi[0]);
glVertex3fv(triunghi[1]);
glVertex3fv(triunghi[2]);
calcNormal(triunghi[3],triunghi[2],triunghi[0],mynormal);
glNormal3fv(mynormal);
glVertex3fv(triunghi[0]);
glVertex3fv(triunghi[2]);
glVertex3fv(triunghi[3]);
calcNormal(triunghi[4],triunghi[3],triunghi[0],mynormal);
glNormal3fv(mynormal);
glVertex3fv(triunghi[0]);
glVertex3fv(triunghi[3]);
glVertex3fv(triunghi[4]);
calcNormal(triunghi[5],triunghi[4],triunghi[0],mynormal);
glNormal3fv(mynormal);
glVertex3fv(triunghi[0]);
glVertex3fv(triunghi[4]);
glVertex3fv(triunghi[5]);
glEnd();
glColor3f(1,0,0);
glFrontFace(GL_CCW);
calcNormal(triunghi[2],triunghi[3],triunghi[4],mynormal);
glBegin(GL_QUADS);
glNormal3fv(mynormal);
glVertex3fv(triunghi[1]);
glVertex3fv(triunghi[2]);
glVertex3fv(triunghi[3]);
glVertex3fv(triunghi[4]);
glEnd();

Secvena de mai sus deseneaz o piramida rosie, cu tot cu baz.






144







Se observ folosirea funciei glVertex3fv aceasta este o variant a funciei
glVertex3f, numai c n acest caz parametrii x, y, z sunt preluai dintr-un vector cu trei
elemente. Acest mod de folosire pentru, acelai tip de aciune, de variante de funcii este
o caracteristic OpenGL. Un exemplu ar fi :

glVertex2d, glVertex2f, glVertex2i, glVertex2s, glVertex3d,
glVertex3f, glVertex3i, glVertex3s, glVertex4d, glVertex4f,
glVertex4i, glVertex4s, glVertex2dv, glVertex2fv, glVertex2iv,
glVertex2sv, glVertex3dv, glVertex3fv, glVertex3iv, glVertex3sv,
glVertex4dv, glVertex4fv, glVertex4iv, glVertex4sv

Aceasta pentru a v face o idee de flexibilitate OpenGL, exemplele putnd
continua.

Crearea automat de normale

Pentru corpuri 3D predefinite n OpenGL exist posibilitatea generrii automate
a normalelor, astfel:

glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);

,tot ce trebuie fcut este s se insereze n program nainte de desenarea
corpurilor respective a acestor dou linii de cod.

Pentru ce a fost nevoie de normale? Pentru ca refleciile venite de la corp i
tonurile de culoare s par naturale, altfel acestea ar fi fost arbitrare fr vreo legtur
cu iluminarea n sine.





4 4. .6 6. .3 3 C Co on nf fi ig gu ur ra ar re ea a m ma at te er ri ia al lu ul lu ui i

Odat ce s-au stabilit luminile urmtorul pas este configurarea materialului.
Materialul precizeaz modul n care lumina va fi reflectat, difuzat sau emanat de
ctre obiect. n acelai timp specificm i culoare suprafeei prin precizarea
materialului. Pentru a specifica materialul se poate folosi urmtoarea secven:

145
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_amb);
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_dif);
glMaterialfv (GL_FRONT, GL_SPECULAR, mat_spec);
glMaterialf (GL_FRONT, GL_SHININESS, 0.7f*128.0f);

Observm folosirea funciei glMaterialfv aceasta are prototipul:

void glMaterialfv(GLenum fata, GLenum proprietate,
const GLfloat *parametri );

, fata poate lua urmtoarele valori:
GL_FRONT se refer la fa ;
GL_BACK se refer la spate;
GL_FRONT_AND_BACK se refer la fa i spate;
, proprietate stabilete care aspect al materialului va fi configurat:
GL_AMBIENT reflexia luminii ambientale (4 valori);
GL_DIFFUSE reflexia luminii difuze(4 valori);
GL_SPECULAR reflexia luciului suprafeei(4 valori);
GL_EMISSION emisia de lumin de ctre suprafa(4 valori);
GL_SHININESS gradul de reflexie lucioas a suprafeei (cu ct este mai mare
cu att suprafaa lucioas este mai extins) (o valoare);
GL_AMBIENT_AND_DIFFUSE - reflexia luminii ambientale i difuze(4
valori);
GL_COLOR_INDEXES se refer la indecii de culoare se pot configura n
acelai toate cele trei proprieti reflexive : ambiental, difuz i lucioas. (3valori)
, parametrii vor fi patru valori ale componentelor culorii RGBA.

glMaterialf este folosit n special pentru a specifica gradul de lucire al suprafeei.
Intervalul de valori pentru acest parametru este ntre 1 i 128. 128 este cel mai nalt grad
de lucire.

Exerciiu1. Realizai un program cu Soarele, Luna i Pmntul, n care soarele s
fie o surs de lumin i n acelai timp o sfer galben. Luna va fi o sfer cenuie i
Pamntul o sfer albastr. Acestea se vor roti.

Exerciiu 2. Construii o molecul de metan (CH
4
). Atomul de carbon va fi o
sfer cenuie. Iar atomii de hidrogen nite sfere albastru deschis de 3 ori mai mici ca
atomul de carbon, plasate pe suprafaa acestuia astfel nct cam 40% din ele s fie
nglobate n atomul de carbon. Atomii de hidrogen vor fi dispui aproximativ n
vrfurile unui tetraedru ce ar avea centrul de greutate n centrul atomului de carbon.
Molecula se va putea roti cu tastele sgei dup cele dou axe.




146




Programare Grafic OpenGL

4.7 Lucrare de laborator 7.

4 4. .7 7. .1 1 G Ge en ne er ra ar re ea a d de e u um mb br re e p pr ri in n u ut ti il li iz za ar re ea a m ma at tr ri ic ce el lo or r. .

Pn acum am realizat efecte de tonuri de culoare dar efectiv nu am generat nici
o umbr. Adic avnd un plan, un obiect i o surs de lumin pe acest plan s apar clar
definit umbra obiectului. OpenGL nu prevede o funcie sau o configuraie n care s
genereze astfel de umbre. Totui printr-o manevrare dibace a matricelor de transformare
i a modurilor de afiare se poate genera o umbr dar nu pentru un ntreg ansamblu ci
doar pentru fiecare obiect luat n parte. Se folosete urmtorul principiu scena se
deseneaz odat normal, i a doua oar se deseneaz corpul a crui umbr se dorete , de
data aceasta nainte de desena corpul i schimbm culoare se fie un gri cenuiu cum
sunt n general umbrele i i producem o transformare geometric. Astfel corpul va fi
turtit pn va fi extrem de subire, turtirea se va face innd seama de poziia sursei de
lumin i poziia i orientarea planului pe care se proiecteaz umbra. Acest corp turtit va
fi poziionat deasupra planului dar foarte aproape de el exact n poziia unde normal ar
trebui s cad umbra.
Pentru a genera matricea de transformare vom folosi urmtoare funcie:

void MakeShadowMatrix(GLfloat points[3][3], GLfloat lightPos[4],
GLfloat destMat[4][4])
{

GLfloat planeCoeff[4];
GLfloat dot;

// se calculeaz coeficienii ecuaiei planului
// pe baza a trei puncte distincte din plan
calcNormal(points,planeCoeff);

//se determina al patrulea coeficient
planeCoeff[3] = - (
(planeCoeff[0]*points[2][0]) +
(planeCoeff[1]*points[2][1]) +
(planeCoeff[2]*points[2][2]));

// facem produsul dintre coordonatele sursei si coeficientii planului
dot = planeCoeff[0] * lightPos[0] +
planeCoeff[1] * lightPos[1] +
147
planeCoeff[2] * lightPos[2] +
planeCoeff[3] * lightPos[3];

// facem proiectiile pe plan
// calculand prima coloana a matricei de umbrire
destMat[0][0] = dot - lightPos[0] * planeCoeff[0];
destMat[1][0] = 0.0f - lightPos[0] * planeCoeff[1];
destMat[2][0] = 0.0f - lightPos[0] * planeCoeff[2];
destMat[3][0] = 0.0f - lightPos[0] * planeCoeff[3];

// a doua coloana
destMat[0][1] = 0.0f - lightPos[1] * planeCoeff[0];
destMat[1][1] = dot - lightPos[1] * planeCoeff[1];
destMat[2][1] = 0.0f - lightPos[1] * planeCoeff[2];
destMat[3][1] = 0.0f - lightPos[1] * planeCoeff[3];

// a treia coloana
destMat[0][2] = 0.0f - lightPos[2] * planeCoeff[0];
destMat[1][2] = 0.0f - lightPos[2] * planeCoeff[1];
destMat[2][2] = dot - lightPos[2] * planeCoeff[2];
destMat[3][2] = 0.0f - lightPos[2] * planeCoeff[3];

// a patra coloana
destMat[0][3] = 0.0f - lightPos[3] * planeCoeff[0];
destMat[1][3] = 0.0f - lightPos[3] * planeCoeff[1];
destMat[2][3] = 0.0f - lightPos[3] * planeCoeff[2];
destMat[3][3] = dot - lightPos[3] * planeCoeff[3];

}

Unde points sunt trei puncte ce definesc planul;
- lightPos sunt coordonatele sursei de lumina;
- destMat este matricea de umbrire;

Orice obiect asupra cruia se aplic matricea de umbrire este turtit i poziionat
n planul de proiecie al umbrei.

Exemplu de utilizarea a matricei de umbrire:

void CALLBACK deseneaza(void)
{
GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat specularLight[]={1.0f,1.0f,1.0f,1.0f};
GLfloat lightPos[] = { 0, 50, -100, 1 };
GLfloat specref[]={1.0f,1.0f,1.0f,1.0f};

148
GLfloat mynormal[3];
GLfloat plan[4][3]={ //parametrii planului pe care proiectata
umbra



{-500,-50,500},
{500,-50,500},
{500,-50,-500},
{-500,-50,-500}
};
GLfloat plan_[4][3]={ //parametrii efectivi ai planului unde este
desenata
//umbra
{-500,-49.9,500},
{500,-49.9,500},
{500,-49.9,-500},
{-500,-49.9,-500}};

GLfloat shadowMat[4][4];
GLfloat pi=3.14159f;
GLint i,j,lx=100,ly=100;
// sursa de lumina se poate roti deasupra n jurul obiectului

lightPos[0]=sin(arot[1]*pi*2/360)*40;
lightPos[1]=50;
lightPos[2]=cos(arot[1]*pi*2/360)*40-150;

// generam matricea de umbrire
MakeShadowMatrix(plan_,lightPos,shadowMat);

glEnable(GL_DEPTH_TEST); // inlaturam fetele invizibile
glFrontFace(GL_CCW); // fata poligonului va fi cea definita invers
acelor de ceas

// activam iluminarea
glEnable(GL_LIGHTING);

// configuram lumina GL_LIGHT0
glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specularLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);

// activam lumina GL_LIGHT0
glEnable(GL_LIGHT0);

149
// activam colorarea indirecta a materialului
glEnable(GL_COLOR_MATERIAL);

// specificam ce parametri vor fi preluati indirect de material prin glColorf
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

//stergem ecranul
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
//specificam materialul
glMaterialfv(GL_FRONT,GL_SPECULAR,specref);
glMateriali(GL_FRONT,GL_SHININESS,128);

// matricea de lucru este cea de vizualizare a modelului
glMatrixMode(GL_MODELVIEW);

glPushAttrib(GL_LIGHTING_BIT);//Salvam luminile in stiva
glDisable(GL_LIGHTING);//Dezactivam luminile

glPushMatrix();

glColor3f(1,1,0);
glTranslatef(lightPos[0],lightPos[1],lightPos[2]);
auxSolidSphere(4.0);//desenam sursa de lumina

glPopMatrix();

glPushMatrix();

glMultMatrixf((GLfloat *)shadowMat);//incarcam matricea de
umbra // umbra va fi de un verde nchis
glColor3f(0,0.3,0);
// facem aceleasi transformari ca si cum am lucra cu
obiectul
glTranslatef(0,0,-150);
glRotatef(a,0,1,0);
glRotatef(b,1,0,0);
auxSolidCube(20.0);//desenam umbra corpului

glPopMatrix();

glPopAttrib();//Incarcam luminile din stiva

glPushMatrix();
//corpul este rosu
glColor3f(1,0,0);
// dupa cum vedeti aceleasi transformari
150
glTranslatef(0,0,-150);
glRotatef(a,0,1,0);
glRotatef(b,1,0,0);
auxSolidCube(20.0);// desenam corpul
glPopMatrix();

glPushMatrix(); // desenam planul pe care se proiecteaza umbra
glColor3f(0,1.0,0);
glBegin(GL_QUADS);
glVertex3fv(plan[0]);
glVertex3fv(plan[1]);
glVertex3fv(plan[2]);
glVertex3fv(plan[3]);
glEnd();
glPopMatrix();


glFlush();
}


Exerciiu 2. Reutiliznd secvenele de cod precedente creai un ceainic cruia
s-i afiai umbra, lumina se va roti deasupra corpului la apsare tastei bara de spaiu.
Corpul
se va putea roti prin apsarea tastelor sgei.

Observai aceast linie de cod :

glMultMatrixf((GLfloat *)shadowMat);//incarcam matricea de umbra

Prin aceasta nmulim matricea de lucru cu matricea de umbrire, rezultatul fiind
depus n matricea de lucru.

O alt linie de cod interesant este urmtoarea:

glPushAttrib(GL_LIGHTING_BIT);

Aceast linie specific c se va salva setrile pentru lumini n stiv pentru a fi
apoi recuperate. Se pot salva cu aceeai funcie i parametru corespunztor i ali
parametri de stare ai OpenGL.
Exemplu:
- GL_ACCUM_BUFFER_BIT culoarea de tergere a bufferului;
- GL_COLOR_BUFFER_BIT bii de in de setrile de culoare ale OpenGL
- GL_CURRENT_BIT bii de stare curent a OpenGL
- GL_DEPTH_BUFFER_BIT - bii ce in de configurarea bufferului de
adncime
151
- GL_ENABLE_BIT - bii ce in de activarea sau dezactivare unei opiuni a
mediului OpenGL;
- GL_EVAL_BIT - bii de evaluatori OpenGL i activarea normalelor generate
automat;
- GL_FOG_BIT - bii ce in de parametrii de cea;
- GL_HINT_BIT bii ce in calitatea trasrii unei linii,a unui punct, a unui
polygon, a ceii;
- GL_LIGHTING_BIT - bii de in de parametrii de iluminare;
- GL_LINE_BIT - bii de in de configurarea liniei;
- GL_LIST_BIT - bii refiritori la listele de afiare ;
- GL_PIXEL_MODE_BIT bii referitori la modul de desenare al unui punct din
imagine;
- GL_POINT_BIT - bii referitori la desenare unui punct individual;
- GL_POLYGON_BIT bii referitori la desenarea poligoanelor;
- GL_POLYGON_STIPPLE_BIT - bii referitori la modelul de umplere a
poligoanelor;
- GL_SCISSOR_BIT - bii referitor la decupari;
- GL_STENCIL_BUFFER_BIT - bii referitori la bufferul ablon;
- GL_TEXTURE_BIT - bii referitori la textur;
- GL_TRANSFORM_BIT - bii referitori la limitele de decupare a scenei;
- GL_VIEWPORT_BIT - bii referitori la limitele pe Oz ale volumului de
decupare.




Exerciiu 3. Creai un program cu dou obiecte un con( auxSolidCone) i un tor
(auxSolidTorus) la care s le generai umbrele. La apsare tastei enter va fi selectat
conul, la o nou apsare torul i tot aa. Obiectul selectat va putea fi rotit prin tastele
sgei.

Exerciiu 4. Creai un program cu dou surse de iluminare i un obiect un
tetraedru.
Generai ambele umbre produse de cele dou surse de lumina, pentru acelai
obiect.

Imagine a ferestrei programului exemplu :
1






152





Programare Grafic OpenGL

4.8 Lucrare de laborator 8.

4 4. .8 8. .1 1 U Ut ti il li iz za ar re ea a l li is st te el lo or r

n momentul de fa cunoatei ndeajuns de multe elemente de OpenGL pentru
a construi element cu element orice structur v imaginai i orice scen. Cu ceea ce tii
pn acum nu putei reutiliza codul OpenGL dect prin simpla lui copiere, nsoit de
transformri geometrice, n zona de program n care avei nevoie. Anticipnd aceast
nevoie OpenGL a introdus listele de desenare prin care codul de program scris exclusiv
n OpenGL este definit odat n cadrul unei liste, i apoi prin apeluri la acea list codul
poate fi refolosit. Listele ofer nu numai o metod mai comod de gestionare a codului
dar la apelrile listei desenarea se face mai rapid. Aceasta deoarece prin list se
pstreaz o structur 3D specificat de acel cod, structur gata de desenare, n timp ce n
secvena propriu-zis de cod trebuie efectuate de fiecare dat calcule. Astfel orice
operaie ce lucreaz cu mediul OpenGL, sau indirect modific un parametru sau o
structur OpenGL este luat n calcul. ns dac secvena respectiv este definit prin
anumii parametri independeni de mediul OpenGL, modificarea acestor parametri i
apelarea mai apoi a listei nu modific de loc aspectul structurii desenate, doar asupra
secvenei de cod originale, i nu asupra listei au efect aceti parametri. Totui este
permis orice transformare geometric definit prin matricele OpenGL. Ce ncrcm n
listele OpenGL? De obicei structuri geometrice, mai puin materiale, lumini i culori,
pentru c uneori pe aceste dorim s le schimbm la reapelri. Pe viitor vom lucru cu
liste i la pstrarea unor texturi ncrcate.

4 4. .8 8. .2 2 C Cr re ea ar re ea a u un ne ei i l li is st te e. .

Pentru a crea o lista folosim funciile glNewListglEndList care au
prototipurile:

void glNewList( GLuint numarlista, GLenum mod);
void glEndList( void);

, unde numarlista este un numr prin care vom identifica lista creat;
mod este modul cum va fi procesat liste putnd lua valorile:
GL_COMPILE doar compileaz lista fr a o executa, adic nu va afia nimic
pe ecran din ceea ce este prevzut n list;
GL_COMPILE_AND_EXECUTE compileaz i execut lista pe loc;
153

Exemplu de definire a unei liste:

glNewList (1, GL_COMPILE_AND_EXECUTE);

// instructiuni OpenGL

glEndList( ); // delimiteaza finalul zonei de definire a listei

Atunci cnd nu dorim s gestionm manual numerele de list, sau dorim s
evitm redefinirea unei liste din neatenie sau uitare, vom folosi funciile ce au
urmtoarele prototipuri:

GLuint glGenLists(GLsizei interval);
GLboolean glIsList(GLuint numarlista);


, glGenLists genereaz primul numr de list, a unei serii continue de numere de
list, mrimea acestei serii fiind definite de interval. Acestea sunt doar numere
disponibile, alocarea fcndu-se pentru fiecare n parte mai pe urm.
,glIsList returneaz TRUE dac numrul de list specificat a fost folosit la
crearea unei liste, altfel FALSE.

Pentru a chema n vederea execuiei o list alocat i compilat folosim funcia
cu prototipul :

void glCallList(GLuint numarlista);

De reinut c n cazul apelrii unei liste parametrii modificai de secvena
compilat n list rmn modificai i dup revenirea din apel. De aceea dac dorii
evitarea acestui lucru este recomandabil folosire funciilor de salvare prin stiv
glPushMatrix, glPopMatrix, glPushAttrib, glPopAttrib.

Cnd se dorete apelarea mai multor liste la acelai apel se folosete funcia cu
prototipul:

void glCallLists(GLsizei n, GLenum type, const GLvoid *lists);

,unde n este numrul de liste;
type este tipul valorilor din list, aceste valori fiind convertite mai apoi la
GLint ;
lists este un vector de tipul specificat n type ce conine numerele de lista.
Pentru type se pot folosi urmtoarele constante specificatoare de tip, acestea
fiind selectate pe criteriul folosirii efective :
GL_INT pentru tipul GLint ;
GL_UNSIGNED_INT pentru GLuint ;
GL_FLOAT pentru GLfloat ; .a.
154


Odat ce nu se mai folosete o list este recomandabil ca aceasta s fie dealocat
elibernd memoria asociat mediului OpenGL, memorie care cel mai adesea este
mapat chiar n memoria plcii grafice.
Pentru aceasta se va folosi funcia cu protipul :

void glDeleteLists(GLuint list, GLsizei range);

Aceasta va terge un numr specificat de range de liste alocate n mod continuu,
ncepnd cu lista specificat de parametrul list.

Exemplu :

glDeleteLists(10,4);

Va terge listele 10,11,12,13.

O alt funcie important este definirea bazei listei adic numerele de list vor
ncepe de la valoare specificat, la apelarea listelor numerele de list folosite vor fi cele
stabilite minus valoare bazei listelor.

Exemplu:

int lista[10];//un vector de numere de lista
int i;

for(i = 0; i < 10; i++) //alocam un numar continuu de liste
lista[i] = i;

// Construim 30 de liste alocand numere de list consecutive
// Definim prima lista
glNewList(1,GL_COMPILE);


glEndList();

// ... a doua lista
glNewList(2,GL_COMPILE);


glEndList();

// si asa mai departe
// ... ultima lista
glNewList(29,GL_COMPILE);

155

glEndList();


// executam primele 10 liste de la 0 la 9
glCallLists(10,GL_INT,lista);

// setam baza la 10
glListBase(10);
// executam urmtoarele 10 liste - de la 10 la 19
glCallLists(10,GL_INT,lista);

// setam baza la 20
glListBase(20);
// executam ultimele 10 liste de la 20 la 29
glCallLists(10,GL_INT,lista);




O lista de desenare poate conine la rndu-i alte liste de desenare pe care le
apeleaz:

Exemplu :

glNewList(10,GL_COMPILE);

// instructiuni OpenGL
glCallList(1);
glCallList(2);

glCallList(5);

glCallList(6);

glEndList();


Totui exist o serie de comenzi OpenGL care nu sunt salvate prin punerea lor
ntr-o list, ceea ce nseamn cu nu vor fi executate la chemarea listei, acestea sunt :
glIsList
glGenLists
glDeleteLists
glFeedbackBuffer
glSelectBuffer
glRenderMode
glReadPixels
156
glPixelStore
glFlush
glFinish
glIsEnabled
glGet


Exerciiu 1. Creai patru tipuri de obiecte din primitive OpenGL un corp
prismatic de forma lui L, un corp prismatic nerotunjit de forma lui U, unul de forma lui
T i altul de forma lui Z. Aceste corpuri vor avea specificate materiale diferite (folosii
glMaterialfv), scena va fi iluminat. Aceste obiecte vor fi pstrate n liste, care la creare
vor fi doar compilate. S se afieze pe 4 rnduri, n 7 coloane ntr-o fereastr, corpuri de
tipul respectiv, pe fiecare rnd de acelai tip, iar pe coloan corpurile vor avea orientri
diferite la alegere. Pe aceeai coloan corpurile vor avea aceeai orientare.






















157





Programare Grafic OpenGL

4.9 Lucrare de laborator 9.

4 4. .9 9. .1 1 L Lu uc cr ru ul l c cu u i im ma ag gi in ni i r ra as st tr ru u n n O Op pe en nG GL L

Ca orice standard grafic OpenGL trebuia s includ i funcii de desenare de
imagini de tip rastru. Ce nseamn rastru? nseamn c imaginea este compus din
puncte, i nu din entiti grafice scalabile ca n cazul imaginilor vectoriale (wmf), ale
fonturilor truetype etc. Un reprezentant important al acestei clase este BMP , un altul
este Iconul (iconia).
Fiierele Bitmap utilizate de OpenGL trebuie s fie necomprimate avnd
culoarea pe 24 de bii. Oricum chiar dac se dispune de astfel de fiiere OpenGL nu are
funcii care s le citeasc pentru c nu ofer suport de lucrul de fiiere. Citirea fiierului,
alocarea memoriei n care acesta va fi citit este treaba mediului de programare n care
este integrat OpenGL. Totui odat ce matricea de pixeli mai corect spus de culori de
pixel este ncrcat n memorie, ntr-un vector, aceasta poate fi folosit de ctre
OpenGL.

Pentru a afia un bitmap pstrat ntr-un vector se poate folosi funcia cu
prototipul:

void glBitmap(GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap
);

, unde width este lungimea imaginii afiate,
height este nlimea imaginii;
xorig, yorig este poziia zonei de afiare n cadrul imaginii;
xmove, ymove valori ale actualizrii poziiei pointerului de rastru ( acesta
specific poziia pentru orice grafic de tip rastru n mediul OpenGL)
vector la imaginea de tip rastru specificat ca o colecie de octei.

Pentru a specifica poziia curent a unui obiect rastru se folosete funcia
glRasterPos, care are o multitudine de variante, recomandabil ar fi folosirea funciei cu
urmtorul prototip:

158
void glRasterPos3f( GLfloat x, GLfloat y, GLfloat z);

, unde x, y, z sunt coordonatele pointerului de rastru.

Alte funcii de grafic rastru sunt :
glDrawPixels pentru afiarea de imagine de tip rastru;
glCopyPixels pentru copierea unei imagini din buffer pe ecran;
glReadBuffer specific bufferul din care se citete imaginea;
glReadPixels citete ntr-un vector pixeli de pe ecran;
glPixelMap specific un mod de interpretarea a culorii pixelilor manipulai;
glPixelStore specific cum sunt citii sau scrii pixelii din memorie;
glPixelZoom specific cum sunt scalai pixelii;
Funcia glDrawPixels este o alt abordare a afirii imaginilor de tip rastru ea are
prototipul:

void glDrawPixels(GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels
);
,unde width este lungimea imaginii,
height este nlimea imaginii pstrate n vector;
format este formatul pixelilor pstrai n vector;
type este tipul elementelor vectorului;
pixels este un vector n care este pstrat imagine.

n ceea ce privete formatul sunt disponibile urmtoarele opiuni :

GL_COLOR_INDEX culoare pixelor este definit pe baz de indici i palet;
GL_STENCIL_INDEX - se refer la indici din bufferul ablon;
GL_DEPTH_COMPONENT - se refer la indici din bufferul de adncime ;
GL_RGBA - se refer la pixeli a cror culoare este dup standardul RGBA;
GL_RED - se refer la intensitile componentei roii a culorii pixelilor, fiecare
valoare din vector fiind o intensitate;
GL_GREEN - acelai lucru dar pentru verde;
GL_BLUE - acelai lucru dar pentru albastru;
GL_ALPHA - pentru alpha;
GL_RGB definete un pixel compus din trei componente rou , verde i
albastru, practic o imagine avnd culoarea pe 24 de bii;
GL_LUMINANCE se specific culoare pixelului pe baza luminozitii;
GL_LUMINANCE_ALPHA specific att luminozitatea ct i alpha ;
GL_BGR_EXT specific pixeli a cror culoare este precizat de componenta
albastr, verde, roie efectiv n aceast ordine;
GL_BGRA_EXT specific pixeli a cror culoare este precizat de componenta
albastr, verde, roie, alpha efectiv n aceast ordine.


Tipul poate fi precizat prin urmtoarele constante:
159
GL_UNSIGNED_BYTE ntreg pe opt bii fr semn la care corespund tipul
OpengGL - GLubyte;
GL_BYTE ntreg pe opt bii cu semn la care corespund tipul OpengGL -
GLbyte;
GL_BITMAP cte un bit stocai pe cte un ntreg pe 8 bii;
GL_UNSIGNED_SHORT ntreg pe 16 bii fr semn GLushort;
GL_SHORT ntreg pe 16 bii cu semn Glshort;
GL_UNSIGNED_INT ntreg pe 32 de bii fr semn Gluint;
GL_INT - ntreg pe 32 de bii cu semn Glint ;
GL_FLOAT tip real n simpl precizie - glFloat;





Exemplu de folosire:

glDrawPixels(BitmapInfo->bmiHeader.biWidth,
BitmapInfo->bmiHeader.biHeight,
GL_RGB, GL_UNSIGNED_BYTE, BitmapBits);

, cu acest apel se afieaz o imagine bitmap citit n memorie, imagine pe 24 de
bii. BitmapBits este un vector spre pixelii imaginii, se observ c primi doi parametri
specific lungimea i nlimea imaginii.

Funcia glPixelStore este deosebit de important cnd se lucreaz cu funciile de
afiare prin aceast specificndu-se cum vor fi interpretate valorile din vector. Ea are
variantele:

void glPixelStoref( GLenum pname, GLfloat param);

void glPixelStorei( GLenum pname, GLint param);

Unde pname specific tipul modificrii vizate, aceasta prin folosirea unei
constante specificator. Aceste constante sunt:

GL_PACK_SWAP_BYTES - inverseaz ordinea octeilor componeni ai
pixelului (dac param este TRUE);
GL_PACK_LSB_FIRST aranjeaz biii dintr-un byte astfel nct astfel nct
cel mai puin semnificativ s fie procesat primul;
GL_PACK_ROW_LENGTH specific numrul de pixeli dintr-un rnd
folosind param;
GL_PACK_SKIP_PIXELS nu mai afieaz un numr de pixeli specificat n
lparam, afiare ncepnd de la pixelii care urmeaz ;
GL_PACK_SKIP_ROWS nu mai afieaz primele param linii ;
GL_PACK_ALIGNMENT specific modul de aranjare a datelor n vector, de
obicei se folosete valoare 4 grupare de 16 bii adic, se mai pot folosi valorile 1,2, 8 ;
160
GL_UNPACK_SWAP_BYTES schimb ordine octeilor la despachetare
bitmapului;
GL_UNPACK_ROW_LENGTH la fel ca la mpachetare;
GL_UNPACK_SKIP_PIXELS la fel ca la mpachetare;
GL_UNPACK_SKIP_ROWS la fel ca la mpachetare;
GL_UNPACK_ALIGNMENT la fel ca la mpachetare;

Exemplu :

glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glReadPixels(0, 0, viewport[2], viewport[3], GL_RGB,
GL_UNSIGNED_BYTE,
bits);



sau

glPixelTransferi(GL_UNPACK_ALIGNMENT, 4);
glPixelTransferi(GL_INDEX_OFFSET, 1);


Folosind glPixelZoom putem scala o imagine, aceast funcie are prototipul:

void glPixelZoom( GLfloat xfactor, GLfloat yfactor);

, unde xfactor i yfactor sunt indicii de scalare pe orizontal i pe vertical e
imaginii, unde valori supraunitare pozitive mrim imaginea, pentru valori subunitare
pozitive micorm imaginea iar pentru valori negative inversm n oglind imaginea.

Pentru a citi pixeli dintr-un buffer al OpenGL ntr-un vector folosim funcia cu
prototipul:
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, GLvoid *pixels
);

, unde x, y sunt poziia colului din stnga sus de unde va ncepe citirea
, width, height sunt lungimea i nlimea zonei citite
, format specific att bufferul din care se face citirea ct i componenta dorit,
, type este tipul elementelor vectorului;
, pixels este vectorul n care va postat imaginea.



161
Specificatori de format :

GL_COLOR_INDEX - indice de culoare cnd se utilizeaz paleta;
GL_STENCIL_INDEX indice din bufferul ablon;
GL_DEPTH_COMPONENT indice din bufferul de adncime;
GL_RED componenta roie a culorii din bufferul de culoare ( de adncime) ;
GL_GREEN - componenta verde a culorii din bufferul de culoare ( de
adncime) ;
GL_BLUE - componenta albastr a culorii din bufferul de culoare ( de
adncime) ;
GL_ALPHA - componenta alfa a culorii din bufferul de culoare ( de adncime) ;
GL_RGB culoare efectiva ;
GL_RGBA culoare plus indicele alfa;
GL_BGR_EXT culoare dar n format BGR;
GL_BGRA_EXT culoare plus alfa n format BGRA;
GL_LUMINANCE luminozitatea;
GL_LUMINANCE_ALPHA luminozitatea plus alfa;

De exemplu pentru a salva o anumit regiune dintr-un ecran ntr-un vector,
formatul va ales GL_RGB, vectorul respectiv va putea fi scris ca imagine ntr-un fiier
bitmap.
Tipul type are aceleai caracteristici ca i la glDrawPixels.




glReadbuffer cu prototipul urmtor permite stabilirea unei surse de pixeli color
pentru o serie de funcii:

void glReadBuffer(GLenum mode);

, mode poate lua valorile
GL_FRONT_LEFT- buffer de afiare principal stng pentru display
stereoscopic;
GL_FRONT_RIGHT- buffer de afiare principal drept pentru display
stereoscopic;
GL_BACK_LEFT- buffer de afiare secundar stng pentru display
stereoscopic;
GL_BACK_RIGHT- buffer de afiare secundar drept pentru display
stereoscopic;
GL_FRONT buffer de afiare principal;
GL_BACK- buffer de afiare secundar cnd se realizeaz double buffering;
GL_LEFT- buffer stng;
GL_RIGHT- buffer drept;
GL_AUXi buffer auxiliary;


162
In mod obinuit se va folosi apelarea:

glReadBuffer(GL_FRONT);


Funcia glCopyPixels cu urmtorul prototip permite copierea de pixeli ntre
bufferele OpenGL:

void glCopyPixels( GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type
);
, unde x, y, width, height specific regiunea ce se copie i n care se copie,
, type specific bufferul n care se copie, bufferul din care se copie fiind
specificat prin glReadBuffer.
Type poate lua valorile:
GL_COLOR destinaia este bufferul de afiare curent;
GL_DEPTH destinaia este bufferul de adncime;
GL_STENCIL destinaia este bufferul ablon.

Exerciiu 1. Alocai un vector de tip GLubyte ( cu funcia malloc) n care s
pstrai o imagine pe 24 de bii. Imaginea va conine steagul Romniei culorile rou,
galben i albastru. Lungimea imaginii va fi de dou ori nlimea. Afiai steagul.
Acelai lucru pentru steagul Franei i Germaniei. Afiai la final imaginea fiecrui
steag n acelai ecran. Creai o funcie care s selecteze steagurile. Schimbarea steagului
selectat se va face apsnd bara de spaiu. Steagurile au aceeai mrime, sunt desenate
pe acelai rnd,
Steagul selectat va fi adus mai n fa dect celelalte neselectate.


4 4. .9 9. .2 2 n nc c r rc ca ar re ea a u un ne ei i i im ma ag gi in ni i b bi it tm ma ap p d di in n f fi i i ie er r

n continuare se va prezenta o funcie de ncrcare ntr-o structur din memorie a
unei imagini bitmap pe 24 de bii:

struct bmptype{
GLubyte *bits;
BITMAPFILEHEADER bmpheader;
BITMAPINFOHEADER bmpinfo;
};
bmptype imaginebmp;

int bmpload(char *bmpfilename,bmptype *bmp)
{
FILE *fp;
int infosize,bitsize;

163

if ((fp = fopen(bmpfilename, "rb")) == NULL)
return (NULL);
fread(&bmp->bmpheader,
sizeof(BITMAPFILEHEADER), 1, fp);
if (bmp->bmpheader.bfType != 'MB')
{

fclose(fp);
return (NULL);
} else
{
infosize = bmp->bmpheader.bfOffBits - sizeof(BITMAPFILEHEADER);
fread (&bmp->bmpinfo, 1, infosize, fp);
if ((bitsize = bmp->bmpinfo.biSizeImage) == 0)
bitsize = bmp->bmpinfo.biWidth *
(bmp->bmpinfo.biBitCount + 7) / 8 *
abs(bmp->bmpinfo.biHeight);
bmp->bits = (GLubyte *)malloc(bitsize);
fread(bmp->bits, 1, bitsize, fp);
fclose(fp);
}
}






Se observ c se aloc n funcia de citirea a fiierului i memorie pentru
vectorul ce conine imaginea. Bmpfilename este numele fiierului de tip bitmap ce se
deschide.

Exemplu de utilizare:
Pentru ncarcare:

bmpload(romania.bmp,imaginebmp);

Pentru afiare:

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelZoom(1, 1);
glRasterPos3f(-15,-11,-20);
glDrawPixels(imaginebmp.bmpinfo.biWidth,
imaginebmp.bmpinfo.biHeight,
GL_RGB, GL_UNSIGNED_BYTE imaginebmp.,bits);

164
Exerciiu 2. Folosind funcia de ncrcare de bitmapuri, ncrcai steagurile
oficiale ale Romniei, Marii Britanii, Franei, Germaniei, Grecie, UE i creai un
program de selectarea ca cel anterior.






























165
Programare Grafic OpenGL

4.10 Lucrare de laborator 10.

4 4. .1 10 0. .1 1 A Ap pl li ic ca ar re ea a t te ex xt tu ur ri il lo or r

Pn acum s-au creat obiecte, s-au iluminat, s-au creat efecte de reflexie. Totui
obiectele create dei au form i culoare nc nu seamn prea bine cu cele din realitate.
Acest lucru se poate rezolva aplicndu-le o textur. Dac se dispune de forma real i de
o textur potrivit, combinate cu un efect de iluminare i o modalitate de creare
realistic a umbrelor , imaginea obiectului simulat fa de cel real va fi greu sau chiar
imposibil de deosebit cu ochiul liber. Ceea ce ofer OpenGL este o imagine care se
apropie n proporie de 80 90 % de imaginea obiectului real. n jocurile actuale aceasta
valoare poate fi mpins pn la 95%, iar n editoarele specializate, profesionale de
grafic 3D aceasta poate fi mpins pn la 98-99% i chiar 99.7% diferenele fiind
practic insesizabile. Ce nseamn o textur? O textur este o imagine bidimensional (
sau unidimensional) care acoper o anumit suprafa a unui corp, n special cea
vizibil, mulndu-se de obicei dup forma corpului. Texturarea este procesul de
asociere dintre o anumit suprafa i o imagine. n OpenGL pentru texturare se pot
folosi imagini uni- i bidimensionale.


4 4. .1 10 0. .2 2 T Te ex xt tu ur ra ar re ea a u un ni id di im me en ns si io on na al l

Texturarea unidimensional sau 1D folosete drept textur un singur rnd de
pixeli. Este o texturare nepretenioas rapid. Ea poate fi utilizat pentru texturarea unui
curcubeu sau a inelelor unei planete (Saturn de exemplu).

Pentru a specifica o texturare 1D se folosete funcia cu prototipul:

void glTexImage1D( GLenum target, GLint level, GLint internalformat,
GLsizei width, GLint border, GLenum format, GLenum type,
const GLvoid *pixels
);

, unde target specific tipul texturii totdeauna egal cu GL_TEXTURE_1D,
level specific nivelul de detaliu al texturii , 0 este nivelul de baz,
internalformat, poate fi o valoare 1,2,3 sau 4 sau una din constantele :

GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16,
GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12,
GL_LUMINANCE16, GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4,
GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8,
GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12,
GL_LUMINANCE16_ALPHA16, GL_INTENSITY, GL_INTENSITY4,
GL_INTENSITY8, GL_INTENSITY12, GL_INTENSITY16, GL_RGB,
GL_R3_G3_B2, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10, GL_RGB12,
166
GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8,
GL_RGB10_A2, GL_RGBA12 sau GL_RGBA16.
width lungime liniei de culoare, sau a dimensiuni texturii ;
border grosimea marginii poate fi 0 sau 1 ;
format este formatul pixelilor texturii poate fi :
GL_COLOR_INDEX
GL_RED
GL_GREEN
GL_BLUE
GL_ALPHA
GL_RGBA
GL_BGR_EXT
GL_BGRA_EXT
GL_LUMINANCE
GL_LUMINANCE_ALPHA
constante descrise n laboratoarele precedente.
type este tipul elementelor vectorului n care este definit textura;
pixels este chiar vectorul n care se afl textura;

Exemplu :
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, 3, 8, 0, GL_RGB,
GL_UNSIGNED_BYTE,
textura);

Se observ folosirea funciei de configurare a modului de texturare. n exemplu
se specific o tranziie liniar pentru zon texturat mai mare, respectiv mai mic dect
rezoluia texturii.


Pentru a activa texturarea 1D se folosete urmtoarea linie de cod :

glEnable(GL_TEXTURE_1D);

, aceasta se plaseaz n program naintea oricrei afiri de obiecte texturate 1D.

Pentru a specifica poziia n cadrul texturii pe baza creia se va textura o regiune
se folosete funcia cu prototipul :

void glTexCoord1f( GLfloat poz);

, poz este o valoare cuprins ntre 0.0 i 1.0 respectiv nceputul texturii i
sfritul ei.

167

4 4. .1 10 0. .3 3 T Te ex xt tu ur ra ar re ea a 2 2D D

Pentru a textura un obiect cu o textur bidimensional (o imagine) se poate
folosi funcia cu prototipul :

void glTexImage2D( GLenum target, GLint level,
GLint internalformat,
GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type,
const GLvoid *pixels
);

,unde target va fi ntotdeauna egal cu GL_TEXTURE_2D,
level nivelul de detaliu al texturrii 0 nivel de baz imaginea original, n
nivel redus al detaliului fa de imaginea de baz ;
internalformat acelai ca la texturarea 1D ;
width, height lungimea, nlimea texturii ;
border grosimea marginii poate fi 0 sau 1;
format acelai ca la texturarea 1D;
type - acelai ca la texturarea 1D;
pixels textura bidimensional sub forma unui vector ;

Exemplu :

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 3, info->bmiHeader.biWidth,
info->bmiHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
rgb);

Pentru a specifica coordonatele texturii vom folosi o varianta a funciei
glTexCoord :

void glTexCoord2f( GLfloat s, GLfloat t);

Coordonatele unei texturi sunt date prin folosirea indicilor s,t,r,q.
Pentru texturi 2D sunt utili doar s,t. acestea specificnd coordinate n cadrul
texturii. Ei variaz ntre 0.0 i 1.0, valori prin care parcurge ntreaga suprafa a texturii.


Pentru texturi se pot seta anumii parametri de texturare prin intermediul funciei
cu prototipul:

void glTexParameteri(GLenum target, GLenum pname, GLint param);
168

,unde target poate lua valorile GL_TEXTURE_1D sau GL_TEXTURE_2D, n
funcie de textura la care ne referim;
pname poate lua una din valorile :
GL_TEXTURE_MIN_FILTER specific comportarea texturrii cnd
suprafaa texturat are o ntindere n pixeli mai mic dect cea a texturii;
GL_TEXTURE_MAG_FILTER - specific comportarea texturrii cnd
suprafaa texturat are o ntindere n pixeli mai mare dect cea a texturii ;
GL_TEXTURE_WRAP_S specific modul de texturare dup s cnd zona
texturat este mai mare dect textura folosit ;
GL_TEXTURE_WRAP_T - specific modul de texturare dup s cnd zona
texturat este mai mare dect textura folosit ;

param specific o valoare pentru proprietatea specificat n pname:
pentru GL_TEXTURE_MIN_FILTER / GL_TEXTURE_MAG_FILTER poate
fi una valorile
GL_NEAREST returneaz pixelul cel mai aproape de centru;
GL_LINEAR - aproximeaz liniar textura;
GL_NEAREST_MIPMAP_NEAREST pixelul se obine din texturi mipmap
GL_LINEAR_MIPMAP_NEAREST pixelul se obine din texturi mipmap
GL_NEAREST_MIPMAP_LINEAR pixelul se obine din texturi mipmap
GL_LINEAR_MIPMAP_LINEAR pixelul se obine din texturi mipmap
pentru GL_TEXTURE_WRAP_S / GL_TEXTURE_WRAP_T se pot alege
valorile:
GL_CLAMP dac s-a depit textura nu se mai deseneaz nimic;
GL_REPEAT dac s-a depit textura se reia aceeai textur prin repetare;


O alt funcie de configurare ar fi glTexEnv cu prototipul :

void glTexEnvi( GLenum target, GLenum pname, GLint param);

La care:
target este scopul funciei aceste trebuie s fie GL_TEXTURE_ENV( Env
vine de la Environment ce se traduce prin mediu, adic mediul OpenGL)
pname trebuie s fie setat or pe GL_TEXTURE_ENV_MODE or pe
GL_TEXTURE_ENV_COLOR
param poate fi una din constantele :
GL_MODULATE realizeaz un produs ntre textur i bufferul de afiare;
GL_DECAL textura este afiata direct pe ecran;
GL_BLEND - textura este combinat cu o culoare nainte de a fi afiat pe
ecran;
Pentru GL_TEXTURE_ENV_COLOR se va specifica culoarea de
combinare ;



169


n mod obinuit se folosete apelarea :

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_DECAL);


Un alt aspect este generarea automat a coordonatelor texturilor. Pentru a activa
aceast obiune se folosesc secvenele:

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);

Pentru a configura generarea :

static GLint s_vector[4] = { 2, 0, 0, 0 };
static GLint t_vector[4] = { 0, 0, 2, 0 };

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeniv(GL_S, GL_OBJECT_PLANE, s_vector);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeniv(GL_T, GL_OBJECT_PLANE, t_vector);

Un s_vector i t_vector sunt folosii ca parametri ntr-o expresie care genereaz
valoare efectiv a coordonatei texturii pe suprafaa texturat astfel :

g= v[0]*x+v[1]*y+v[2]*z+v[3]*w;

,unde g este coordonata de texturare generat, x,y,z,w coordinate ale punctului
de pe suprafa, v este vectorul specificat n exemplu fie prin s_vector fie prin t_vector.

Exerciiu 1. Texturai o piramid cu o textur care s creeze efectul de trepte.
Mai nti calculai texturile i afiai apoi ncercai o generare automat a coordonatelor
de texturare.

Exerciiu 2. Creai un cilindru pe care s-l texturai.









170


4 4. .1 10 0. .4 4 U Ut ti il li iz za ar re ea a t te ex xt tu ur ri il lo or r m mi ip pm ma ap p

Texturile mipmap se folosesc pentru a crete vitez de procesare, pentru
suprafee ndeprtate se folosesc texturi cu rezoluie inferioar, n timp ce pentru a
aceleai suprafee apropiate se folosesc texturi cu cea mai bun rezoluie disponibile.
OpenGL genereaz plecnd de la o imagine de baz texturi cu rezoluii njumtite, pe
cte nivele se dorete.

Pentru a specifica folosirea texturilor mipmap respectiv generarea acestora se
poate folosi o secven asemntoare cu urmtoarea:






// pentru texturi 1D
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_LINEAR);
gluBuild1DMipmaps(GL_TEXTURE_1D, 3, 8, 0, GL_RGB,
GL_UNSIGNED_BYTE,
roygbiv_image);

// pentru texturi 2D
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, info->bmiHeader.biWidth,
info->bmiHeader.biHeight, 0, GL_RGB,
GL_UNSIGNED_BYTE, rgb);


Aceste funcii au prototipurile:

int gluBuild1DMipmaps( GLenum target, GLint components,
GLint width, GLenum format,GLenum type,
const void *data
);

int gluBuild2DMipmaps( GLenum target, GLint components,
GLint width, GLint height,
GLenum format, GLenum type,
171
const void *data
);

Se observ c sunt aceeai parametrii de la glTexImage.
Texturile care vor fi generate vor trebui ncrcate cu glTexImage specificnd
prin level nivelul mipmap utilizat.

Este recomandat ca la ncrcarea texturilor s se foloseasc liste de afiare care
reduc mult timpul de procesare.


Exerciiu 3. Desenai un dreptunghi care va fi texturat cu o imagine de nalt
rezoluie. Imaginea va fi centrat pe ecran, la apsare tastei sus imaginea se va apropia,
la apsare tastei jos imaginea se va deprta. Utilizai mipmap i listele de afiare pentru
a optimiza programul.






















172
Programare Grafic OpenGL

4.11 Lucrare de laborator 11.

4 4. .1 11 1. .1 1 C Cu ua ad dr ri ic ce e

Alternativa la obiectele grafice predefinite n glaux sunt o serie de obiecte
definite n glu, obiecte care sunt grupate sub denumirea de cuadrice. Acestea sunt:
- gluSphere deseneaz o sfer;
- gluCylinder deseneaz un cilindru;
- gluDisk deseneaz un disc;
- gluPartialDisk deseneaz un fragment de disc;

Spre deosebire de sfera desenat prin glaux sfera generat prin cuadrice poate fi
configurat, calitatea obiectului, a formei, poate fi mbuntit, desigur cu timpi de
procesare suplimentari.

Pentru a putea afia o cuadric mai nti trebuie creat, iar la sfrit dup ce s-a
ncheiat lucrul cu ea trebuie dealocat.

Astfel avem funciile cu urmtoarele prototipuri :

pentru crearea de cuadrice:


GLUquadricObj* gluNewQuadric( void);

pentru dealocarea de cuadrice:

void gluDeleteQuadric( GLUquadricObj *state );


, exemplu:
myquadric=gluNewQuadric();

gluDeleteQuadric(myquadric);




, pentru a configura o cuadrica vom folosi secvena:

gluQuadricDrawStyle(myquadric,GLU_FILL);//1
gluQuadricNormals(myquadric,GLU_SMOOTH); //2
gluQuadricOrientation(myquadric,GLU_OUTSIDE); //3
gluQuadricTexture(myquadric,GL_TRUE); //4

173
Linia 1 specific c modelul va fi acoperit n ntregime.
Linia 2 specific c normalele vor fi generate pentru un aspect lin, fin al
suprafeei.
Linia 3 specific orientarea normalelor cuadricei spre exterior;
Linie 4 specific c cuadrica va fi texturat.

Aceste funcii au urmtoarele prototipuri:

void gluQuadricDrawStyle( GLUquadricObj *qobj, GLenum drawStyle);
void gluQuadricNormals( GLUquadricObj *qobj, GLenum normals);
void gluQuadricOrientation( GLUquadricObj *quadObject,
GLenum orientation);
void gluQuadricTexture( GLUquadricObj *quadObject,
GLboolean textureCoords);

unde drawStyle specific stilul de desenat al cuadricei:
GLU_FILL cuadrica va fi desenata prin poligoane umplute;
GLU_LINE cuadrica va fi desenata din linii;
GLU_SILHUETTE cuadrica este desenata prin linii, cu cteva excepii, n care
unele linii nu se mai traseaz;
GLU_POINT cuadrica este desenat numai prin vrfurile poligoanelor
componente;
pentru normals sunt disponibile dou opiuni:
GLU_NONE nu se genereaz normale ;
GLU_FLAT pentru fiecare faet a cuadricei se genereaz cte o normal ;
GLU_SMOOTH este generat cte o normal pentru fiecare vrf al cuadricei ;
pentru orientation avem :
GLU_INSIDE normalele sunt orientate spre interior ;
GLU_OUTSIDE normalele sunt orientate spre exterior ;
pentru texturare exist doar dou opiuni GL_TRUE sau
GL_FALSE.


Funciile care deseneaz efectiv cuadricele au prototipurile:

void gluSphere( GLUquadricObj *qobj, GLdouble radius,
GLint slices, GLint stacks);

void gluCylinder( GLUquadricObj *qobj,
GLdouble baseRadius, GLdouble topRadius,
GLdouble height,
GLint slices, GLint stacks);

void gluDisk( GLUquadricObj *qobj,
GLdouble innerRadius, GLdouble outerRadius,
GLint slices, GLint loops);

174
void gluPartialDisk( GLUquadricObj *qobj,
GLdouble innerRadius, GLdouble outerRadius,
GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle);

Se observ c slices este caracteristic pentru toate cuadricele acesta specific
numrul de buci n care va fi descompus corpul geometric, cu ct acesta este mai mare
cu att aspectul corpului va fi mai precis.
Al doilea element de descompunere este stacks sau loops, care descompune pe
cealalt ax analizabil corpul geometric.
Pentru a defini parametrii efectivi geometrici pentru sfer s-a dat doar raza
Radius, pentru cilindru raza bazei baseRadius, raza captului superior topRadius, i
nlimea. Pentru disc s-a dat doar raza intern innerRadius i cea extern
outerRadius. Pentru discul parial s-a dat i unghiul de nceput al seciunii startAngle
i valoarea unghiului de acoperit sweepAngle.

Exerciiu 1. Creai patru cuadrice cte una de acelai tip, i cam de aceleai
dimensiuni i afiai-le pe toate n aceeai fereastr.

Exerciiu 2.Pentru programul precedent la apsare barei de spaiu, toate
cuadricele vor fi afiate pe rnd n cele patru stiluri de desenare.

Exerciiu 3.Pentru cuadrica de tip sfer, setai iluminarea,o lumin, i materialul
sferei. Alegei stilul de desenare plin. Prin tastele direcionale, cretei sau scdei cu o
unitate numrul de slices sau de stacks, i afiai schimbarea.

Exerciiu 4. Pentru o sfer ncercai s o texturai cu bitmapul numit moon.bmp.
Afiai. Acum ncercai s creai o secven de program astfel nct prin tastele
direcionale s rotii sfera. Vei folosi texturarea i ncrcarea de bitmapuri din
laboratoarele anterioare.

Exerciiu 5. Creai modelul Soare, Luna, Pmnt, fiecare fiind o cuadrica.
Soarele va fi o sfer galben lucioas. Pentru Lun si Pamant se folosesc texturile
moon.bmp i earth.bmp. La rularea programului sferele s se afle n micare. Luna va
avea o raz jumtate din raza Pmntului. Iar Soarele o raz de trei ori cte cea
Pmntului. Pe baza funciei glLookAt i a tastelor direcionale deplasai-v prin
sistemul solar creat.













175



Exempl u de t ext ur ar e a Luni i : Exempl u de t ext ur ar e a Ter r ei :















Exemplu de texturare a unui cilindru:




















176
Programare Grafic OpenGL

4.12 Lucrare de laborator 12.

4 4. .1 12 2. .1 1 L Lu uc cr ru ul l c cu u b bu uf ff fe er re el le e n n O Op pe en nG GL L

Operaiile de afiare n OpenGL se fac prin intermediul bufferelor. Acestea sunt
zone de memorie care acoper (mapeaz) suprafaa ferestrei de lucru, fiecrui pixel din
fereastra de lucru corespunzndu-i un pixel din buffer. Exist mai multe tipuri de
buffere. Exist un buffer de afiare numite buffer de culoare,un buffer de culoare
secundar pentru creterea calitii animaiei,un buffer de adncime, un buffer ablon
(stencil), un buffer de acumulare.

4 4. .1 12 2. .2 2 B Bu uf ff fe er ru ul l d de e c cu ul lo oa ar re e

La bufferul de culoare fiecare element din buffer constituie culoarea unui pixel,
fie ea un indice de culoare, fie un set de componente de culoare RGBA. n OpenGL
pentru a realiza minimum de afiare grafic avem nevoie doar de un buffer de culoare
numit i buffer principal, buffer frontal sau buffer vizibil. Ori de cte ori se face o
desenare vizibil, aceasta se face n acest buffer, dac desenm n alt buffer trebuie s
transferm informaia din bufferele respective n acest buffer pentru a o face vizibil.
Pentru a preciza c desenare se face direct n acest buffer n glaux folosim secvena:

auxInitDisplay(AUX_SINGLE | AUX_RGBA) ;

La animaii sau la desenarea de scene complexe observm c se produc plpiri,
aceasta deoarece n timpul desenrii se reactualizeaz n permanen suprafaa ecranului
prin citirea acestui buffer, astfel chiar dac suntem n mijlocul unei desenri, se va afia
pe ecran coninutul bufferului. Pentru a evita acest lucru vom folosi dou buffere cel
vizibil, discutat anterior, i unul invizibil un buffer secundar. Odat ce s-a specificat c
se lucreaz cu dou buffere toate desenele ce se vor face din acel moment vor fi
desenate n bufferul invizibil. Astfel vom desena tot ce dorim n bufferul secundar iar
dup ce operaiile de desenare s-au terminat vom transfera datele din acest buffer n
bufferul principal ce este vizibil. Acest transfer este ndeajuns de rapid pentru a se evita
plpirea.
n glaux pentru a specifica c se va lucra cu dou buffere se folosete secvena:

auxInitDisplay(AUX_DOUBLE | AUX_RGBA) ;

, iar n Win32, acest mod de lucru este implicit, dar cu toate acestea trebuie
specificat prin folosirea constantei PFD_DOUBLEBUFFER.

Pentru a transfera datele din bufferul invizibil n cel vizibil se folosete o funcie
care n glaux este :

auxSwapBuffers( ) ;

177
iar n Win32 :

SwapBuffers(hDC) ;

, unde hDC este dispozitivul de context ataat ferestrei aplicaiei.

Totui dac se dorete schimbarea setrii implicite prin care desenarea se face n
bufferul secundar. Se poate folosi funcia cu prototipul :

void glDrawBuffer( GLenum mode );

,unde mode specific bufferul n care OpenGL va desena acesta fiind specificat
prin urmtoarele constante:

GL_NONE nu se va desena n nici un buffer;
GL_FRONT_LEFT specific bufferul principal stng pentru aplicaii
stereoscopice;
GL_FRONT_RIGHT - specific bufferul principal drept pentru aplicaii
stereoscopice;
GL_BACK_LEFT - specific bufferul secundar stng pentru aplicaii
stereoscopice;
GL_BACK_RIGHT specific bufferul secundar drept pentru aplicaii
stereoscopice;
GL_FRONT specific bufferul principal;
GL_BACK specific bufferul secundar;
GL_LEFT - specific bufferul stng att cel principal ct i cel secundar, pentru
aplicaii stereoscopice;
GL_RIGHT specific bufferul drept att cel principal ct i cel secundar,
pentru aplicaii stereoscopice;
GL_FRONT_AND_BACK - specific att bufferul principal ct i cel secundar,
ct i bufferele stng i drept ale acestora;
GL_AUXi specific un buffer auxiliar i, i fiind o valoare ntre 0 i
GL_AUX_BUFFERS;

n mod implicit pentru lucrul cu un singur buffer mode este setat la GL_FRONT,
iar pentru lucrul cu dou buffere mode este setat la GL_BACK.

Exerciiu 1. Creai o aplicaie n care animai un corp folosind glaux. Setai mai
nti utilizare unui mod de lucru cu un singur buffer, apoi cu dou buffere. Observai
schimbrile n calitatea animaiei.







178



4 4. .1 12 2. .3 3 B Bu uf ff fe er ru ul l d de e a ad d n nc ci im me e


Atunci cnd se creeaz o scen complex, sau un obiect compus din mai multe
poligoane, se dorete ca poligoanele din spate s nu apra desenate peste cele din fa.
Sau la intersecii de suprafee s se deseneze partea din suprafa vizibil i nu cea
invizibil. Acest lucru s-a rezolvat prin ataarea la bufferul de culoare a unui buffer de
adncime. n bufferul de adncime se pstreaz poziia pe oz, a punctului desenat n
bufferul de culoare cu o anumit precizie. Astfel dac se va desena o nou obiect,
adncimea punctelor noului obiect va fi comparat cu cea din bufferul de adncime,
dac va fi mai mic aceste puncte( condiie ce se analizeaz pentru fiecare punct n
parte) vor fi desenate n bufferul de culoare i se va actualiza valorile de adncime din
bufferul de adncime, altfel nici unul dintre aceste buffere nu va fi modificat. Pentru a
activa folosirea bufferelor de adncime se va utiliza secvena:

glEnable(GL_DEPTH_TEST);

Pentru a stabili condiia de alterare a bufferelor, se va folosi funcia cu urmtorul
prototip:

void glDepthFunc( GLenum func );

, unde func este o condiie, care implicit este GL_LESS adic dac adncime sau
coordonat pe Oz a pixelului este mai mic dect a celui anterior desenat ( la poziia
respectiv de pe ecran, buffer) atunci acesta va fi desenat pot fi precizate i alte
condiii prin urmtoarele constante:
GL_NEVER - afiare nu este permis;
GL_LESS afiarea este permis dac Z nou < Z vechi;
GL_EQUAL afiarea este permis dac Z nou = Z vechi.
GL_LEQUAL afiarea este permis dac Z nou <= Z vechi.
GL_GREATER afiarea este permis dac Z nou > Z vechi.
GL_NOTEQUAL afiarea este permis dac Z nou difer de Z vechi.
GL_GEQUAL afiarea este permis dac Z nou >= Z vechi.
GL_ALWAYS modificare este permis oricnd.

Pe lng aceste funcii mai sunt disponibile i altele pentru configurarea lucrului
cu buffere de adncime n OpenGL acestea au urmtoarele prototipuri:

void glDepthRange( GLclampd znear, GLclampd zfar );

, care stabilete limitele ntre care se ncadreaz factorii de adncime n mod
implicit acestea fiind 0.0 pentru znear i 1.0 pentru zfar;

void glClearDepth( GLclampd depth);
179

, care stabilete valoare de tergere a bufferului de adncime, implicit aceasta
fiind egal 1.0.

Atunci cnd se terge bufferul de culoare trebuie s se tearg i cel de a
adncime altfel, la o nou scen vor fi luate n considerare adncimile punctelor
precedente, aceasta se face cu secvena:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


Crearea efectului de secionare folosind bufferul de adncime

Putem folosi urmtoarea secven:

glDrawBuffer(GL_NONE);

glBegin(GL_POLYGON);
glVertex3f(-100.0, 100.0, cutting_plane);
glVertex3f(100.0, 100.0, cutting_plane);
glVertex3f(100.0, -100.0, cutting_plane);
glVertex3f(-100.0, -100.0, cutting_plane);
glEnd();

glDrawBuffer(GL_BACK);

, ia funcioneaz n felul urmtor nainte de secven desenm corpul, apoi
desenm un plan de secionare ntr-un buffer de culoare inexistent, fiind afectat doar
planul de adncime, tot ce este n spatele planului de secionare nu v-a mai fi afiat,
planul efectiv va fi invizibil. Se observ c dup trasarea acestui plan, se revine la
modul normal de afiare.

Aceast secven nltur prin secionare doar partea din spate.

Exerciiu 2. Creai un program care s secioneze un corp afind doar partea din
spate, acest corp va fi un ceainic (auxSolidTeapot), vei folosi secvena precedent, plus
funcia
glDepthFunc ( ).

Precizia de calculare a adncimii pentru acest buffer poate fi de 16bii sau de 32
de bii, valoare implicit este de 32 de bii. Cu ct aceast precizie este mai mare scena
va putea fi mai complex.





180
4 4. .1 12 2. .4 4 F Fo ol lo os si ir re ea a b bu uf ff fe er ru ul lu ui i a ab bl lo on n

Bufferul ablon (stencil) permite pstrarea anumitor zone din fereastr. Astfel
dac se proiecteaz un simulator de zbor, sau de curse, bordul avionului, sau cel al
mainii rmne neschimbat comparativ cu mediul exterior, pentru aceasta se poate
folosi bufferul ablon. Bufferul ablon are o abordare asemntoare cu a bufferului de
adncime, avnd cu toate aceste a serie de funcii specifice.

Pentru a activa bufferul ablon vom folosi secvena:

glEnable(GL_STENCIL_TEST);

n Win32 la specificatorul de format pentru pixel trebuie setat cStencilBits la 1(
adic fiecrui pixel i se va asocia doar un singur bit n ablon)
Pentru se specifica n glaux folosirea bufferului de tip ablon se folosete
secvena:

auxInitDisplay( AUX_RGB | AUX_DOUBLE | AUX_DEPTH |
AUX_STENCIL);

n plus se mai folosesc funciile:

void glClearStencil(GLint s);

, care stabilete valoare prin care se va terge bufferul ablon;

void glStencilFunc(GLenum func, GLint ref, GLuint mask)

, stabilete care puncte vor fi nlocuite i care pstrate,
- func este acelai cal glDepthFunc
- ref este o valoare de refein a bufferului ablon;
- mask este valoarea prin care se specific o condiie suplimentar pentru
pstrarea unui pixel;

void glStencilMask(GLuint mask)

, seteaz condiia de modificare a unui pixel, de obicei se folosete valoarea 1,
pentru masc;

void glStencilOp(GLenum fail, GLenum zfail, GLzpass)

, stabilete testele pentru trecerea prin ablon:
fail specific ce se ntmpl dac pixelul nu a trecut de testul ablon aceasta
este definit prin constantele :
GL_KEEP se pstreaz valoarea din ablon;
GL_ZERO se seteaz cu 0 valoarea din ablon;
GL_REPLACE se nlocuiete valoarea din ablon;
181
GL_INCR se incrementeaz valoarea din ablon;
GL_DECR se decrementeaz valoarea din ablon;
GL_INVERT neag pe bii valoare din ablon;
zfail stabilete aciunea ce se ntreprinde dac testul ablon este trecut dar nu s-
a trecut de testul de adncime (aciunea este descris de aceleai constante de mai
nainte) ;
zpass stabilete aciunea ce se ntreprinde dac s-a trecut de testul ablon i de
testul de adncime ;

Exemplu :

glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

sau

glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);



n plus mai este secvena de tergere complet a bufferului ablon:

glClear(GL_STENCIL_BUFFER_BIT);

Exerciiu 3. Creai un program n care s animai un corp solid. Corpul va fi
vzut printr-o deschidere circular poziionat n mijlocul ecranului. Vei folosi
bufferele ablon.

4 4. .1 12 2. .5 5 F Fo ol lo os si ir re ea a b bu uf ff fe er ru ul lu ui i d de e a ac cu um mu ul la ar re e

Bufferul de acumulare poate fi folosit la cumularea, adunare de imagini de
afiare, peste alte imagini, putnd fi folosit pentru a simula efecte de inerie a vederii la
care marginile corpului n micare sunt vizualizate nceoat, suprapus. Sau mai poate fi
folosit pentru o trecere mai lin de la muchiile ce delimiteaz un corp la mediul ambiant
(anti aliasing).

Pentru a activa folosirea bufferului de acumulare se folosete:
pentru Win32 se seteaz cAcumBits la o valoare diferit de 0,
pentru glaux se folosete secvena:

auxInitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH |
AUX_ACCUM);

, se observ folosirea constantei AUX_ACCUM.

182
Pentru a specifica modul cum se face acumularea n acest buffer se folosete
funcia cu prototipul :

void glAccum( GLenum op, GLfloat value );

,unde op specific acest mod prin constantele:
- GL_ACCUM valoare componentelor culorii (0.0 1.0) este citit din bufferul
surs specificat prin glReadBuffer, nmulit cu value i adunat la valoarea din
bufferul de acumulare;
- GL_LOAD - valoare componentelor culorii (0.0 1.0) este citit din bufferul
surs specificat prin glReadBuffer, nmulit cu value i scris direct n bufferul
de acumulare nlocuind valoare precedent;
- GL_ADD - adun valoare specificat de value la fiecare component a culorii
(RGBA) specificat n bufferul de acumulare;
- GL_MULT - nmulete fiecare component a culorii din bufferul de acumulare
cu value i produsul obinut este pus n bufferul de acumulare;
- GL_RETURN transfer datele din bufferul de acumulare n bufferul de
afiare, mai nti nmulind fiecare componenet cu value i normaliznd-o
pentru intervalul 0.0-1.0.
, value este o valoare ntre 0.0 i 1.0 prin care configureaz acumularea;

Exemplu:

// se deseneaz scena ce va fi ncetosata
draw_frame(0);
// transferm in bufferul de acumulare 50% din intensitatea pixelilor
//din scena
glAccum(GL_LOAD, 0.5);

// redesenam de zece ori scena in la momente de timp successive
// si acumulam in bufferul de acumulare 5% din intensitatea pixelor din
// aceste secvente cadru
for (i = 1; i <= 10; i ++)
{
draw_frame(-i);
glAccum(GL_ACCUM, 0.05);
};

// afisam continutul bufferului de acumulare
glAccum(GL_RETURN, 1.0);

Exerciiu 4. Creai un program pe baza secvenei prezentate n care un corp n
rotaie sau alt gen de micare s prezinte astfel de nceori ca urmare a ineriei
ochiului.



183
Programare Grafic OpenGL

4.13 Lucrare de laborator 13

4 4. .1 13 3. .1 1 E Ef fe ec ct te e s sp pe ec ci ia al le e n n O Op pe en nG GL L

OpenGL punea la dispoziia programatorului o serie de efecte speciale
predefinite, din care dou ceaa (fog) i mbinarea(blend) sunt cele mai utilizate. Dei au
fost concepute viznd n principal scopul specificat prin denumire n anumite
configuraii se pot crea i alte genuri de efecte surprinztoare cu ajutorul acestora dou
i lucrul cu bufferul de acumulare sau componenta alfa a culorii.

4 4. .1 13 3. .2 2 C Cr re ea ar re ea a e ef fe ec ct tu ul lu ui i d de e c ce ea a

Efectul de cea n OpenGL se manifesta ca o diminuare a culorii obiectelor
scenei, pn la dispariia complet a acestora. Culorile obiectelor sunt alterate prin
culoarea ceii fcndu-se o trecere gradual de la culoarea corpului la cea a ceii.
Trecerea poate fi mai lin sau mai abrupt n funcie de parametrii configurabili ai ceii.
Totui ceaa n OpenGL, nu este mai mult dect acest lucru. nchipuirea c prin cea s-
ar dispune de nite mase de aburi sub forma unor nori sau pcle care s-ar putea dispune
convenabil n faa sau printre obiecte, nu este situaia de fapt a ceii standard din
OpenGL. Totui efectul prezentat anterior se poate obine cu mai mult efort prin
folosirea unor combinaii de efecte. Ceaa se poate configura pentru fiecare obiect n
parte sau pentru un grup de obiect.
Pentru a activa ceaa se folosete secvena:

glEnable(GL_FOG);

, iar pentru a o dezactiva:

glDisable(GL_FOG);

Pentru a configura ceaa se poate folosi secvena :

glFogf(GL_FOG_MODE, GL_LINEAR);
glFogfv(GL_FOG_COLOR, fog_color);

Funcia glFogf specific modul de estompare al luminii ce traverseaz ceaa, ea
are urmtorul prototip:

void glFogf( GLenum pname, GLfloat param);

, unde pname specfic parametrul configurat:
GL_FOG_MODE - specific funcia de estompare( atenuare) folosit, pentru
aceasta param poate lua valorile:
GL_LINEAR funcie liniara;
GL_EXP funcie exponenial;
184
GL_EXP2 funcie exponenial ptratic;
GL_FOG_DENSITY specific densitatea ceii implicit param este 1.0,
acesta trebuie s fie pozitiv folosit pentru atenuarea exponenial;
GL_FOG_START - pentru a specifica poziia pe oz de nceput al ceii,care
implicit este 0.0, folosit pentru atenuare liniar;
GL_FOG_END pentru a specifica poziia pe oz de deprtare a zonei de cea ,
implicit este 1.0, folosit pentru atenuare liniar ;
GL_FOG_INDEX - pentru a specifica indicele de cea, implicit este 0.0;
GL_FOG_COLOR - pentru a specifica culoarea ceii - unde param este un
vector de patru elemente este folosit n combinaie cu varianta glFogfv sau glFogiv a
funciei.

O alt secven folosit este :

glHint (GL_FOG_HINT, GL_NICEST);

,care specific calitatea maxim a efectului de cea n dauna vitezei de
procesare, alt variant ar fi fost folosire constantei GL_FASTEST care pune accentul
de vitez.

Exemplu de folosire a ceii:


























185
n care ceaa s-a configurat cu secvena:

glEnable(GL_FOG);
glFogf(GL_FOG_MODE,GL_LINEAR);
glFogfv(GL_FOG_COLOR,fog_color);
glFogf(GL_FOG_DENSITY, FogDensity);
glFogf (GL_FOG_START, -maxim(30,400.0*(1-FogDensity)));
glFogf (GL_FOG_END, maxim(30,400.0*(1-FogDensity)));

Exerciiu 1.Creai un program n care s putei selecta cele trei tipuri de
extompri specifice ceii liniar, exponenial, exponenial ptratic prin apsare unei
taste. Vei lucra cu glaux, desennd un singur corp. Adugai programului i opiunea de
a apropia deprta corpul.

4 4. .1 13 3. .3 3 C Cr re ea ar re ea a e ef fe ec ct tu ul lu ui i d de e m mb bi in na ar re e

Cu ajutorul efectului de mbinare(blend) se pot crea corpuri transparente, de
diferite culori, chiar cu anumite efecte de iluminare.
Pentru a activa opiunea de mbinare se poate folosi secvena:

glEnable(GL_BLEND);

Pentru a configura mbinarea se folosete funcia cu prototipul:

void glBlendFunc( GLenum sfactor, GLenum dfactor );

, unde sfactor specific sursa de culoare i poate lua valorile:

- GL_ZERO culoare surs va fi negru (0,0,0,0)
-GL_ONE culoare surs va fi alb(1,1,1,1);
- GL_SRC_COLOR culoare surs propriu-zis;
- GL_DST_COLOR culoare surs este nmulit prin culoare destinaie;
- GL_ONE_MINUS_DST_COLOR culoarea surs este nmulit cu 1 minus
culoarea destinaiei;
- GL_SRC_ALPHA culoarea sursei este nmulit cu alfa sursei;
- GL_ONE_MINUS_SRC_ALPHA culoarea sursei este nmulit cu 1 minus
alfa sursei;
- GL_DST_ALPHA- culoarea sursei este nmulit cu alfa destinaiei
- GL_ONE_MINUS_DST_ALPHA culoarea sursei este nmulit cu 1 minus
alfa destinaiei;
- GL_SRC_ALPHA_SATURATE culoarea sursei este nmulit cu minimul
dintre alfa sursei i 1 minus alfa destinaiei;


,iar dfactor specific culoarea destinaiei lund valori descrise de constante
asemntoare:

186
- GL_ZERO
- GL_ONE
- GL_SRC_COLOR
- GL_ONE_MINUS_SRC_COLOR
- GL_SRC_ALPHA
- GL_ONE_MINUS_SRC_ALPHA
- GL_DST_ALPHA
- GL_ONE_MINUS_DST_ALPHA.

dar de data acesta referitoare la destinaie.

Exemplu:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glPushMatrix();
glTranslatef(0.0, 0.0, -15.0);
glRotatef(-rotation, 0.0, 1.0, 0.0);
// desenam ceainicul netransparent
glDisable(GL_BLEND);
glColor3f(1.0, 1.0, 0.0);
auxSolidTeapot(1.0);
glPopMatrix();

glPushMatrix();
glTranslatef(0.0, 0.0, -10.0);
glRotatef(rotation, 0.0, 1.0, 0.0);
// desenam ceainicul transparent
glEnable(GL_BLEND);
// se observa ca alfa este setat la 0.25
glColor4f(1.0, 1.0, 1.0, 0.25);
auxSolidTeapot(1.0);
glPopMatrix();














187
Exemplu de program de mbinare:

























Exerciiu 2. Creai un program n care n interiorul unui cub transparent s fie
poziionat un cub netransparent, rotit puin fa de cel transparent.

Exerciiu 3. Modificnd programul precedent creai dou cuburi transparente
unul coninndu-l pe cellalt i al doilea pe un al treilea netransparent. Aceste cuburi vor
fi centrate i se vor roti n direcii diferite.













188

Programare Grafic OpenGL

4.14 Lucrare de laborator 14.

4 4. .1 14 4. .1 1 C Cu ur rb be e B Be ez zi ie er r i i N Nu ur rb bs s

Pn acum cu primitivele de care dispunem putem desena curbe, suprafee curbe
doar prin nite structuri complicate de cod. ns mediul OpenGL pune la dispoziie nite
structuri ce permit generarea unor asemenea curbe doar prin specificare unor centre de
curbare i a capetelor curbelor,respectiv a marginilor suprafeelor. O abordare este cea
prin evaluatori prin care construim curbe i suprafee i gestionm manual parametrii
generai, o alta este folosind structurile NURBS, n care totul este prelucrat automat.

4 4. .1 14 4. .2 2 C Cu ur rb be el le e i i s su up pr ra af fe e e el le e B Be ez zi ie er r

Teoria matematic i formulele ce stau n spatele generrii acestor curbe sunt
destul de complexe pentru a fi expus aici. n acest sens vom aborda acest subiect dintr-
o perspectiv practic adic se dorete crearea unei structuri se va explica exact
secvenele de cod folosite.

Exemplu:

glMap1f(GL_MAP1_VERTEX_3, // tipul curbei desenate
0.0f, // limita inferioar a intervalului
100.0f, // limita superioar a intervalului
3, // distanta dintre puncte n vectori
nNumPoints, // numrul de puncte de control
&ctrlPoints[0][0]); // vectorul punctelor de control

// activm evaluatorul
glEnable(GL_MAP1_VERTEX_3);

// genereaz curba cu o precizie de o sut de diviziuni
glBegin(GL_LINE_STRIP);
for(i = 0; i <= 100; i++)
{
// genereaz un vrf pe baza evaluatorului specificat
glEvalCoord1f((GLfloat) i);
}
glEnd();

Numrul de diviziuni poate di crescut n funcie de precizia grafic dorit.



189

Funcia glMap1f configureaz un evaluator de curbe unidimensional ea are
urmtorul prototip:


void glMap1f( GLenum target, GLfloat u1, GLfloat u2,
GLint stride, GLint order, const GLfloat *points
);

, unde target specific rezultatul dorit a fi obinut fie c se refer la nite
vrfuri, fie la normale, fie la culori, fie la coordonate de texturare, el este definit prin
constantele:
GL_MAP1_VERTEX_3 se refer la nite vrfuri definite prin x, y,
z (glVertef3f);
GL_MAP1_VERTEX_4 se refer la nite vrfuri definite prin x, y, z,
w(glVertef4f) ;
GL_MAP1_INDEX - se refer la colori definite prin index;
GL_MAP1_COLOR_4 se refer la culori RGBA(glColor4f);
GL_MAP1_NORMAL se refer la o normal definit prin coordonatele
vrfului x, y, z (glNormal3f);
GL_MAP1_TEXTURE_COORD_1 se refer la coordonatele unei texturri cu
texturi unidimensionale (glTexCoord1f);
GL_MAP1_TEXTURE_COORD_2 se refer la coordonatele unei texturri cu
texturi bidimensionale(glTexCoor21f) ;
GL_MAP1_TEXTURE_COORD_3 se refer la coodonatele unei texturri cu
texturi specificate prin s, t, r(glTexCoord3f);
GL_MAP1_TEXTURE_COORD_4 se refer la coordonatele unei texturri cu
texturi specificate prin s, t, r, q(glTexCoord4f);
, u1,u2 valoare inferioar, respectiv superioar a maprii liniare a punctelor de
pe curb ;
, stride numrul de componente ale unui punct definit n vectorul points ;
, order numrul de puncte de control ;
, points vectorul punctelor de control ;

Apoi urmeaz funcia prin care activm generarea automat e elementelor
grafice prin evaluatori.

glEnable(tip_element_grafic);
, unde tipul este acelai ca i target.

Urmeaz generarea efectiv a punctelor de ctre funcia cu prototipul:

void glEvalCoord1f( GLfloat u );

, unde u este o valoare din intervalul u1, u2, cu semnificaie specificat anterior,
la prototip, i-n secvena de program.

190
Exerciiu 1. Creai un program care s genereze o curb alctuit din o sut de
diviziuni, aceast curb este definit de 4 puncte de control. Cu ajutorul mouselui
selectai cte un punct de control la care s-i schimbai poziia, apoi s-l deselectai.



4 4. .1 14 4. .3 3 E Ev va al lu ua at to or ri i p pe en nt tr ru u s su up pr ra af fe e e e. .

Sunt practic identici cu cei de la curbe, diferena fiind c mai apare a coordonat.

Exemplu:

glMap2f(GL_MAP2_VERTEX_3, // tipul evaluatorului
0.0f, // limita inferiora a coordonatei u
10.0f, // limita superiora a coordonatei u
3, // numarul de componente al unui element al vectorului
3, // numrul de puncte de control pe direcia u
0.0f, // limita inferiora a coordonatei v
10.0f, // limita superiora a coordonatei v
9, // distanta dintre dou elemente consecutive pe v
3, // numrul de puncte de control pe direcia v
&ctrlPoints[0][0][0]); // vectorul cu puncte

// activam evaluatorul
glEnable(GL_MAP2_VERTEX_3);

// genereaz punctele suprafeei
glMapGrid2f(10,0.0f,10.0f,10,0.0f,10.0f);

// afieaz suprafaa sub forma unei reele de linii
glEvalMesh2(GL_LINE,0,10,0,10);

Funcia glMap2f are prototipul:

void glMap2d( GLenum target, GLdouble u1, GLdouble u2,
GLint ustride, GLint uorder,
GLdouble v1, GLdouble v2,
GLint vstride, GLint vorder,
const GLdouble *points
);

, pentru target se vor folosi practic aceleai constante cu diferena c n loc de
MAP1 vom avea MAP2;
, restul sunt similare cu cele de la glMap1d;

Funcia glMapGrid2f care genereaz punctele suprafeei are prototipul:

191
void glMapGrid2f( GLint un, GLfloat u1, GLfloat u2,
GLint vn, GLfloat v1, GLfloat v2
);

, unde un ,vn sunt numrul de diviziuni pe u i pe v;
, u1,u2 sunt limitele intervalului de generare pe u( adic de la ce coordonat se
ncepe generarea punctelor pe u);
,v1, v2 - sunt limitele intervalului de generare pe v;



Funcia glEvalMesh2 genereaz efectiv suprafaa. Are urmtorul prototip :

void glEvalMesh2( GLenum mode,
GLint i1, GLint i2,
GLint j1, GLint j2
);

, unde mode este definit prin constantele:
GL_POINT se deseneaz doar punctele;
GL_LINE se va desena o suprafa din linii;
GL_FILL se va desena o suprafa continu;
, i1,i2 intervalul de puncte definite n grid ce se vor afia pe u ;
,j1,j2 intervalul de puncte definite n grid ce se vor afia pe v ;


Exerciiu 2. Generai o suprafa plin folosind o matrice de 3 x 3 puncte de
control. Numrul de diviziuni va fi de 30 x 30. Se va selecta prin apsarea barei de
spaiu n mod ciclic modul de desenare al suprafeei din cele trei moduri existente.


4 4. .1 14 4. .4 4 C Cu ur rb be el le e i i s su up pr ra af fe e e el le e d de e t ti ip p N NU UR RB BS S

Acest tip de curbe este similar tipului Bezier, cu unele diferene de calcul efectiv
al curbelor i de implementare OpenGL. Denumirea NURBS provine de la iniialele
denumirii complete a acestui gen de curbe Non-Uniform Rational B-Spline.
Curbele NURBS sunt definite n biblioteca glu i sunt apelate doar dup ce au
fost create. Asfel pentru a crea o structur NURBS se folosete secvena :

GLUnurbsObj *pNurb = NULL; //declaram structura


pNurb = gluNewNurbsRenderer();// creem structura

, la fel cnd nu se mai folosete se dealoc structura prin secvena :

if(pNurb) // daca este alocata o dealocam
192
gluDeleteNurbsRenderer(pNurb);

Pentru a configura o structur NURBS folosim funcia cu prototipul:

void gluNurbsProperty(GLUnurbsObj *nobj,
GLenum property, GLfloat value
);

,unde nobj este structura NURBS,
, property este proprietatea ce se configureaz, ea este definit prin constantele:
GLU_SAMPLING_TOLERANCE - specific lungimea maxim n pixeli
pentru eantionarea curbei implicit este 50 , folosit mpreun cu
GLU_PATH_LENGTH ;

GLU_DISPLAY_MODE specific modul cum va fi desenat suprafaa sau
curba - GLU_FILL trasare complet, GLU_OUTLINE_POLYGON - trasare din linii,
GLU_OUTLINE_PATCH - trasarea acelor linii specificate de utilizator;
GLU_CULLING genereaz eliminarea suprafeelor din afara zonelor stabilite
de afiare daca este setat pe GL_TRUE, implicit este setat cu GL_FALSE;
GLU_PARAMETRIC_TOLERANCE specific distana maxim n pixeli,
cnd este folosit abordarea parametric, implicit este 0.5 ;
GLU_SAMPLING_METHOD stabilete metoda de eantionare:
GLU_PATH_LENGTH este setarea implicit,alta ar fi GLU_PARAMETRIC_ERROR,
definit de GLU_PARAMETRIC_TOLERANCE, i GLU_DOMAIN_DISTANCE
definit prin numrul de puncte pe u i pe v ;
GLU_U_STEP specific numrul de puncte pe direcia u, pe unitate, implicit
este 100.0 ;
GLU_V_STEP specific numrul de puncte pe direcia v, pe unitate, implicit
este 100.0 ;
GLU_AUTO_LOAD_MATRIX - apeleaz automat prin internet serverul
OpenGL pentru a genera matricele, de proiecie, afiare.

Exemplu :

gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 25.0f);

gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);

Pentru a genera o curb NURBS se folosete funcia cu prototipul:

void gluNurbsCurve(
GLUnurbsObj *nobj,
GLint nknots, GLfloat *knot,
GLint stride, GLfloat *ctlarray,
GLint order, GLenum type
);

193
,un nobj este strutura NURBS,
,nknots este numrul de noduri,
,knot este un vector de noduri,
,stride este distana dintre punctele de control din vector,
,ctlarray este vectorul de generare al curbei NURBS,
,order este ordinul curbei nurbs implicit 4,
,type este tipul evaluatorului folosit definit mai sus este setat la
GL_MAP1_VERTEX3, cel mai frecvent.

Aceast funcie se ncadreaz ntre gluBeginCurve(nobj) gluEndCurve(nobj).



Pentru a genera o suprafa NURBS se folosete o secven de genul :

gluBeginSurface(pNurb);

// creaz suprafaa
gluNurbsSurface(pNurb, // structura NURBS
8, Knots, // numrul de noduri i vectorul de noduri pe s
8, Knots, // numrul de noduri i vectorul de noduri pe t
4 * 3, // Distanta dintre punctele de control pe s
3, // Distanta dintre punctele de control pe t
&ctrlPoints[0][0][0], // vector cu punctele de control
4, 4, // ordinal curbei pe s i pe t
GL_MAP2_VERTEX_3); // tipul evaluatorului folosit


gluEndSurface(pNurb);

Aceast funcie are prototipul:

void gluNurbsSurface( GLUnurbsObj *nobj,
GLint sknot_count, GLfloat *sknot,
GLint tknot_count, GLfloat *tknot,
GLint s_stride, GLint t_stride,
GLfloat *ctlarray,
GLint sorder, GLint torder,
GLenum type
);







194


Exerciiu 3. Realizai aceleai programe de la exerciiu 1 i 2 dar folosind curbe
NURBS.

Exerciiu 4. Realizai o suprafa NURBS ondulat texturat cu o imagine
ncrcat din fiier.




Exemple de aplicaie NURBS :

































195
5 BIBLIOGRAFIE
5



1. Dave Astle, Kevin Hawkins Beginning OpenGL Game Programming ,
Premier Press, Boston, 2004;
2. Paul Martz,OpenGL(R) Distilled (OpenGL), Addison Wesley Professional,
2006;
3. Richard S. Wright Jr., Michael R. Sweet ,OpenGL Super Bible, Waite Group
Press. ,2007;
4. Rodica Baciu , Programarea Aplicaiilor Grafice 3D cu OpenGL, Editura
Albastr, Cluj-Napoca 2005;
5. The Red Book of OpenGL
6. http://www.opengl.org
7. http://www.sgi.com/software/opengl
8. http://www.cs.utah.edu/~narobins/opengl.html
9. www.mesa3d.org/


























196
1 ELEMENTE INTRODUCTIVE 3
1.1 Sistemul grafic OpenGL ................................................................. 3
1.2 Sisteme grafice pentru grafica 3D.................................................. 4
1.3 Caracteristici OpenGL.................................................................... 6
2 BAZELE PROGRAMRII N OPENGL 8
2.1 Arhitectura OpenGL ....................................................................... 8
2.2 Descriere general OpenGL, GLU i GLAUX .............................. 10
2.2.1 OpenGL Utility Library (GLU) 10
2.2.2 Biblioteci disponibile 11
2.3 GLAUX ......................................................................................... 12
2.3.1 Funciile callback GLAUX 18
3 PRIMITIVE GEOMETRICE 26
3.1 Primitive geometrice OpenGL ...................................................... 26
3.1.1 Formatul comenzilor OpenGL 28
3.1.2 Specificarea primitivelor geometrice OpenGL 29
3.1.3 Atribute ale primitivelor de ieire 33
3.2 Reprezentarea curbelor i a suprafeelor curbe ........................... 47
3.2.1 Evaluatori 48
3.2.2 Curbe Bezier 50
3.2.3 Suprafee Bezier 56
3.2.4 Interfaa NURBS 62
3.2.5 Curbe NURBS 64
3.3 Suprafee cvadrice ....................................................................... 74
3.4 Primitive raster ............................................................................. 79
3.4.1 Reprezentarea imaginilor bitmap 81
3.4.2 Reprezentarea fonturilor prin bitmap-uri 85
3.4.3 Redarea pixmap-urilor 100
3.5 Utilizarea atributelor de redare n OpenGL ................................ 108
3.5.1 Controlarea strii OpenGL 108
3.5.2 Setarea strii curente 109
3.5.3 Interogarea strii i stiva de parametrii 109
4 INDRUMAR DE LABORATOR 110
4.1 Lucrare de laborator 1. ............................................................... 110
4.1.1 Introducere n OpenGL 110
4.1.2 Crearea unei aplicaii OpenGL 110
4.2 Lucrare de laborator 2. ............................................................... 114
4.2.1 Utilizarea funciilor bibliotecii glaux 114
4.2.2 Funcii de iniializare: 114
4.2.3 Funcii de interfa i de ciclare 115
4.2.4 Funciile de lucrul cu mouse 116
4.2.5 Funciile de lucru cu tastatura 117
4.3 Lucrare de laborator 3. ............................................................... 120
4.3.1 Aplicaii OpenGL n Win32 120
4.3.2 Crearea unei aplicaii Win32 necompletate 120
4.4 Lucrare de laborator 4. ............................................................... 128
4.4.1 Primitive grafice OpenGL 128
4.4.2 Desenarea de puncte 128
4.4.3 Desenarea de linii 128
4.4.4 Desenarea unui triunghi 129
4.4.5 Desenarea unui patrulater 130
4.4.6 Desenarea unui poligon 130
197
4.4.7 Funcii grafice auxiliare 130
4.4.8 Modificare mrimii punctului 130
4.4.9 Modificare parametrilor liniei 131
4.4.10 Modificare parametrilor figurilor nchise 131
4.5 Lucrare de laborator 5. ............................................................... 135
4.5.1 Transformri geometrice n OpenGL 135
4.5.2 ncrcarea i descrcarea din stiv a unei matrice 135
4.5.3 Transformri elementare de coordonate 137
4.5.4 Configurarea mediului vizual 138
4.6 Lucrare de laborator 6. ............................................................... 140
4.6.1 Iluminare, lumini i materiale. 140
4.6.2 Configurarea iluminrii 140
4.6.3 Configurarea materialului 144
4.7 Lucrare de laborator 7. ............................................................... 146
4.7.1 Generarea de umbre prin utilizarea matricelor. 146
4.8 Lucrare de laborator 8. ............................................................... 152
4.8.1 Utilizarea listelor 152
4.8.2 Crearea unei liste. 152
4.9 Lucrare de laborator 9. ............................................................... 157
4.9.1 Lucrul cu imagini rastru n OpenGL 157
4.9.2 ncrcarea unei imagini bitmap din fiier 162
4.10 Lucrare de laborator 10. ........................................................... 165
4.10.1 Aplicarea texturilor 165
4.10.2 Texturarea unidimensional 165
4.10.3 Texturarea 2D 167
4.10.4 Utilizarea texturilor mipmap 170
4.11 Lucrare de laborator 11. ........................................................... 172
4.11.1 Cuadrice 172
4.12 Lucrare de laborator 12. ........................................................... 176
4.12.1 Lucrul cu bufferele n OpenGL 176
4.12.2 Bufferul de culoare 176
4.12.3 Bufferul de adncime 178
4.12.4 Folosirea bufferului ablon 180
4.12.5 Folosirea bufferului de acumulare 181
4.13 Lucrare de laborator 13............................................................ 183
4.13.1 Efecte speciale n OpenGL 183
4.13.2 Crearea efectului de cea 183
4.13.3 Crearea efectului de mbinare 185
4.14 Lucrare de laborator 14. ........................................................... 188
4.14.1 Curbe Bezier i Nurbs 188
4.14.2 Curbele i suprafeele Bezier 188
4.14.3 Evaluatori pentru suprafee. 190
4.14.4 Curbele i suprafeele de tip NURBS 191
5 BIBLIOGRAFIE 195

S-ar putea să vă placă și