Sunteți pe pagina 1din 136

MILITARA

ACADEMIA TEHNICA

grafic computerizat
Aplicaii n OpenGL
Ediia a II-a

Cristian MOLDER

Editura Academiei Tehnice Militare

Bucures, ti, 2016


Aceasta carte a fost redactata n limbajul LATEX 2 , utilizand versiunea gratuita
MiKTEX 2.9.5870 pentru Windows.

Descrierea CIP a Bibliotecii Naionale a Romniei


MOLDER, CRISTIAN
Grafic computerizat : Aplicaii n OpenGL /
Cristian Molder. - Bucureti : Editura Academiei Tehnice
Militare, 2016
Bibliogr.
ISBN 978-973-640-148-0

004.92

Imagini coperta I:
Artificial Intelligence Virtual Assistant Denise
c Guilherme Lindroth
Confederate Wraith Motorcycle Josh Flores
c
Imagini coperta IV:
Ferrari F2007 3D Model Project
c Mario Cordova
VFX of Rush c Double Negative (Dneg)
Imagine coperta interioar
a:
Formula 1 Car 3D Models
c boscorelli3D
Cuprins

1 Introducere n OpenGL 5
1.1 OpenGL vs. Direct3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Biblioteci grafice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2 Programarea aplicatiilor n mediul MS Visual Studio 9


2.1 Instalarea bibliotecii GLUT . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Crearea unui proiect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Crearea unui cod sursa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4 Compilarea si executarea unui proiect . . . . . . . . . . . . . . . . . . . . . 14

3 Structurarea aplicatiilor OpenGL 16


3.1 Initializarea ferestrei grafice . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2 Gestionarea evenimentelor . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

4 Definirea si afisarea obiectelor grafice 20


4.1 Parametrii initiali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.2 Puncte, linii si poligoane . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.3 Tipare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.4 Vectorul normala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.5 Matrice de date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5 Proiectii si transform ari 37


5.1 Proiectii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.2 Transformari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.3 Manipularea stivelor de matrice . . . . . . . . . . . . . . . . . . . . . . . . 50
5.4 Planuri de decupare suplimentare . . . . . . . . . . . . . . . . . . . . . . . 54

6 Iluminarea scenelor si culoarea obiectelor 57


6.1 Surse de lumina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.2 Proprietatile de material ale obiectelor . . . . . . . . . . . . . . . . . . . . 60

7 Texturi 63
7.1 Initializarea texturilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
7.2 Coordonate poligonale de texturare . . . . . . . . . . . . . . . . . . . . . . 66
7.3 Coordonate automate de texturare . . . . . . . . . . . . . . . . . . . . . . 78

8 Animatii cu sprite-uri 82
8.1 Sprite-uri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

3
4 CUPRINS

9 Curbe si suprafete parametrice 95


9.1 Curbe Bezier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
9.2 Suprafete Bezier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

10 Interfete grafice (GUI) 101


10.1 Interactiunea cu mouse si tastatura . . . . . . . . . . . . . . . . . . . . . . 101
10.1.1 Evenimente generate de tastatura . . . . . . . . . . . . . . . . . . . 101
10.1.2 Utilizarea tastelor speciale . . . . . . . . . . . . . . . . . . . . . . . 103
10.1.3 Evenimente generate de mouse . . . . . . . . . . . . . . . . . . . . . 106
10.2 Crearea meniurilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

11 Fonturi 113
11.1 Fonturi bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
11.2 Fonturi stroke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

12 Fisiere cu obiecte grafice 119


12.1 Fisiere de tip Alias/Wavefront (.OBJ) . . . . . . . . . . . . . . . . . . . . . 119

A Materiale 131

A Coduri ASCII standard (0-127) 133

Bibliografie 136
Capitolul 1

Introducere n OpenGL

OpenGL (Open Graphics Library) reprezinta o specificatie standardizata a unei interfe-


te de programare a aplicatiilor (API) portabila pe diferite platforme, destinata crearii
aplicatiilor de grafica computerizata 2D si 3D. Interfata de programare consta n peste
250 de functii diferite care pot fi utilizate la crearea unor scene complexe tridimensionale
pornind de la primitive grafice simple. Biblioteca OpenGL a fost creata si dezvoltata de
catre Silicon Graphics Inc. (SGI) n anul 1992, fiind actual utilizata pe larg n cadrul
aplicatiilor de tip CAD, realitate virtuala, vizualizare stiintifica sau a informatiilor sau
simulatoarelor de zbor. Se utilizeaza, de asemenea, n cadrul jocurilor video, domeniu n
care se afla n competitie directa cu Direct3D pe platformele care utilizeaza sistemul de
operare Microsoft Windows.

1.1 OpenGL vs. Direct3D


Direct3D (parte a interfetei de programare DirectX) este implementat oficial doar pe
sisteme care folosesc sistemul de operare Microsoft Windows, incluzand versiuni embed-
ded utilizate pe consolele video Xbox si Sega Dreamcast.

OpenGL poate fi implementat pe majoritatea platformelor, incluzand Microsoft Win-


dows, sisteme care au la baza Unix, precum Mac OS X, Linux sau console video Pla-
yStation 3. Variante ale OpenGL ruleaza pe console Nintendo GameCube si Wii sau
pe sisteme portabile Nintendo NS si PlayStation. Cu exceptia Windows si Xbox, toate
sistemele de operare care permit grafica 3D cu accelerare grafica utilizeaza OpenGL ca
interfata primara de programare a aplicatiilor.

Figura 1.1: Logo-urile interfetelor de programare a aplicatiilor (API) OpenGL si DirectX

Driverele OpenGL ale Microsoft, incluse n versiunile de Windows anterioare versiunii


Vista, nu ofera accelerare hardware sau suport direct pentru extensii. Aceste versiuni
de Windows necesita, prin urmare, instalarea de catre utilizatori a unor drivere de client

5
6 CAPITOLUL 1. INTRODUCERE IN OPENGL

(ICD) dezvoltate de catre producatorii de procesoare grafice pentru suportul hardware


OpenGL. Aceste drivere sunt, n marea majoritate a cazurilor, incluse de catre producatori
n driverele placilor grafice. Prin urmare, simpla instalare a driverelor placii grafice este
suficienta pentru obtinerea unui suport hardware OpenGL.

Windows Vista ofera trei tipuri de implementare OpenGL. Prima dintre acestea efec-
tueaza corespondenta directa dintre OpenGL si Direct3D prin traducerea comenzilor
OpenGL n comenzi Direct3D. Acest lucru permite accelerare hardware OpenGL pana
la versiunea 1.4, versiunile ulterioare putand fi apelate ca extensii. Al doilea tip utilizeaza
drivere de producator ce necesita a fi instalate pe Windows XP. Cea de-a treia posibili-
tate este o implementare completa ce permite accesul direct OpenGL peste versiunea 2
pe procesoarele grafice.

Din punct de vedere comparativ, Direct3D a fost conceput ca o interfata hardware.


Setul de caracteristici al Direct3D este derivat din setul de caracteristici al hardware-ului.
Pe de alta parte, OpenGL este conceput ca un sistem de randare 3D care poate fi accelerat
hardware. In concluzie, aceste doua interfete de programare (API) sunt proiectate n mod
diferit, dar cu functionalitati comune.

Exista, totusi, diferente. Direct3D a fost creata pentru gestionarea resurselor hardware
de catre aplicatie, n timp ce OpenGL face gestiunea prin intermediul implementarii.
Acest compromis permite ca OpenGL sa scada nivelul de dificultate n crearea API, n
acelasi timp cu cresterea complexitatii implementarii. In cazul Direct3D, programatorul
gestioneaza resursele hardware independent, implementarea fiind simpla, avand posibili-
tatea de a aloca resursele aplicatiei n modul cel mai eficient.

La scurt timp dupa aparitia bibliotecilor grafice Direct3D si OpenGL, Microsoft si SGI
au intrat n asa-numitul API War sau razboi al interfetelor de programare a aplicatiilor.
Microsoft a argumentat faptul ca Direct3D este cel mai rapid n raport cu OpenGL, de-
ficitul de performanta al celui din urma fiind justificat pe baza cerintelor de rigurozitate
n programarea aplicatiilor OpenGL. In anul 1996, n schimb, n cadrul conferintei SI-
GGRAPH (Special Interest Group on Computer Graphics), SGI a demonstrat faptul ca
performantele mai scazute ale OpenGL se datorau slabei implementari a OpenGL pe sis-
temele Windows si nu datorita unor eventuale lipsuri ale bibliotecii OpenGL.

Initial, OpenGL a fost creat pentru a fi utilizat pe platformele grafice SGI care, la
momentul respectiv, erau foarte puternice. Interfata continea circa 250 de instructiuni,
dar doar un subset de 100 de instructiuni putea fi utilizat n cadrul aplicatiilor de dezvol-
tare a jocurilor video. Firma 3Dfx a creat ulterior un set incomplet de instructiuni sub
denumirea MiniGL, care a stat la baza crearii nucleului grafic al jocului Quake. Acest
lucru a reprezentat un punct de nceput pentru dezvoltarea bibliotecii OpenGL.

Extensiile OpenGL reprezinta instructiuni specifice fiecarui producator de procesoare


video si sunt create ca supliment la nucleul comun de instructiuni. Instructiunile su-
plimentare permit noi functionalitati si sunt standardizate periodic de catre OpenGL
Architecture Review Board (ARB). Pe de alta parte, Direct3D este specific unui singur
producator, Microsoft, ceea ce o face sa fie o interfata de programare mult mai consistenta,
dar blocand accesul la caracteristici suplimentare specifice producatorilor de procesoare
grafice. In momentul n care placile video au permis suportul instructiunilor de tip pi-
1.1. OPENGL VS. DIRECT3D 7

xel shader, Direct3D a oferit un singur standard Pixel Shader 1.1 cu care GeForce 3 si,
ulterior, Radeon 8500 au confirmat compatibilitatea. Sub OpenGL, nsa, toate aceste
posibilitati au putut fi accesate prin intermediul unor extensii.

Din punct de vedere teoretic, abordarea Microsoft permite ca o aplicatie sa poata fi


rulata concomitent pe mai multe tipuri de procesoare video, n timp ce, n cazul OpenGL,
codul trebuie scris separat pentru fiecare procesor n parte. In realitate, Pixel Shader 1.1
era creat pe baza extensiilor OpenGL pentru procesoarele nVidia. In momentul aparitiei
procesorului Radeon 8500, Microsoft a creat versiunea Pixel Shader 1.4 care, la randul
ei, era un pseudolimbaj de asamblare creat pe baza extensiilor OpenGL specifice pro-
cesoarelor grafice ATi. Din fericire, acest lucru a durat foarte putin, pana n momentul
aparitiei procesoarelor grafice cu tehnica pixel shader de generatia a doua, care erau foarte
similare n functionalitati. Prin urmare, Pixel Shader 2.0 a permis unificarea codului sub
Direct3D. In acelasi timp, OpenGL a introdus propriile extensii ARB pentru tehnicile
pixel si vertex shader, comune pentru ambii producatori de procesoare video.

Luand n considerare domeniul de aplicatii, OpenGL este utilizat preponderent n


aplicatii profesionale de grafica (precum filme de animatie), n timp ce Direct3D este uti-
lizat n majoritatea cazurilor n cadrul jocurilor video. La un anumit moment de timp,
majoritatea placilor video profesionale suportau doar OpenGL, dar n momentul de fata
producatorii majori (nVidia, ATi si Matrox) ofera suport atat pentru OpenGL, cat si
pentru Direct3D.

Versiune An Particularit
ati
OpenGL 1.0 1992 Prima versiune realizata
OpenGL 1.1 1997 Introducerea utilizarii texturilor
OpenGL 1.2 1998 Introducerea subseturilor de imagini
OpenGL 1.2.1 1998 Extensie ARB, versiune minora
OpenGL 1.3 2001
OpenGL 1.4 2002
OpenGL 1.5 2003
OpenGL 2.0 2004 Proiectata de 3Dlabs, prima varianta a formatului actual de OpenGL
OpenGL 2.1 2006 Introducerea versiunii 1.20 a OpenGL Shading Language
OpenGL 3.0 2008 Introducerea versiunii 1.30 a OpenGL Shading Language
OpenGL 3.1 2009 Introducerea versiunii 1.40 a OpenGL Shading Language
OpenGL 3.2 2009 Introducerea versiunii 1.50 a OpenGL Shading Language
OpenGL 3.3 2010 Compatibilitate hardware cu Direct3D 10.0
OpenGL 4.0 2010 Compatibilitate hardware cu Direct3D 11.0
OpenGL 4.1 2010 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 2.0
OpenGL 4.2 2011
OpenGL 4.3 2012 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 3.0
OpenGL 4.4 2013
OpenGL 4.5 2014 Compatibilitate cu OpenGL ES (OpenGL for Embedded Systems) 3.1
8 CAPITOLUL 1. INTRODUCERE IN OPENGL

1.2 Biblioteci grafice


Deoarece OpenGL ofera un nivel de programare primitiv, pentru a usura munca pro-
gramatorilor, au fost create diverse biblioteci grafice care permit un nivel de programare a
aplicatilor mai nalt. Spre deosebire de instructiunile OpenGL specifice, care contin pre-
fixul gl, instructiunile bibliotecilor grafice de nivel mai nalt contin, n general, prefixul
acestora (vezi tabelul) sau se bazeaza pe alte biblioteci existente.

Biblioteca GLUT (OpenGL Utility Toolkit) efectueaza operatii de I/O cu siste-


mul de operare existent. Aceste functii includ definiri de ferestre, controlul acestora si
mo-nitorizarea evenimentelor de tip mouse sau tastatura. De asemenea, se ofera rutine de
desenare a unor primitive geometrice (n modul solid sau wireframe) de tipul cuburilor,
sferelor, sau obiectului Utah teapot. Toate instructiunile GLUT contin prefixul glut.

Biblioteca GLU (OpenGL Utility Library) consta ntr-un numar de instructiuni


care ofera rutine de trasare de nivel nalt superioare rutinelor primitive ale OpenGL. Din-
tre acestea se remarca generarea minimapelor de texturi, trasarea suprafetelor cuadrice,
a NURBS, ntrepatrunderea primitivelor poligonale (tessellation), interpretarea codurilor
de eroare OpenGL, precum si o gama extinsa de rutine de transformare utile n vizu-
alizarea volumelor si pozitionarea camerei video. De asemenea, include rutine pentru
trasarea de primitive, precum sfere, cilindri si discuri. Instructiunile specifice bibliotecii
GLU contin prefixul glu. Documentatia necesara pentru cele doua biblioteci grafice pot
fi obtinute la adresa https://www.opengl.org/registry/. B

Biblioteca GLM (OpenGL Mathematics) reprezinta o biblioteca de functii mate-


matice bazata pe specificatiile limbajului GSLS (OpenGL Shading Language). Biblioteca
permite utilizarea functiilor specifice GLSL, dar si a unor functii suplimentare, precum
transformari de matrice, cuaternioni, formate de date, numere aleatoare etc. Poate fi
utilizata si n cazul aplicarii de rendering software, procesarii de imagine sau simularii de
fenomene fizice. Detaliile pot fi regasite la adresa http://glm.g-truc.net/.

Biblioteca GLEW (OpenGL Extension Wrangler) reprezinta un mecanism pentru


determinarea acelor extensii OpenGL care sunt suportate de catre o anumita platforma
de lucru. Extensiile OpenGL sunt modalitati prin care unei aplicatii OpenGL i se pot
adauga functionalitati noi, inexistente n nucleul de baza. Extensiile sunt utilizate pentru
a avea acces la functii specifice ale unui anumit producator de hardware grafic.

Bibliotec
a grafic
a Prefix instructiune Exemplu de instructiune
OpenGL Utility Toolkit (GLUT) glut glutMainLoop()
OpenGL Utility Library (GLU) glu gluOrtho2D()
OpenGL Mathematics(GLM) glm glmReadOBJ()
OpenGL User Interface Library (GLUI) - -
OpenGL Easy Extension Library (GLee) - -
OpenGL Extension Wrangler Library (GLEW) - -
OpenGL FrameWork (GLFW) - -
Capitolul 2

Programarea aplicatiilor n mediul


MS Visual Studio

2.1 Instalarea bibliotecii GLUT


Pentru a crea o aplicatie OpenGL n Windows se utilizeaza biblioteca GLUT (OpenGL
Utility Toolkit), fiind necesara instalarea unor fisiere specifice n diferite directoare, astfel:
glut32.dll n directorul Windows/System
glut32.lib n directorul {VC Root}/Lib
glut.h n directorul {VC Root}/Include/GL
unde {VC Root} este directorul mediului de programare Visual C++, ca, de exemplu
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\.

2.2 Crearea unui proiect


Pentru a crea un proiect nou, se parcurg urmatoarele etape:

1. apelarea optiunii New Project n mediul Microsoft Visual Studio cu Ctrl+Shift+N;


2. selectarea sablonului Win32 Console Application, selectarea directorului Location
si a numelui proiectului Name, urmata de apasarea butonului OK;

9
10 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT

3. apasarea optiunii Next n fereastra de ntampinare Welcome to the Win32 Appli-


cation Wizard;

4. selectarea optiunii Empty project n fereastra Application Settings urmata de


apasarea butonului Finish.

2.3. CREAREA UNUI COD SURSA 11

2.3 Crearea unui cod surs


a
In momentul imediat urmator crearii unui proiect, interfata mediului de programare
este goala. Pentru a observa folderele specifice unui proiect, se apeleaza n partea dreapta
tab-ul Solution Explorer, n care se gasesc toate datele legate de fisierele proiectului. In
cazul de fata, corespunzatoare proiectului test, directoarele vor aparea sub o structura
arborescenta.

Detaliind arborele test se poate observa ca directorul Source Files care trebuie sa
contina fisierul sursa este gol. Prin urmare, este necesara fie (A) crearea unui fisier sursa,
fie (B) adaugarea unuia deja existent.
12 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT

A. Crearea unui fisier surs a nou. Situatia de fata apare atunci cand programatorul
se afla n situatia n care nu exista un cod sursa, fiind necesara crearea acestuia. Pentru
a crea un fisier sursa nou este necesara parcurgerea urmatorilor pasi:
1. se efectueaza click dreapta pe meniul Source Files din tab-ul Solution Explorer al
interfetei mediului de programare si se selecteaza optiunea Add;
2. se selecteaza optiunea New Item (Ctrl+Shift+A);

3. se selecteaza tipului de fisier C++ File (.cpp) n noua fereastra Add New Item;
4. se introduc directorul (Location) si numele fisierului sursa (Name) si apoi se apasa
butonul (Add).

In acest moment, n folderul proiectului corespunzator codului sursa a aparut (ca exem-
plu al autorului) fisierul cod.cpp, iar n meniul de editare acesta este deschis pentru
introducerea codului C.

2.3. CREAREA UNUI COD SURSA 13

B. Ad augarea unui fisier surs a. Aceasta operatie se face, de obicei, atunci cand
programatorul doreste introducerea n cadrul proiectului a unui cod sursa care este deja
scris ntr-un fisier pe calculator. Pentru aceasta se parcurg urmatoarele etape:
1. se efectueaza click dreapta pe meniul Source Files din tab-ul Solution Explorer al
interfetei mediului de programare si se selecteaza optiunea Add;
2. se selecteaza optiunea Existing Item (Shift+Alt+A);

3. la aparitia ferestrei Add Existing Item se selecteaza fisierul sursa dorit si se apasa
butonul Add.
14 IILOR IN MEDIUL MS VISUAL STUDIO
CAPITOLUL 2. PROGRAMAREA APLICAT

Dupa parcurgerea etapelor mentionate, n folderul Source Files al proiectului se va


gasi fisierul sursa ncarcat, iar n fereastra de editare va aparea codul sursa existent n
acel fisier dupa un dublu click pe numele fisierului.

2.4 Compilarea si executarea unui proiect


Dupa ce codul sursa a fost creat n totalitate, proiectul trebuie sa fie compilat, creat
un executabil si apoi rulat.

Pentru compilarea proiectului se utilizeaza optiunea Compile (Ctrl+F7) din meniul


Build sau butonul dedicat din bara de meniu.

In cazul n care nu sunt erori se poate trece la crearea executabilului prin apelarea

optiunii Build Solution (F7) din meniul Build sau prin butonul dedicat din bara de
meniu.

Dupa compilarea si construirea cu succes a executabilului, n fereastra din partea in-


ferioara a interfetei mediului de programare denumita Output si destinata mesajelor vor
aparea 0 erori si 0 atentionari.
2.4. COMPILAREA S
I EXECUTAREA UNUI PROIECT 15

In final, programul ruleaza prin apelarea optiunii Start Debugging (F5) din meniul

Debug sau prin butonul dedicat din bara de meniu.


Capitolul 3

Structurarea aplicatiilor OpenGL

3.1 Initializarea ferestrei grafice


Prima etapa n generarea unei aplicatii OpenGL este intializarea unei ferestre grafice.
Acest lucru presupune specificarea proprietatilor ei, precum si alocarea bufferelor necesare.
Cele cinci rutine GLUT de initializare sunt:

glutInit(int *argc, char **argv) initializeaza GLUT si proceseaza orice argu-


ment introdus n linie de comanda. Aceasta rutina trebuie apelata naintea oricarei
alte rutine GLUT;
glutInitDisplayMode(unsigned int mode) specifica daca se utilizeaza modelul de
culoare RGBA sau un alt model specificat. De asemenea, se poate specifica utilizarea
unei ferestre cu buffer simplu sau dublu, precum si a unui buffer de adancime (de
exemplu, glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB) specifica o fereastra cu
buffer de remprospatare dublu cu model de culoare RGB);
glutInitWindowPosition(int x, int y) specifica pozitia n pixeli a coltului din
stanga-sus a ferestrei grafice;
glutInitWindowSize(int width, int size) specifica n pixeli latimea (width) si
naltimea (size) ferestrei grafice;
glutCreateWindow(char *string) specifica crearea unei fereastre grafice avand
bara de titlul definita prin intermediul unui sir de caractere (string).

Pentru a afisa o fereastra dupa ce aceasta a fost initializata, se utilizeaza rutinele GLUT
de afisare. Cea mai importanta dintre acestea o reprezinta rutina glutDisplayFunc(void
(*func)(void)). De oricate ori este necesara o reafisare a continutului ferestrei grafice,
aceasta rutina apeleaza o functie asociata, definita prin numele func.

Pentru executia rutinelor si comenzilor grafice se utilizeaza rutina glutMainLoop(void).


Toate comenzile grafice sunt acum executate si afisate. Rutina implica intrarea ntr-o
bucla de executie nentrerupta (infinita).

In exemplul 3.1 se prezinta modul de utilizare al rutinelor GLUT pentru generarea


unei ferestre grafice. Structura programului reprezinta un schelet tipic pentru realizarea
tuturor programelor n OpenGL cu ajutorul limbajului C. Comenzile de initializare ale

16
3.2. GESTIONAREA EVENIMENTELOR 17

scenei vor fi stocate n procedura init(), iar operatiile grafice sunt dispuse n procedura
display(), apelata cu ajutorul rutinei glutDisplayFunc.

Exemplul 3.1 Initializarea ferestrei grafice

#include <GL/glut.h>

void init (void){


// instructiuni de initializare a scenei
}

void display (void){


// instructiuni grafice
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow ("fereastra");
init ();
glutDisplayFunc (display);
glutMainLoop ();
return 0;
}

Programul este structurat n trei module. Primul dintre acestea, n ordinea importantei,
l reprezinta modulul principal main. In aceasta regiune se efectueaza initializarile obliga-
torii ale ferestrei grafice si se apeleaza celelalte proceduri din program. Celelalte doua
module, display si init, contin comenzile grafice OpenGL si, respectiv, atributele sce-
nei.

3.2 Gestionarea evenimentelor


Programele OpenGL pot fi structrate n functie de evenimentele care intervin n executia
aplicatiei, precum apasarea unei taste, rescalarea ferestrei sau starea de repaus. Toate
aceste evenimente sunt gestionate prin intermediul procedurilor specifice bibliotecii GLUT.
Structura generala a unui program OpenGL care permite gestionarea evenimentelor este
prezentata n exemplul 3.2.

Modul de operare al bibliotecii GLUT este bazat n ntregime pe gestionarea evenimen-


telor. Pentru fiecare eveniment n parte exista o procedura care permite apelarea unei
functii. La pornirea aplicatiei (intrarea n bucla continua) se apeleaza functia de redi-
mensionare (reshape) - daca aceasta exista. Daca ulterior se produce un eveniment care
18 CAPITOLUL 3. STRUCTURAREA APLICAT
IILOR OPENGL

are asociata n program o functie corespunzatoare, aceasta este apelata prin intermediul
procedurilor GLUT. In caz contrar se apeleaza functia asociata starii idle.

Exemplul 3.2 Structurarea gestionarii evenimentelor

#include <GL/glut.h>

void init (void){


// instructiuni de initializare a scenei
}

void display (void){


// instructiuni grafice
}

void reshape (int w, int h){


// instructiuni executate la redimensionarea ferestrei grafice
}

void idle (void){


// instructiuni executate in lipsa unor evenimente
}

void keyboard(unsigned char key, int x, int y){


// instructiuni executate la apasarea unei taste
}

void mouse (int button, int state, int x, int y){


// instructiuni executate la apasarea unei buton de mouse
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow ("fereastra");
init ();
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutIdleFunc (idle);
glutKeyboardFunc (keyboard);
glutMouseFunc (mouse);
glutMainLoop ();
return 0;
}
3.2. GESTIONAREA EVENIMENTELOR 19

Functia init() are rolul de a seta parametrii grafici ai scenei. In acest loc se definesc
de obicei matricele obiectelor geometrice, culorile utilizate s.a. La sfarsitul aceste functii
este de preferat ca toate specificatiile initiale ale scenei sa fie deja definite.

Functia display() are ca scop executarea tuturor instructiunilor necesare modelarii


scenei. Acest lucru presupune manipularea unui volum de date semnificativ, neparametri-
zat, ci prin intermediul unor variabile globale.

Functia reshape() permite executarea unor instructiuni n momentul n care fereastra


este redimensionata sau repozitionata. Functia are doi parametri de intrare, noile latimi
si naltimi ale ferestrei, si are ca rol principal modificarea parametrilor de proiectie si
vizualizare a scenei.

Functia idle() este apelata n situatiile n care nu are loc niciun alt eveniment,
executia acesteia fiind independenta de utilizator. Pentru afisarea modificarilor pro-
duse de instructiunile din functie, este necesara includerea la sfarsitul secventei de cod a
instructiunii glutPostRedisplay() care apeleaza automat functia display().

Functiile keyboard() si mouse() permit executia unor instructiuni la producerea unor


evenimente legate de dispozitivele de intrare (tastatura si mouse-ul). Cele doua functii au
ca parametri de intrare pozitia mouse-ului, precum si tipul si starea butonului apasat la
momentul producerii evenimentului. Ca si n cazul functiei idle(), este necesara apelarea
instructiunii glutPostRedisplay().

main()

init()

init()

glutDisplayFunc(display) glutPostRedisplay()

display() glutReshapeFunc(reshape)
reshape()

glutKeyboardFunc(keyboard)
Event? keyboard()
Yes

glutIdleFunc(idle) No
glutMouseFunc(mouse)
mouse()
idle()

Figura 3.1: Gestionarea evenimentelor prin intermediul bibliotecii GLUT


Capitolul 4

Definirea si afisarea obiectelor grafice

4.1 Parametrii initiali


Afisarea unor obiecte geometrice sau primitive grafice se face prin parcurgerea obliga-
torie a unor etape prestabilite, precum managementul ferestrei grafice, definirea culorilor
fundalului si a obiectului, a formei acestuia si executarea instructiunilor grafice pentru
transferul imaginii rezultate n bufferul grafic.

S
tergerea ferestrei grafice. Afisarea pe un monitor se face diferit fata de cazul unei
coli de hartie. Diferenta este realizata prin faptul ca hartia este deja alba sau avand o
anumita culoare prestabilita, n timp ce n cazul monitorului culoarea de fundal trebuie
specificata, iar eventualele artefacte deja existente trebuie eliminate prin stergerea buffe-
rului. Toate operatiile sunt efectuate n cadrul functiei de initializare init().

Pentru setarea culorii fundalului se utilizeaza instructiunea glClearColor() ai carei


parametri sunt cele trei culori primare (RGB) si parametrul de transparenta alpha (A).
Stergerea continutului de memorie asociat bufferului video se poate face cu ajutorul
instructiunii glClear() cu parametrul specific tipului bufferului sters de continut. De
exemplu, liniile de cod urmatoare permit setarea culorii de fundal a ferestrei n negru si
stergerea bufferului video de culoare.

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}

Parametrii posibili ai instructiunii glClear() sunt enumerati n tabelul urmator.

Parametru Denumire buffer

GL_COLOR_BUFFER_BIT Buffer de culoare

GL_DEPTH_BUFFER_BIT Buffer de ad
ancime

GL_ACCUM_BUFFER_BIT Buffer de acumulare

GL_STENCIL_BUFFER_BIT Buffer de sablon

20
4.1. PARAMETRII INIT
IALI 21

Pentru a putea sterge mai multe buffere, instructiunea glClear() se poate utiliza
repe-titiv prin modificarea parametrului

glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glClear(GL_ACCUM_BUFFER_BIT);

sau o singura data, prin enumerarea parametrilor.

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT);
In ultimul caz durata necesara efectuarii operatiilor de stergere este potential mai mica
decat n situatia enumerarii succesive.

Alegerea unei culori. Trasarea unui obiect grafic se efectueaza n OpenGL independent
de alegerea culorii asociate obiectului. Odata aleasa o anumita culoare, toate obiectele
care vor fi trasate ulterior vor avea culoarea respectiva, astfel ncat daca se doreste afisarea
unor obiecte n culori diferite, de fiecare data este necesara modificarea culorii curente.

Alegerea unei culori curente se face n cadrul functiei display() cu ajutorul instructiu-
nii glColor(). In functie de tipul argumentelor introduse, functia capata un sufix specific
(n cazul parametrilor de tip real, functia devine glColor3f()). Exemplul de mai jos
permite alegerea unei culori curente rosii.

void display (void){


glColor3f(1.0, 0.0, 0.0);
...
}

Parametrii de culoare specifici celor trei culori primare (RGB) iau valori reale cuprinse
ntre 0 (lipsa) si 1 (maxim). Astfel, cele opt culori elementare pot fi definite cu ajutorul
urmatoarelor opt variante de instructiuni.

glColor3f(0.0, 0.0, 0.0); negru


glColor3f(1.0, 0.0, 0.0); rosu
glColor3f(0.0, 1.0, 0.0); verde
glColor3f(0.0, 0.0, 1.0); albastru
glColor3f(0.0, 1.0, 1.0); cyan
glColor3f(1.0, 0.0, 1.0); magenta
glColor3f(1.0, 1.0, 0.0); galben
glColor3f(1.0, 1.0, 1.0); alb

De remarcat faptul ca n cazul instructiunii de stergere a bufferului existau patru para-


metrii, n timp ce n cazul instructiunii de alegere a culorii curente numarul parametri-lor
este doar de trei, lipsind transparenta (alpha).

Executia instructiunilor grafice. Datorita multitudinii de variante ale dispozitivelor


grafice hardware datorate specializarii fiecaruia din acestea, operatiile pot fi efectuate n
ordine diferita de catre procesorul grafic. Pentru a asigura executia instructiunilor din
cadrul unei aplicatii, n cadrul functiei display() se apeleaza instructiunile glFlush()
si glFinish().
22 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

void display (void){


...
glFlush();
glFinish();
}

Prima dintre ele asigura nceperea executiei instructiunilor precedente acesteia, n timp
ce a doua forteaza executia tuturor instructiunilor anterioare. Doar n cazul n care, pen-
tru o aplicatie data, simpla utilizare a lui glFlush() nu este suficienta, se recomanda
includerea lui glFinish().

Instructiunea glFlush() se utilizeaza doar n cazul alegerii n cadrul functiei principale


main() a unor buffere simple.

int main (int argc, char** argv){


...
glutInitDisplayMode(GLUT_SINGLE);
...
}
In situatia n care se utilizeaza buffere duble (mai ales n cazul animatiilor), n locul
lui glFlush() se foloseste instructiunea glutSwapBuffers().

int main (int argc, char** argv){


...
glutInitDisplayMode(GLUT_DOUBLE);
...
}

Dubla bufferare permite o executie mai rapida a instructiunilor grafice deoarece, n


timpul afisarii unui buffer curent, celalalt buffer este utilizat pentru realizarea n paralel a
cadrului urmator al secventei de imagini. Succesiunea de cadre se realizeaza prin schim-
barea alternativa a bufferelor curente afisate.

Sistemul de coordonate al ferestrei. Alegerea dimensiunilor si pozitiei ferestrei gra-


fice curente se face n cadrul functiei principale main(), prin intermediul procedurilor
glutInitWindowPosition() si glutInitWindowSize(). Punctul de referinta pentru
pozitionarea ferestrei este reprezentat de coltul din stanga jos ale carui coordonate n
pixeli este (0, 0). Dimensiunile ferestrei reprezinta numarul de pixeli de pe ecranul moni-
torului pe axa orizontala (latimea) si, respectiv, pe axa verticala (naltimea).

In interiorul ferestrei, initial sistemul de coordonate de vizualizare este centrat n punc-


tul de coordonate (0, 0, 0) si ia valori pe axele orizontale si verticale cuprinse ntre -1 si 1.
De remarcat faptul ca axa corespunzatoare adancimii nu este vizibila. In acest moment
singurele obiecte care pot fi vizualizate sunt obiectele din plan (2D).

In cazul modificarii dimensiunii sau pozitiei ferestrei se utilizeaza un set de instructiuni


situate n interiorul functiei reshape(), instructiuni care vor fi prezentate n capitolul
dedicat proiectiilor si transformarilor (5).
4.2. PUNCTE, LINII S
I POLIGOANE 23

4.2 Puncte, linii si poligoane


Cele mai simple primitive geometrice sunt reprezentate de catre puncte, linii si poligoa-
ne. Acestea pot fi trasate fie n plan (2D), fie n spatiu (3D), n functie de coordonatele
definite.

Punctele reprezinta numere reale, denumite si vertex-uri, definite fie n plan, prin spe-
cificarea coordonatelor x si y, fie n spatiu, prin specificarea celor trei coordonate x, y si
z. In cazul coordonatelor omogene poate exista o a patra coordonata, notata w. Daca w
este nenul, coordonatele punctului n spatiul tridimensional sunt (x/w, y/w, z/w).

In OpenGL un punct (sau vertex) este specificat cu ajutorul instructiunii glVertex().


In functie de numarul de coordonate si de tipul de date, functia capata sufixe, dupa cum
urmeaza.
glVertex[234][sifd][v](x,y,[z],[w]);
Sufixul [234] reprezinta numarul de coordonate utilizate pentru definirea punctului,
iar [sifd] defineste tipul datelor utilizate. In cazul n care se utilizeaza vectori de coordo-
nate predefiniti, apare si sufixul [v]. In exemplele urmatoare se prezinta diferite moduri
de definire a unor puncte.
glVertex2s(2, 1);

glVertex3d(0.2, 1.2, 3.1415926535898);

glVertex4f(2.3, 1.1, -3.0, 2.0);

GLdouble dvect[3] = (5.2, 9.2, 24.0);


glVertex3dv(dvect);
Liniile (sau segmentele de dreapta) sunt specificate n OpenGL prin intermediul puncte-
lor de nceput si sfarsit ale acestora, avand dimensiune finita. Poligoanele sunt definite
ca regiuni nchise, avand o singura bucla formata din segmente de dreapta, definite prin
intermediul unor puncte.

Specificarea coordonatelor unor puncte cu ajutorul instructiunii glVertex() serveste


la definirea diferitelor obiecte grafice, n cadrul unei structuri, avand forma urmatoare.
glBegin(...);
glVertex(...);
...
glVertex(...);
glEnd();
Instructiunea glBegin() are ca argument tipul de obiect grafic ales, variantele posibile
fiind specificate n tabelul de mai jos. Numarul de puncte incluse n interiorul structurii
este dat de tipul de obiect grafic ales. De exemplu, pentru definirea unui triunghi sunt
necesare trei puncte, iar pentru definirea unui poligon, numarul acestora poate fi de minim
trei. In tabelul urmator se prezinta tipurile de primitive grafice definite cu ajutorul unei
structuri glBegin().
24 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

Parametru Denumire obiect grafic

GL_POINTS punct

GL_LINES segment de dreapta

GL_LINE_STRIP segmente de dreapta interconectate

GL_LINE_LOOP idem, cu contur nchis

GL_TRIANGLES triunghi

GL_TRIANGLE_STRIP triunghiuri interconectate

GL_TRIANGLE_FAN suprafete triunghiulare

GL_QUADS patrulater

GL_QUAD_STRIP patrulatere interconectate

GL_POLYGON poligon

Instructiunile specifice primitivelor grafice sunt incluse de obicei n cadrul functiei


display(), avand grija ca n prelabil sa fie specificata culoarea curenta.

Exemplul urmator permite definirea unui segment de dreapta situat ntre doua puncte
din spatiul de coordonate (2, 3, 1) si (1, 1, 3), avand culoarea rosie.

void display (void){


...
glColor3f(1.0, 0.0, 0.0); // culoare rosie
glBegin(GL_LINES); // segment de dreapta
glVertex3f(2.0, 3.0, 1.0); // punct de inceput
glVertex3f(1.0, 1.0, 3.0); // punct de sfarsit
glEnd();
...
}

De asemenea, fiecare nod din cadrul unei primitive grafice poate avea propria culoare,
caz n care instructiunea glColor() se repreta n interiorul structurii glBegin() pentru
fiecare modificare de culoare n parte.

void display (void){


...
glBegin(GL_TRIANGLES); // triunghi
glColor3f (1.0, 0.0, 0.0); // culoare rosie
glVertex3f (0.2, 0.25, 0.0); // varful 1
glColor3f (0.0, 1.0, 0.0); // culoare verde
glVertex3f (0.8, 0.25, 0.0); // varful 2
glColor3f (0.0, 0.0, 1.0); // culoare albastra
glVertex3f (0.5, 0.8, 0.0); // varful 3
glEnd();
...
}
4.2. PUNCTE, LINII S
I POLIGOANE 25

1 4 3 1 3 2
0 5 1
4
5 3
0
2 3 5 0
2 0 6 4
1 2
4
GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP

3 3 5
1 2 5 6
0 1
7
2
0 4 3 1 0 6
4 7 2
4
GL_POLYGON GL_QUADS GL_QUAD_STRIP

4 6 1
0 2 3 5 3 4
2
5
1
3 7 0 5
1 2 0
8 4
GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN

Figura 4.1: Primitive grafice n OpenGL

In exemplul 4.1 se prezinta secventa completa de instructiuni a unei aplicatii care per-
mite afisarea unui patrat umplut alb pe fundal negru.

Exemplul 4.1 Patrat alb pe fond negru

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(0.5, 0.5, 0.0);
glVertex3f(0.5, -0.5, 0.0);
glVertex3f(-0.5, -0.5, 0.0);
glVertex3f(-0.5, 0.5, 0.0);
glEnd();
glFlush();
}
26 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow ("patrat");
init ();
glutDisplayFunc (display);
glutMainLoop ();
return 0;
}

De remarcat faptul ca, n afara de functiile init() si display(), nu exista alte functii
de gestionare a evenimentelor, astfel ncat la redimensionarea sau repozitionarea ferestrei,
imaginea rezultata nu va fi ajustata. Pentru a elimina acest lucru fara a face apel la o
functie reshape(), instructiunea glClearColor() poate fi introdusa n cadrul functiei
display(), nsa aspectul imaginii nu poate fi controlat, imaginea fiind redimensionata la
scara n functie de noua forma a ferestrei grafice.

void display (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
...
}
In figura 4.1 sunt prezentate aspectele primitivelor grafice realizabile prin intermediul
structurii glBegin(). Indexul punctelor dintr-un obiect reprezinta ordinea enumerarii
acestora n interiorul structurii.

4.3 Tipare
In mod implicit, primitivele grafice de tipul punctelor sau al liniilor sunt trasate pe
ecran cu latimea de 1 pixel, iar poligoanele sunt umplute. Acesti parametri pot fi nsa
modificati, dupa cum urmeaza.

Puncte. Controlul dimensiunii unui punct poate fi facut prin intermediul instructiunii
glPointSize() al carui argument reprezinta dimensiunea n pixeli, pozitiva si nenula.
Instructiunea trebuie inclusa naintea unei primitive grafice.

In exemplul urmator se prezinta modul de setare a dimensiunii punctelor pentru o


primitiva grafica de tip GL_POINTS.

glPointSize(4);
glBegin(GL_POINTS);
...
glEnd();

Linii. In cazul segmentelor de dreapta (linii) se poate controla atat grosimea, cat si ti-
parul liniei curente. Setarea grosimii liniei se face cu ajutorul instructiunii glLineWidth()
4.3. TIPARE 27

avand ca argument grosimea n numar de pixeli pozitiv si nenul, implicit fiind 1. Setarea
tiparului unei linii se face prin intermediul instructiunii glLineStipple(), avand ca ar-
gumente un factor de alungire (valori ntregi cuprinse ntre 1 si 255) si un tipar descris
sub forma unui numar binar pe 16 biti exprimat sub forma hexazecimala. Activarea sau
dezactivarea proprietatii de tipar unei linii se face prin instructiunile glEnable() sau
glDisable() avand ca parametru GL_LINE_STIPPLE.

In exemplul urmator se prezinta instructiunile necesare trasarii unei linii cu grosimea


de 3 pixeli, avand tiparul binar 0xF0F (0000111100001111) si factor de scala 2.
glLineWidth(3);
glEnable(GL_LINE_STIPPLE);
glLineStipple(2, 0xF0F);
glBegin(GL_LINES);
glVertex3f(0.0, -0.9, 0.0);
glVertex3f(0.0, 0.9, 0.0);
glEnd();
glDisable(GL_LINE_STIPPLE);
Poligoane. Poligoanele sunt trasate implicit ca arii nchise si umplute cu culoare (po-
ligoane solide). Este posibila nsa umplerea acestora cu diferite tipare sau chiar trasarea
lor fara umplere (wireframe). In plus, deoarece suprafetele poligonale dispun de doua
fatete (interioara si exterioara), acestea pot fi controlate independent.

Prin conventie, poligoanele ale caror noduri sunt enumerate n sens invers orar au
fateta exterioara ndreptata catre ecran (reprezinta fateta vizibila). In mod implicit,
ambele fatete ale unei suprafete sunt umplute, dar acest lucru poate fi modificat prin
intermediul instructiunii glPolygonMode(). Cele doua argumente specifica fateta modifi-
cata (GL_FRONT, GL_BACK sau GL_FRONT_AND_BACK) si, respectiv, umplerea (GL_FILL) sau
golirea (GL_LINE) acesteia. Variante de combinatii sunt prezentate n cele ce urmeaza.
glPolygonMode(GL_FRONT, GL_FILL);

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
In cazul n care se doreste schimbarea tipului de fateta rezultat implicit la definirea n
sens invers orar a punctelor unui poligon, se poate utiliza instructiunea glFrontFace(),
care permite setarea fatetei exterioare la enumerarea nodurilor n sens orar (GL_CW) sau
n sens invers orar (GL_CCW).
glFrontFace(GL_CW);

glFrontFace(GL_CCW);
In exemplul 4.2 se prezinta o aplicatie care permite trasarea a patru patrare definite
prin enumerarea nodurilor n sens orar (1 si 3) sau n sens invers orar (2 si 4). Fatetele
exterioare sunt umplute, iar cele interioare sunt goale.

In unele aplicatii este utila eliminarea fatetelor interioare sau chiar a celor exterioare,
deoarece acestea sunt invizibile, lucru posibil cu ajutorul instructiunii glCullFace(),
unde argumentul reprezinta fatetele eliminate.
28 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

Exemplul 4.2 Patrate cu fatete interioare umplute si fatete exterioare goale

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT, GL_FILL); // fateta exterioara umpluta
glPolygonMode(GL_BACK, GL_LINE); // fateta interioara goala
glFrontFace(GL_CW); // sens orar = fateta interioara
glBegin(GL_POLYGON); // poligonul 1, sens orar
glVertex3f(0.8, -0.8, 0.0);
glVertex3f(0.2, -0.8, 0.0);
glVertex3f(0.2, -0.2, 0.0);
glVertex3f(0.8, -0.2, 0.0);
glEnd();
glBegin(GL_POLYGON); // poligonul 2, sens invers orar
glVertex3f(0.2, 0.2, 0.0);
glVertex3f(0.8, 0.2, 0.0);
glVertex3f(0.8, 0.8, 0.0);
glVertex3f(0.2, 0.8, 0.0);
glEnd();
glFrontFace(GL_CCW); // sens orar = fateta exterioara
glBegin(GL_POLYGON); // poligonul 3, sens orar
glVertex3f(-0.2, -0.8, 0.0);
glVertex3f(-0.8, -0.8, 0.0);
glVertex3f(-0.8, -0.2, 0.0);
glVertex3f(-0.2, -0.2, 0.0);
glEnd();
glBegin(GL_POLYGON); // poligonul 4, sens invers orar
glVertex3f(-0.2, 0.8, 0.0);
glVertex3f(-0.8, 0.8, 0.0);
glVertex3f(-0.8, 0.2, 0.0);
glVertex3f(-0.2, 0.2, 0.0);
glEnd();
glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow ("fatete");
init ();
4.3. TIPARE 29

y
(-1, 1) (1, 1)

4 2

3 1

(-1, -1) (1, -1)

Figura 4.2: Definirea fatetelor n cadrul exemplului 4.2

glutDisplayFunc (display);
glutMainLoop ();
return 0;
}

Activarea sau dezactivarea eliminarii unor fatete cu glCullFace() se face prin inter-
mediul instructiunii glEnable() sau glDisable() cu argumentul GL_CULL_FACE. Pen-
tru instructiunea glCullFace() se poate folosi ca argument GL_FRONT, GL_BACK sau
GL_FRONT_AND_BACK.

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
...
glDisable(GL_CULL_FACE);

Umplerea unui poligon cu un anumit tipar se poate face cu ajutorul instructiunii


glPolygonStipple() al carui argument reprezinta un tipar binar de dimensiune 32 32
exprimat sub forma unei matrice de numere hexazecimale. Activarea sau dezactivarea
tiparului se face prin intermediul instructiunilor glEnable() sau glDisable() avand ca
argument GL_POLYGON_STIPPLE.

Exemplul urmator prezinta operatiile necesare pentru umplerea unui patrat cu un


tipar de forma unei table de sah. De retinut faptul ca variabilele trebuie definite chiar la
nceputul functiei display(). Rescalarea ferestrei grafice nu modifica structura tiparului.

void display (void){


GLubyte tipar[] = {
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
30 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,


0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
};
...
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(tipar);
glBegin(GL_POLYGON);
glVertex3f(0.5, 0.5, 0.0);
glVertex3f(0.5, -0.5, 0.0);
glVertex3f(-0.5, -0.5, 0.0);
glVertex3f(-0.5, 0.5, 0.0);
glEnd();
glDisable(GL_LINE_STIPPLE);
...
}

4.4 Vectorul normal


a
Un vector normala este definit ca un vector a carui directie este perpendiculara pe o
suprafata data. In cazul unei suprafete plane directia normalei este aceeasi n orice punct
al suprafetei, dar pentru o suprafata curba directia normalei difera.

In OpenGL se poate specifica o normala pentru fiecare poligon sau vertex. Vertex-
urile aceluiasi poligon pot avea aceeasi normala (n cazul suprafetelor plane) sau pot fi
diferite (n cazul suprafetelor curbe). Vectorii normala pot fi calculati n OpenGL doar
pentru noduri si servesc n principal la determinarea cantitatii de lumina receptionate de
suprafata n nodul respectiv.

Instructiunea care permite calculul unui vector normala este glNormal3(), avand ca
argumente coordonatele tridimensionale ale vertexului respectiv.

glNormal3f(0.0, 0.0, 0.0);


glVertex3f(1.0, 3.0, 2.2);
In exemplul de mai sus se determina vectorul normala din punctul de coordonate
(0.0, 0.0, 0.0) si asociat nodul de coordonate (1.0, 3.0, 2.2).
4.5. MATRICE DE DATE 31

4.5 Matrice de date


In cazul n care unele suprafete poligonale contin un numar mare de noduri, definirea
acestuia cu ajutorul structurii glbegin() presupune existenta unui numar de instructiuni
glVertex() egal cu numarul de noduri. Pentru a evita aceasta situatie se prefera intro-
ducerea coordonatelor nodurilor cu ajutorul unor matrice de date.

Dispunerea datelor n matrice de noduri permite cresterea performantei unei aplicatii


prin reducerea numarului de instructiuni efectuate si prin scaderea redundantei procesarii
nodurilor. Pentru a defini complet un obiect geometric cu ajutorul matricelor de date
este necesara parcurgerea a trei etape esentiale:
1. activarea unui numar de sase matrice, fiecare avand stocate diferite tipuri de date:
cordonatele nodurilor, indicii de culoare, normalele la suprafata, coordonatele texturii
sau etichetele laturilor poligonale;
2. specificarea datelor din matrice;
3. trasarea grafica a obiectului cu ajutorul matricelor de date, prin accesarea indivi-
duala a elementelor matricelor, prin crearea unei liste cu elementele matricelor sau
prin procesarea secventiala a elementelor matricelor.

1. Activarea matricelor. Primul pas n definirea matricelor de date este activarea aces-
tora cu ajutorul instructiunii glEnableClientState(), avand ca argument una din cele
sase matrice posibile. Variantele posibile sunt matricele de puncte (GL_VERTEX_ARRAY), de
culoare (GL_COLOR_ARRAY), indexurile de culoare (GL_INDEX_ARRAY), matricele normale-
lor (GL_NORMAL_ARRAY), a texturilor (GL_TEXTURE_COORD_ARRAY) si a etichetelor laturilor
poligonale (GL_EDGE_FLAG_ARRAY).

In practica este putin probabil sa fie activate toate cele sase matrice. De exemplu, n
cazul utilizarii n scena a unor surse de lumina, se utilizeaza matricele de puncte si de
normale.

glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

Daca este necesara dezactivarea uneia dintre matrice, se poate utiliza instructiunea
glDisableClientState(), cu acelasi argument ca si n cazul instructiunii de activare.

2. Specificarea datelor. Pentru a preciza datele matriceale se utilizeaza sase instruc-


tiuni diferite, cate una pentru fiecare tip de data.

glVertexPointer(size, type, stride, *pointer);


glColorPointer(size, type, stride, *pointer);
glIndexPointer(size, type, stride, *pointer);
glNormalPointer(type, stride, *pointer);
glTexCoordPointer(size, type, stride, *pointer);
glEdgeFlagPointer(stride, *pointer);

Diferentele principale dintre cele sase instructiuni constau n modul de specificare al


tipului si dimensiunii datelor. Argumentul size precizeaza dimensiunea datelor, type
32 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

specifica tipul datelor, stride reprezinta offsetul n bytes dintre doua date consecutive,
iar *pointer determina adresa de memorie a primei date din matrice.

Instructiune Argumentul size Argumentul type

glVertexPointer 2, 3, 4 GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glNormalPointer 3 GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glColorPointer 3, 4 GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,

GL_UNSIGNED_SHORT, GL_INT,

GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE

glIndexPointer 1 GL_UNSIGNED_BYTE, GL_SHORT, GL_INT,

GL_FLOAT, GL_DOUBLE

glTexCoordPointer 1, 2, 3, 4 GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glEdgeFlagPointer 1 GLboolean

In exemplul urmator se prezinta modul de definire si accesare al unui obiect grafic


definit printr-o matrice de noduri si o matrice de culori. Coordonatele nodurilor sunt
definite n plan, fiind exprimate sub forma unor perechi de numere ntregi n variabila
vertices. Culorile asociate fiecarui nod sunt definite n variabila colors sub forma unor
triade.

static GLfloat vertices[] = {0.25, 0.25, // (x0, y0)


0.10, 0.32, // (x1, y1)
0.17, 0.25, // (x2, y2)
0.17, 0.32, // (x3, y3)
0.25, 0.25, // (x4, y4)
0.32, 0.32}; // (x5, y5)

static GLfloat colors[] = {1.0, 0.2, 0.2, // (r0, g0, b0)


0.2, 0.2, 1.0, // (r1, g1, b1)
0.8, 1.0, 0.2, // (r2, g2, b2)
0.7, 0.7, 0.7, // (r3, g3, b3)
0.3, 0.3, 0.3, // (r4, g4, b4)
0.5, 0.5, 0.5}; // (r5, g5, b5)

glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_FLOAT, 0, colors);


glVertexPointer(2, GL_FLOAT, 0, vertices);

Argumentul stride are rolul de a defini pasul cu care sunt citite datele dintr-un vec-
tor. Acest lucru este util atunci cand toate datele (noduri, culori, normale etc.) sunt
compactate ntr-un singur vector de date.
4.5. MATRICE DE DATE 33

De exemplu, fiind definit vectorul alldata, care contine o enumerare alternanta de


culori si puncte, accesarea datelor se poate face dupa cum urmeaza.
static GLfloat alldata[] = {
1.0, 0.2, 0.2, 100.0, 100.0, 0.0, // (r0, g0, b0, x0, y0, z0)
0.2, 0.2, 1.0, 0.0, 200.0, 0.0, // (r1, g1, b1, x1, y1, z1)
0.8, 1.0, 0.2, 100.0, 300.0, 0.0, // (r2, g2, b2, x2, y2, z2)
0.2, 1.0, 0.2, 200.0, 300.0, 0.0, // (r3, g3, b3, x3, y3, z3)
0.2, 1.0, 1.0, 300.0, 200.0, 0.0, // (r4, g4, b4, x4, y4, z4)
0.2, 0.1, 1.0, 200.0, 100.0, 0.0}; // (r5, g5, b5, x5, y5, z5)

glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_FLOAT, 6*sizeof(GLfloat), alldata);


glVertexPointer(3, GL_FLOAT, 6*sizeof(GLfloat), &alldata[3]);
De retinut ca indexarea vectorilor se face n limbajul C ncepand cu 0. In plus, deoarece
adresarea variabilelor se face prin intermediul pointerilor, adresele de memorie trebuie sa
ramana nemodificate pe parcursul aplicatiei. In acest scop, variabilele se definesc static.

3. Trasarea obiectelor. Datele pot fi extrase n trei moduri posibile: element cu


element, n secvente de date sau n liste.

a. Accesarea individuala se poate face cu ajutorul instructiunii glArrayElement()


avand ca argument indexul (pozitia) nodului n vectorul de date. Aceasta instructiune
este apelata de obicei n cadrul unei structuri glBegin()/glEnd().

De exemplu, utilizand datele din vectorii colors si vertices din exemplul anterior,
se poate trasa un triunghi cu elementele de la pozitiile 3, 5 si 6 ale vectorilor.
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(2, GL_INT, 0, vertices);
glBegin(GL_TRIANGLES);
glArrayElement(2);
glArrayElement(3);
glArrayElement(5);
glEnd();
Ultimele cinci linii de cod au acelasi efect ca si urmatoarea lista de instructiuni.
glBegin(GL_TRIANGLES);
glColor3fv(colors+(2*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(2*3*sizeof*(GL_INT));
glColor3fv(colors+(3*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(3*3*sizeof*(GL_INT));
glColor3fv(colors+(5*3*sizeof*(GL_FLOAT));
glVertex3fv(vertices+(5*3*sizeof*(GL_INT));
glEnd();
34 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

Deoarece instructiunea glArrayElement() este unica pentru un singur punct, utiliza-


rea acesteia este mai avantajoasa din punctul de vedere al vitezei de executie. Trebuie
avut nsa grija ca n cadrul structurii glBegin() datele sa nu fie modificate dinamic pe
parcursul executiei aplicatiei.

b. Accesarea n lista se poate face cu ajutorul instructiunii glDrawElements(), avand


sintaxa:

gldrawElements(mode, count, type, *indices);

Argumentul mode reprezinta modul de definire al datelor (acelasi ca si argumentul


utilizat n cadrul instructiunii glBegin()), count este numarul de elemente ale caror
indexuri sunt precizate n argumentul indices, iar type specifica tipul de date utilizate
(GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT sau GL_UNSIGNED_INT).

static GLubyte frontIndices = {4, 5, 6, 7};


static GLubyte rightIndices = {1, 2, 6, 5};
static GLubyte bottomIndices = {0, 1, 5, 4};
static GLubyte backIndices = {0, 3, 2, 1};
static GLubyte leftIndices = {0, 4, 7, 3};
static GLubyte topIndices = {2, 3, 7, 6};
...
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_INT, 0, vertices);
...
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, frontIndices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, rightIndices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, bottomIndices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, backIndices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, leftIndices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, topIndices);

Indicii pot fi concatenati si ntr-o singura variabila, ca n exemplul urmator.

static GLubyte allIndices [] = {4, 5, 6, 7, 1, 2, 6, 5,


0, 1, 5, 4, 0, 3, 2, 1,
0, 4, 7, 3, 2, 3, 7, 6};
...
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_INT, 0, vertices);
...
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, allIndices);

c. Accesarea secventiala se poate face cu ajutorul instructiunii glDrawArrays(), avand


sintaxa:

glDrawArrays(mode, first, count);


4.5. MATRICE DE DATE 35

3 2

7 6

0 1

4 5

Figura 4.3: Indexarea nodurilor fatetelor unui cub

Instructiunea permite construirea unei secvente de primitive geometrice utilizand ele-


mentele matricelor de date, ncepand de la elementul cu indexul first si pana la indexul
first+count-1. Argumentul mode este definit identic ca si n cazul glDrawElements().

Exemplul 4.3 permite definirea unui model de forma unei case, alcatuit din doua obiecte
poligonale avand culori diferite ale nodurilor.

Exemplul 4.3 Casa RGB

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);

// vector de date
static GLfloat allData[] = {
0.8, 0.8, 0.8, -0.5, 0.2, // 4x vertexuri corp casa
0.8, 0.8, 0.8, -0.5, -0.6,
0.8, 0.8, 0.8, 0.5, -0.6,
0.8, 0.8, 0.8, 0.5, 0.2,
1.0, 0.0, 0.0, -0.8, 0.2, // 3x vertexuri acoperis
0.0, 1.0, 0.0, 0.8, 0.2,
0.0, 0.0, 1.0, 0.0, 0.7
};
// vector de indici de ordine a utilizarii datelor
static GLubyte allIndices[] = {4, 5, 6, 0, 1, 2, 3};

glClear(GL_COLOR_BUFFER_BIT);
36 CAPITOLUL 4. DEFINIREA SI AFISAREA OBIECTELOR GRAFICE

// activare utilizare matrice de vertexuri si de culori


glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

// specificare mod citire culori


glColorPointer(3, GL_FLOAT, 5*sizeof(GLfloat), allData);

// specificare mod citire vertexuri


glVertexPointer(2, GL_FLOAT, 5*sizeof(GLfloat), &allData[3]);

// desenare acoperis
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, allIndices);

// desenare corp casa


glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &allIndices[3]);

glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Cub RGB");
init ();
glutDisplayFunc (display);
glutMainLoop ();
return 0;
}
Capitolul 5

Proiectii si transform
ari

5.1 Proiectii
Spatiul 3D al lumii reale poate fi privit ca un spatiul traditional definit ntr-un sistem
de coordonate carteziene XY Z, avand axele X si Y dispuse normal, iar axa Z a adancimii
este negativa n directia de privire a observatorului (figura 5.1). Aceasta orientare a axelor
este specifica modelarii n grafica computerizata, deoarece planul imaginii proiectate este
reprezentat de planul XY , iar proiectia se face de-a lungul axei de adancime Z.

y
Vector de orientare

Coordonatele Direcie de vizualizare


punctului
de vizualizare -z

Sistemul de coordonate
x al lumii reale

Figura 5.1: Definirea parametrilor de vizualizare n OpenGL

Ca model fizic, procesul de vizualizare poate fi definit n termenii privirii printr-un


cadru rectangular dispus n fata observatorului. Acesta se poate deplasa n spatiul lumii
reale si se poate seta pozitia si orientarea punctului de observare. Orientarea si forma
cadrului determina n final factorul de forma al imaginii.

Definirea punctului de vizualizare. In procesul de definire al scenei, fiecare obiect


este modelat n propriul sau sistem de coordonate, dupa care este plasat n scena respec-
tiva utilizand transformari de coordonate. Spatiul lumii reale (al scenei) este, n final,
transformat cu ajutorul unor transformari de vizualizare, prin pozitionarea punctului
de vizualizare n scena. In interiorul spatiului lumii reale trebuie definite patru puncte
esentiale:

37
38 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

pozitia (coordonatele) punctului de vizualizare;


directia de observatie a punctului de vizualizare;
vectorul directiei verticale a punctului de vizualizare;
dimensiunile campului vizual.

Primii trei parametri de vizualizare se definesc cu ajutorul instructiunii gluLookAt(),


avand urmatoarea sintaxa:

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

Toate argumentele sunt de tip GLdouble si exprima urmatoarele: eyex, eyey si eyez
reprezinta coordonatele punctului de vizualizare, centerx, centery si centerz sunt coor-
donatele varfului vectorului directiei de vizualizare, iar upx, upy si upz sunt coordonatele
varfului vectorului directiei verticale.

y
(upx, upy, upz)

(centerx, centery, centerz)

(eyex, eyey, eyez) -z

Figura 5.2: Exemplu de pozitionare a punctului de vizualizare n OpenGL

In cazul n care instructiunea gluLookAt() nu este apelata, punctul de vizualizare


este dispus n originea sistemului de coordonate al lumii reale, directia de vizualizare este
orientata de-a lungul axei Z negative, iar vectorul directiei verticale este orientat de-a
lungul axei Y pozitive. Acest lucru este echivalent cu instructiunea de mai jos.

gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);

Pentru a putea utiliza pozitionarea punctului de vizualizare se activeaza matricea spe-


cifica GL_MODELVIEW cu ajutorul instructiunii glMatrixMode(), dupa care matricea trans-
formarilor este resetata prin ncarcarea matricei identitate.

Orice transformare sau proiectie este efectuata prin intermediul unei matrice caracte-
ristice de transformare, activata prin intermediul instructiunii glMatrixMode(). Prin in-
termediul argumentului instructiunii glMatrixMode() se specifica tipul matricei utilizate
la momentul respectiv, care poate fi: matricea de vizualizare (GL_MODELVIEW), matricea
de proiectie (GL_PROJECTION) sau matricea texturilor (GL_TEXTURE).
5.1. PROIECT
II 39

Matricea de vizualizare are dimensiunea 4 4 si poate incorpora simultan mai multe


transformari individuale. Deoarece anterior nu au fost aplicate alte transformari de vizu-
alizare, dupa ncarcarea matricei, aceasta este initializata cu matricea identitate, care nu
produce nicio modificare.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);

Definirea tipului proiectiei. Transformarile de vizualizare permit definirea n spatiu


a punctului de vizualizare, dar acest spatiu nu poate fi observat pe dispozitivele stan-
dard de afilasare. In acest scop, spatiul 3D este proiectat ntr-un spatiu 2D, care are
corespondenta cu dispozitivul de afisare utilizat, precum ecranul monitorului.

In OpenGL sunt implementate doua tipuri de proiectii: ortografica si perspectiva.


Proiectia ortografica permite pastrarea caracteristicilor de paralelism pe fiecare din axele
sistemului de coordonate al lumii reale. Obiectele care au aceiasi dimensiune dar care
sunt situate la pozitii diferite n spatiu 3D sunt proiectate identic, avand aceeasi dimen-
siune n spatiul 2D. Proiectia perspectiva se apropie mai mult de sistemul vizual uman,
liniile paralele din spatiul 3D fiind convergente la infint (sau la linia de orizont) n spatiul
2D. Ca urmare, obiectele identice ca dimensiune, situate la departare fata de punctul de
vizualizare, au un aspect redus n raport cu cele situate n apropiere.

A. Proiectia ortografica este specificata prin intermediul unui volum de vizualizare


de forma paralelipipedica si poate fi implementata cu ajutorul instructiunii glOrtho(),
avand urmatoarea sintaxa:
glOrtho(left, right, bottom, top, near, far);
Argumentele definesc limitele volumului de vizualizare si sunt de tip GLdouble. Ca si
n cazul definirii punctului de vizualizare, trebuie initializata o matrice de transformare
care, de aceasta data, este matricea de proiectie (GL_PROJECTION).

top
left

right

bottom

near far

Figura 5.3: Definirea volumului de vizualizare pentru proiectia ortografica n OpenGL

Secventa de cod urmatoare permite definirea unei proiectii ortografice al carei volum
de vizualizare este un paralelipiped cu dimensiunea 6 6 4.
40 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-3.0, 3.0, -3.0, 3.0, 1.5, 5.5);
In cazul particular al coordonatelor 2D, se poate utiliza instructiunea glOrtho2D()
pastrand doar primele patru argumente ale instructiunii glOrtho(), valorile parametrilor
near si far fiind luati implicit -1.0 si 1.0.

B. Proiectia perspectiva este specificata prin intermediul unui volum de vizualizare de


forma unui trunchi de piramida cu baza dreptunghiulara, avand varful piramidei situat
n punctul de vizualizare.

Instructiunea gluPerspective() permite aplicarea n OpenGL a proiectiei perspective


si are sintaxa urmatoare:

gluPerspective(fovy, aspect, near, far);

Argumentele sunt de tip GLdouble si definesc unghiul de deschidere pe verticala al


piramidei (fovy), factorul de forma al bazei conului (aspect) si limitele de adancime (near
si far) pe axa Z. Factorul de forma reprezinta raportul dintre latimea w si naltimea h
a ferestrei grafice. Se utilizeaza aceeasi matrice de transformare ca si n cazul precedent
(GL_PROJECTION).

aspect

w
fovy

near

far

Figura 5.4: Definirea volumului de vizualizare pentru proiectia perspectiva n OpenGL cu instructiunea
gluPerspective()

In exemplul de mai jos se prezinta instructiunile necesare pentru aplicarea unei proiectii
perspective al carei volum de vizualizare este definit printr-un unghi de deschidere pe
verticala de 60 , un factor de forma de 800/600 si coordonatele de adancime 4.0 si 12.0.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 800/600, 4.0, 12.0);

O alta modalitate de aplicare a proiectiei perspectiva este utilizarea instructiunii


glFrustum() care, spre deosebire de cazul precedent, permite definirea unui volum de
vizualizare nesimetric.
5.1. PROIECT
II 41

left
top

bottom
right
near

far

Figura 5.5: Definirea volumului de vizualizare pentru proiectia perspectiva n OpenGL cu instructiunea
glFrustum()

glFrustum(left, right, bottom, top, near, far);


Parametrii reprezinta coordonatele bazei mici a trunchiului de piramida (left, right,
bottom, top), precum si coordonatele de adancime (near si far).

Astfel, secventa de cod precedenta poate fi reformulata cu ajutorul lui glFrustum()


dupa cum urmeaza:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-4.0, 4.0, -3.0, 3.0, 5.2, 12.0);
Definirea regiunilor de vizualizare. Fereastra grafica este definita initial n functia
initiala main() cu ajutorul instructiunii glutInitWindowSize(). Pe parcursul derularii
aplicatiilor, insa, fereastra poate fi redimensionata, fapt care determina (n lipsa unor
corectii) deformarea imaginii rezultate. Pentru a compensa acest lucru se utilizeaza
instructiunea glViewport() care permite definirea regiunii din fereastra grafica n care
se proiecteaza cadrul de vizualizare. Instructiunea mai este utila si n cazul n care se
doreste afisarea unor scene n mai multe regiuni ale ferestrei grafice.
glViewport(x, y, width, height);
Argumentele x si y sunt de tip GLint si permit definirea coltului stanga-jos al regiunii,
iar argumentele width si height, de tip GLsizei, determina latimea si, respectiv, naltimea
regiunii din fereastra grafica.

Pentru a compensa deformarea datorata redimensionarii ferestrei, este necesara in-


cluderea instructiunii glViewport() n cadrul functiei reshape(). Noile dimensiuni ale
ferestrei grafice sunt transmise automat din main() de catre rutina glutReshapeFunc().
void reshape (int w, int h){
...
glViewport(0, 0, w, h)
...
}
42 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Nedistorsionat Distorsionat

Figura 5.6: Proiectia cadrului de vizualizare n fereastra grafica

In cazul n care se doreste afisarea n regiuni diferite ale ferestrei grafice, valorile lui
width si height vor fi, de asemenea, diferite.

In cadrul unei aplicatii este necesar a fi definiti parametrii de vizualizare, modul de


proiectie, precum si dimensiunea ferestrei vizibile. Rezulta, astfel, o suita de linii de cod
avand structura urmatoare:
glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, w/h, 4.0, 10.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(10.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

Modul full screen. Pentru a intra n modul full screen se poate utiliza instructiunea
glutFullScreen().
glutFullScreen();
Pentru a iesi din modul full screen se utilizeaza instructiunile glutReshapeWindow()
si glutPositionWindow().
glutReshapeWindow(width, height);
glutPositionWindow(x, y);
Amble seturi de instructiuni se introduc, n cazul intrarii sau iesirii automate n modul
full screen, n cadrul functiei display() sau idle() iar, n cazul comenzii cu ajutorul
mouse-ului sau a tastaturii, n functiile mouse() sau keyboard().
5.1. PROIECT
II 43

In exemplul 5.1 se prezinta o aplicatie care permite desenarea scheletului unei case
schematizate, afisate n proiectie perspectiva.

Exemplul 5.1 Vedere n proiectie perspectiva a unei case

#include <GL/glut.h>

void reshape (int w, int h) {


glViewport(0, 0, w, h); // redimensionare fereastra
glMatrixMode(GL_PROJECTION); // proiectie in perspectiva
glLoadIdentity();
gluPerspective(60, w/h, 20.0, 2.0);
glMatrixMode(GL_MODELVIEW); // punct de vizualizare
glLoadIdentity();
gluLookAt(3.0, 2.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);
static GLfloat house[] = { // coordonate noduri
-1.0, -1.0, 2.0,
1.0, -1.0, 2.0,
1.0, 1.0, 2.0,
0.0, 2.0, 2.0,
-1.0, 1.0, 2.0,
-1.0, -1.0, -2.0,
1.0, -1.0, -2.0,
1.0, 1.0, -2.0,
0.0, 2.0, -2.0,
-1.0, 1.0, -2.0
};
static GLubyte indices[] = { // ordine trasare fatete
0, 1, 2, 4,
2, 3, 4,
5, 6, 7, 9,
7, 8, 9,
1, 6, 7, 2,
2, 7, 8, 3,
9, 4, 3, 8,
5, 0, 4, 9
};
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnableClientState(GL_VERTEX_ARRAY);
44 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Figura 5.7: Rezultatul afis


arii unei case n proiectie perspectiva si n proiectie ortografica

glVertexPointer(3, GL_FLOAT, 0, house);


glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, indices);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[4]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[7]);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[11]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[14]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[18]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[22]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[26]);
glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (640, 480);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Casa");
init ();
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop ();
return 0;
}

In cazul n care se doreste afisarea n proiectie ortografica, n functia reshape() se


nlocuieste linia
gluPerspective(60, w/h, 20.0, 2.0);
cu linia
glOrtho(-5.0, 5.0, -5.0, 5.0, 20.0, 2.0);
5.1. PROIECT
II 45

(eyex, eyey, eyez)

(centerx, centery, centerz)



elevatie
azimut

Figura 5.8: Definirea coordonatelor polare pentru deplasarea punctului de vizualizare n jurul obiectului

Exemplul 5.1 poate fi adaptat pentru deplasarea coordonatei punctului de vizualizare


pe cele doua coordonate polare, azimut () si elevatie (). Deplasarea punctului de vizu-
alizare se poate face interactiv, cu ajutorul tastelor A si D pe azimut si a tastelor W si S
pe elevatie.

Daca se considera doar deplasarea pe azimut, acest lucru presupune modificarea punc-
tului de vizualizare pe conturul unui cerc din planul XoZ, conform relatiilor 5.1.

eyex = R sin()
(5.1)
eyez = R cos()

unde [0, 2).

Pentru adaugarea unei deplasari pe elevatie, toate coordonatele punctului de vizuali-


zare vor fi modificate conform relatiilor 5.2.

eyex = R sin() cos()
eyey = R sin() (5.2)
eyez = R cos() cos()

unde [0, 2) si [, ].

Daca se doreste suplimentar apropierea sau departarea punctului de vizualizare din


(eyex, eyey, eyez) n raport cu punctul de coordonate (centerx, centery, centerz),
se va modifica interactiv valoarea razei R, de exemplu utilizand tastele Z si X. In acest caz
trebuie avut grija ca volumul spatiului de vizualizare sa fie dimensionat corespunzator,
astfel ncat sa includa obiectul modelat indiferent de distanta R.

Deoarece coordonatele de vizualizare nu mai sunt fixe, instructiunile corespunzatoare


stabilirii coordonatelor de vizualizare vor fi mutate din functia reshape n functia display
pentru a fi executate continuu, conform exemplului 5.2 Toate modificarile de unghiuri sau
de raza vor fi specificate prin intermediul functiei keyboard.
46 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Exemplul 5.2 Vedere n proiectie perspectiva a unei case

#include <GL/glut.h>
#include "math.h"

#define PI 3.1415
float r=3; // valoare initiala raza
float a,b=0; // valori initiale unghiuri

void reshape (int w, int h) {


glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, w/h, 20.0, 2.0);
}

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);

float eyex=r*sin(a)*cos(b); // recalculare eyex


float eyey=r*sin(b); // recalculare eyey
float eyez=r*cos(a)*cos(b); // recalculare eyez

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

static GLfloat house[] = {


-1.0, -1.0, 2.0,
1.0, -1.0, 2.0,
1.0, 1.0, 2.0,
0.0, 2.0, 2.0,
-1.0, 1.0, 2.0,
-1.0, -1.0, -2.0,
1.0, -1.0, -2.0,
1.0, 1.0, -2.0,
0.0, 2.0, -2.0,
-1.0, 1.0, -2.0
};

static GLubyte indices[] = {


0, 1, 2, 4,
2, 3, 4,
5, 6, 7, 9,
5.1. PROIECT
II 47

7, 8, 9,
1, 6, 7, 2,
2, 7, 8, 3,
9, 4, 3, 8,
5, 0, 4, 9
};
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, house);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, indices);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[4]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[7]);
glDrawElements(GL_POLYGON, 3, GL_UNSIGNED_BYTE, &indices[11]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[14]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[18]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[22]);
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &indices[26]);
glFlush();
}

void keyboard(unsigned char key, int x, int y) {


switch (key) {
case a: a=a-PI/20; break; // decrementare azimut
case d: a=a+PI/20; break; // incrementare azimut
case w: b=b+PI/20; break; // incrementare elevatie
case s: b=b-PI/20; break; // decrementare elevatie
case z: r=r+0.5; break; // departare
case x: r=r-0.5; break; // apropiere
}
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (640, 480);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Casa");
init ();
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard); // specificare functie tastatura
glutMainLoop ();
return 0;
}
48 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

5.2 Transform
ari
Operatiile de transformare permit pozitionarea unui sistem de coordonate local (de
exemplu, al unui model) n sistemul de coordonate al sistemului lumii reale (al scenei).
Cele trei transformari de baza sunt translatia, rotatia si scalarea.

Fiecare transformare individuala reprezentata sub forma matriceala M multiplica ma-


tricea curenta a modelului C, rezultand o noua matrice curenta CM. Trebuie, ca urmare,
acordata o mare atentie succesiunii transformarilor, deoarece acestea nu sunt comutative.

Translatia reprezinta modificarea originii sistemului de coordonate al modelului prin


translatarea acestuia pe cele trei axe de coordonate.

Instructiunea OpenGL pentru translatie este glTranslate(), avand sintaxa:

glTranslate{fd}(x, y, z);

unde x, y si z sunt argumentele care definesc valoarea translatiei pe fiecare dintre axele
de coordonate.

Rotatia reprezinta modificarea sistemului de coordonate al modelului prin rotirea aces-


tuia cu un anumit unghi, n sens invers orar, n jurul unui vector de rotatie.

Instructiunea OpenGL pentru translatie este glRotate(), avand sintaxa:

glRotate{fd}(angle, x, y, z);

unde x, y si z sunt argumentele care definesc varful vectorului de rotatie, acesta avand
originea n originea sistemului de coordonate al modelului, iar angle reprezinta unghiul
cu care modelul este rotit.

De exemplu, pentru a roti un obiect cu un unghi de 45 n jurul axei Z, se poate utiliza


instructiunea:

glRotate(45, 0.0, 0.0, 1.0);

Scalarea reprezinta modificarea sistemului de coordonate prin scalarea (multiplicarea)


fiecarei axe cu un factor de scala propriu.

Instructiunea OpenGL pentru translatie este glScale(), avand sintaxa:

glScale{fd}(x, y, z);

unde x, y si z sunt factorii de scalare corespunzatori fiecareia din cele trei axe de coordo-
nate ale modelului.

De exemplu, pentru a scala un obiect pe axa X cu un factor de -0.5 si pe axa Y cu


factorul 2.0, se poate utiliza instructiunea:

glScale(-0.5, 2.0, 0.0);



5.2. TRANSFORMARI 49

In exemplul 5.3 se prezinta aplicarea celor trei operatii de transformare geometrica


asupra unui patrat. Initial sunt trasate axele de coordonate n planul 2D, sub forma unor
linii (GL_LINES) ale caror noduri sunt definite n vectorul axe. Coordonatele nodurilor
patratului (GL_QUADS) , precum si culorile asociate sunt stocate n vectorul patrat. Sunt
afisate forma si pozitia initiala a patratului nainte si dupa aplicarea transformarilor ge-
ometrice. Aceasta presupune translatarea obiectului pe distanta (0.7, 0.6), urmata de
rotirea n sens trigonometric n jurul axei Z cu 15 si, n final, de scalarea acestuia cu
factorii (0.4, 0.2).

Exemplul 5.3 Aplicarea transformarilor geometrice asupra unui patrat

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display (void){


glClear(GL_COLOR_BUFFER_BIT);
static GLfloat patrat[] = {
1.0, 1.0, 1.0, -0.5, -0.5, -0.5,
0.0, 1.0, 0.0, +0.5, -0.5, -0.5,
1.0, 0.0, 0.0, +0.5, +0.5, -0.5,
0.0, 0.0, 1.0, -0.5, +0.5, -0.5
};
static GLfloat axe[] = {
-0.85, 0.0,
+0.85, 0.0,
0.0, -0.85,
0.0, +0.85
};

glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glPolygonMode(GL_FRONT, GL_LINE);
glEnableClientState(GL_VERTEX_ARRAY);
glColor3f(0.5, 0.5, 0.5);
glVertexPointer(2, GL_FLOAT, 0, axe);
glDrawArrays(GL_LINES, 0, 4); // axe de coordonate 2D
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 6*sizeof(GLfloat), patrat);
glVertexPointer(3, GL_FLOAT, 6*sizeof(GLfloat), &patrat[3]);
glDrawArrays(GL_QUADS, 0, 4); // pozitie initiala
glTranslatef(0.7, 0.6, 0.0);
glRotatef(15, 0.0, 0.0, 1.0);
glScalef(0.4, 0.2 ,0.0);
glDrawArrays(GL_QUADS, 0, 4); // pozitie finala
glDisableClientState(GL_VERTEX_ARRAY);
50 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Figura 5.9: Rezultatul aplic


ari transformarilor geometrice asupra unui patrat

glDisableClientState(GL_COLOR_ARRAY);
glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (300, 300);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Transformari geometrice");
init ();
glutDisplayFunc (display);
glutMainLoop ();
return 0;
}

5.3 Manipularea stivelor de matrice


Matricele de proiectie si de vizualizare curente reprezinta varful unor stive de matrice,
ca n figura 5.10. Stivele de matrice sunt utile pentru construirea unor modele iererhice,
n care obiectele complexe sunt construite pornind de la obiecte mai simple.

Un exemplu clasic este modelarea unui automobil ale carui roti pot fi reprezentate
printr-un singur obiect redesenat de patru ori, la alte coordonate. Succesiunea de operatii
poate fi descrisa succint, astfel: modeleaza caroseria, memoreaza pozitia curenta, depla-
seaza la pozitia rotii stanga-fata, modeleaza roata, revino la pozitia anterioara, memo-
reaza pozitia curenta, deplaseaza la pozitia rotii dreapta-fata, modeleaza roata s.a.m.d.

Deoarece transformarile sunt memorate n matrice, mecanismul oferit de stivele de ma-


trice este ideal n scopul memorarii succesive a pozitiilor. Pozitia matricei curente poate
fi controlata prin intermediul instructiunilor glPushMatrix(), care introduce matricea
5.3. MANIPULAREA STIVELOR DE MATRICE 51

Stiva Stiva
matricelor matricelor
de vizualizare de proiecie
0 0
1 32 matrice 4 x 4 1 2 matrice 4 x 4

31

Figura 5.10: Stivele matricelor de vizualizare si de proiectie

curenta n stiva, si glPopMatrix(), care extrage matricea din stiva si o face matrice
curenta. Tipul matricei manipulate este ales cu ajutorul instructiunii glMatrixMode(),
avand ca argument posibil GL_PROJECTION sau GL_MODELVIEW.

Stiva matricelor de vizualizare are o dimensiune de 32 de niveluri dar, n unele versiuni


de OpenGL, numarul acestora poate fi mai mare. Stiva matricelor de proiectie contine
doar doua niveluri, deoarece acestea nu sunt utilizate n numar mare. Pentru a determina
numarul de niveluri ale stivelor se utilizeaza instructiunea glGetIntegerv(), cu sintaxa:

glGetIntegerv(matrix, *params);

unde matrix reprezinta variabila de stare citita (GL_MAX_MODELVIEW_STACK_DEPTH sau


GL_MAX_PROJECTION_STACK_DEPTH), iar params este numele variabilei n care este depusa
valoarea citita.

Matrice curent Matrice curent

glPushMatrix() glPopMatrix()

Stiv Stiv

Figura 5.11: Operatii de depunere sau extragere a unei matrice din stiva
52 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Exemplul 5.4 Modelarea unei scene cu ajutorul stivei

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void reshape(int w, int h) {


glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,0,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(18,5,20,0,0,0,0,1,0);
}

void display (void){


static GLfloat platou[] = {
-5.0, 0.0, -5.0,
+5.0, 0.0, -5.0,
+5.0, 0.0, +5.0,
-5.0, 0.0, +5.0
};
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glColor3f(0.0, 0.5, 0.5);
glVertexPointer(3, GL_FLOAT, 0, platou);
glDrawArrays(GL_QUADS, 0, 4); // platou vernil
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(4.0, 0.5, 4.0); // sfera rosie
glColor3f(0.8, 0.0, 0.0);
glutWireSphere(0.5, 15, 15);
glPopMatrix();
glPushMatrix();
glTranslatef(4.0, 0.5, -4.0); // sfera alba
glColor3f(0.8, 0.8, 0.8);
glutWireSphere(0.5, 15, 15);
glPopMatrix();
glPushMatrix();
glTranslatef(-4.0, 0.5, -4.0); // sfera albastra
glColor3f(0.0, 0.0, 0.8);
glutWireSphere(0.5, 15, 15);
5.3. MANIPULAREA STIVELOR DE MATRICE 53

glPopMatrix();
glPushMatrix();
glTranslatef(-4.0, 0.5, 4.0); // sfera verde
glColor3f(0.0, 0.8, 0.0);
glutWireSphere(0.5, 15, 15);
glPopMatrix();
glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (300, 300);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Manipularea stivelor");
init ();
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop ();
return 0;
}

In exemplul 5.4 se prezinta modelarea unei suprafete pe care sunt dispuse patru sfere,
fiecare dintre acestea fiind pozitionate relativ la centrul suprafetei, prin utilizarea stivelor
matricelor de vizualizare.

In cazul n care nu se doreste utilizarea stivelor, secventa de cod asociata modelarii


celor patru sfere se modifica, prin precizarea coordonatelor de translatie curenta relative
la translatia anterioara, dupa cum urmeaza.

Figura 5.12: Exemplu de utilizare a stivelor pentru plasarea unor obiecte


54 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

...
glMatrixMode(GL_MODELVIEW);
glTranslatef(4.0, 0.5, 4.0); // sfera rosie
glColor3f(0.8, 0.0, 0.0);
glutWireSphere(0.5, 15, 15);
glTranslatef(0.0, 0.0, -8.0); // sfera alba
glColor3f(0.8, 0.8, 0.8);
glutWireSphere(0.5, 15, 15);
glTranslatef(-8.0, 0.0, 0.0); // sfera albastra
glColor3f(0.0, 0.0, 0.8);
glutWireSphere(0.5, 15, 15);
glTranslatef(0.0, 0.0, 8.0); // sfera verde
glColor3f(0.0, 0.8, 0.0);
glutWireSphere(0.5, 15, 15);
glFlush();
...
In ambele situatii, rezultatul obtinut este cel prezentat n figura 5.3.

5.4 Planuri de decupare suplimentare


Fata de cele sase planuri de decupare proprii volumului de vizualizare, OpenGL are
prevazuta posibilitatea definirii a nca sase planuri de decupare suplimentare. Acest lucru
este util pentru extragerea obiectelor sau a unor parti ale acestora care nu se doreste a fi
vizibile.

Fiecare dintre cele sase planuri de decupare este definit cu ajutorul coeficientilor
ecuatiei proprii.

Ax + By + Cz + D = 0. (5.3)

Aceste planuri sunt transformate corespunzator de catre transformarile de modelare


si de vizualizare. Volumul decupat rezulta din intersectia volumului ntreg cu fiecare
semispatiu definit de catre planurile de decupare respective.

Activarea sau dezactivarea unui plan de decupare se poate face cu ajutorul instructiu-
nilor glEnable() si, respectiv, glDisable(), avand ca argument GL_CLIP_PLANEi, unde
i reprezinta indexul planului.

Definirea unui plan de decupare suplimentar se face cu instructiunea glClipPlane(),


avand urmatoarea sintaxa:

glClipPlane(plane, *equation);

unde plane reprezinta indexul planului, definit sub forma GL_CLIP_PLANEi, iar equation
este vectorul coeficientilor reali ai ecuatiei planului (5.3).
5.4. PLANURI DE DECUPARE SUPLIMENTARE 55

Exemplul 5.5 Aplicarea planurilor de decupare asupra unei sfere

#include <GL/glut.h>

void init (void){


glClearColor(0.0, 0.0, 0.0, 0.0);
}

void reshape(int w, int h) {


glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,0,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5,5,5,0,0,0,0,1,0);
}

void display (void){


GLdouble plan0[4]={0.0, 1.0, 0.0, 0.0};
GLdouble plan1[4]={1.0, 0.0, 0.0, 0.0};
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.5, 0.5);
glClipPlane(GL_CLIP_PLANE0, plan0);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE1, plan1);
glEnable(GL_CLIP_PLANE1);
glutWireSphere(2, 30, 30);
glFlush();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (300, 300);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Planuri de decupare");
init ();
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop ();
return 0;
}

Toate versiunile OpenGL admit cel putin sase planuri de decupare, dar numarul real
al acestora poate fi determinat cu ajutorul instructiunii glGetIntegerv() avand ca ar-
56 CAPITOLUL 5. PROIECT
II SI TRANSFORMARI

Figura 5.13: Exemplu de utilizare a planurilor de decupare pe o sfera

gument variabila de stare GL_MAX_CLIP_PLANES.

glGetIntegerv(GL_MAX_CLIP_PLANES, *params);
Aplicatia din exemplul 5.5 permite decuparea unui sfert dintr-o sfera prin intermediul
a doua planuri de decupare, unul orizontal si unul vertical.
Capitolul 6

Iluminarea scenelor si culoarea


obiectelor

Randarea finala a unei scene tine cont de tipul si numarul surselor de iluminare utili-
zate, precum si de materialul cu care obiectele din scena sunt modelate. OpenGL permite
manipularea iluminarii si a obiectelor dintr-o scena n scopul generarii diferitelor efecte.

Afisarea unei scene n tridimensional trebuie sa tina cont de pozitia n care se afla obser-
vatorul, astfel ncat, pentru obiectele situate pe aceeasi axa de adancime, suprafetele as-
cunse sa nu fie vizibile. Pentru a le elimina, se efectueaza un test de pozitionare cu ajutorul
unui buffer de adancime (depth buffer), care este executat prin intermediul instructiunii
glEnable(GL_DEPTH_TEST). Pentru ca bufferul de adancime sa fie activat, este necesara
initilizarea acestuia n functia main().
void init (void){
...
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT|...);
...
}

int main(int argc, char** argv)


{
...
glutInitDisplayMode(GLUT_DEPTH|...);
...
}
Modelul de iluminare OpenGL aproximeaza culoarea unui obiect n functie de procen-
tajul de culori elementare RGB reflectate de catre suprafata obiectului respectiv. Ca si n
cazul surselor de lumina, suprafetele obiectelor dispun de coeficienti de reflexie a luminii
ambientale, difuze sau speculare. In plus fata de aceste componente, obiectele pot emite
lumina proprie, dar care nu interactioneaza cu sursele externe de lumina.

Rezultatul randarii unei scene este obtinut prin determinarea interactiunii dintre sur-
sele de lumina si parametrii de material ai obiectelor din scena respectiva. De exemplu, un
obiect de culoare rosie care este iluminat de o sursa de lumina galbena va deveni invizibil,
n timp ce, pentru o sursa de lumina alba, obiectul al redeveni vizibil n rosu.

57
58 CAPITOLUL 6. ILUMINAREA SCENELOR SI CULOAREA OBIECTELOR

6.1 Surse de lumin


a
O sursa de lumina este definita n OpenGL prin intermediul mai multor parametri si
prin parcurgerea urmatoarelor etape: activarea, pozitionarea si definirea parametrilor de
lumina.

1. Activarea sursei de lumina se face n doua etape, prin activarea initiala a iluminarii
globale a unei scene cu ajutorul instructiunii glEnable(GL_LIGHTNING), urmata de acti-
varea individuala a surselor de lumina, prin instructiunea glEnable(GL_LIGHTi), unde i
reprezinta indexul sursei de lumina (cu valori cuprinse ntre 0 si 7).

2. Definirea sursei de lumina se face cu ajutorul instructiunii glLight(), avand


urmatoarea sintaxa:
glLight{i|f}(light, pname, param);
glLight{i|f}v(light, pname, *param);
unde light reprezinta denumirea sursei (GL_LIGHT0, ... , GL_LIGHT7), pname este de-
numirea parametrului sursei, iar param este valoarea parametrului pname. Denumirile
parametrilor, valorile implicite ale acestora, precum si semnificatia lor sunt prezentate n
tabelul urmator.

Denumire parametru Valoare implicit


a Semnificatie

GL_AMBIENT (0.0, 0.0, 0.0, 1.0) intensitatea RGBA a luminii ambientale

GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) intensitatea RGBA a luminii difuze

GL_SPECULAR (1.0, 1.0, 1.0, 1.0) intensitatea RGBA a luminii speculare

GL_POSITION (0.0, 0.0, 1.0, 0.0) coordonatele (x, y, z, w) ale sursei de lumina

GL_SPOT_DIRECTION (0.0, 0.0, -1.0) directia (x, y, z) a fasciculului de lumina

GL_SPOT_EXPONENT 0.0 exponentul fasciculului de lumina

GL_SPOT_CUTOFF 180.0 deschiderea conului fasciculului de lumina

GL_CONSTANT_ATTENUATION 1.0 constanta de atenuare al luminii

GL_LINEAR_ATTENUATION 0.0 factorul de atenuare liniara a luminii

GL_QUADRATIC_ATTENUATION 0.0 factorul de atenuare patratica a luminii

Valorile implicite ale parametrilor GL_DIFFUSE si GL_SPECULAR sunt valabile doar pen-
tru sursa GL_LIGHT0, pentru restul surselor acesteia fiind (0.0, 0.0, 0.0, 1.0).

Exponentul fasciculului de lumina specifica atenuarea intensitatii luminoase radiate la


un anumit unghi fata de directia principala. Cei trei coeficienti de atenuare (constant,
liniar si patratic) caracterizeaza atenuarea n distanta a luminii si are la baza formula:

1
Ip = Il , (6.1)
kc + kl d + kp d2

6.1. SURSE DE LUMINA 59

unde Ip este intensitatea la distanta d fata de sursa, iar Il este intensitatea emisa de sursa.

In plus fata de setarile surselor de lumina individuale, mai exista posibilitatea definirii
unor parametri suplimentari, denumiti parametri ai modelului de iluminare global. Acesti
parametri sunt modificati prin intermediul instructiunii glLightModel() cu urmatoarea
sintaxa:

glLightModel{i|f}(pname, param);
glLightModel{i|f}v(pname, *param);

unde pname este numele parametrului, iar param reprezinta valoarea parametrului pname.

Denumire parametru Valoare implicit


a Semnificatie

GL_LIGHT_MODEL_AMBIENT (0.2, 0.2, 0.2, 1.0) intensitatea RGBA a luminii ambientale a sce-

nei

GL_LIGHT_MODEL_LOCAL_VIEWER 0.0 sau GL_FALSE modul de calcul al unghiurilor de reflexie spe-

culara

GL_LIGHT_MODEL_TWO_SIDE 0.0 sau GL_FALSE modul de iluminare al fatetelor interioare si

exterioare

Lumina ambientala a scenei presupune existenta unei iluminari suplimentare fata de


sursele definite de utilizator, avand parametrii impliciti definiti ca n tabelul de mai sus.

Localizarea punctului de observatie determina modul de calcul al reflexiilor speculare,


lucru care implica necesitatea calculului vectorilor normala. In cazul n care punctul de
observatie este considerat a fi infinit (implicit), normalele la suprafata sunt paralele, n
timp ce, n cazul punctului local, normalele difera.

Calculul iluminarii se face pentru fiecare poligon n parte, fie ca acesta este interior
sau exterior. In mod implicit, calculele sunt efectuate doar pentru suprafata exterioara,
dar pot exista aplicatii n cadrul carora este necesara si iluminarea fatetelor interioare.

OpenGL aproximeaza lumina ca o combinatie de 4 componente independente:

1. componenta difuz a (GL_DIFFUSE): raza de lumina provine de la o sursa de lumina


si este incidenta direct pe suprafata obiectului;
2. componenta ambiental a (GL_AMBIENT): toate nodurile scenei sunt influentate de
aceasta componenta. Atunci cand o raza de lumina loveste o suprafata, ea este
mprastiata egal n toate directiile. Dupa un numar de ricoseuri pe suprafetele scenei
apare senzatia ca lumina provine de peste tot;
3. componenta specular a (GL_SPECULAR): este componenta care creeaza reflexii ale
suprafetelor de tipul metalului sau oglinzii. Este de preferat ca aceasta componenta
sa fie utilizata doar pentru anumite materiale specifice;
60 CAPITOLUL 6. ILUMINAREA SCENELOR SI CULOAREA OBIECTELOR

4. componenta emisiv a (GL_EMISSION): este utilizata pentru a crea efectul obiectelor


cu lumina proprie (LED-uri, becuri s.a.). De retinut ca obiectul nu emite lumina, ci
doar se creeaza senzatia.

6.2 Propriet
atile de material ale obiectelor
Fiecare obiect dintr-o scena contine o serie de proprietati de material, precum culorile
de reflexie, speculare sau ambientale sau, n situatia n care obiectul are si lumina proprie,
culoarea luminii emise. Toti acesti parametri pot fi definiti n OpenGL cu ajutorul unor
functii specifice.

Pentru a defini parametrii de material se utilizeaza instructiunea glMaterial(), astfel:


glMaterial{i|f}(face, pname, param);
glMaterial{i|f}v(face, pname, *param);
unde face precizeaza fateta obiectului (GL_FRONT, GL_BACK sau GL_FRONT_AND_BACK)
careia i se aplica proprietatea, pname reprezinta denumirea parametrului specificat, iar
param specifica valoarea parametrului respectiv.

Denumire parametru Valoare implicit


a Semnificatie

GL_AMBIENT (0.2, 0.2, 0.2, 1.0) culoarea luminii ambientale a obiectului

GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) culoarea luminii difuze a obiectului

GL_AMBIENT_AND_DIFFUSE culoarea luminii ambientale si difuze

GL_SPECULAR (0.0, 0.0, 0.0, 1.0) culoarea luminii speculare a obiectului

GL_SHININESS 0.0 exponentul luminii speculare

GL_EMISSION (0.0, 0.0, 0.0, 1.0) culoarea luminii emisive a obiectului

GL_COLOR_INDEXES (0, 1, 1) indicii culorilor ambientale, difuze si speculare

In OpenGL sunt implementate doua modele de iluminare (plata si Gouraud) care pot
fi activate prin intermediul instructiunii glShadeModel(), avand ca argumente posibile
GL_FLAT (pentru modelul plat):

glShadeModel(GL_FLAT);
sau GL_SMOOTH (pentru modelul Gouraud):
glShadeModel(GL_SMOOTH);

In exemplul 6.1 se prezinta o aplicatie de iluminare a unei scene cu doua surse de


lumina si un obiect sub forma de sfera.
ILE DE MATERIAL ALE OBIECTELOR
6.2. PROPRIETAT 61

Exemplul 6.1 Iluminarea unei sfere cu doua surse de lumina

#include <GL/glut.h>

GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; // valorile parametrilor


GLfloat diffuse0[] = {1.0, 0.0, 0.0, 1.0 }; // surselor de lumina
GLfloat diffuse1[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat position0[] = { 1.0, 1.0, 0.0, 0.0 };
GLfloat position1[] = { -1.0, -1.0, 0.0, 0.0 };

GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 }; // valorile parametrilor


GLfloat mat_diffuse[] = { 0.5, 0.5, 0.5, 1.0 }; // de material
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

void init(void) {
glClearColor(0.0, 0.1, 0.1, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // model de iluminare Gouraud

// parametrii surselor de lumin\u{a}


glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position0);

glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);


glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
glLightfv(GL_LIGHT1, GL_POSITION, position1);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // activarea sursei de lumina rosie
glEnable(GL_LIGHT1); // activarea sursei de lumina albastra
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// parametrii de material ai sferei


glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 25);
glutSolidSphere(1.0, 30, 32); // sfera solida
glFlush();
}
62 CAPITOLUL 6. ILUMINAREA SCENELOR SI CULOAREA OBIECTELOR

Model plat Model Gouraud

Figura 6.1: Iluminarea unei sfere solide cu doua surse de lumina, rosie si albastra, n model plat si
Gouraud

void reshape(int w, int h) {


glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -10.0, 10.0);
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Iluminare sfer\u{a}");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

De remarcat faptul ca, n cazul utilizarii unui model de tip plat, pentru aceiasi parame-
tri ai sferei rezultatul este mai slab din punct de vedere perceptual, suprafetele poligonale
avand iluminare constanta (figura 6.1).
Capitolul 7

Texturi

Operatia de texturare reprezinta modalitatea care ofera cele mai bune rezultate n
generarea imaginilor realiste. Texturarea presupune aplicarea unei texturi pe un obiect
grafic fara operatii de calcul geometric suplimentare. In cadrul scenelor, obiectele sunt
n mare parte definite poligonal, astfel ncat n calculul intensitatilor pixelilor intra, pe
langa informatia de culoare furnizata de catre modelul de iluminare, si o informatie supli-
mentara extrasa dintr-o matrice denumita harta a texturii (texture map). Aceasta harta
poate contine date provenite de la o imagine naturala sau sintetica, precum si date supli-
mentare precum intensitatea sau transparenta.

Procesul de transpunere al hartii texturii pe obiectul grafic se numeste proiectie a


texturii (texture mapping) si se executa prin identificarea punctelor din obiect asociate
punctelor din harta texturii utilizand operatii geometrice simple. Hartile texturilor pot fi
1D, 2D sau 3D, astfel:
Hartile de textura 1D reprezinta vectori de culori care pot fi aplicate unui obiect
grafic pe orice directie;
Hartile de textura 2D reprezinta matrice de culori care pot fi aplicate unei suprafete
din scena;
Hartile de textura 3D reprezinta matrice 3D de culori care pot fi aplicate unor obiecte
definite n spatiul 3D, de obicei de natura teoretica n studiile stiintifice (ncepand
cu versiunea OpenGL 1.2).

In cadrul procesului de texturare, atat obiectul grafic modelat, cat si textura contin
informatie de culoare. Cea mai simpla modalitate de texturare presupune nlocuirea
informatiei de culoare a obiectului cu informatia de culoare a texturii, desi sunt posibile
si variante de combinare a acestora.

7.1 Initializarea texturilor


Pentru a putea utiliza texturi n openGL este necesara activarea acestora prin inter-
mediul instructiunii glEnable(), avand ca argument una din variabilele GL_TEXTURE_1D,
GL_TEXTURE_2D sau GL_TEXTURE_3D.

In cele ce urmeaza se vor exemplifica aplicatii cu texturi 2D (suprafete).

63
64 CAPITOLUL 7. TEXTURI

glEnable(GL_TEXTURE_2D);
...
glDisable(GL_TEXTURE_2D);

Definirea unei texturi se face prin asocierea unui nume si a datelor specifice, cu ajutorul
instructiunilor glGenTextures() si glBindTexture() cu urmatoarele sintaxe:

glGenTextures(n, textureNames);

unde n este numarul de texturi utilizate, iar textureNames contine denumirile celor n
texturi si

glBindTexture(target, textureName);

unde textureName este numele texturii asociate tipului texturii target (GL_TEXTURE_1D,
GL_TEXTURE_2D sau GL_TEXTURE_3D).

Modul de texturare al obiectului este ales prin intermediul instructiunii glTexEnv():

glTexEnv{i|f}(target, pname, param);


glTexEnv{i|f}v(target, pname, *param);

unde target este setat ca fiind GL_TEXTURE_ENV, pname specifica parametrul de texturare
modificat (GL_TEXTURE_ENV_MODE sau GL_TEXTURE_ENV_COLOR).

Pentru parametrul GL_TEXTURE_ENV_MODE, variabila param poate lua una din valorile
GL_DECAL, GL_REPLACE (nlocuiri), GL_MODULATE (modulare) sau GL_BLEND (amestec), iar
pentru parametrul GL_TEXTURE_ENV_COLOR, variabila param este definita sub forma a
patru componente reale R, G, B si A.

Tabela 7.1: Functii de culoare si transparenta


Format intern GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND

GL_ALPHA Cf Cf nedefinit Cf C

At Af At Af At A

GL_LUMINANCE Lt Cf Lt nedefinit Cf (1 Lt ) + Cc Lt C

Af Af Af A

GL_LUMINANCE_ALPHA Lt Cf Lt nedefinit Cf (1 Lt ) + Cc Lt C

At Af At Af At A

GL_INTENSITY It Cf It nedefinit Cf (1 It ) + Cc It C

It Af I t Af (1 It ) + Ac It A

GL_RGB Ct Cf Ct Ct Cf Ct C

Af Af Af Af A

GL_RGBA Ct Cf Ct Cf (1 At ) + Ct At Cf (1 Ct ) + Cc Ct C

At Af At Af Af At A
7.1. INIT
IALIZAREA TEXTURILOR 65

In functie de tipul de texturare specificat prin parametrul GL_TEXTURE_ENV_MODE,


operatiile aritmetice de combinare a culorii (C) si a transparentei (A) obiectului si a
texturii sunt exprimate sub forma functiilor prezentate n tabelul 7.1.

Pentru a asocia unei texturi parametrii principali ai acesteia, precum formatul intern
sau numarul coordonatelor de culoare, se utilizeaza instructiunea glTexImage2D(), astfel:
glTexImage2D(target, level, internalFormat, width, height, border,
format, type, pixels);
unde target are valoarea GL_TEXTURE_2D, level precizeaza numarul de rezolutii al tex-
turii (implicit 0), internalFormat specifica formatul intern al texturii si poate avea una
din valorile enumerate mai jos:
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_INTESITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSITY12,
GL_INTENSITY16,
GL_RGBA, GL_R3_G3_B3, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10,
GL_RGB12, GL_RGB16,
GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2,
GL_RGBA12, GL_RGBA16

Cifrele de la sfarsitul valorilor specifica numarul de biti pe care este exprimat pa-
rametrul respectiv. De exemplu, GL_RGB5_A1 precizeaza faptul ca fiecare din cele trei
componente RGB este exprimata pe 5 biti, iar componenta de transparenta A este speci-
ficata pe 1 bit.

Parametrii width si height definesc dimeniunile hartii texturii sub forma unor puteri
ale lui 2, iar border determina dimensiunea marginii texturii n pixeli (0 = fara margine).

Parametrii format si type descriu formatul si tipul de date al hartii texturii. Acestia
pot lua valorile, pentru parametrul format:
GL_COLOR_INDEX
GL_RGB
GL_RGBA
GL_RED
GL_GREEN
GL_BLUE
GL_ALPHA
GL_LUMINANCE
GL_LUMINANCE_ALPHA
66 CAPITOLUL 7. TEXTURI

si pentru parametrul type:


GL_BYTE
GL_UNSIGNED_BYTE
GL_SHORT
GL_UNSIGNED_SHORT
GL_INT
GL_UNSIGNED_INT
GL_FLOAT
GL_BITMAP

In final, parametrul pixels contine informatia de imagine a texturii.

Specificarea functiilor de aplicare/interpolare a texturii se face prin intermediul instruc-


tiunii glTexParameter(), cu sintaxa:
glTexParameter{i|f}(target, pname, param);
glTexParameter{i|f}v(target, pname, *param);
unde target specifica tipul texturii si poate fi GL_TEXTURE_2D sau GL_TEXTURE_1D, iar
param reprezinta valoarea parametrului pname, specificate n tabelul de mai jos.

Denumire parametru (pname) Valoare parametru (param)

GL_TEXTURE_WRAP_S GL_CLAMP, GL_REPEAT

GL_TEXTURE_WRAP_T GL_CLAMP, GL_REPEAT

GL_TEXTURE_MAG_FILTER GL_NEAREST, GL_LINEAR

GL_TEXTURE_MIN_FILTER GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,

GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,

GL_LINEAR_MIPMAP_LINEAR

GL_TEXTURE_BORDER_COLOR orice patru valori n intervalul [0.0, 1.0]

GL_TEXTURE_PRIORITY [0.0, 1.0] pentru obiectul texturat curent

7.2 Coordonate poligonale de texturare


Pentru a asocia un texel (punct al hartii texturii) unui pixel al obiectului din scena n
scopul precizarii conditiilor initiale de texturare/interpolare, se utilizeaza instructiunea
glTexCoord():
glTexCoord{1|2|3|4}{s|d|i|f}(coords);
glTexCoord{1|2|3|4}{s|d|i|f}v(*coords);
Aceasta functie are ca rezultat asocierea texelului de coordonate specificate prin para-
metrul coord vertexului asociat din poligonul dorit a fi texturat. Textura este considerata
ca avand propriul sistem de coordonate, cu valori cuprinse n intervalul [0, 1]. In cazul n
7.2. COORDONATE POLIGONALE DE TEXTURARE 67

care se doreste repetarea texturii pe un poligon, limita superioara 1 este modificata cu


valoarea numarului de repetitii pe axa respectiva.
glBegin)(...);
...
glTexCoord2f(0.0, 0.0);
glVertex3f(-2.0, -1.0, 0.0);
...
glEnd();
In cele mai multe dintre situatii, harta texturii este specificata sub forma unui fi-
sier extern de tip imagine n format RAW (*.raw). Acest lucru presupune existenta n
program a unei secvente de cod care sa permita ncarcarea n memorie a fisierului imagine.

glVertex2v(v2);

glTexCoord2v(t3); glTexCoord2v(t2);

glVertex2v(v3);

glVertex2v(v0);

glTexCoord2v(t0); glTexCoord2v(v1);
glTexCoord2v(t1); glVertex2v(v1);
Poligon
Textur

Figura 7.1: Asocierea coordonatelor texturii cu cele ale poligonului

In exemplul 7.1 se prezinta aplicarea unei texturi RGB, citita dintr-un fisier RAW
(texture.raw), pe o fateta poligonala a unui cub.

In cadrul setarii parametrilor de texturare, una din optiuni este reprezentata de tipul
filtrului de interpolare utilizat n cazul maririi (GL_TEXTURE_MIN_FILTER) sau micsorarii
imaginii (GL_TEXTURE_MAG_FILTER). Aceasta alegere se face prin intermediul instructiunii
glTexParameter() prezentate anterior. Tipurile posibile de interpolare sunt de tip liniar
(GL_LINEAR) sau prin determinarea texelului asociat cel mai apropiat (GL_NEAREST).

In cazul maririi unei imagini (GL_TEXTURE_MAG_FILTER), un pixel din noua imagine


va corespunde unei portiuni dintr-un texel. Prin filtrare de tip GL_NEAREST, valoarea
pixelului va fi obtinuta prin determinarea texelului cel mai apropiat de centrul pixelu-
lui, rezultand distorsionari ale imaginii rezultate. In cazul utilizarii interpolarii liniare
GL_LINEAR, valoarea pixelului este rezultatul medierii ponderate a unei regiuni de texeli
situati n jurul centrului pixelului. Aceasta metoda necesita, n schimb, un volum mai
mare de calcul, dar rezultatele sunt superioare. Similar, n cazul micsorarii unei ima-
gini (GL_TEXTURE_MIN_FILTER), se pot utiliza cele doua tipuri de filtre (GL_NEAREST sau
GL_LINEAR). In plus, mai exista patru optiuni suplimentare folosite doar n cazul utilizarii
texturilor multirezolutie.
68 CAPITOLUL 7. TEXTURI

Textur (256x256) Rezultat

Figura 7.2: Aplicarea unei texturi pe o suprafata poligonala

Pentru a observa efectul acestor filtre n cazul maririi imaginii rezultate din exemplul
7.1, se modifica n cod prin interschimbare comenzile:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
si
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
detaliul rezultatului putand fi observat n figura 7.3.

Din exemplul 7.1 se poate observa ca ntreaga suprafata poligonala laterala a cubului
este acoperita n ntregime de catre textura, aceasta fiind scalata astfel ncat sa se ajus-
teze pe dimensiunea suprafetei texturate. In unele aplicatii este nsa necesara repetarea
texturii pe suprafata poligonala respectiva si nu scalarea ei. Acest lucru este posibil prin
modificarea coordonatelor de texturare.

In cazul texturarii suprafetei prin scalare, nodurilor poligonale le erau asociate nodurile
terminale ale texturii, de coordonate (0.0, 0.0), (0.0, 1.0), (1.0, 1.0) si (0.0, 1.0), dupa
cum se poate observa din secventa de cod urmatoare:
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
ceea ce semnifica faptul ca ntr-o suprafata poligonala exista doar o singura textura ele-
mentara, scalata.

Determinarea noilor coordonate ale texturii se face prin calcularea numarului de tex-
turi elementare (de dimensiunea imaginii ncarcate) care sunt necesare pentru umplerea
suprafetei poligonale respective.
7.2. COORDONATE POLIGONALE DE TEXTURARE 69

GL_NEAREST GL_LINEAR

Figura 7.3: Utilizarea filtrelor de interpolare n cazul maririi unei imagini (detaliu al exemplului 7.1)

Texturarea se poate face n doua moduri, pentru fiecare din directiile verticala si orizon-
tala, fie prin repetare (GL_REPEAT), fie prin prelungirea ultimei linii a texturii (GL_CLAMP).

Pentru fiecare din directii exista un parametru asociat: GL_TEXTURE_WRAP_S pe ori-


zontala si GL_TEXTURE_WRAP_T pe verticala. Modificarea acestor parametri se face prin
intermediul instructiunii glTexParameter().

Cele patru combinatii posibile de texturare sunt prezentate n secventele de cod urma-
toare:

a) prin prelungire pe verticala si orizontala


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

b) prin prelungire pe orizontala si continuu pe verticala


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

c) prin prelungire pe verticala si continuu pe orizontala


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

d) continuu pe verticala si orizontala


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
70 CAPITOLUL 7. TEXTURI

pixel

texel

Textur Poligon Textur Poligon

Mrire Micorare

Figura 7.4: Asocierea dintre pixeli si texeli la marirea sau micsorarea unei imagini

Exemplul 7.1 Texturarea fatetei unui cub cu o imagine

#include <GL/glut.h>
#include <stdio.h>

#define tex_width 256 // latime textura


#define tex_height 256 // inaltime textura
static GLubyte texImage[tex_width][tex_height][3]; // memorie textura
static GLuint texName[1]; // etichete texturi utilizate

void readTexture(void) { // procedura citire fisier textura


FILE * file;
GLubyte data; int i,j,k;

file=fopen("texture.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
readTexture();
glGenTextures(1, texName); // definire textura
7.2. COORDONATE POLIGONALE DE TEXTURARE 71

glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}

void reshape(int w, int h) {


glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,0,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(6,2,3,0,0,0,0,1,0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.5,0.5,0.5);
glBegin(GL_QUADS);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glEnd();
glEnable(GL_TEXTURE_2D); // activarea texturarii 2D
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glEnd();
glDisable(GL_TEXTURE_2D); // dezactivarea texturarii 2D
glBegin(GL_QUADS);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glEnd();
glFlush();
}
72 CAPITOLUL 7. TEXTURI

a) b)

c) d)

Figura 7.5: Rezultatul aplic


arii diferitelor metode de texturare continua

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Texturare patrat");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

Prin modificarea codului din exemplul 7.1 si utilizand o texturare continua cu 2 2


texturi elementare a aceleiasi suprafete, modificand coordonatele de texturare:
7.2. COORDONATE POLIGONALE DE TEXTURARE 73

glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);


glTexCoord2f(2.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(2.0, 2.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 2.0); glVertex3f(1.0, 1.0, 1.0);
se obtin rezultatele din figura 7.5.

Deoarece textura prezinta continuitate la margini, tranzitia dintre doua texturi elemen-
tare nu este sesizabila n cadrul exemplului d). Aceasta caracteristica este importanta n
alegerea texturilor elementare, astfel ncat acestea sa permita o texturare continua fara
introducerea unor artefacte sau a unor discontinuitati perceptuale.

In exemplul 7.2 se prezinta texturarea unei suprafete plane cuprinse ntre coordonatele
(-0.6, -0.4) si (0.6, 0.4). Textura de dimensiune 256 256 pixeli este aplicata prin repetare
de trei ori pe orizontala si de doua ori pe verticala.

Exemplul 7.2 Texturarea repetitiva a unei suprafete

#include <GL/glut.h>
#include <stdio.h>

static GLubyte texImage[256][256][3]; // memorie imagine fundal


static GLuint texName[1]; // etichete texturi utilizate

void readTexture(void) { // procedura citire imagine fundal


FILE * file;
GLubyte data; int i,j,k;

file=fopen("wall.raw", "rb");
for (i=0; i<256; i++){
for (j=0; j<256; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
readTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
74 CAPITOLUL 7. TEXTURI

Textur (256x256) Rezultat (3x2)

Figura 7.6: Texturarea multipla a unei suprafete plane

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB,


GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glEnable(GL_TEXTURE_2D);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-0.6, 0.4);
glTexCoord2f(3, 0);
glVertex2f(0.6, 0.4);
glTexCoord2f(3, 2);
glVertex2f(0.6, -0.4);
glTexCoord2f(0, 2);
glVertex2f(-0.6, -0.4);
glEnd();
glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (512, 256);
glutCreateWindow("Texturare repetitiva");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
7.2. COORDONATE POLIGONALE DE TEXTURARE 75

(1, 0) (1, 1)
Polul nord

Latitudini de 20

Ecuator

Polul sud
(0, 0) (0, 1)

Longitudini de 20

(1, 0) (1, 1)

(0, 0) (0, 1)

Figura 7.7: Texturarea unei sfere pornind de la o textura n proiectie cilindrica

O aplicatie complexa este reprezentata de texturarea unei sfere prin proiectia unei
texturi. Complexitatea problemei este data de modelarea sferei, prin intermediul poli-
goanelor triunghiulare sau rectangulare. desi este preferata prima dintre variante. O alta
problema este asocierea coordonatelor de texturare nodurilor fiecaruia dintre poligoanele
elementare.
Modelarea sferei se poate face prin discretizarea domeniului de valori al unghiurilor de
azimut si de elevatie, corespunzatoare longitudinilor si, respectiv, latitudinilor. Azimutul
ia valori n intervalul [0, 2], n timp ce elevatia are valorile cuprinse ntre si .
Astfel, pentru o sfera modelata printr-un numar de m sectiuni latitudinale si n sectiuni
longitudinale, pasurile unghiurilor vor fi = 2/m si = /n.

In functie de unghiurile curente, i = i si j = j /2, se obtin vertexurile


de coordonate pi,j = (xi,j , yi,j , zi,j ), pentru care xi,j = r cos j cos i , yi,j = r sin j si
zi,j = r cos j sin i , cu ajutorul carora se vor construi poligoanelele elementare. Coor-
donatele de texturare asociate vertexurilor j vor fi i/m si j/n.

Pentru a obtine rezultatul din figura 7.7 se poate utiliza exemplul 7.3, cu parametrii
m = 30, n = 20 si textura de dimensiune 512 256 texeli. Functia CreateSphere() nou
creata are ca rol generarea unei sfere discrete poligonale. Sintaxa functiei este:
CreateSphere(centerx, centery, centerz, r, m, n, method);
unde centerx, centery si centerz sunt coodonatele centrului sferei, r este raza sferei,
76 CAPITOLUL 7. TEXTURI

m si n sunt numarul de sectiuni latitudinale si, respectiv, longitudinale, iar method re-
prezinta tipul de poligonale elementare utilizate (0 pentru poligoane triunghiulare sau 1
pentru poligoane rectangulare).

Exemplul 7.3 Texturarea unei sfere

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

#define tex_width 512


#define tex_height 256
static GLubyte texImage[tex_width][tex_height][3];
static GLuint texName[1];
const float PI = 3.14159265358979f;

void ReadTexture(void) {
FILE * file;
GLubyte data;
int i,j,k;
file=fopen("earth.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
ReadTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}

void reshape(int w, int h) {


glViewport(0, 0, w, h);
7.2. COORDONATE POLIGONALE DE TEXTURARE 77

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,4,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1,2,5,0,0,0,0,1,0);
}

void CreateSphere(double cx, double cy, double cz, double r,


int m, int n, int method) {
int i,j; // variabile incrementare
float t1,t2,t3; // variabile pas unghiuri
float nx, ny, nz; // variabile vectori normale
float px, py, pz; // variabile vertex

for (j=0; j<n; j++) { // incrementare unghi elevatie


t1 = j * PI / n - PI / 2; // phi j
t2 = (j+1) * PI / n - PI / 2; // phi j+1

if (method == 0)
glBegin(GL_QUAD_STRIP); // poligonare rectangulara
else
glBegin(GL_TRIANGLE_STRIP); // poligonare triunghiulara

for (i=0; i<=m; i++) { // incrementare unghi azimut

t3 = i * 2 * PI / m; // theta i

nx = cos(t1) * cos(t3); // cordonate vector normala


ny = sin(t1);
nz = cos(t1) * sin(t3);
px = cx + r * nx; // coordonate vertex curent
py = cy + r * ny;
pz = cz + r * nz;
glNormal3f(nx,ny,nz); // vector normala
// coordonate textura
glTexCoord2f(i/(double)m,j/(double)n);
glVertex3f(px,py,pz); // vertex curent

nx = cos(t2) * cos(t3); // coordonate vector normala


ny = sin(t2);
nz = cos(t2) * sin(t3);
px = cx + r * nx; // coordonate vertex curent
py = cy + r * ny;
pz = cz + r * nz;
glNormal3f(nx,ny,nz); // vector normala
// coordonate textura
glTexCoord2f(i/(double)m,(j+1)/(double)n);
glVertex3f(px,py,pz); // vertex curent
78 CAPITOLUL 7. TEXTURI

}
glEnd();
}
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
CreateSphere(0.0, 0.0, 0.0, 1.0, 30, 20, 1);
glDisable(GL_TEXTURE_2D);
glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Texturare sfera");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

7.3 Coordonate automate de texturare


Generarea automata a coordonatelor de texturare este utila n cazul n care se doreste
simularea reflexiei ntr-un mediu arbitrar sau a unui obiect stralucitor.
In locul generarii coordonatelor de texturare de catre utilizator prin instructiunea
glTexCoord(), OpenGL permite generarea automata a acestor coordonate cu ajutorul
instructiunii glTexGen(), astfel:
glTexGen{i|f|d}(coord, pname, param);
glTexGen{i|f|d}v(*coord, pname, *param);
unde coord reprezinta coordonata texturii care urmeaza a fi generata (GL_S, GL_T, GL_R
sau GL_Q), parametrul pname poate avea valorile GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE
sau GL_EYE_PLANE.

In cazul n care pname este GL_TEXTURE_GEN_MODE, valorile posibile ale lui param sunt
GL_OBJECT_LINEAR, GL_EYE_LINEAR sau GL_SPHERE_MAP si specifica tipul functiei utili-
zate la generarea coordonatelor de texturare.

In exemplul 7.4 se prezinta o aplicatie care are ca scop proiectia obiectelor din scena
pe o suprafata sferica (Sphere Environment Mapping).
7.3. COORDONATE AUTOMATE DE TEXTURARE 79

Exemplul 7.4 Proiectia sferica a scenei

#include <GL/glut.h>
#include <stdio.h>

#define tex_width 256


#define tex_height 256
static GLubyte texImage[tex_width][tex_height][3];
static GLuint texName[1];

void ReadTexture(void) {
FILE * file;
GLubyte data;
int i,j,k;

file=fopen("scena.raw", "rb");
for (i=0; i<tex_width; i++){
for (j=0; j<tex_height; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
texImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
ReadTexture();
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, texImage);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

// definirea textur\u{a}rii sferice a scenei


glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
80 CAPITOLUL 7. TEXTURI

void reshape(int w, int h) {


glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,w/h,0,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3,3,3,0,0,0,0,1,0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glutSolidSphere(1,60,64);
glDisable(GL_TEXTURE_2D);
glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Texturare sferica a scenei");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

Proiectia sferica este realizata cu ajutorul urmatoarelor setari:

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);


glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);

De remarcat faptul ca, pentru a obtine un rezultat cat mai realist, imaginea utilizata
ca textura trebuie sa reprezinte proiectia sferica ntr-un unghi solid de 180 a scenei re-
flectate pe sfera pe care se aplica texturarea. Daca se doreste un realism cat mai apropiat
de reflexia obtinuta pe o sfera metalica, trebuie inclusi si parametrii de material ai sferei,
precum si activarea unei surse de iluminare a scenei.

Rezultatul exemplului 7.4, precum si imaginea utilizata la texturare, pot fi observate


n figura 7.8.
7.3. COORDONATE AUTOMATE DE TEXTURARE 81

Textur (256x256) Rezultat

Figura 7.8: Rezultatul texturarii sferice a unei scene

In afara de texturarea sferica, mai exista posibilitatea generarii automate a coordo-


natelor de texturare prin intermediul modurilor GL_OBJECT_PLANES si GL_EYE_PLANE,
bazate pe distantele dintre vertexurile poligoanelor si un anumit plan. In primul mod,
GL_OBJECT_PLANES, textura este fixata n coordonatele obiectului, n timp ce, n modul
GL_EYE_PLANES, textura este fixa n coordonatele de vizualizare.

In 3D, un plan este definit de ecuatia implicita Ax + By + Cx + D = 0. Coeficientii


A, B si C caracterizeaza orientarea (directia) planului si reprezinta normala (vectorul
perpendicular) pe plan. Coeficientul D determina distanta planului respectiv n raport
cu originea sistemului de coordonate (n cazul n care vectorul [ABC] este unitar).

Ecuatiile Ax+By +Cx+D = 0 si N Ax+N By +N Cx+N D = 0 definesc acelasi plan,


n schimb modifica valoarea coordonatelor de texturare cu o cantitate proportionala cu
N , obtinandu-se rezultate diferite (caracterizeaza frecventa de aparitie a texturii/scalare).

Parametru Valoare parametru (param)

GL_TEXTURE_WRAP_S GL_CLAMP, GL_REPEAT

GL_TEXTURE_WRAP_T GL_CLAMP, GL_REPEAT

GL_TEXTURE_MAG_FILTER GL_NEAREST, GL_LINEAR

GL_TEXTURE_MIN_FILTER GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,

GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,

GL_LINEAR_MIPMAP_LINEAR

GL_TEXTURE_BORDER_COLOR orice patru valori n intervalul [0.0, 1.0]

GL_TEXTURE_PRIORITY [0.0, 1.0] pentru obiectul texturat curent


Capitolul 8

Animatii cu sprite-uri

8.1 Sprite-uri
Un sprite reprezinta o imagine compusa din cadre succesive cu aceiasi dimensiune. De
obicei sprite-urile reprezinta caractere sau obiecte animate ale unei aplicatii sau jocuri.
Fiecare cadru contine pictograma caracterului sau a obiectului, reprezentata pe un fundal
transparent.

Figura 8.1: Imagine de tip sprite cu sase cadre succesive ale unui caracter

Sprite-urile sunt suprapuse n aplicatie pe un fundal care este afisat decupat doar ntr-
o portiune rectangulara. Regiunea se poate deplasa lateral pentru a simula miscarea n
spatiu. Acest tip de fundal se numeste Side-Scrolling Background. La modificarea pozitiei
sprite-ului, regiunea afisata se va deplasa lateral cu o anumita viteza pe principiul unei
ferestre glisante.

Regiunea transparenta a fiecarui cadru din sprite este utila pentru a vizualiza fundalul
si a elimina efectul nedorit al unui obiect opac rectangular. In acest scop se vor utiliza
propritatile de afisare cu transparenta a texturilor.

Figura 8.2: Exemplu de fundal de tip Side-Scrolling

82
8.1. SPRITE-URI 83

K WW K WW + WW

HW

WW

Figura 8.3: Principiul deplasarii ferestrei glisante pe imaginea de fundal

Pentru deplasarea simultana a caracterului si a fundalului se utilizeaza o variabila


contor K a cadrului curent. In functie de aceasta valoare, fundalul B[K] va fi afisat
partial sub forma unei texturi de dimensiunea ferestrei aplicatiei (WW , HW ), care este
decupata din ntreaga imagine de fundal IB ncepand cu coordonata (K WW , 0). La
fiecare modificare a valorii contorului K fundalul va fi deplasat stanga sau dreapta cu
incrementul WW .

B[K] = IB [K WW : K WW + WW , 0 : HW ] . (8.1)

Simultan, cadrul curent afisat S[K] al spirite-ului IS este dat de valoarea modulo N a
valorii variabile contor K, unde N este numarul total de cadre din imaginea sprite.

S[K] = IS [modN (K 1)/N WS : (modN (K))/N WS , 0 : HS ] . (8.2)

Suprapunerea cadrului curent din imaginea sprite peste fundal se face prin aplicarea
unei combinari cu transparenta pentru cele doua imagini considerate ca fiind doua texturi
poligonale suprapuse.
(K { 1)/N WS K/N WS

K=1 K=2 K=3 K=4 K=5 K=6

HS

WS

Figura 8.4: Principiul selectarii cadrului curent din imaginea sprite


84 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

Combinarea transparenta se activeaza prin intermediul instructiunii glEnable() avand


ca argument GL_BLEND. Exista mai multe tipuri de combinatii posibile, stabilite prin
intermediul isntructiunii glBlendFunc()

glBlendFunc(sFactor, dFactor)

unde sFactor specifica modul de calcul al coeficientilor de combinare ai sursei, iar dFactor
specifica modul de calcul al coeficientilor de combinare ai destinatiei pentru fiecare din
cele patru argumente de culoare (R, G, B si A). Prin sursa se nteleg cele patru argumente
care se doresc a fi suprapuse (sosesc n buffer-ul video), n timp ce destinatia reprezinta
valorile celor patru argumente deja existente n buffer-ul video la momentul suprapunerii.

Parametru Mod de calcul (fR , fG , fB , fA )

GL_ZERO (0, 0, 0, 0)

GL_ONE (1, 1, 1, 1)

GL_SRC_COLOR (Rs0 /kR , Gs0 /kG , Bs0 /kB , As0 /kA )

GL_ONE_MINUS_SRC_COLOR (1, 1, 1, 1) (Rs0 /kR , Gs0 /kG , Bs0 /kB , As0 /kA )

GL_DST_COLOR (Rd0 /kR , Gd0 /kG , Bd0 /kB , Ad0 /kA )

GL_ONE_MINUS_DST_COLOR (1, 1, 1, 1) (Rd0 /kR , Gd0 /kG , Bd0 /kB , Ad0 /kA )

GL_SRC_ALPHA (As0 /kA , As0 /kA , As0 /kA , As0 /kA )

GL_ONE_MINUS_SRC_ALPHA (1, 1, 1, 1) (As0 /kA , As0 /kA , As0 /kA , As0 /kA )

GL_DST_ALPHA (Ad0 /kA , Ad0 /kA , Ad0 /kA , Ad0 /kA )

GL_ONE_MINUS_DST_ALPHA (1, 1, 1, 1) (Ad0 /kA , Ad0 /kA , Ad0 /kA , Ad0 /kA )

GL_CONSTANT_COLOR (Rc , Gc , Bc , Ac )

GL_ONE_MINUS_CONSTANT_COLOR (1, 1, 1, 1) (Rc , Gc , Bc , Ac )

GL_CONSTANT_ALPHA (Ac , Ac , Ac , Ac )

GL_ONE_MINUS_CONSTANT_ALPHA (1, 1, 1, 1) (Ac , Ac , Ac , Ac )

GL_SRC_ALPHA_SATURATE (i, i, i, 1)

GL_SRC1_COLOR (Rs1 /kR , Gs1 /kG , Bs1 /kB , As1 /kA )

GL_ONE_MINUS_SRC1_COLOR (1, 1, 1, 1) (Rs1 /kR , Gs1 /kG , Bs1 /kB , As1 /kA )

GL_SRC1_ALPHA (As1 /kA , As1 /kA , As1 /kA , As1 /kA )

GL_ONE_MINUS_SRC1_ALPHA (1, 1, 1, 1) (As1 /kA , As1 /kA , As1 /kA , As1 /kA )

min (As ,kA Ad )


unde i = kA
.

Relatia de calcul pentru fiecare din cele patru canale de culoare (RGBA) este determi-
nata cu ajutorul ecuatiei 8.3.

Cbuf f er = Csursa sF actor + Cbuf f er dF actor (8.3)


8.1. SPRITE-URI 85

Obiect (384x128x3)

Fundal (512x384x3) Masc transparen obiect (384x128x1)

Figura 8.5: Imagini utilizate pentru exemplificarea aplicarii transparentei

Combinarea se face ntotdeauna ntre informatia existenta n buffer-ul video (denumit


destinatie) si imaginea curenta (denumita sursa). De exemplu, suprapunerea unei imagini
cu un anumit grad de transparenta peste o imagine opaca deja existenta n buffer-ul video
se face prin intermediul operatiei:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),

ceea ce seminifica faptul ca fiecare canal de culoare rezultat va fi compus ca suma dintre cu-
loarea imaginii sursa si culoarea deja existenta multiplicata cu coeficientul de transparenta
al imaginii sursa.

dColor = sColor + (1-sAlpha)*dColor

Canalul ALPHA este considerat ca fiind opacitatea unui obiect si are valori normate
curpinse n intervalul [0, 1]. Prin urmare, valoarea 0 reprezinta transparenta totala, n
timp ce valoarea 1 este caracteristica unei opacitati totale.

Canal R (Red)

Canal G (Green)

Canal B (Blue)

Canal A (Alpha)

Figura 8.6: Canalele de culoare si transparenta ale obiectului din figura 8.5
86 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

Pentru ca o imagine sa contina informatia de transparenta, aceasta trebuie sa contina


cele patru canale, respectiv R, G, B si A (vezi figura 8.6). In cazul utilizarii unei imagini n
format RAW pentru stocarea obiectului, deoarece acest format nu permite stocarea decat
trei canale (RGB), este necesar un fisier suplimentar RAW cu un singur canal (grayscale)
alocat informatiei de transparenta. In exemplul din figura 8.5 s-a utilizat fisierul obj.raw
de tip 24 BPP RGB pentru stocarea obiectului suprapus pe fundal si fisierul mask.raw
de tip 8 BPP Grayscale pentru informatia de transparenta.

In cazul n care fundalul este reprezentat doar pe cele trei canale de culoare (RGB),
canalul de transparenta al acestuia este considerat implicit opac.

Exemplul 8.1 Aplicarea unui obiect cu transparenta pe un fundal opac

#include <GL/glut.h>
#include <stdio.h>

#define bg_w 512 // Dimensiuni imagine fundal


#define bg_h 384
#define ob_w 384 // Dimensiuni imagine obiect
#define ob_h 128

static GLubyte bgImage[bg_w][bg_h][3]; // memorie imagine fundal


static GLubyte spImage[ob_w][ob_h][4]; // memorie imagine obiect
static GLuint texName[2]; // etichete texturi utilizate

void readBG(void) { // procedura citire imagine fundal


FILE * file;
GLubyte data; int i,j,k;
file=fopen("bg.raw", "rb");
for (i=0; i<bg_w; i++){
for (j=0; j<bg_h; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
bgImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void readSP(void) { // procedura citire imagine obiect


FILE * file;
GLubyte data; int i,j,k;
file=fopen("obj.raw", "rb");
for (i=0; i<ob_w; i++){
for (j=0; j<ob_h; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
8.1. SPRITE-URI 87

spImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void readMK(void) { // procedura citire masca sprite


FILE * file;
GLubyte data; int i,j;
file=fopen("mask.raw", "rb");
for (i=0; i<ob_w; i++){
for (j=0; j<ob_h; j++){
fread(&data, 1, 1, file);
spImage[i][j][3]=(GLubyte)data;
}
}
fclose(file);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);

readBG(); // Citire fisier imagine fundal


readSP(); // Citire fisier imagine obiect
readMK(); // Citire fisier imagine transparenta

glGenTextures(2, texName);

glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bg_w, bg_h, 0,
GL_RGB, GL_UNSIGNED_BYTE, bgImage);

glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ob_w, ob_h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, spImage);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Mod combinare
glEnable(GL_TEXTURE_2D);
}
88 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

void display(void) {
glBindTexture(GL_TEXTURE_2D, texName[0]); // Selectare fundal

glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1.0, 1.0);
glTexCoord2f(1, 0);
glVertex2f(1.0, 1.0);
glTexCoord2f(1, 1);
glVertex2f(1.0, -1.0);
glTexCoord2f(0, 1);
glVertex2f(-1.0, -1.0);
glEnd();

glEnable(GL_BLEND); // Activare combinare imagini

glBindTexture(GL_TEXTURE_2D, texName[1]); // Selectare obiect

glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-0.9, 0.8);
glTexCoord2f(1, 0);
glVertex2f(0.612, 0.8);
glTexCoord2f(1, 1);
glVertex2f(0.612, 0.05);
glTexCoord2f(0, 1);
glVertex2f(-0.9, 0.05);
glEnd();

glDisable(GL_BLEND); // Dezactivare combinare imagini

glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (640, 480);
glutCreateWindow("Combinare imagini cu transparenta");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

In figura 8.7 sunt prezentate comparativ rezultatele posibile ale combinarii imaginilor
din figura 8.5 cu diferite argumente ale functiei glBlendFunc().
8.1. SPRITE-URI 89

glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ZERO); glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);


glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ZERO); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);


glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_DST_ALPHA, GL_ONE); glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_DST_ALPHA, GL_ZERO); glBlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA);


glBlendFunc(GL_ONE, GL_ONE); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ZERO);
glBlendFunc(GL_DST_ALPHA, GL_DST_ALPHA); glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glBlendFunc(GL_ONE, GL_DST_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);


glBlendFunc(GL_ZERO, GL_ONE); glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ZERO, GL_ZERO); glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_DST_COLOR, GL_ONE); glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_DST_COLOR, GL_ZERO); glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);


glBlendFunc(GL_DST_COLOR, GL_DST_ALPHA); glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA);


glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_ALPHA);

glBlendFunc(GL_SRC_COLOR, GL_ONE); glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_COLOR, GL_ZERO); glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);


glBlendFunc(GL_SRC_COLOR, GL_DST_ALPHA); glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_DST_ALPHA);

Figura 8.7: Rezultate ale combinatiilor imaginilor din figura 8.5


90 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

Pornind de la exemplu de combinare a imaginilor cu transparenta se poate imagina un


simplu joc cu sprite-uri pornind de la cele doua imagini din figura 8.1 ca obiect si figura
8.2 ca fundal. Obiectul este deplasat prin intemediul tastelor A si S si afisat normal
sau n oglinda, n functie de sensul deplasarii.

Exemplul 8.2 Joc cu sprite

#include <GL/glut.h>
#include <stdio.h>

#define bg_w 1024 // Dimensiuni imagine fundal


#define bg_h 256
#define ob_w 768 // Dimensiuni imagine sprite
#define ob_h 64

static GLubyte bgImage[bg_w][bg_h][3]; // memorie imagine fundal


static GLubyte spImage[ob_w][ob_h][4]; // memorie imagine sprite
static GLuint texName[2]; // etichete texturi utilizate

bool fullscreen=false; // Variabila stare Fullscreen


bool sensDirect=true; // Variabila stare sens deplasare

char K=0; // Frame curent sprite


float W1,W3=0; // Coordonate texturare fundal
float W4=0.16;

void readBG(void) { // procedura citire imagine fundal


FILE * file;
GLubyte data; int i,j,k;
file=fopen("bg.raw", "rb");
for (i=0; i<bg_w; i++){
for (j=0; j<bg_h; j++){
for (k=0; k<3; k++){
fread(&data, 1, 1, file);
bgImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void readSP(void) { // procedura citire imagine sprite


FILE * file;
GLubyte data; int i,j,k;
file=fopen("sprite.raw", "rb");
for (i=0; i<ob_w; i++){
for (j=0; j<ob_h; j++){
for (k=0; k<3; k++){
8.1. SPRITE-URI 91

fread(&data, 1, 1, file);
spImage[i][j][k]=(GLubyte)data;
}
}
}
fclose(file);
}

void readMK(void) { // procedura citire masca sprite


FILE * file;
GLubyte data; int i,j,k;
file=fopen("mask.raw", "rb");
for (i=0; i<ob_w; i++){
for (j=0; j<ob_h; j++){
fread(&data, 1, 1, file);
spImage[i][j][3]=(GLubyte)data;
}
}
fclose(file);
}

void reshape (int w, int h) {


glViewport(0,0,w,h);
glClear(GL_COLOR_BUFFER_BIT);
}

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);

readBG();
readSP();
readMK();

glGenTextures(2, texName);

glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bg_w, bg_h, 0,
GL_RGB, GL_UNSIGNED_BYTE, bgImage);

glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ob_w, ob_h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, spImage);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
92 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

glEnable(GL_TEXTURE_2D);
}

void display(void) {

glBindTexture(GL_TEXTURE_2D, texName[0]);

glBegin(GL_QUADS);
glTexCoord2f(W1, 0);
glVertex2f(-1.0, 1.0);
glTexCoord2f(W1+0.5, 0);
glVertex2f(1.0, 1.0);
glTexCoord2f(W1+0.5, 1);
glVertex2f(1.0, -1.0);
glTexCoord2f(W1, 1);
glVertex2f(-1.0, -1.0);
glEnd();

if (sensDirect) {
W3=0.16*K;
W4=0.16*(K-1);
}
else {
W3=0.16*(K-1);
W4=0.16*K;
}

glBindTexture(GL_TEXTURE_2D, texName[1]);

glEnable(GL_BLEND);

glBegin(GL_QUADS);
glTexCoord2f(W3, 0);
glVertex2f(-0.2, -0.25);
glTexCoord2f(W4, 0);
glVertex2f(0.2, -0.25);
glTexCoord2f(W4, 1);
glVertex2f(0.2, -0.67);
glTexCoord2f(W3, 1);
glVertex2f(-0.2, -0.67);
glEnd();

glDisable(GL_BLEND);

glFlush();
}

void keyboard (unsigned char key, int x, int y) {


switch (key) {
8.1. SPRITE-URI 93

case a: { // Deplasarea stanga


K=(K+1)%6;
if (W1>0) W1=W1-0.01;
sensDirect=false;
break;
}
case s: { // Deplasare dreapta
K=(K+1)%6;
if (W1<0.49) W1=W1+0.01;
sensDirect=true;
break;
}
case 27: { // Terminare joc
exit(0); break;
}
case 13: // Full Screen
if (fullscreen) {
glutReshapeWindow(512, 256);
glutPositionWindow(100, 100);
fullscreen=false;
}
else {
glutFullScreen();
fullscreen=true;
}
break;
default : break;
}
glutPostRedisplay();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (512, 256);
glutCreateWindow("Animatie cu sprite");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}

Schimbarea sensului deplasarii are ca efect inversarea coordonatelor de texturare pe


orizontala a cadrului curent din imaginea sprite (variabilele W3 si W4 ).
94 CAPITOLUL 8. ANIMAT
II CU SPRITE-URI

Figura 8.8: Captura a aplicatiei din exemplul 8.2

Pentru a nu depasi cadrul imaginii de fundal se verifica n permanenta limita infe-


rioara (W1 > 0) si superioara (W1 < 0.49) a coordonatelor de texturare, cadrul curent
reprezentand 50% din latimea imaginii de fundal.
Capitolul 9

Curbe si suprafete parametrice

Curbele si suprafetele parametrice sunt definite cu ajutorul unor puncte de control care,
n functie de tipul acestora (Bezier, Spline etc.), au diferite semnificatii. In OpenGL, pen-
tru generarea curbelor si a suprafetelor parametrice se utilizeaza polinoamele Bezier n
cadrul evaluatorilor.

9.1 Curbe B
ezier
O curba Bezier reprezinta o functie de o variabila (parametru):

C(u) = [ X(u) Y(u) Z(u) ], (9.1)

unde u variaza ntr-un domeniu finit (de obicei, n intervalul [0, 1]).

Pentru a construi curba C(u), este necesara determinarea tuturor valorilor celor trei
functii asociate axelor de coordonate, n functie de variatia parametrului u n intervalul
de definitie. Acest lucru este efectuat n OpenGL prin intermediul evaluatorilor.

O curba Bezier cubica este definita prin intermediul a patru puncte de control. Astfel,
pentru a initializa o astfel de curba este necesara apelarea instructiunii glMap1(), astfel:

glMap1{f|d}(target, umin, umax, stride, order, *points);

unde target specifica tipul punctelor de control si, implicit, determina numarul de puncte
necesare a fi incluse n vectorul *points, umin si umax definesc limitele de variatie ale pa-
rametrului u, stride reprezinta numarul de puncte din vectorul *points dintre doua
puncte de control succesive, iar order este ordinul curbei (gradul polinomului plus 1).

Evaluarea propriu-zisa a valorilor curbei n intervalul de variatie a parametrului u se


face prin intermediul instructiunii glEvalCoord1():

glEvalCoord1{f|d}(u);
glEvalCoord1{f|d}v(*u);

unde u are o valoare curenta din intervalul de variatiei al parametrului u.

95
96 CAPITOLUL 9. CURBE SI SUPRAFET
E PARAMETRICE

Parametrul target Semnificatie puncte (*points)

GL_MAP1_VERTEX_3 coordonatele vertexurilor x, y, z

GL_MAP1_VERTEX_4 coordonatele vertexurilor x, y, z, w

GL_MAP1_INDEX culori indexate

GL_MAP1_COLOR_4 R, G, B, A

GL_MAP1_NORMAL coordonate vectorului normala

GL_MAP1_TEXTURE_COORD_1 coordonatele s ale texturii

GL_MAP1_TEXTURE_COORD_2 coordonatele s, t ale texturii

GL_MAP1_TEXTURE_COORD_3 coordonatele s, t, r ale texturii

GL_MAP1_TEXTURE_COORD_4 coordonatele s, t, r, q ale texturii

Desi valorile parametrului u pot fi alese oriunde n interval, de obicei se utilizeaza


divizarea uniforma a acestuia ntr-un numar de n valori, cu instructiunea glMapGrid1():

glMapGrid1{f|d}(n, umin, umax);

unde n are aceeasi semnificatie cu n.

Pentru a aplica aceeasi divizare tuturor evaluatorilor, se foloseste glEvalMesh():

glEvalMesh1(mode, p1, p2);

unde mode poate lua valorile GL_POINT sau GL_LINE, iar p1 si p2 definesc intervalul de
variatie al parametrului, conform formulei:

u = umin + i (umax umin )/n, i [p1, p2]. (9.2)

In exemplul 9.1 se prezinta trasarea unei curbe Bezier de ordinul 4 (cubica) cu patru
puncte de control si cu parametrul u n intervalul [0, 1] si 30 de puncte de subdivizare.

Exemplul 9.1 Curba Bezier de ordinul 4

#include <GL/glut.h>

GLfloat puncte_control[4][3] = { // puncte de control


{-4.0, -4.0, 0.0},
{ 4.0, -4.0, 0.0},
{-4.0, 0.0, 0.0},
{ 4.0, 4.0, 0.0}
};

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);

9.1. CURBE BEZIER 97

// curba Bezier de ordinul 4


glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &puncte_control[0][0]);
glEnable(GL_MAP1_VERTEX_3);
}

void reshape(int w, int h) {


glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void display(void) {
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);

glBegin(GL_LINE_STRIP); // evaluare puncte pe curba


for (i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();

glPointSize(5.0); // afisare puncte de control


glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++)
glVertex3fv(&puncte_control[i][0]);
glEnd();

glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Curba Bezier");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
98 CAPITOLUL 9. CURBE SI SUPRAFET
E PARAMETRICE

(4, 4)

t
g en
tan c u rb

(-4, 0)

tangent
(-4, -4) (4, -4)

Figura 9.1: Generarea unei curbe Bezier cubice prin intermediul a patru puncte de control

9.2 Suprafete B
ezier
Suprafetele Bezier sunt generate similar curbelor de acelasi tip, exceptand faptul ca de
aceasta data avem de a face cu doi parametri, u si v.

Definirea evaluatorului se face cu ajutorul instructiunii glMap2():


glMap2{f|d}(target, umin, umax, ustride, uorder,
vmin, vmax, vstride, vorder, *points);
cu semnificatii ale parametrilor identice sau similare cazului monodimensional glMap1().

Evaluatorul se defineste prin intermediul comenzii glEvalCoord2(), astfel:


glEvalCoord2{f|d}(u, v);
glEvalCoord2{f|d}v(*values);

Ca si n cazul curbelor, parametrii u si v pot fi definiti echidistanti cu ajutorul instruc-


tiunii glMapGrid2() sau glEvalMesh2(), cu aceleasi semnificatii si argumente ca si n
cazul unidimensional.
glMapGrid2{f|d}(nu, umin, umax, nv, vmin, vmax);
glEvalMesh2(mode, i1, i2, j1, j2);

In exemplul 9.2 se prezinta o suprafata de tip Bezier generata cu evaluatori, definita


prin 16 puncte de control, suprafata fiind alcatuita din 16 16 patch-uri (suprafete ele-
mentare).
9.2. SUPRAFET
E BEZIER 99

Exemplul 9.2 Suprafata Bezier de ordinul 4

#include <GL/glut.h>

// 16 puncte de control (A,B,...,O,P)


GLfloat puncte_control[4][4][3] = {
{{-2.0,2.0,1.0}, {-1.0,3.0,-1.0}, {1.0,3.0,1.0}, {2.0,2.0,-1.0}},
{{-1.5,1.0,1.0}, {-0.5,1.5,-1.0}, {1.5,1.5,1.0}, {2.5,1.0,-1.0}},
{{-2.5,-1.0,1.0}, {-1.5,-0.5,-1.0}, {0.5,-0.5,1.0}, {1.5,-1.0,-1.0}},
{{-2.0,-2.0,1.0}, {-1.0,-1.0,-1.0}, {1.0,-1.0,1.0}, {2.0,-2.0,-1.0}}
};

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);

// suprafata Bezier de ordinul 4


glMap2f(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4,
0.0, 1.0, 12, 4, &puncte_control[0][0][0]);
glEnable(GL_MAP2_VERTEX_3);
glMapGrid2f(15, 0.0, 1.0, 15, 0.0, 1.0);
}

void reshape(int w, int h) {


glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,w/h,0,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5.0, 5.0, 5.0, 0.0, 0.5, 0.0, 0.0, 1.0, 0.0);
}

void display(void) {
int i, j;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);

for (j = 0; j <= 15; j++) {


glBegin(GL_LINE_STRIP);
for (i = 0; i <= 15; i++) // generare curbe verticale
glEvalCoord2f((GLfloat)i/15.0, (GLfloat)j/15.0);
glEnd();
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 15; i++) // generare curbe orizontale
glEvalCoord2f((GLfloat)j/15.0, (GLfloat)i/15.0);
glEnd();
};
100 CAPITOLUL 9. CURBE SI SUPRAFET
E PARAMETRICE

y
B

C
A
F
D
E
J
G
H
I N
L
M K

z O x
P

Figura 9.2: Generarea unei suprafete Bezier cubice prin intermediul a 16 puncte de control

glPointSize(5.0);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
glVertex3fv(&puncte_control[i][j][0]);
glEnd();
glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Suprafata Bezier");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

Pentru simplificarea codului, n locul utilizarii n procedura display a celor trei cicluri
for pentru trasarea suprafetei, acestea pot fi nlocuite cu comanda echivalenta:
glEvalMesh2(GL_LINE, 0, 16, 0, 16);
Capitolul 10

Interfete grafice (GUI)

10.1 Interactiunea cu mouse si tastatur


a
Dupa cum s-a precizat n subcapitorul 3.2, biblioteca GLUT poate gestiona o serie de
evenimente, printre care lucrul cu dispozitivele de intrare (mouse si tastatura). Functiile
asociate celor doua tipuri de evenimente sunt:
glutKeyboardFunc() pentru tastatura;
glutSpecialFunc() pentru taste speciale;
glutMouseFunc() pentru apasarea butoanelor unui mouse;
glutMotionFunc() pentru miscarea mouse-ului cu un buton apasat;
glutPassiveMotionFunc() pentru miscarea mouse-ului fara niciun buton apasat;
care au ca argument numele procedurii (apelate numai n cazul ntamplarii evenimentului
respectiv). In subcapitolele urmatoare sunt descrise exemple de gestionare a fiecarui tip
de eveniment n parte.

10.1.1 Evenimente generate de tastatur


a
In exemplul 10.1 se prezinta un exemplu pentru utilizarea tastaturii. Prin intermediul
a trei taste se vor trasa trei tipuri de obiecte utilizand o lista de sase vertexuri, astfel:
T pentru obiecte de tip GL_TRIANGLES, C pentru obiecte de tip GL_LINE_LOOP si P
pentru obiecte de tip GL_POLYGON.

Procedura care determina efectele apasarii unei taste este definita prin argumentul
instructiunii glutKeyboardFunc(). In functia argument keyboard, n functie de tasta
apasata (memorata automat de catre sistem n variabila key), se modifica valoarea unei
variabile tip care defineste tipul obiectului. Valoarea implicita este precizata la nceputul
codului, fiind 1 (obiecte de tip triunghi).

Dupa fiecare modificare efectuata ntr-un case se precizeaza necesitatea reactualizarii


ferestrei grafice prin intermediul instructiunii glutPostRedisplay();.

In procedura display obiectul este decis printr-o functie de tip switch care verifica
valoarea variabilei tip si stabileste argumentul functiei glBegin().

101
102 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

Exemplul 10.1 Utilizarea tastelor pentru alegerea tipului de obiect afisat

#include <GL/glut.h>

int tip=1; // variabila tipului de obiect


// cu valoarea initiala 1
void init (void) {
glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display (void) {


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
switch(tip) { // alegerea tipului de obiect
case 1: // pentru tip = 1 se alege
glBegin(GL_TRIANGLES); // obiectul de tip GL_TRIANGLES
case 2: // pentru tip = 2 se alege
glBegin(GL_LINE_LOOP); // obiectul de tip GL_LINE_LOOP
case 3: // pentru tip = 3 se alege
glBegin(GL_POLYGON); // obiectul de tip GL_POLYGON
}
glVertex2f(-0.8,0.0); // lista celor 6 puncte utilizate
glVertex2f(-0.8,0.8);
glVertex2f(0.0,0.8);
glVertex2f(0.8,0.0);
glVertex2f(0.8,-0.8);
glVertex2f(0.0,-0.8);
glEnd();
glFlush ();
}

void keyboard (unsigned char key, int x, int y) {


switch (key) { // modificarea variabilei tip
case t: // daca tasta apasata este t,
tip=1; // variabila tip ia valoarea 1
break;
case c: // daca tasta apasata este c,
tip=2; // variabila tip ia valoarea 2
break;
case p: // daca tasta apasata este p,
tip=3; // variabila tip ia valoarea 3
break;
}
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
10.1. INTERACT
IUNEA CU MOUSE SI TASTATURA 103

Figura 10.1: Obiectele rezultate din exemplul 10.1

glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Tastatura");
init ();
glutDisplayFunc (display);
glutKeyboardFunc (keyboard); // evenimentului tip tastatura
glutMainLoop ();
return 0;
}

De retinut faptul ca argumentele procedurii keyboard sunt prestabilite si reprezinta


codul ASCII al tastei apasate (key), precum si pozitia cursorului mouse-ului n momentul
aparitiei evenimentului (x si y).
void keyboard (unsigned char key, int x, int y);
valorile argumentelor de intrare sunt umplute automat de catre sistem n momentul
aparitiei evenimentului de apasare a unei taste.

10.1.2 Utilizarea tastelor speciale


Tastele speciale pot fi utilizate similar tastelor obisnuite cu ajutorul instructiunii GLUT
glutSpecialFunc(). Argumentul acestei instructiuni este o functie special care are ca
parametri de intrare codul key al tastei speciale apasate, precum si coordonatele x si y ale
cursorului n momentul apasarii tastei. Spre deosebire de cazul tastelor normale, variabila
codului tastelor speciale este definita de tip int, nu de tip unsigned char.
void special (int key, int x, int y);
Lista codurilor tastelor speciale este prezentata n tabelul urmator. De retinut ca
tastele ESC, backspace, TAB, delete si ENTER sunt considerate taste normale si sunt
determinate dupa codurile ASCII proprii (27, 8, 9, 127 si 13).
104 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

Cod tast
a special
a Denumire tast
a Cod tast
a special
a Denumire tast
a
GLUT_KEY_F1 Tasta F1 GLUT_KEY_LEFT Tasta sageata stanga
GLUT_KEY_F2 Tasta F2 GLUT_KEY_RIGHT Tasta sageata dreapta
GLUT_KEY_F3 Tasta F3 GLUT_KEY_UP Tasta sageata sus
GLUT_KEY_F4 Tasta F4 GLUT_KEY_DOWN Tasta sageata jos
GLUT_KEY_F5 Tasta F5 GLUT_KEY_PAGE_UP Tasta pagina sus
GLUT_KEY_F6 Tasta F6 GLUT_KEY_PAGE_DOWN Tasta pagina jos
GLUT_KEY_F7 Tasta F7 GLUT_KEY_HOME Tasta HOME
GLUT_KEY_F8 Tasta F8 GLUT_KEY_END Tasta END
GLUT_KEY_F9 Tasta F9 GLUT_KEY_INSERT Tasta Insert
GLUT_KEY_F10 Tasta F10
GLUT_KEY_F11 Tasta F11
GLUT_KEY_F12 Tasta F12

In exemplul 10.2 este prezentata o aplicatie care deplaseaza n plan un obiect grafic
simplu cu ajutorul celor patru taste sageti, permite comutarea ntre afisarea pe ntreg
ecranul sau n fereastra prin apasarea tastei ENTER, precum si terminarea programului
cu ajutorul tastei ESC.

Exemplul 10.2 Utilizarea tastelor speciale pentru deplasarea pe ecran a unui obiect grafic

#include <GL/glut.h>

bool fullscreen=0; // variabila logica mod Full Screen


float ox,oy=0; // coordonate centru obiect

void init (void) {


glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display (void) {


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glBegin(GL_LINES); // trasare obiect centrat in (ox,oy)
glVertex2f(ox-0.1,oy);
glVertex2f(ox+0.1,oy);
glVertex2f(ox,oy-0.1);
glVertex2f(ox,oy+0.1);
glEnd();
glFlush ();
}

void keyboard (unsigned char key, int x, int y) {


switch (key) {
case 27: // tasta ESC
exit(0); break;
case 13: // tasta ENTER
10.1. INTERACT
IUNEA CU MOUSE SI TASTATURA 105

if (fullscreen) {
glutReshapeWindow(320, 320);
glutPositionWindow(100, 100);
fullscreen=false;
}
else {
glutFullScreen(); // mod Full Screen
fullscreen=true;
}
break;
default:break;
}
glutPostRedisplay();
}

void special (int key, int x, int y) {


switch (key) {
case GLUT_KEY_LEFT: // tasta sageata stanga
if (ox>-0.9) ox=ox-0.1; // decrementare coordonata ox
break;
case GLUT_KEY_RIGHT: // tasta sageata dreapta
if (ox<0.9) ox=ox+0.1; // incrementare coordonata ox
break;
case GLUT_KEY_UP: // tasta sageata sus
if (oy<0.9) oy=oy+0.1; // incrementare coordonata oy
break;
case GLUT_KEY_DOWN: // tasta sageata jos
if (oy>-0.9) oy=oy-0.1; // decrementare coordonata oy
break;
default:break;
}
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Taste speciale");
init ();
glutDisplayFunc (display);
glutKeyboardFunc (keyboard); // eveniment tip taste normale
glutSpecialFunc (special); // eveniment tip taste speciale
glutMainLoop ();
return 0;
}
106 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

x y

1 320 1
1

y
-1 1 x

320
-1

Coordonate ecrane (pixeli) Coordonate scen (unitare)

Figura 10.2: Modificarea coordonatelor din valori absolute ale ecranului n coordonate unitare centrate

10.1.3 Evenimente generate de mouse


Spre deosebire de evenimentul generat prin apasarea unei taste, n cazul unui mouse
avem de a face cu mai multe tipuri de evenimente, cum ar fi apasarea unuia din butoanele
mouse-ului si miscarea mouse-ului. In plus, apasarea butonului poate avea mai multe
stari: buton ramas apasat (pressed ) sau buton eliberat (released ).

Corespunzator celor doua tipuri de evenimente posibile pentru un mouse, avem la


dispozitie functiile glutMouseFunc(), glutMotionFunc() si glutPassiveMotionFunc().
Argumentul functiei glutMouseFunc() este numele procedurii apelate n cazul aparitiei
evenimentului respectiv. Procedura poate avea orice denumire (de exemplu, mouse), dar
are ca intrari ntotdeauna patru variabile de tip int:
void mouse (int button, int state, int x, int y);
unde button reprezinta indicele butonului de mouse apasat, state este starea acestuia,
iar x si y sunt pozitiile cursorului la momentul evenimentului.

Valorile posibile ale variabilei button sunt GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON


si GLUT_RIGHT_BUTTON. Variabila de stare a butonului, state, poate avea valorile GLUT_UP
sau GLUT_DOWN, cu interpretarile evidente. Pentru pozitia mouse-ului, x si y au valorile n
pixeli, relative la coltul din stanga sus al ferestrei grafice.

Pentru functiile glutMotionFunc() si glutPassiveMotionFunc(), procedura apelata


contine doua variabile, x si y, deoarece nu se iau n considerare tipul si starea butonului
de mouse apasat, ci doar aparitia evenimentului si pozitia mouse-ului:
void motion (int x, int y);
Exemplul 10.3 prezinta o aplicatie care are ca scop afisarea unui cursor n forma de
cruce la pozitia curenta n momentul apasarii butonului din stanga al mouse-ului.
10.1. INTERACT
IUNEA CU MOUSE SI TASTATURA 107

Exemplul 10.3 Crearea si deplasarea unui cursor cu ajutorul mouse-ului

#include <GL/glut.h>

float x0 = 160, y0 = 160; // variabilele coordonate curente

void init (void) {


glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display (void) {


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f(x0/160-1,1-y0/160-0.05); // desenarea cursorului
glVertex2f(x0/160-1,1-y0/160+0.05); // la coordonatele
glVertex2f(x0/160-1-0.05,1-y0/160); // normate si centrate
glVertex2f(x0/160-1+0.05,1-y0/160);
glEnd();
glFlush();
}

void mouse (int button, int state, int x, int y) {


if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
x0=x; y0=y; // extragerea coordonatelor la apasare buton stanga
}
glutPostRedisplay();
}

void motion (int x, int y) {


x0=x; y0=y; // extragerea coordonatelor la buton apasat
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Cursor");
init ();
glutDisplayFunc (display);
glutMouseFunc (mouse); // eveniment apasare buton de mouse
glutMotionFunc (motion); // eveniment deplasare mouse cu buton apasat
glutMainLoop ();
return 0;
}
108 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

GLUT_LEFT_BUTTON

GL
UT
_D
OW
N
Figura 10.3: Aparitia continu
a a cursorului prin tinerea apasata a butonului stanga a mouse-ului si
deplasarea acestuia

Pastrarea apasata a butonului respectiv, concomitent cu deplasarea mouse-ului n fe-


reastra are ca efect modificarea pozitiei cursorului conform cu pozitia mouse-ului.

Initial se definesc doua variabile, x0 si y0, de tip float, care vor avea ca scop memo-
rarea pozitiei mouse-ului n momentul aparitiei unui eveniment asociat dispozitivului.
Acestea sunt initializate n mijlocul ecranului. Procedura mouse are ca scop crearea unui
cursor n forma de cruce la pozitia curenta n momentul n care este apasat (GLUT_DOWN)
butonul din stanga al mouse-ului (GLUT_LEFT_BUTTON).

Daca mouse-ul este deplasat si butonul din stanga ramane apasat, exista n consecinta
un eveniment continuu care este gestionat prin apelarea procedurii motion prin interme-
diul functiei glutMotionFunc(motion). La fiecare miscare a mouse-ului n aceasta stare
este memorata din nou pozitia curenta, dupa care se reafiseaza cursorul.

Deoarece valorile x0 si y0 extrase sunt exprimate n pixeli, acestea trebuie reconver-


tite n intervalul [1, 1]. Acest lucru este efectuat prin normare la dimensiunile ferestrei,
inversarea coordonatei y si centrarea fata de originea axelor (figura 10.2).

In cazul n care se doreste modificarea aplicatiei astfel ncat cursorul sa fie afisat
oricand, indiferent de starea de apasare a butoanelor mouse-ului, se utilizeaza functia
glutPassiveMotionFunc(), noul cod fiind prezentat n exemplul 10.4.

In acest caz, functia glutMouseFunc() nu mai este utila, fiind eliminata mpreuna
cu procedura mouse asociata. In schimb, procedura motion ramane neschimbata, fiind
apelata atat de catre functia glutPassiveMotionFunc() (n cazul n care nu se apasa
niciun buton), cat si de functia glutMotionFunc() (n cazul n care unul dintre butoane
este apasat).
10.1. INTERACT
IUNEA CU MOUSE SI TASTATURA 109

Exemplul 10.4 Afisarea cursorului mouse-ului

#include <GL/glut.h>

float x0 = 160, y0 = 160;

void init (void) {


glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display (void) {


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f(x0/160-1,1-y0/160-0.05);
glVertex2f(x0/160-1,1-y0/160+0.05);
glVertex2f(x0/160-1-0.05,1-y0/160);
glVertex2f(x0/160-1+0.05,1-y0/160);
glEnd();
glFlush();
}

void motion (int x, int y) {


x0=x;
y0=y;
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Cursor");
init ();
glutDisplayFunc (display);
glutPassiveMotionFunc (motion); // deplasare mouse fara buton apasat
glutMainLoop ();
return 0;
}

Pentru ambele tipuri de evenimente se apeleaza aceeasi procedura motion, deoarece n


situatia de fata nu este important tipul butonului apasat (n cazul n care acest lucru se
ntampla). Procedura display ramane identica celei din exemplul 10.3.
110 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

Figura 10.4: Rezultatul apelarii meniului aplicatiei 10.4

10.2 Crearea meniurilor


Pentru crearea meniurilor se utilizeaza instructiunile oferite de bibliotecile GLUT si
GLUI. Meniurile oferite de biblioteca GLUT sunt mai simple fata de cele din GLUI.

Meniurile bibliotecii GLUT se introduc n partea principala a programului (main) si


sunt create cu instructiunea glutCreateMenu(). Argumentul acestei instructiuni repre-
zinta numele procedurii apelate n cazul apelarii meniului n timpul rularii aplicatiei.

Optiunile meniului creat anterior sunt introduse una cate una cu ajutorul instructiunii
glutAddMenuEntry(), avand ca argumente denumirea optiunii si valoarea acesteia.

In final, meniul trebuie asociat unui buton de mouse, specificand acest buton ca argu-
ment al instructiunii glutAttachMenu().

int main (...) {


...
glutCreateMenu(color);
glutAddMenuEntry("Red",Opt1);
glutAddMenuEntry("Green",Opt2);
glutAddMenuEntry("Blue",Opt3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
...
}

In exemplul 10.5 este prezentata o aplicatie care permite selectarea culorii de umplere
a unui obiect poligonal cu ajutorul unui meniu apelabil prin intermediul butonului din
dreapta al mouse-ului.
10.2. CREAREA MENIURILOR 111

Exemplul 10.5 Aplicatie care utilizeaza meniul bibliotecii GLUT

#include <GL/glut.h>

#define Opt1 1 // definirea celor trei optiuni de culoare


#define Opt2 2
#define Opt3 3

float R, G, B = 1; // definirea variabilelor de culoare

void init (void) {


glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display (void) {


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(R,G,B); // stabilirea culorii obiectului
glBegin(GL_POLYGON);
glVertex2f(0.0,0.5);
glVertex2f(-0.5,-0.5);
glVertex2f(0.5,-0.5);
glEnd();
glutSwapBuffers();
}

void color (int option) { // procedura de selectare a culorii


switch (option) {
case Opt1: // optiunea 1
R=1;G=0;B=0;
break;
case Opt2: // optiunea 2
R=0;G=1;B=0;
break;
case Opt3: // optiunea 3
R=0;G=0;B=1;
break;
}
glutPostRedisplay();
}

int main (int argc, char** argv) {


glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize (320, 320);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Meniu GLUT");
init ();
glutDisplayFunc (display);
112 CAPITOLUL 10. INTERFET
E GRAFICE (GUI)

glutIdleFunc (display);
glutCreateMenu (color); // creare meniu
glutAddMenuEntry ("Red", Opt1); // creare optiunea 1
glutAddMenuEntry ("Green", Opt2); // creare optiunea 2
glutAddMenuEntry ("Blue", Opt3); // creare optiunea 3
glutAttachMenu (GLUT_RIGHT_BUTTON); // asociere buton mouse
glutMainLoop ();
return 0;
}

Pentru ca aparitia meniului sa nu creeze artefacte remanente n fereastra grafica, se


prefera utilizarea unui buffer video dublu (GLUT_DOUBLE) n care codul este executat cu
instructiunea glutSwapBuffers().
Capitolul 11

Fonturi

11.1 Fonturi bitmap


OpenGL permite, prin intermediul bibliotecii GLUT, utilizarea unor fonturilor de tip
bitmap (sau imagine) pentru a afisa caractere. Fonturile sunt caracterizate prin tip si
dimensiune. Bibilioteca GLUT permite utilizarea a trei tipuri de fonturi de diferite di-
mensiuni, specificate prin cuvintele cheie urmatoare:

Tabela 11.1: Tipuri de fonturi bitmap utilizate n GLUT


Denumire Descriere tip font

GLUT_BITMAP_8_BY_13 Font matriceal, dimensiune 8x13 pixeli

GLUT_BITMAP_9_BY_15 Font matriceal, dimensiune 9x15 pixeli

GLUT_BITMAP_TIMES_ROMAN_10 Font Adobe Times New Roman, dimensiune 10 puncte

GLUT_BITMAP_TIMES_ROMAN_24 Font Adobe Times New Roman, dimensiune 24 puncte

GLUT_BITMAP_HELVETICA_10 Font Adobe Helvetica, dimensiune 10 puncte

GLUT_BITMAP_HELVETICA_12 Font Adobe Helvetica, dimensiune 12 puncte

GLUT_BITMAP_HELVETICA_18 Font Adobe Helvetica, dimensiune 18 puncte

Pentru afisarea unui caracter se parcurg doua etape. Prima dintre acesta presupune sta-
bilirea coordonatei pozitiei n care se va afisa caracterul dorit prin intermediul instructiunii
glRasterPos(). Pozitia poate fi specificata n plan sau n spatiu, n functie de tipul
aplicatiei (2D sau 3D).

glRasterPos2d(x,y);
glRasterPos3d(x,y,z);

Afisarea caracterelor se face individual, prin instructiunea glutBitmapCharacter(),


avand urmatoarea sintaxa:

glutBitmapCharacter(font, caracter);

unde font este denumirea fontului utilizat, iar caracter este caracterul afisat, exprimat
sub forma directa sau prin cod ASCII.

113
114 CAPITOLUL 11. FONTURI

Exemplul 11.1 Afisarea caracterului A cu fonturi bitmap

#include <GL/glut.h>

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);

glRasterPos2d(0.0,0.6);
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, A);

glRasterPos2d(0.0,0.4);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, A);

glRasterPos2d(0.0,0.2);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, A);

glRasterPos2d(0.0,0.0);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, A);

glRasterPos2d(0.0,-0.2);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, A);

glRasterPos2d(0.0,-0.4);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, A);

glRasterPos2d(0.0,-0.6);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, A);

glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (320, 240);
glutCreateWindow("Bitmap text");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
11.1. FONTURI BITMAP 115

Figura 11.1: Exemplu de afisare a caracterului A cu fonturi de tip bitmap

In exemplul 11.1 se prezinta afisarea unui singur simbol (A) cu toate cele sapte tipuri
de fonturi enumerate anterior. Afisarea se face la coordonata x=0 si ncepand cu y=0.6
cu pas de -0.2.

Pentru a afisa siruri de caractere este necesara repetarea instructiunii pentru fiecare
caracter din sir, specificand pozitia initiala doar pentru primul caracter al sirului.

Exemplul 11.2 prezinta afisarea unui sir de caractere stocate n vectorul *text si ac-
cesate secvenctial prin intermediul pointerului *c. Sirul este parcurs pana cand pointerul
curent devine un pointer NULL (0) care semnifica sfarsitul sirului.

Afisarea textului Hello world! se face pornind de la coordonata (x, y)=(-0.8, 0.0).

Figura 11.2: Exemplu de afisare a sirului Hello world! cu fonturi de tip bitmap
116 CAPITOLUL 11. FONTURI

Exemplul 11.2 Afisarea unui sir de caractere cu fonturi bitmap

#include <GL/glut.h>

char *text="Hello world!"; // sir de caractere

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);

glRasterPos2d(-0.8,0.0); // pozitie inceput text


char *c; // pointer caracter
for (c=text;*c!=0;c++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,*c);

glFlush();
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (320, 240);
glutCreateWindow("Bitmap text");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

11.2 Fonturi stroke


Fonturile de tip stroke sunt fonturi vectoriale tridimensionale care, spre deosebire de
fonturile bitmap, pot fi scalate fara a deforma calitatea vizuala a acestora. Biblioteca
GLUT dispune de doua tipuri de fonturi pentru simboluri cu cod ASCII ntre 32 si 127.

Tabela 11.2: Tipuri de fonturi stroke utilizate n GLUT


Denumire Descriere tip font

GLUT_STROKE_ROMAN Font Roman Simplex proportionat

GLUT_STROKE_MONO_ROMAN Font Roman Simplex mono-space


11.2. FONTURI STROKE 117

Afisarea unui caracter cu font stroke se face cu instructiunea glutStrokeCharacter,


avand urmatoarea sintaxa:
glutStrokeCharacter(font, caracter);
unde font este denumirea fontului utilizat, iar caracter este caracterul afisat, exprimat
sub forma directa sau prin cod ASCII.

Caracterul este afisat n originea sistemului de coordonate tridimensional, de-a lungul


axei pozitive oX. Deoarece dimensiunea initiala a acestor fonturi este mare, este necesara
o rescalare a acestora.

In exemplul 11.3 este prezentata afisarea textului Hello world! cu fontul stroke de
tip GLUT_STROKE_ROMAN n pozitie initiala (cu culoare rosie) si translatat pe axa Ox cu
-1.5 si pe axa Oz cu 1.0 (cu culoare galbena). In ambele situatii, fontul a fost rescalat pe
cele trei axe cu factorul de 0.005.

Exemplul 11.3 Afisarea unui sir de caractere cu fonturi stroke

#include <GL/glut.h>

char *text="Hello world!"; // text


char *c; // pointer caracter

void init(void) {
glClearColor(0,0,0,0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3, 3, 3, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glColor3f(0.5,0.5,0.5);
glBegin(GL_LINES); // axe de coordonate normate
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glVertex3f(0,-1,0);
glVertex3f(0,1,0);
glVertex3f(0,0,-1);
glVertex3f(0,0,1);
glEnd();

glPushMatrix(); // Salvare matrice transformare


glScalef(.005,.005,.005); // Scalare font
118 CAPITOLUL 11. FONTURI

Figura 11.3: Exemplu de afisare a sirului Hello world! cu fonturi de tip stroke

glColor3f(1,0,0); // rosu
for (c=text;*c;c++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);

glPopMatrix(); // Reincarcare matrice transf.


glTranslatef(-1.5,0,1.0); // Translatie text
glScalef(.005,.005,.005); // Scalare font

glColor3f(1,1,0); // galben
for (c=text;*c;c++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
glFlush();
}

int main(int argc, char *argv[]) {


glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("Stroke text");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Capitolul 12

Fisiere cu obiecte grafice

12.1 Fisiere de tip Alias/Wavefront (.OBJ)


OpenGL are posibilitatea importarii obiectelor grafice create n Alias Wavefront prin
intermediul bibliotecii OpenGL Mathematics (sau GLM). In cadrul acestei biblioteci sunt
la dispozitie o serie de instructiuni care au ca rol interpretarea obiectelor existente sub
forma unor fisiere de tip *.OBJ.

Fisierele de tip *.OBJ pot contine o serie de informatii, cele mai importante (pentru
obiecte poligonale) fiind:
Vertexuri:
geometrice (v);
texturi (vt);
normale (vn);
Elemente:
puncte (p);
linii (l);
fatete (f);
Grupuri:
nume de grup (g);
nume de obiect (o);
Atribute de afisare/randare:
interpolare de culoare (c_interp);
interpolare de dizolvare (d_interp);
nume de material (usemtl);
biblioteca de material (mtllib).

Biblioteca GLM permite definirea mai multor tipuri de structuri, gestionarea datelor
din fisiere de tip *.OBJ (obiect), .MTL (material) sau din fisiere imagini (pentru textu-
rare), precum si manipularea obiectelor prin instructiuni specifice, prezentate n cele ce
urmeaza.

119
120 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

Tipurile de structuri utilizate ntr-un fisier *.OBJ sunt:


GLMgroup - structura care defineste un grup dintr-un model;
GLMmaterial - structura care defineste un material dintr-un model;
GLMmodel - structura care defineste un model;
GLMtriangle - structura care defineste un triunghi dintr-un model.

Incarcarea unui model/obiect se face prin intermediul instructiunii glmReadOBJ(), cu


urmatoarea sintaxa:
nume_obiect = glmReadOBJ("fisier.obj");
In prealabil, nume_obiect va trebui definita ca o variabila de tip GLMmodel.

Pentru afisarea obiectelor, se utilizeaza instructiunea glmDraw(object, mode). Afi-


sarea se poate face n mai multe moduri, specificate prin argumentul mode al instructiunii,
moduri prezentate n tabelul 12.1. Se pot specifica concomitent mai mult variante de
parametru, delimitate prin caracterul |.

Tabela 12.1: Moduri de afisare ale obiectelor *.OBJ


Parametrul mode Mod de afisare

GLM_NONE Afisarea muchiilor obiectului

GLM_FLAT Afisarea obiectului cu normalele exterioare

GLM_SMOOTH Afisarea obiectului cu normelele la puncte

GLM_TEXTURE Afisarea obiectului cu coordonatele de textura

GLM_COLOR Afisarea obiectului cu culoare

GLM_MATERIAL Afisarea obiectului cu materiale

Alte instructiuni utile oferite de catre biblioteca GLM sunt prezentate n tabelul 12.2.

Tabela 12.2: Instructiuni ale bibliotecii GLM


Instructiune cu sintax
a Semnificatie

glmUnitize (obiect) Translatarea obiectului n origine si normarea acestuia

glmScale (obiect, factor) Scaleaza obiectul cu un anumit factor

glmFacetNormals (obiect) Genereaza normalele fatetelor obiectului

glmVertexNormals (obiect, unghi) Genereaza normalele la punctele obiectului

glmLinearTexture (obiect) Genereaza coordonatele de texturare linara

glmSpheremapTexture (obiect) Genereaza coordonatele de texturare sferica


12.1. FIS
IERE DE TIP ALIAS/WAVEFRONT (.OBJ) 121

In fisierul patrat.obj se prezinta modalitatea cea mai simpla de descriere a unui


patrat prin intermediul unui fisier *.OBJ. Fisierul va contine doar cele patru vertexuri
necesare definirii colturilor patratului (v), precum si indexul utilizarii acestora pentru
crearea fatetei (f).

Fisierul 12.1 Descrierea unui patrat ntr-un fisier patrat.obj

v 0.000000 0.500000 0.000000 # vertexul 1


v 0.000000 0.000000 0.000000 # vertexul 2
v 0.500000 0.000000 0.000000 # vertexul 3
v 0.500000 0.500000 0.000000 # vertexul 4

f 1 2 3 4 # fateta 1

Extrapoland cazul precedent, se poate genera un fisier *.OBJ care sa contina un obiect
de tip cub. Pentru descrierea acestuia sunt necesare opt vertexuri si sase fatete (fisierul
12.2). De retinut faptul ca fiecare fateta este definita prin indexul punctelor utilizate la
trasarea acesteia, ordinea enumerarii vertexurilor n lista fiind importanta.

Fisierul 12.2 Descrierea unui cub ntr-un fisier cub.obj

v 0.000000 2.000000 2.000000 # vertexul 1


v 0.000000 0.000000 2.000000 # vertexul 2
v 2.000000 0.000000 2.000000 # vertexul 3
v 2.000000 2.000000 2.000000 # vertexul 4
v 0.000000 2.000000 0.000000 # vertexul 5
v 0.000000 0.000000 0.000000 # vertexul 6
v 2.000000 0.000000 0.000000 # vertexul 7
v 2.000000 2.000000 0.000000 # vertexul 8

f 1 2 3 4 # fateta 1
f 8 7 6 5 # fateta 2
f 4 3 7 8 # fateta 3
f 5 1 4 8 # fateta 4
f 5 6 2 1 # fateta 5
f 2 6 7 3 # fateta 6

In exemplul 12.1 se prezinta codul necesar alocarii memoriei, ncarcarii si afisarii obiec-
tului. Pentru ncarcarea bibliotecii GLM, spre deosebire de GLUT si GLU, se apeleaza
fisierul sursa glm.cpp:

#include <GL/glm.cpp>
In continuare se defineste modelul (obiectul) grafic si se aloca memoria necesara ca
variabila de tip GLMmodel:
122 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

Exemplul 12.1 Incarcarea unui obiect grafic dintr-un fisier Alias/Wavefront (*.OBJ)

#include <GL/glut.h>
#include <GL/glm.cpp> // incarcare biblioteca GLM

GLMmodel *obiect = NULL; // alocare memorie obiect

void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj"); // incarcare date din fisier
glmFacetNormals(obiect); // calcul normale fatete
glmDraw(obiect, GLM_FLAT); // desenare obiect
glFlush();
}

void reshape(int w, int h) {


glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, w/h, 1.0, 20.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(3.5, 3.5, 3.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Cub OBJ");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

GLMmodel *obiect = NULL;


Incarcarea propriu-zisa a datelor din fisierul *.OBJ se face prin intermediul instructiunii
glmReadOBJ():
12.1. FIS
IERE DE TIP ALIAS/WAVEFRONT (.OBJ) 123

Fisierul 12.3 Definirea materialelor si texturilor ntr-un fisier materiale.mtl

newmtl bronze # nume material 1


Ka 0.2125 0.1275 0.0540 # coeficient material 1 ambiental
Kd 0.7140 0.4284 0.1814 # coeficient material 1 difuz
Ks 0.3935 0.2719 0.1667 # coeficient material 1 specular
Ns 40 # exponent coeficient specular 1
map_Kd opengl.ppm # fisier textura difuza

newmtl silver # nume material 2


Ka 0.1922 0.1922 0.1922 # coeficient material 2 ambiental
Kd 0.5075 0.5075 0.5075 # coeficient material 2 difuz
Ks 0.5083 0.5083 0.5083 # coeficient material 2 specular
Ns 80 # exponent coeficient specular 2

newmtl gold # nume material 3


Ka 0.2472 0.1995 0.0745 # coeficient material 3 ambiental
Kd 0.7516 0.6065 0.2265 # coeficient material 3 difuz
Ks 0.6238 0.5558 0.3660 # coeficient material 3 specular
Ns 80 # exponent coeficient specular 3

obiect = glmReadOBJ("patrat.obj");
Pentru afisare este necesar calculul normalelor fatetelor obiectului:
glmFacetNormals(obiect);
dupa care se aplica instructiunea de afisare glmDraw():
glmDraw(obiect, GLM_FLAT);
Pe langa coordonatele si indecsii fatetelor, se mai pot preciza tipurile de material speci-
ficate ntr-un fisier *.MTL si utilizate pentru fiecare grup de fatete n parte. Materialul
este definit printr-o structura de tip GLMmaterial care are urmatoarele componente:
newmtl - denumirea materialului;
Ns - exponentul specular Phong (intre 0 si 200);
Kd - coeficientul de culoare difuza;
Ka - coeficientul de culoare ambientala;
Ks - coeficientul de culoarea speculara;
d - factorul de dizolvare (transparenta);
map_Kd - textura difuza;
map_Ka - textura ambientala;
map_Ks - textura speculara;
124 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

map_Bump - textura de relief;


map_d - textura de opacitate.

Fisierul cub.obj se va modifica astfel ncat sa se specifice materialele utilizate. Este


necesara initial specificarea prin intermediul instructiunii mtllib a fisierului care contine
toate materialele utilizate.

Pentru aceasta, fatetele care utilizeaza acelasi material vor constitui un grup cu eti-
cheta proprie (de exemplu, g fatete14). Dupa definirea numelui de grup se specifica
tipul materialului utilizat prin instructiunea usemtl urmata de numele materialului.

In fisierul 12.4 sunt exemplificate modificarile aduse fisierului cub.obj fata de exemplul
12.2 pentru a utiliza materiale.

Fisierul 12.4 Descrierea unui cub cu materialele asociate ntr-un fisier cub.obj

mtllib materiale.mtl # fisierul cu materiale

v 0.000000 2.000000 2.000000


v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000

g fatete14 # grupul 1
usemtl bronze # utilizare material 1
f 1 2 3 4
f 8 7 6 5

g fatete25 # grupul 2
usemtl silver # utilizare material 2
f 5 1 4 8
f 5 6 2 1

g fatete36 # grupul 3
usemtl gold # utilizare material 3
f 4 3 7 8
f 2 6 7 3

Pentru a putea aplica materialele, instructiunea glmDraw() va fi, de asemenea, modi-


ficata pentru includerea optiunii de afisare cu material si de randare:
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL);
12.1. FIS
IERE DE TIP ALIAS/WAVEFRONT (.OBJ) 125

avandu-se grija ca n codul sursa sa se introduca o sursa de lumina si sa se activeze testul


si bufferul de adancime (vezi exemplul 12.2).

Exemplul 12.2 Incarcarea unui obiect grafic cu materiale dintr-un fisier Alias/Wavefront
(*.OBJ)

#include <GL/glut.h>
#include <GL/glm.cpp>

GLMmodel *obiect = NULL;

GLfloat ambient[] = { 0.8, 0.8, 0.8, 0.0 };


GLfloat diffuse[] = { 0.8, 0.8, 0.8, 0.0 };
GLfloat specular[] = { 0.8, 0.8, 0.8, 0.0 };
GLfloat position[] = { 3.0, 3.0, 3.0, 0.0 };

void init(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);

glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);


glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj");
glmFacetNormals(obiect);
glmVertexNormals(obiect, 90);
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL);
glFlush();
}

void reshape(int w, int h) {


glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, w/h, 1.0, 20.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
126 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Cub OBJ");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

In mod implicit, fisierele de tip *.MTL pot contine si informatie de textura, dar aceasta
nu poate fi citita direct n mediul OpenGL. Pentru a include, totusi, texturile, se poate
utiliza ncarcarea fisierelor imagine de tip *.PPM care contin texturile cu instructiunea
glmReadPPM():
int w, h;
GLubyte *textura = 0;
textura = glmReadPPM ("textura.ppm", &w, &h);
Instructiunea are ca efect ncarcarea datelor n variabila textura, precum si a dimen-
siunilor acesteia n variabilele w si h, necesare ulterior pentru parametrizarea texturii.

Dupa cum se poate observa n exemplul 12.3, texturarea se face n mod similar unei tex-
turari poligonale utilizand instructiuni specifice, precum: glGenTextures(), glTexEnvi(),
glTexParameteri(), glTexImage2D() si glBindTexture(), .

Pentru a combina informatia de material cu cea de textura este necesara ca texturarea


sa se aplice prin modulare (GL_MODULATE):
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Pe langa parametrii GL_SMOOTH si GL_MATERIAL, instructiunea glmDraw() va contine
si argumentul de texturare GL_TEXTURE:
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL|GLM_TEXTURE);
In final, dupa desenarea obiectului 3D cu instructiunea glmDraw(), texturarea propriu-
zisa se face prin proiectie linara:
glmLinearTexture(obiect);
Fisierul cub.obj trebuie modificat, astfel ncat sa includa informatiile legate de asoci-
erea dintre vertexurile poligonale (v), cele ale texturii (vt) si, optional, vertexurile nor-
malelor (vn) conform sintaxei:
f v/vt v/vt v/vt v/vt

f v/vt/vn v/vt/vn v/vt/vn v/vt/vn


12.1. FIS
IERE DE TIP ALIAS/WAVEFRONT (.OBJ) 127

Fisierul 12.5 Descrierea unui cub cu materialele si texturile asociate ntr-un fisier cub.obj

mtllib materiale.mtl

v 0.000000 1.000000 1.000000 # vertex 1


v 0.000000 0.000000 1.000000 # vertex 2
v 1.000000 0.000000 1.000000 # vertex 3
v 1.000000 1.000000 1.000000 # vertex 4
v 0.000000 1.000000 0.000000 # vertex 5
v 0.000000 0.000000 0.000000 # vertex 6
v 1.000000 0.000000 0.000000 # vertex 7
v 1.000000 1.000000 0.000000 # vertex 8

vt 1.000000 1.000000 # coordonata textura 1


vt 1.000000 0.000000 # coordonata textura 2
vt 0.000000 0.000000 # coordonata textura 3
vt 0.000000 1.000000 # coordonata textura 4

g fatete14 # fatetele opuse 1 si 4


usemtl bronze # utilizare material 1
f 3/1 4/2 1/3 2/4 # asociere vertexuri v cu vt
f 6/1 5/2 8/3 7/4 # asociere vertexuri v cu vt

g fatete25 # fatetele opuse 2 si 5


usemtl gold # utilizare material 2
f 7/1 8/2 4/3 3/4 # asociere vertexuri v cu vt
f 2/1 1/2 5/3 6/4 # asociere vertexuri v cu vt

g fatete36 # fatetele opuse 3 si 6


usemtl silver # utilizare material 3
f 5/3 1/4 4/1 8/2 # asociere vertexuri v cu vt
f 2/3 6/4 7/1 3/2 # asociere vertexuri v cu vt

Exemplul 12.3 Incarcarea unui obiect grafic cu materiale dintr-un fisier Alias/Wavefront
(*.OBJ) si texturarea obiectului

#include <GL/glut.h>
#include <GL/glm.cpp>

GLfloat ambient[] = { 0.8, 0.8, 0.8, 0.0 };


GLfloat diffuse[] = { 0.8, 0.8, 0.8, 0.0 };
GLfloat specular[] = { 0.8, 0.8, 0.8, 0.0 };
GLfloat position[] = { 3.0, 3.0, 3.0, 0.0 };

GLMmodel *obiect = NULL; // eticheta date obiect 3D


GLubyte *textura = 0; // eticheta date textura
128 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

int w, h; // dimensiuni textura


static GLuint texName[1]; // eticheta textura

void init(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);


glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);

textura = glmReadPPM("textura.ppm", &w, &h);// incarcare textura


glGenTextures(1, texName); // generare textura
glBindTexture(GL_TEXTURE_2D, texName[0]); // setare tip textura 2D
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
GL_RGB, GL_UNSIGNED_BYTE, textura);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
obiect = glmReadOBJ("cub.obj"); // incarcare obiect
glmUnitize(obiect);
glmFacetNormals(obiect);
glmVertexNormals(obiect, 90);
glmDraw(obiect, GLM_SMOOTH|GLM_MATERIAL|GLM_TEXTURE);
glmLinearTexture(obiect);
glFlush();
}

void reshape(int w, int h) {


glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, w/h, 1.0, 20.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
12.1. FIS
IERE DE TIP ALIAS/WAVEFRONT (.OBJ) 129

a) b)

c) d)

Figura 12.1: Rezultatul afis


arii obiectelor n modul de iluminare plat: a) fara material, b) cu material,
c) cu textur
a si d) cu material si textura

int main(int argc, char** argv) {


glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition (100, 100);
glutInitWindowSize (400, 400);
glutCreateWindow("Cub OBJ");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
130 CAPITOLUL 12. FISIERE CU OBIECTE GRAFICE

a) b)

c) d)

Figura 12.2: Rezultatul afis arii obiectelor n modul de iluminare interpolat: a) fara material, b) cu
material, c) cu textur
a si d) cu material si textura

Rezultatele care pot fi obtinute cu ajutorul exemplelor 12.1-12.3 sunt exemplificate n


figurile 12.1 si 12.2.
Anexa A

Materiale

Valorile din tabelul urmator pot fi utilizate pentru alegerea proprietat, ilor de material
ale obiectelor.

Valorile sunt specificate ca argumente ale diferit, ilor parametri de material:


glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
glMaterialfv(GL_FRONT, GL_SHININESS, shin*128.0);

131
ANEXA A. MATERIALE

Nr.crt. Denumire amb dif spec shin


1. emerald [0.0215 0.1745 0.0215 ] [0.07568 0.61424 0.07568] [0.63300 0.72781 0.63300] 0.6
2. jade [0.135 0.2225 0.1575 ] [0.54 0.89 0.63 ] [0.31623 0.31623 0.31623] 0.1
3. obsidian [0.05375 0.05 0.06625] [0.18275 0.17 0.22525] [0.33274 0.32863 0.34643] 0.3
4. pearl [0.25 0.20725 0.20725] [1 0.829 0.829 ] [0.29665 0.29665 0.29665] 0.088
5. ruby [0.1745 0.01175 0.01175] [0.61424 0.04136 0.04136] [0.72781 0.62696 0.62696] 0.6
6. turquoise [0.1 0.18725 0.1745 ] [0.396 0.74151 0.69102] [0.29725 0.30829 0.30668] 0.1
7. brass [0.32941 0.22353 0.02745] [0.78039 0.56863 0.11373] [0.99216 0.94118 0.80784] 0.21794872
8. bronze [0.2125 0.1275 0.054 ] [0.714 0.4284 0.18144] [0.39355 0.27191 0.16672] 0.2
9. chrome [0.25 0.25 0.25 ] [0.4 0.4 0.4 ] [0.77460 0.77460 0.77460] 0.6
10. copper [0.19125 0.0735 0.0225 ] [0.7038 0.27048 0.0828 ] [0.25678 0.13762 0.08601] 0.1
11. gold [0.24725 0.1995 0.0745 ] [0.75164 0.60648 0.22648] [0.62828 0.55580 0.36607] 0.4
12. silver [0.19225 0.19225 0.19225] [0.50754 0.50754 0.50754] [0.50827 0.50827 0.50827] 0.4
13. black plastic [0 0 0 ] [0.01 0.01 0.01 ] [0.5 0.5 0.5 ] 0.25
14. cyan plastic [0 0.1 0.06 ] [0 0.50980 0.50980] [0.50196 0.50196 0.50196] 0.25
15. green plastic [0 0 0 ] [0.1 0.35 0.1 ] [0.45 0.55 0.45 ] 0.25
16. red plastic [0 0 0 ] [0.5 0 0 ] [0.7 0.6 0.6 ] 0.25
17. blue plastic [0 0 0 ] [0 0 0.5 ] [0.6 0.6 0.7 ] 0.25
18. white plastic [0 0 0 ] [0.55 0.55 0.55 ] [0.7 0.7 0.7 ] 0.25
19. yellow plastic [0 0 0 ] [0.5 0.5 0 ] [0.6 0.6 0.5 ] 0.25
20. black rubber [0.02 0.02 0.02 ] [0.01 0.01 0.01 ] [0.4 0.4 0.4 ] 0.078125
21. cyan rubber [0 0.05 0.05 ] [0.4 0.5 0.5 ] [0.04 0.7 0.7 ] 0.078125
22. green rubber [0 0.05 0 ] [0.4 0.5 0.4 ] [0.04 0.7 0.04 ] 0.078125
23. red rubber [0.05 0 0 ] [0.5 0.4 0.4 ] [0.7 0.04 0.04 ] 0.078125
24. blue rubber [0 0 0.05 ] [0.4 0.4 0.5 ] [0.04 0.04 0.7 ] 0.078125
25. white rubber [0.05 0.05 0.05 ] [0.5 0.5 0.5 ] [0.7 0.7 0.7 ] 0.078125
26. yellow rubber [0.05 0.05 0 ] [0.5 0.5 0.4 ] [0.7 0.7 0.04 ] 0.078125
132
Anexa A

Coduri ASCII standard (0-127)

Tabela A.1: Caractere ASCII de control (codurile 0-31)


Dec Oct Hex Simbol Descriere
0 000 00 NUL Null char
1 001 01 SOH Start of Heading
2 002 02 STX Start of Text
3 003 03 ETX End of Text
4 004 04 EOT End of Transmission
5 005 05 ENQ Enquiry
6 006 06 ACK Acknowledgment
7 007 07 BEL Bell
8 010 08 BS Back Space
9 011 09 HT Horizontal Tab
10 012 0A LF Line Feed
11 013 0B VT Vertical Tab
12 014 0C FF Form Feed
13 015 0D CR Carriage Return
14 016 0E SO Shift Out / X-On
15 017 0F SI Shift In / X-Off
16 020 10 DLE Data Line Escape
17 021 11 DC1 Device Control 1 (oft. XON)
18 022 12 DC2 Device Control 2
19 023 13 DC3 Device Control 3 (oft. XOFF)
20 024 14 DC4 Device Control 4
21 025 15 NAK Negative Acknowledgement
22 026 16 SYN Synchronous Idle
23 027 17 ETB End of Transmit Block
24 030 18 CAN Cancel
25 031 19 EM End of Medium
26 032 1A SUB Substitute
27 033 1B ESC Escape
28 034 1C FS File Separator
29 035 1D GS Group Separator
30 036 1E RS Record Separator
31 037 1F US Unit Separator

133
134 ANEXA A. CODURI ASCII STANDARD (0-127)

Tabela A.2: Caractere ASCII imprimabile (codurile 32-127)


Dec Oct Hex Simbol Descriere
32 040 20 Space
33 041 21 ! Exclamation mark
34 042 22 Double quotes (or speech marks)
35 043 23 # Number
36 044 24 $ Dollar
37 045 25 % Procenttecken
38 046 26 & Ampersand
39 047 27 Single quote
40 050 28 ( Open parenthesis (or open bracket)
41 051 29 ) Close parenthesis (or close bracket)
42 052 2A * Asterisk
43 053 2B + Plus
44 054 2C , Comma
45 055 2D - Hyphen
46 056 2E . Period, dot or full stop
47 057 2F / Slash or divide
48 060 30 0 Zero
49 061 31 1 One
50 062 32 2 Two
51 063 33 3 Three
52 064 34 4 Four
53 065 35 5 Five
54 066 36 6 Six
55 067 37 7 Seven
56 070 38 8 Eight
57 071 39 9 Nine
58 072 3A : Colon
59 073 3B
; Semicolon
60 074 3C Less than
61 075 3D =
Equals
62 076 3E Greater than
63 077 3F ? Question mark
64 100 40 @ At symbol
65 101 41 A Uppercase A
66 102 42 B Uppercase B
67 103 43 C Uppercase C
68 104 44 D Uppercase D
69 105 45 E Uppercase E
70 106 46 F Uppercase F
71 107 47 G Uppercase G
72 110 48 H Uppercase H
73 111 49 I Uppercase I
74 112 4A J Uppercase J
75 113 4B K Uppercase K
76 114 4C L Uppercase L
77 115 4D M Uppercase M
78 116 4E N Uppercase N
79 117 4F O Uppercase O
80 120 50 P Uppercase P
81 121 51 Q Uppercase Q
82 122 52 R Uppercase R
83 123 53 S Uppercase S
135

Tabela A.2: Caractere ASCII imprimabile (codurile 32-127)


Dec Oct Hex Simbol Descriere
84 124 54 T Uppercase T
85 125 55 U Uppercase U
86 126 56 V Uppercase V
87 127 57 W Uppercase W
88 130 58 X Uppercase X
89 131 59 Y Uppercase Y
90 132 5A Z
 Uppercase Z
91 133 5B Opening bracket
92 134 5C  Backslash
93 135 5D Closing bracket
94 136 5E Caret - circumflex
95 137 5F Underscore
96 140 60 Grave accent
97 141 61 a Lowercase a
98 142 62 b Lowercase b
99 143 63 c Lowercase c
100 144 64 d Lowercase d
101 145 65 e Lowercase e
102 146 66 f Lowercase f
103 147 67 g Lowercase g
104 150 68 h Lowercase h
105 151 69 i Lowercase i
106 152 6A j Lowercase j
107 153 6B k Lowercase k
108 154 6C l Lowercase l
109 155 6D m Lowercase m
110 156 6E n Lowercase n
111 157 6F o Lowercase o
112 160 70 p Lowercase p
113 161 71 q Lowercase q
114 162 72 r Lowercase r
115 163 73 s Lowercase s
116 164 74 t Lowercase t
117 165 75 u Lowercase u
118 166 76 v Lowercase v
119 167 77 w Lowercase w
120 170 78 x Lowercase x
121 171 79 y Lowercase y
122 172 7A z Lowercase z
123 173 7B { Opening brace
124 174 7C Vertical bar
125 175 7D } Closing brace
126 176 7E Equivalency sign - tilde
127 177 7F Delete
Bibliografie

[1] Astle, D., and Hawkins, K. Beginning OpenGL Game Programming. Premier
Press, 2004.
[2] Chin, N., Frazier, C., Ho, P., Liu, Z., and Smith, K. P. The OpenGL
Graphics System Utility Library (Version 1.3). Silicon Graphics.
[3] Foley, J. D., van Dam, A., Feiner, S. K., and Hughes, J. F. Computer
Graphics. Principle and Practice in C, 2nd ed. Addison-Wesley, 1997.
[4] Gonzalez, R. C., and Woods, R. E. Digital Image Processing, 3rd ed. Prentice
Hall, 2008.
[5] Hearn, D., and Baker, M. P. Computer Graphics. C Version, 2nd ed. Prentice
Hall, 1996.
[6] Hill, Jr., F. S., and Kelley, S. M. Computer Graphics using OpenGL, 3rd ed.
Prentice Hall, 2006.
[7] Kilgard, M. J. The OpenGL Utility Toolkit (GLUT) Programming Interface. API
Version 3. Silicon Graphics.
[8] Martz, P. OpenGL Distilled. Addison-Wesley, 2006.
[9] Molder, C. Grafica computerizata. Editura Albastra, 2009.
[10] Poynton, C. Digital Video and HDTV. Algorithms and Interfaces, 1st ed. Morgan
Kaufmann, 2003.
[11] Rost, R. J. OpenGL Shading Language, 2nd ed. Addison-Wesley, 2006.
[12] Seddon, C. OpenGL Game Development. Wordware Publishing, 2005.
[13] Segal, M., and Akeley, K. The OpenGL Graphics System: A Specification
(Version 2.1). Silicon Graphics.
[14] Segal, M., and Akeley, K. The OpenGL Graphics System: A Specification
(Version 3.0). Silicon Graphics.
[15] Shreiner, D., Woo, M., Neider, J., and Davis, T. OpenGL Programming
Guide: The Official Guide to Learning OpenGL, Version 2.1, 6th ed. Addison-
Wesley, 2008.
[16] Wright, Jr., R. S., Lipchak, B., and Haemel, N. OpenGL Super Bible:
Comprehensive Tutorial and Reference, 4th ed. Addison-Wesley, 2007.

136

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