Explorați Cărți electronice
Categorii
Explorați Cărți audio
Categorii
Explorați Reviste
Categorii
Explorați Documente
Categorii
Tipul de date
Corespondentul n C
8-bit integer
16-bit integer
32-bit integer
32-bit floating-point
64-bit floating-point
8-bitunsigned integer
16-bit unsigned integer
signed char
Short
int sau long
Float
Double
unsigned char
unsigned short
Tipul
definit
n
OpenGL
GLbyte
GLshort
GLint, GLsizei
GLfloat, GLclampf
GLdouble, GLclampd
GLubyte, GLboolean
GLushort
ui
GLuint,GLenum,
GLbitfield
Iniializare fereastr
void glutInit(int *argc, char **argv);
Funcia ntoarce identificatorul ferestrei curente. Funcia ntoarce 0 dac nu exist nici o
fereastr curent sau fereastra curent a fost distrus.
Selectarea cursorului asociat ferestrei curente
void glutSetCursor(int cursor) ;
Crearea meniurilor
Meniurile create cu ajutorul GLUT-ului sunt meniuri simple, pop-up n cascad. n timp
ce un meniu este folosit el nu poate fi ters, nu i se pot aduga alte opiuni i nu i se pot
terge din opiuni.
Funcia adaug o nou opiune meniului curent. Opiunea este adugat la sfritul listei
de articole a meniului.
- name - specific textul prin care va fi reprezentat opiunea introdus
- value - reprezint valoarea transmis funciei callback asociat meniului la
selectarea opiunii respective
Adugarea unui sbmeniu ntr-un meniu
void glutAddSubMenu(char* name, int menu) ;
Funcia terge opiunea sau submeniul identificat de parametrul entry. Opiunile din
meniu de sub opiunea tears sunt renumerotate.
Distrugerea unui meniu
void glutDestroyWindow(int menu) ;
Funcia distruge meniul specificat prin parametru. Distrugerea unui meniu nu are nici un
efect asupra submeniurilor. Dac meniul distrus este cel curent, atunci meniul curent va
deveni invalid.
Setarea meniului curent
void glutSetMenu(int menu) ;
Funcia ntoarce identificatorul meniului curent. Funcia ntoarce 0 dac nu exist meniu
curent sau meniul curent a fost distrus.
Ataare / detaare meniu unui buton al mouse-ului
void glutAttachMenu(int button) ;
void glutDetachMenu(int button) ;
Parametrul func reprezint funcia callback care va fi apelat la apsarea / eliberarea unei
taste care genereaz un caracter ASCII. Parametrul key al funciei callback reprezint
Parametrul func specific funcia callback care va fi apelat la apsarea / eliberarea unui
buton al mouseului.Parametrul button al funciei callback poate avea una din urmtoarele
valori:
GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON
sau
GLUT_RIGHT_BUTTON. Parametrul state poate fi GLUT_UP sau GLUT_DOWN
dup cum butonul mouse-ului a fost apsat sau eliberat. Parametrii x i y reprezint
poziia mouse-ului la apariia evenimentului. Valorile x i y sunt relative la colul stnga
sus al ferestrei aplicaiei.
Deplasarea mouse-ului
void glutMotionFunc(void (*func)(int x, int y)) ;
font specific fontul vectorial folosit, care poate avea una din urmtoarele valori:
GLUT_STROKE_ROMAN
GLUT_STROKE_MONO_ROMAN
character specific caracterul ce va fi afiat
Exemplu
Funcia output prezentata mai jos realizeaza afiarea unui text cu format, incepand dintro pozitie specificata a ferestrei curente.
void output(GLfloat x, GLfloat y, char *format,...)
{
va_list args;
Aceasta este ultima funcie care trebuie apelat in funcia main a aplicaiei. Ea conine
bucla de execuie (infinit) a aplicaiei n care aplicaia ateapt evenimente. Orice
eveniment este tratat prin rutina callback specificat anterior n funcia main, prin apelul
funciei GLUT specifice tipului de eveniment.
Execuia unui proces n background
void glutIdleFunc(void (*func)(void)) ;
Terminarea afirii
O aplicaie GLUT poate rula pe mai multe maini. De exemplu, s presupunem
c programul principal este rulat pe o main client i rezultatul procesrii (imaginea
afiat) apare pe un terminal sau pe o staie de lucru (server), care este conectat n reea.
De obicei clientul adun o colecie de comenzi ntr-un singur pachet nainte de a-l trimite
n reea. Codul de reea de la client nu permite detectarea momentului n care programul
grafic a terminat desenarea unui cadru sau a unei scene 3D. Astfel, clientul poate atepta
la infint comenzi de desenare ca s completeze un pachet. Pentru a fora clientul s
trimit pachetul chiar dac nu este plin se folosete funcia glFlush .
void glFlush(void);
n cazul n care nu exist nici un client i toate comenzile sunt executate pe server
functia glFlush nu va avea nici un efect. Pentru ca un program s funcioneze corect att
n reea ct i pe o singur maina, se va include apelul functieie glFlush la sfritul
fiecrei scene. Funcia glFlush nu ateapt terminarea desenrii, ci doar foreaz
nceperea execuiei desenrii. Dac folosirea funciei glFlush nu este suficient pentru o
aplicaie, atunci se va folosi i funcia glFinish. Aceasta funcioneaz ca i glFlush dar
ateapt rspuns de notificare de la echipamentul grafic de indicare a terminri desenarii.
glFinish se va folosi pentru sincronizarea task-urilor.
void glFinish(void);
Observaie: folosirea excesiv a lui glFinish poate reduce performanele aplicaiei mai
ales dac se lucreaz n reea. Dac este suficient folosirea funciei glFlush
se va folosi aceasta n locul funciei glFinish.
*/
*/
*/
/*
*
afiare (buffer
singular i RGBA).
Exemplu 2
Programul din fiierul exemplu2.c trateaz evenimentele de la mouse. Se afieaz un
dreptunghi centrat n fereastra de afiare. La apsarea butonului stnga al mouse-ul
dreptunghiul va fi rotit pn la apsarea butonului drept al mouse-ului.
/* fiierul exemplul2.c */
#include "glut.h"
#include <stdlib.h>
static GLfloat spin = 0.0;
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(spin, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glRectf(-25.0, -25.0, 25.0, 25.0);
glPopMatrix();
glutSwapBuffers();
}
void spinDisplay(void)
{
spin = spin + 2.0;
if (spin > 360.0)
spin = spin - 360.0;
glutPostRedisplay();
}
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void mouse(int button, int state, int x, int y)
{
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(spinDisplay);
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(NULL);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
icosaedru
octaedru
sfera
teapot
tetraedru
tor
Aceste obiecte pot fi afiate prin familii de curbe sau ca obiecte solide.
Exemplu: funcii de desenare cub, sfer si tor prin dou familii de curbe i ca solide.
Desenare cub de latur size prin dou familii de curbe
void glutWireCube(GLdouble size);
Toate aceste obiecte sunt desenate centrate n originea sistemului de coordonate real.
n momentul n care se fac modificri asupra unui obiect complex poate apare
efectul de plpire a imaginii. Pentru evitarea acestui efect se asociaz ferestrei
aplicaiei un buffer dublu. Astfel, ntr-un buffer se pstreaz imaginea nemodificat
(imaginea ce este afiat pe ecran), iar n cel de-al doilea se construiete imaginea
modificat. n momentul n care s-a terminat construirea imaginii modificate se
interschimb buffer-ele (lucrul cu dou buffere este asemnator lucrului cu mai multe
pagini video n DOS). Pentru interschimbarea bufferelor se folosete funcia:
glutSwapBuffers :
void glutSwapBuffers(void) ;
La execuia secvenei din exemplu, obiectele A i B vor fi desenate cu rou iar obiectul C
cu albastru. Comanda set_current_color(green) nu are nici un efect.
Pentru a seta o culoare de desenare se poate apela funcia glColor3f :
void glColor3f(GLfloat red, GLfloat green, GLfloat blue) ;
/* negru */
/* rou */
/* verde */
/* galben */
/* albastru */
/* magenta */
/* cyan */
/* alb */
Valorile red, green, blue sunt n intervalul [0, 1]. Culoarea implicit de tergere
este (0, 0, 0, 0) - negru. Parametrul alpha specific opacitatea; valoarea sa implicit este
0.0.
void glClear(GLbitfield mask);
Funcia seteaz bufferul indicat prin parametrul mask la valoarea specificat. Valorile
posibile ale parametrului mask sunt prezentate n tabelul II.2:
Mask
Buffer-ul ce va fi ters
GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT
Buffer-ul de adncime
Tabelul II.2.
Figura II.2
GL_LINES
GL_POLYGON
GL_TRIANGLES
GL_QUADS
GL_LINE_STRIP
GL_LINE_LOOP
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUAD_STRIP
GL_LINES specific afiarea mai multor segmente de dreapt, cte unul pentru fiecare
pereche de vrfuri. Vrfurile sunt conectate n ordinea v0 v1, v2 v3, v4 v5 etc. Dac
este dat un numr impar de vrfuri, ultimul vrf este ignorat.
GL_LINE_STRIP specific o polilinie de la vrful v0 la varful vn, conectnd vrfurile
n ordinea dat;
GL_LINE_LOOP specific un poligon, vrfurile fiind unite n ordinea dat; ultimul
vrf este conectat cu primul.
GL_POLYGON specific un poligon de la vrful v0 la vrful vn-1 (n trebuie s fie cel
puin 3). Poligonul trebuie s fie un poligon convex simplu. Pentru poligoanele concave
rezultatul afirii este nedefinit. De asemenea, vrfurile trebuie s fie situate n acelai
plan;
GL_QUADS specific o serie de patrulatere separate. Primul patrulater este desenat
folosind vrfurile v0, v1, v2 i v3, urmtorul v4, v5, v6 i v7 etc. Dac n nu este multiplu
de 4 vrfurile suplimentare sunt ignorate;
GL_TRIANGLES specific o serie de triunghiuri separate;
GL_QUAD_STRIP specific o serie de patrulatere conectate. Primul patrulater este
desenat folosind vrfurile v0, v1, v2 i v3, Urmtorul refolosete ultimele dou vrfuri
v2, v3 i folosete urmtoarele dou n ordinea v5 i v6. Fiecare patrulater folosete
ultimele dou vrfuri de la patrulaterul anterior. n fiecare caz n trebuie s fie cel puin 4
i multiplu de 2;
GL_TRIANGLE_STRIP specific o serie de triunghiuri conectate. Primul triunghi
folosete vrfurile v0, v1 i v2. Urmtorul v2, v1 i v3, urmtorul v2, v3 i v4. Se observ
c ordinea asigur ca toate triunghiurile s fie orientate la fel;
GL_TRIANGLE_FAN specific o serie de triunghiuri conectate ntr-un vrf comun,
vrful v0. Primul triunghi este desenat folosind vrfurile v0, v1 i v2, urmtorul folosete
v0, v2 i v3, urmtorul v0, v3 i v4 etc.
Funcia glEnd marcheaz sfritul listei de vrfuri.
void glEnd(void);
Exemplu:
Primitiva redat n figura II.4 este specificat prin urmtoarea secven :
glBegin(GL_POLYGON);
glVertex2f(0.0, 0.0);
glVertex2f(0.0, 3.0);
glVertex2f(3.0, 3.0);
glVertex2f(4.0, 1.5);
glVertex2f(3.0, 0.0);
glEnd();
Figura II.4
Comentarii
Stabilete coordonatele vrfului
Stabilete culoarea curent a
vrfului
Seteaz indexul curent de
culoare
Stabileste vectorul normal
Genereaz coordonatele
Execut lista (listele) de afiare
Seteaz
coordonatele de
texturare
controloleaz
desenarea
muchiilor
Stabilete
proprietile
de
material
Tabelul II.3. Funcii care pot fi apelate ntre glBegin i glEnd
Dac ntre apelurile funciilor glBegin i glEnd apar apelurile altor funcii GLUT
se va genera cod de eroare. Pot apare ns instruciuni ale limbajului de programare n
care este implementat aplicaia.
Exemplu
Desenarea unui cerc prin linii.
#define PI 3.1415926535897;
GLint circle_points = 100;
glBegin(GL_LINE_LOOP);
for (i = 0; i < circle_points; i++)
{
angle = 2*PI*i/circle_points;
glVertex2f(cos(angle), sin(angle));
}
glEnd();
Acest exemplu nu reprezint cel mai eficient mod de a desena un cerc, mai ales
dac acest lucru se va face n mod repetat. Comenzile grafice folosite sunt rapide, dar
pentru fiecare vrf se calculeaz un unghi i se apeleaz functiile sin i cos. n plus apare
i overhead-ul introdus de bucl. Dac cercul va fi afiat de mai multe ori, pentru a
mbunti timpul de execuie, se vor calcula o singur dat coordonatele vrfurilor i se
vor salva ntr-un vector sau se va crea o list de afiare (display list).
ntre comenzile glBegin i glEnd vrfurile sunt generate doar la ntlnirea
apelului glVertex*. n momentul apelului funciei glVertex*, sistemul asociaz vrfului
respectiv culoarea curent, coordonatele de texturare, vectorul normal etc.
Exemplu
Primul vrf este desenat cu rou, iar al doilea i al treilea cu albastru:
glBegin(GL_POINTS);
glColor3f(0.0, 1.0, 0.0);
/* verde */
/* rou */
glVertex(...);
glColor3f(1.0, 1.0, 0.0);
/* galben */
/* albastru */
glVertex(...);
glVertex(...);
glEnd();
Funcia afieaz dreptunghiul definit de colurile (x1, y1) i (x2, y2). Dreptunghiul se afl
n planul z=0 i are laturile paralele cu axele x, respectiv y. Dac este folosit varianta cu
vectori, colurile dreptunghiului sunt specificate prin doi vectori, fiecare coninnd o
pereche (x, y). TYPE reprezint tipul coordonatelor colurilor dreptunghiului (s - GLshort,
i GLint , f - GLfloat, d - GLdouble).
Funcia seteaz limea n pixeli a punctelor ce vor fi afiate. Parametrul size reprezint
dimensiunea punctului exprimat n pixeli ecran. Ea trebuie s fie mai mare ca 0.0, iar
valoarea sa implicit este 1.0.
II.8.2. Atributele liniilor
n OpenGL segmentele de dreapt pot fi desenate avnd diferite limi, ca linii
continue sau ca linii punctate sau ntrerupte.
II.8.2.1.Limea liniilor
void glLineWidth(GLfloat width);
Funcia seteaz limea n pixeli a liniilor ce vor fi afiate; width trebuie s fie mai
mare ca 0.0, iar valoarea implicit este 1.0.
II.8.2.2. Tipul liniilor
Pentru afiarea liniilor punctate sau ntrerupte se va apela funcia glLineStipple,
care definete ablonul de generare a liniilor, apoi se va activa folosirea liniilor punctate
sau ntrerupte folosind funcia glEnable:
void glLineStipple(GLint factor, GLushort pattern);
Figura II.5
Generarea de linii cu ablon se va activa apelnd funcia glEnable cu parametrul
GL_LINE_STIPPLE i va fi dezactivat prin apelul funciei glDisable cu acelai
argument.
void glEnable(Glenum cap);
cap este o constant simbolic ce specific o capabilitate OpenGL. Ea poate avea una
din urmtoarele valori:
GL_CULL_FACE - activeaz / dezactiveaz eliminarea prilor nevizibile ale
obiectelor folosind metoda Back Face Culling.
GL_DEPTH_TEST activeaz / dezactiveaz calcularea valorilor buffer-ului de
adncime.
GL_LIGHTi - activeaz / dezactiveaz luarea n calcul a sursei de lumin i la
calculul de iluminare.
GL_LIGHTING activeaz / dezactiveaz calcularea culorii corespunztoare
fiecrui vrf.
GL_LINE_STIPPLE activeaz / dezactiveaz generarea liniilor folosind
ablon.
GL_NORMALIZE - acitiveaz /dezactiveaz normalizarea vectorilor normal.
GL_POLYGON_STIPPLE - activeaz / dezactiveaz folosirea ablonului
curent la afiarea poligoanelor.
Exemplu:
glLineStipple(1, 0x3F07);
glEnable(GL_LINE_STIPPLE);
drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES); \
*/
*/
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0101);
/*
linie punctat */
/*
linie ntrerupt */
/*
ntrerupt/punctat/ntrerupt
*/
drawOneLine (250.0, 125.0, 350.0, 125.0);
/*
linia a doua */
glLineWidth (5.0);
glLineStipple (1, 0x0101);
drawOneLine (50.0, 100.0, 150.0, 100.0);
glLineStipple (1, 0x00FF);
drawOneLine (150.0, 100.0, 250.0, 100.0);
glLineStipple (1, 0x1C47);
drawOneLine (250.0, 100.0, 350.0, 100.0);
glLineWidth (1.0);
/*
*/
/*
/*
linia a patra:
/*
ntrerupt/punctat/ntrerupt */
for (i = 0; i < 6; i++) {
drawOneLine (50.0 + ((GLfloat) i * 50.0),
50.0, 50.0 + ((GLfloat)(i+1) * 50.0), 50.0);
}
/*
*/
/*
GLubyte fly[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60,
0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 400.0, -100.0, 300.0, -1.0, 1.0);
}
int main(int argc, char** argv)
{
In mod implicit, pentru fiecare octet primul bit este considerat bitul cel mai semnificativ,
Ordinea biilor se poate modifica prin apelul funciei glPixelStore*().
Dac flag este GL_TRUE, atunci flag-ul de contur va fi setat la TRUE (valoarea
implicit ), i orice vrf definit n continuare va fi considerat ca aparinnd muchiilor de
contur pn la un nou apel al funciei glEdgeFlag* cu parametrul GL_FALSE.
Exemplu: Marcarea muchiilor de contur ale unui poligon
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_POLYGON);
glEdgeFlag(GL_TRUE);
glVertex3fv(V0);
glEdgeFlag(GL_FALSE);
glVertex3fv(V1);
glEdgeFlag(GL_TRUE);
glVertex3fv(V2);
glEnd();
Figura II.7.
delimitat prin planul din fa i planul din spate , plane paralele cu planul de
vizualizare, definite prin distanele lor fa de poziia observatorului (planul de
vizualizare). Planul din fa va fi folosit ca plan de proiecie. Lui i se ataeaz un sistem
de coordonate 2D avnd axa vertical (sus) orientat ca i axa vertical a planului de
vizualizare. Deschiderea camerei de luat vederi este determinat printr-o fereastr
rectangular, cu laturile paralele cu axele, definit n planul de proiecie.
- (left, bottom) i (right, top) reprezint colurile ferestrei din planul din fa
- znear, zfar reprezint distanele de la poziia observatorului la planul din fa,
respectiv spate. Ambele distane trebuie s fie pozitive.
2 * near
right - left
P 0
2 * near
B 0
top - bottom
0
C D
0
-1 0
unde
A
right left
top bottom
, B
right - left
top - bottom
C-
far near
2 * far * near
, Dfar - near
far - near
unde
(left, bottom) i (right, top) reprezint colurile ferestrei din planul din fa
near, far reprezint distanele de la poziia observatorului la planul din fa,
respectiv planul din spate
2
right - left
2
0
top - bottom
unde
tx -
tx
ty
-2
tz
far - near
0 1
right left
top bottom
far near
, ty , tz right - left
top - bottom
far - near
Matricea curent este nmulit cu matricea de proiecie rezultat, rezultatul fiind depus n
matricea curent.
Tot pentru proiecia ortografic poate fi folosit i funcia gluOrtho2D care
definete matricea de proiecie ortografic n care near=-1 i far=1.
void gluOrtho2D( Gldouble left, Gldouble right,
Gldouble bottom, Gldouble top);
unde
- (left, bottom) i (right, top) reprezint colurile ferestrei din planul din fa
(px, py) reprezint coordonatele n fereastr ale colului stnga jos al porii de
afiare (n pixeli). Valorile implicite sunt (0,0).
width, height reprezint limea, respectiv nlimea porii de afiare. Valorile
implicite sunt date de limea i nlimea ferestrei curente de afiare.
Fie (xd, yd, zd) coordonatele dispozitiv normalizate ale unui vrf i (xw, yw, zw)
coordonatele vrfului n fereastra de afiare. Transformarea n poarta de
vizualizare este definit astfel :
xw = ox + (width/2)xd
yw = oy + (height/2)yd
zw = ((f-n)/2)zd + (n+f)/2
Parametrul mode reprezint matricea asupra creia se vor efectua modificrile ulterioare.
El poate avea una dintre urmtoarele valori:
- GL_MODELVIEW matricea curent va fi matriciea de modelare i vizualizare
- GL_PROJECTION matricea curent va fi matricea de proiecie.
- GL_TEXTURE
matricea curent va fi matricea textur.
In programul din fiierul exemplu5.c, naintea transformrii de vizualizare, matricea
curent este setat la matricea identitate (de 4 linii i 4 coloane) cu ajutorul functiei
glLoadIdentity.
void glLoadIdentity(void);
Exemplu
Considerm urmtoarea secven care specific o secven de trei transformri:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf(N);
/* aplic transformarea N */
glMultMatrixf(M);
/* aplic transformarea M */
glMultMatrixf(L);
/* aplic transformarea L */
glBegin(GL_POINTS);
glVertex3f(v);
glEnd();
Un sistem OpenGL pstreaz cte o stiv de matrici pentru fiecare mod matrice
selectat cu ajutorul funciei MatrixMode. Astfel, exist :
Stiva matricilor Modelview (cel puin 32 matrici 4 x 4);
Stiva matricilor de proiecie (cel puin 2 matrici 4 x 4) ;
Stiva matricilor textur(cel puin 2 matrici 4 x 4).
Matricea curent este ntotdeauna matricea din vrful stivei corespunztoare
modului matrice curent.
O stiv de matrici este folositoare pentru construirea modelelor ierarhice n care sunt
construite obiecte complexe pornind de la obiecte simple. De exemplu, s presupunem c
se deseneaz o main i exist o singur rutin care deseneaz o roat. Aceast rutin
deseneaz roata ntr-o anumit poziie i orientare. Cnd se deseneaz maina, rutina de
afiare a roii se va apela de 4 ori, aplicndu-se diferite transformri pentru a poziiona
corect roile. De exemplu, pentru desenarea primei roi aceasta trebuie s fie translatat.
La desenarea celei de a doua roi trebuie aplicat o alt translaie (dar fa de poziia
iniial nu trebuie inut cont de prima translaie) i n acelai mod pentru desenarea
celorlalte roi.
Deoarece transformrile sunt pstrate ca matrici, o stiv de matrici furnizeaz un
mecanism util pentru efectuarea unei transformri ca apoi s se realizeze o alt
transformare fr a se mai ine cont de transformarea anterioar. Toate operaiile cu
matrici (glLoadMatrix, glMultMatrix, glLoadIdentity i funciile care creeaz matrici
de transformare specifice) lucreaz cu matricea curent sau cu matricea din vrful stivei.
Pentru lucrul cu stivele de matrici OpenGL pune la dispoziie funciile
glPushMatrix i glPopMatrix.
void glPushMatrix(void);
Funcia adaug un nou element la stiva curent i memoreaz matricea curent att n
elementul din vrful stivei ct i n intrarea urmtoare. Stiva curent este determinat de
ultimul apel al funciei glMatrixMode. Dac prin adugare se depaete capacitatea
stivei se genereaz eroare.
void glPopMatrix(void);
Funcia elimin intrarea din vrful stivei i nlocuiete matricea curent cu matricea care
era memorat n a 2-a intrare a stivei. Dac stiva avea o singur intrare, apelul funciei
glPopMatrix genereaz eroare.
Exemplu
Programul din fiierul exemplu5.c afieaz un cub care este mai nti scalat
(transformarea de modelare). Transformarea de vizualizare const dintr-o translaie a
poziiei observatorului pe axa z, n poziia (0,0,5). Observatorul privete spre origine iar
direcia axei sus este direcia axei OY a sistemului de coordonate obiect.
/* exemplu5.c */
#include "glut.h"
void init(void)
{
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glLoadIdentity ();
gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);
glScalef (1.0, 2.0, 1.0);
glutWireCube (1.0);
glFlush ();
}
void reshape (int w, int h)
{
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
II.10. Iluminarea
II.10.1. Specificarea culorilor pentru lumin i materiale
In capitolul II.6 ne-am referit la modul uzual n care sunt specificate culorile de
afiare a obiectelor. Funciile glColor3 specific un triplet (R, G, B). Funciile glColor4
adaug tripletului (R,G,B) o valoare de opacitate, numit valoarea alfa (A).
OpenGL permite utilizarea a dou moduri de reprezentare a culorilor de afiare:
modul RGBA: pentru fiecare pixel se memoreaz valorile R, G, B i A.
modul indexat: pentru fiecare pixel se memoreaz un numr, reprezentnd un index
ntr-o tabela de culori.
Valorile R, G, B i A variaz n domeniul [0, 1].
n modul RGBA, pentru selectarea culorii curente de desenare se folosesc funciile
glColor*.
void glColor3{b s i f d ub us ui} (TYPE r, TYPE g, TYPE b);
void glColor4{b s i f d ub us ui} (TYPE r, TYPE g, TYPE b, TYPE
a);
void glColor3{b s i f d ub us ui}v (const TYPE* v);
void glColor4{b s i f d ub us ui}v (const TYPE* v);
1-byte integer
2-byte integer
4-byte integer
Valoarea
minim
-128
-32,768
-2,147,483,648
Valoarea minim
se mapeaza la
-1.0
-1.0
-1.0
Valoarea
maxim
127
32,767
2,147,483,647
Valoarea maxim
se mapeaz la
1.0
1.0
1.0
0.0
255
1.0
0.0
65,535
1.0
0.0
4,294,967,295
1.0
Tip
b
s
i
u
b
u
s
u
i
n modelul Gouraud culoarea fiecrui vrf este tratat n mod individual. Pentru un
segment de dreapt culoarea se obine prin interpolarea culorilor vrfului. Pentru un
poligon, culorile punctelor interioare se obin prin interpolare pe baza culorilor vrfurilor.
Exemplu : n fiierul exemplul6.c se afieaz un triunghi folosind modelul de iluminare
Gouraud.
/* fiierul exemplul6.c */
#include "glut.h"
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
}
void triangle(void)
{
glBegin (GL_TRIANGLES);
glColor3f (1.0, 0.0, 0.0);
glVertex2f (5.0, 5.0);
glColor3f (0.0, 1.0, 0.0);
glVertex2f (25.0, 5.0);
glColor3f (0.0, 0.0, 1.0);
glVertex2f (5.0, 25.0);
glEnd();
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
triangle ();
glFlush ();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
if (w <= h)
gluOrtho2D (0.0, 30.0, 0.0, 30.0*(GLfloat) h/(GLfloat) w);
else
gluOrtho2D (0.0, 30.0*(GLfloat) w/(GLfloat) h, 0.0, 30.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
n modelul Lambert culoarea unei primitive este dat de culoarea unui singur
vrf. Culoarea unui segment de dreapt este dat de culoarea celui de-al doile vrf.
Culoarea unui poligon este dat de culoarea unui vrf, conform tabelului II.5. Vrfurile
poligoanelor sunt numerotate ncepnd cu 1. Pentru a evita confuzii n ceea ce privete
culoarea de desenare n modelul Lambert se va specifica o singur culoare pentru o
primitiv.
Tipul poligonului
Poligon singular
triangle strip
triangle fan
independent triangle
quad strip
independent quad
i+2
3i
2i+2
4i
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere (1.0, 20, 16);
glFlush ();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-1.5*(GLfloat)w/(GLfloat)h,
1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
II.10.3.1. Crearea, poziionarea i activarea uneia sau a mai multor surse de lumin
n programul din fiierul exemplul7.c se folosete o singur surs de lumin alb.
Poziia sa este specificat prin apelul funciei glLightfv. Acest exemplu folosete
culoarea implicit pentru sursa de lumina 0 (GL_LIGHT0), care este alb ; dac se
dorete o surs de lumin avnd o alt culoare se va folosi funcia glLight*. ntr-o scen
pot fi incluse cel mult 8 surse de lumin diferite. Culoarea implicit a acestor surse de
lumin este negru. Ele pot fi poziionate la o distan finit sau infinit fa de scen.
Sursele de lumin pot produce un fascicul de lumin mai ngust sau mai larg. Dup ce au
fost definite caracteriticile surselor de lumin, acestea trebuie s fie activate folosind
funcia glEnable. De asemenea, trebuie apelat funcia glEnable avnd ca parametru
GL_LIGHTING pentru a activa efectuarea calculelor de iluminare (n mod implicit
acestea sunt dezactivate).
Crearea surselor de lumin
Sursele de lumin au o serie de proprieti cum sunt culoarea, poziia i direcia.
Funcia folosit pentru a specifica toate proprietile luminii este glLight*.
void glLight{if}(GLenum light, GLenum pname, TYPE param);
void glLight{if}v(GLenum light, GLenum pname, TYPE *param);
Valoarea implicita
(0.0, 0.0, 0.0, 1.0)
(1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0)
(0.0, 0.0, 1.0, 0.0)
(0.0, 0.0, -1.0)
0.0
180.0
1.0
0.0
Observatie
Intensitatea ambiant a luminii (RGBA)
Intensitatea luminii difuze (RGBA)
Intensitatea luminii speculare (RGBA)
Poziia (x, y, z, w) a luminii
Direcia (x, y, z) spotului de lumin
Exponentul spotului delumin
Unghiul spotului de lumin
Factor de atenuare constant
Factor de atenuare liniar
GL_QUADRATIC_ATTENUATION
0.0
Tabelul II.6.
Valorile implicite din tabelul de mai sus pentru GL_DIFFUSE i GL_SPECULAR se
aplic doar pentru sursa de lumin GL_LIGHT0. Pentru celelate surse de lumin,
valoarea implicit este (0.0, 0.0, 0.0, 1.0) att pentru GL_DIFFUSE ct i pentru
GL_SPECULAR.
Exemplu : definirea culorilor, poziiei i a factorilor de atenuare pentru o surs de lumin
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5);
Figura II.10.
Direcia este specificat n coordonate obiect omogene. Valoarea implicit a direciei este
(0.0, 0.0, -1.0).
Surse de lumin multiple
ntr-o scen pot fi definite cel mult 8 surse de lumin. Constatele folosite pentru
referirea celor 8 surse de lumin sunt : GL_LIGHT0, GL_LIGHT1, GL_LIGHT2,
GL_LIGHT3, , GL_LIGHT7. Dac se specific o alt surs de lumin trebuie s i se
seteze parametrii corespunztori ca i n cazul sursei de lumin GL_LIGHT0.
Exemplu : definirea unui spot de lumina alb :
GLfloat light1_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat light1_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light1_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light1_position[] = { -2.0, 2.0, 1.0, 1.0 };
GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2);
n exemplul din fiierul exemplul7.c singurul element care este definit explicit
pentru modelul de iluminare este lumina ambiant global. De asemenea, modelul de
iluminare definete i poziia observatorului (la infinit sau la distan finit de scen)
precum i modul de efectuare a calculelor de iluminare a feelor fa respectiv spate ale
scenei. n programul din fiierul exemplul7.c se folosesc valorile implicite pentru acestea
observatorul este plasat la infinit i calculele de iluminare sunt efectuate pentru feele
fa. Folosirea unui observator local scenei crete complexitatea calculelor deoarece
sistemul OpenGL trebuie s calculeze unghiul dintre observator i fiecare obiect.
Folosind un observator plasat la infinit unghiul este ignorat i rezultatele sunt ceva mai
puin realiste.
n OpenGL modelul de iluminare are trei componente :
Intensitatea luminii ambiante globale
Poziionarea observatorului (local scenei sau la infinit)
Diferenierea calculrii iluminrii pentru feele obiectelor fa, respectiv spate.
n exemplul de mai sus valorile folosite pentru lmodel_ambient sunt valorile implicite
pentru GL_LIGHT_MODEL_AMBIENT.
Valoare implicita
(0.2, 0.2, 0.2, 1.0)
(0.8, 0.8, 0.8, 1.0)
(0.0, 0.0, 0.0, 1.0)
0.0
(0.0, 0.0, 0.0, 1.0)
(0,1,1)
Observaie
Culoarea ambiant a materialului
Culoarea difuz a materialului
Culoarea ambiant i difuz a materialului
Culoarea specular a materialului
Exponentul specular
Culoarea emis a materialului
Indicii de culoare ambiant, difuz i specular
Tabelul II.7.
Reflexia difuz i ambiant
Parametrii GL_DIFFUSE i GL_AMBIENT setai cu funcia glMaterial*
afecteaz culoarea luminii ambiante i difuze reflectate de un obiect.
Exemplu: asignarea simultan a aceleeai valori luminii reflectate difuze i ambiante :
GLfloat mat_amb_diff[] = { 0.1, 0.5, 0.8, 1.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
mat_amb_diff);
Reflexia specular
OpenGL permite setarea culorii RGBA a strlucirii speculare (folosind
GL_SPECULAR) i poate controla dimensiunea i luminozitatea strlucirii (folosind
GL_SHININESS). Parametrului GL_SHININESS i se poate asocia o valoare n
domeniul [0.0, 128.0];cu ct valoarea este mai mare cu att stlucirea este mai mic i
mai luminoas.
Exemplu :
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
Emisia
Prin asocierea unei culori RGBA parametrului GL_EMISSION se poate face ca
un obiect s par c furnizeaz lumin de culoarea selectat.
Exemplu:
GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
glPopMatrix();
material
GLint i;
GLfloat cosine, sine;
static GLfloat circoords[100][2];
static GLint inited=0;
if(inited==0){
inited=1;
for(i=0;i<100;i++){
circcoords[i][0]=cos(i*2*PI/100.0);
circcoords[i][1]=sin(i*2*PI/100.0);
}
}
glBegin(GL_POLYGON);
for(i=0;i<100;i++)
glVertex2fv(&circcoords[i][0]);
glEnd();
for(i=0;i<100;i++){
cosine=cos(i*2*PI/100.0);
sine=sin(i*2*PI/100.0);
glVertex2f(cosine,sine);
}
glEnd();
glEndList();
}
Listele de afiare sunt un mod convenabil i eficient de a vedea sub forma unui
nume o secven de comenzi OpenGL. O list de afiare conine numai apeluri OpenGL.
Alte apeluri - ca n exemplul de mai sus, cum ar fi funciile C cos i sin nu sunt stocate
n listele de afiare. Coordonatele i celelalte variabile (cum ar fi coninutul vectorului)
sunt evaluate i copiate n lista de afiare avnd valorile de la momentul compilrii listei.
Dup compilarea listei aceste valori nu pot fi modificate. Lista de afiare poate fi tears
i se poate crea una nou, dar o list de afiare existent nu poate fi editat.
Exemplu
Programul din fiierul exemplul8.c vizualizeaz unui tor din diferite unghiuri. Cel mai
eficient mod de a face acest lucru este de a pstra torul ntr-o list de afiare. Apoi, de
cte ori se dorete s se modifice poziia observatorului se va modifica matricea
ModelView i se va executa lista de afiare pentru desenarea torului.
/* fiierul exemplul8.c */
#include "glut.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glCallList(theTorus);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
}
/* la apsarea tastei 'x' - se rotete n jurul axei x
la apsarea tastei 'y' - se rotete n jurul axei y
la apsarea tastei 'i' - se poziioneaza torul n poziia
original
*/
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'x':
case 'X':
glRotatef(30.,1.0,0.0,0.0);
glutPostRedisplay();
break;
case 'y':
case 'Y':
glRotatef(30.,0.0,1.0,0.0);
glutPostRedisplay();
break;
case 'i':
case 'I':
glLoadIdentity();
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
glutPostRedisplay();
break;
case 27:
exit(0);
break;
}
}
int main(int argc, char **argv)
{
glutInitWindowSize(200, 200);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Utilizatorul poate roti torul n jurul axei OX sau OY prin apsarea tastelor x
respectiv y. De cte ori se ntampl acest lucru este apelat funcia callback keyboard
care nmulete matricea de rotaie de 30o n jurul axei x sau y cu matricea curent
ModelView, dup care este apelat funcia glutPostRedisplay, care face ca funcia
glutMainLoop s apeleze funcia display i s afieze torul dup prelucrarea altor
evenimente. La apsarea tastei i funcia keyboard reface matricea iniial ModelView i
reafieaz torul n poziia sa iniial. Funcia display terge fereastra i apeleaz funcia
glCallList pentru a executa comenzile din lista de afiare.
Dac nu s-ar fi folosit liste de afiare funcia display ar fi trebuit s conin
comenzi de desenare a torului de fiecare dat cnd ar fi fost apelat.
O list de afiare conine numai comenzi OpenGL. n exemplul din fiierul
exemplul8.c sunt stocate apelurile funciilor glBegin, glVertex i glEnd. Parametrii
apelurilor sunt evaluai i valorile lor sunt copiate n lista de afiare la crearea sa. Toate
calculele trigonometrice pentru crearea torului sunt fcute o singur dat ceea ce duce la
creterea performanelor afirii.
Exemplu: aplicarea unor transformri unor obiecte geometrice i apoi
rezultatului:
desenarea
glNewList(1, GL_COMPILE);
afiseaza_obiectele_geometrice();
glEndList();
glLoadMatrix(M);
glCallList(1);
Dac obiectele sunt transformate de fiecare dat n acelai mod este bine s se
pstreze matricea de transformare ntr-o list de afiare.
Exemplu
In unele implementri, se vor putea mbuntai performanele prin transformarea
obiectelor n momentul definirii lor n loc de a le transforma de fiecare dat cnd sunt
afiate :
glNewList(1, GL_COMPILE);
glLoadMatrix(M);
afiseaza_obiectele_geometrice();
glEndList();
glCallList(1);
identificatorul su. n fiierul exemplul9.c lista de afiare este creat n funcia init. n
funcia display lista de afiare va fi apelat de 10 ori. Listele de afiare aloc memorie
pentru a stoca comenzile i valorile oricrei variabilele necesare. Funcia glTranslatef
din lista de afiare modific poziia urmtorului obiect ce va fi afiat. Apelul drawLine
este de asemenea afectat de funcia glTranslatef care o precede.
/* fiierul exemplul9.c */
#include glut.h
#include <stdlib.h>
GLuint listName;
void init (void)
{
listName = glGenLists (1);
glNewList (listName, GL_COMPILE);
glColor3f (1.0, 0.0, 0.0);
/*
*/
glBegin (GL_TRIANGLES);
glVertex2f (0.0, 0.0);
glVertex2f (1.0, 0.0);
glVertex2f (0.0, 1.0);
glEnd ();
glTranslatef (1.5, 0.0, 0.0); /*
glEndList ();
glShadeModel (GL_FLAT);
}
void drawLine (void)
{
glBegin (GL_LINES);
glVertex2f (0.0, 0.5);
glVertex2f (15.0, 0.5);
glEnd ();
}
void display(void)
{
GLuint i;
glClear (GL_COLOR_BUFFER_BIT);
modificare poziie
*/
/*
*/
/*
afiare 10 triunghiuri
*/
glCallList (listName);
drawLine ();
glFlush ();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
gluOrtho2D (0.0, 2.0, -0.5 * (GLfloat) h/(GLfloat) w,
1.5 * (GLfloat) h/(GLfloat) w);
else
gluOrtho2D (0.0, 2.0*(GLfloat) w/(GLfloat) h, -0.5, 1.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(650, 50);
glutCreateWindow(argv[0]);
init ();
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutDisplayFunc (display);
glutMainLoop();
return 0;
}
Observaie: Dac o list de afiare conine comenzi de transformare trebuie avut grij
care va fi efectul acestora n program mai trziu.
La un moment dat poate fi creat numai o singur lista de afiare. Cu alte cuvinte
trebuie terminat crearea unei liste de afiare (glNewList i glEndList) nainte de a crea
o alt list. Apelul funciei glEndList fr a fi apelat nainte funcia glNewList va genera
eroarea GL_INVALID_OPERATION.
Funcia aloc un domeniu de range numere continue nefolosite ca indici pentru liste de
afiare. Valoarea ntoars de funcie reprezint indicele de nceput a blocului de indici
nefolosii. Indicii returnai vor fi marcai ca folosii astfel ca apelurile ulterioare ale
funciei glGenLists nu vor ntoarce aceti indici pn nu vor fi teri. Funcia ntoarce 0
dac nu este disponibil numarul de indici cerui sau dac range este 0.
Exemplu: alocarea unui singur index; dac el este liber va fi folosit pentru a crea o nou
list de afiare :
listIndex = glGenLists(1);
if (listIndex != 0) {
glNewList(listIndex,GL_COMPILE);
...
glEndList();
}
Funcia specific nceperea unei liste de afiare. Funciile OpenGL care vor fi apelate
(pn la ntlnirea funciei glEndList care marcheaz sfritul listei de afiare) sunt
stocate n lista de afiare, excepie facnd cteva funcii OpenGL care nu pot fi stocate.
Aceste funcii restricionate sunt executate imediat n timpul crerii listei de afiare.
-
list este un ntreg pozitiv diferit de 0 care identific n mod unic lista de afiare.
valorile
posibile
ale
parametrului
mode
sunt
GL_COMPILE
glFlush()
GlNormalPointer()
glDeleteLists()
glGenLists()
GlPixelStore()
glDisableClientState()
glGet*()
GlReadPixels()
glEdgeFlagPointer()
glIndexPointer()
GlRenderMode()
glEnableClientState()
glInterleavedArrays()
GlSelectBuffer()
glFeedbackBuffer()
glIsEnabled()
GlTexCoordPointer()
glFinish()
glIsList()
GlVertexPointer()
Tabelul II.8.
La folosirea unui sistem OpenGL n reea, clientul poate rula pe o main i
server-ul pe alta. Dup crearea unei liste de afiare ea se va afla la server astfel c serverul nu se poate baza pe client pentru nici o informaie relativ la lista de afiare. Astfel,
orice comand care ntoarce o valoare nu poate fi stocat ntr-o list de afiare. n plus,
comenzile care modific starea clientului cum ar fi glPixelStore, glSelectBuffer i
comenzile de definire a vectorilor de vrfuri nu pot fi stocate ntr-o list de afiare.
Operaiile unor comenzi OpenGL depind de starea clientului. De exemplu,
funciile de specificare a vrfurilor vectorilor (cum ar fi glVertexPointer, glColorPointer
i glInterleavedArrays) seteaz pointeri de stare ai clientului i nu pot fi stocate ntr-o
list de afiare. Funciile glArrayElement, glDrawArrays i glDrawElements transmit
date ctre server pentru a construi primitive din elementele vectorilor. Astfel de operaii
pot fi stocate ntr-o list de afiare.
Vectorul de vrfuri stocat n lista de afiare este obinut prin dereferenierea datei
din pointeri nu prin stocarea pointerilor . Astfel, modificrile datelor din vectorul de
vrfuri nu va afecta definirea primitivei n lista de afiare.
Funcii cum ar fi glFlush i glFinish nu pot fi stocate ntr-o list de afiare
deoarece depind de starea clientului n momentul execuiei.
Dup crearea unei liste de afiare aceasta poate fi executat prin apelul funciei
glCallList. O list de afiare poate fi executat de mai multe ori i de asemenea o list de
afiare poate fi executat mbinndu-se cu apeluri n modul imediat.
void glCallList (GLuint list);
Functia execut lista de afiare specificat de parametrul list. Comenzile din lista de
afiare sunt executate n ordinea n care au fost salvate ca i cum ar fi executate fr a se
folosi o lista de afiare. Dac lista nu a fost definit nu se va ntmpla nimic.
Funcia glCallList poate fi apelat din orice punct al programului atta timp ct
contextul OpenGL care acceseaz lista de afiare este activ (contextul care a fost activ la
crearea listei de afiare sau un context din acelai grup partajat). O list de afiare poate
fi creat ntr-o funcie i executat n alt funcie atta timp ct indexul su o identific n
mod unic. De asemenea, contextul unei liste de afire nu poate fi salvat ntr-un fiier i
nici nu se poate crea o list de afiare dintr-un fiier. n acest sens o list de afiare este
proiectat pentru a fi folosit temporar.
II.11.3. Liste de afiare ierarhice
O list de afiare ierarhic este o list de afiare care execut o alt list de afiare
prin apelul funciei glCallList, ntre perechile de funcii glNewList i glEndList. O list
de afiare ierarhic este folositoare pentru un obiect alctuit din componente, n mod
special dac aceste componente sunt folosite de mai multe ori.
Exemplu: o list de afiare care deseneaz o biciclet prin apelul altor liste de afiare
pentru desenarea componentelor :
glNewList(listIndex,GL_COMPILE);
glCallList(handlebars);
glCallList(frame);
glTranslatef(1.0,0.0,0.0);
glCallList(wheel);
glTranslatef(3.0,0.0,0.0);
glCallList(wheel);
glEndList();
OpenGL permite crearea unei liste de afiare care s apeleze o alt list de afiare
care nu a fost nc creat. Nu va avea nici un efect dac prima list o apeleaz pe cea de a
doua care nc nu a fost definit.
Exemplu : list de afiare ierarhic
glNewList(1,GL_COMPILE);
glVertex3f(v1);
glEndList();
glNewList(2,GL_COMPILE);
glVertex3f(v2);
glEndList();
glNewList(3,GL_COMPILE);
glVertex3f(v3);
glEndList();
glNewList(4,GL_COMPILE);
glBegin(GL_POLYGON);
glCallList(1);
glCallList(2);
glCallList(3);
glEnd();
glEndList();
Funcia ntoarce GL_TRUE dac indexul specificat de parametrul list este deja folosit
pentru o list de afiare i GL_FALSE n caz contrar.
Pentru a terge n mod explicit o list de afiare sau un domeniu continuu de liste
se folosete funcia glDeleteLists. Folosirea funciei glDeleteLists elibereaz indicii
corespunztori listelor terse s fie disponibili din nou.
void glDeleteLists(GLuint list, GLsizei range);
Funcia terge range liste de afiare ncepnd de la indexul specificat de list. Este ignorat
ncercarea de a se terge o list de afiare care nu a fost creat.
II.11.5. Execuia listelor de afiare multiple
OpenGL furnizeaz un mecanism eficient de a executa succesiv liste de afiare.
Acest mecanism necesit introducerea indicilor listelor de afiare ntr-un vector si apoi
apelarea funciei glCallLists. O utilizare pentru acest mecanism este acela de a crea un
font i fiecare indice de list de afiare s corespund valorii ASCII a caracterului din
font. Pentru a avea mai multe fonturi este necesar stabilirea unui index iniial diferit
pentru fiecare font. Acest index iniial poate fi specificat prin apelarea funciei glListBase
nainte de a apela glCallLists.
void glListBase(GLuint base);
Funcia specific offset-ul care este adunat indicilor listelor de afiare n apelul funciei
glCallLists pentru a obine indicii listelor de afiare finali. Valoarea implicit a
parametrului base este 0. Parametrul base nu are nici un efect asupra apelului glCallList,
care execut o singur list de afiare, sau asupra funciei glNewList.
void glCallLists(GLsizei n, GLenum type, const GLvoid *lists);
Functia execut n liste de afiare. Indicii listelor care vor fi executate vor fi calculai prin
adunarea offset-ului indicat de baza curent a listei de afiare (specificat cu ajutorul
funciei glListBase la valorile ntregi indicate de parametrul lists.
Parametrul type specific tipul valorilor din lists. El poate avea una din valorile
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT,
GL_INT, GL_UNSIGNED_INT sau GL_FLOAT, adic ceea ce indic lists poate fi
tratat ca un vector de bytes, unsigned bytes, shorts, unsigned shorts, integers, unsigned
integers, sau floats. De asemenea parametrul type poate avea una din valorile
GL_2_BYTES, GL_3_BYTES sau GL_4_BYTES caz n care succesiuni de 2, 3 sau 4
octei vor fi citii din lists i apoi sunt deplasai i adunai octet cu octet pentru a calcula
offset-ul listei de afiare. Pentru aceasta este folosit urmtorul algoritm (byte[0]
reprezint nceputul secvenei de octei).
/* b = 2, 3 sau 4; octeii sunt numerotai n vector 0,1,2,3 */
offset = 0;
for (i = 0; i < b; i++) {
offset = offset << 8;
offset += byte[i];
}
index = offset + listbase;
Exemplu
Definirea listelor de afiare multiple: afiarea caracterelor dintr-un set de caractere
vectorial
void initStrokedFont(void)
/* seteaz indicii listelor de afiare pentru fiecare caracter
corespunztor valorii lor ASCII */
{
GLuint base;
base = glGenLists(128);
glListBase(base);
glNewList(base+'A', GL_COMPILE);
drawLetter(Adata); glEndList();
glNewList(base+'E', GL_COMPILE);
drawLetter(Edata); glEndList();
glNewList(base+'P', GL_COMPILE);
drawLetter(Pdata); glEndList();
glNewList(base+'R', GL_COMPILE);
drawLetter(Rdata); glEndList();
glNewList(base+'S', GL_COMPILE);
drawLetter(Sdata); glEndList();
glNewList(base+' ', GL_COMPILE);
/* spaiu */
Funcia glGenLists aloc 128 de indici continui pentru listele de afiare. Primul
indice alocat devine baza listei de afiare. Pentru fiecare caracter va fi creat cte o list
de afiare; fiecare index al listei de afiare este suma dintre indicele de baz i valoarea
ASCII a literei. n acest exemplu sunt create numai cteva litere i caracterul . Dup
crearea listelor de afiare poate fi apelata funcia glCallLists pentru a le executa.
Exemplu
Apelul functiei printStrokedString avnd ca parametru un caracter :
void printStrokedString(GLbyte *s)
{
GLint len = strlen(s);
glCallLists(len, GL_BYTE, s);
}
glVertex2f(0.0,1.0);
glEnd();
glTranslatef(1.5,0.0,0.0);
glEndList();
Dac se va apela urmtoarea secven de cod, segmentul de dreapt desenat dup lista de
afiare va avea culoarea roie (culoarea curent) i va fi translatat cu (1.5, 0.0, 0.0):
glCallList(listIndex);
glBegin(GL_LINES);
glVertex2f(2.0,-1.0);
glVertex2f(1.0,0.0);
glEnd();
Uneori este necesar ca modificrile strii s fie pstrate, dar alteori dup execuia
unei liste de afiare se dorete s se revin la starea anterioar. ntr-o list de afiare nu
poate fi folosit funcia glGet*, aa c trebuie folosit un alt mod de a interoga i stoca
valorile variabilelor de stare. n acest scop poate fi folosit funcia glPushAttrib pentru a
salva un grup de variabile de stare i glPopAttrib pentru a reface variabilele.
Exemplu
Refacerea variabilelor de stare din interiorul unei liste de afiare
glNewList(listIndex,GL_COMPILE);
glPushMatrix();
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(0.0,0.0);
glVertex2f(1.0,0.0);
glVertex2f(0.0,1.0);
glEnd();
glTranslatef(1.5,0.0,0.0);
glPopAttrib();
glPopMatrix();
glEndList();
Exemplu
Dac se folosete lista de afiare de mai sus atunci se va desena un segment de dreapt de
culoare verde i netranslatat:
void display(void)
{
GLint i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
ori*/
drawLine();
glFlush();
}