Sunteți pe pagina 1din 10

Grafic pe calculator n C i OpenGL

Sistemul de vizualizare OpenGL


1. Definirea proieciei perspectiv i a volumului de vizualizare
n OpenGL un punct este reprezentat printr-un vector coloan. Pentru matricele 4 4
utilizate n reprezentarea unei transformri geometrice n coordonate omogene, este utilizat
convenia coloan major. Conform acestei convenii, fiind dat un numr de 16 valori reale, n
ordinea a0 , a1,K, a15 , matricea corespunztoare este:

a0
a
1
A=
a2

a3

a4
a5
a6
a7

a8 a12
a9 a13
.
a10 a14

a11 a15

(1)

Sistemul de referin universal, WCS, definit n OpenGL este un sistem drept. De


asemenea, sistemul de referin de observare, VCS, este un sistem drept i este definit, ca
localizare i orientare, n raport cu sistemul de referin universal. Originea sistemului de
referin de observare, coincide cu centrul de proiecie (sistemul de vizualizare OpenGL
constituie un caz particular al sistemului PHIGS).
n sistemul de referin de observare se poate defini o transformare de proiecie
paralel ortografic sau de proiecie perspectiv. OpenGL ofer funcii ce permit definirea
proieciei perspectiv pe un plan perpendicular pe axa zv a sistemului de referin de
observare, cu direcia de observare spre zv (fig.1).

Direcia de observare

yv

Ov

zv
xv

zv

C
C

z v = znear

z v = zfar

Fig. 1 Definirea proieciei perspectiv i a volumului de vizualizare n OpenGL

Lucrarea 5
Volumul de vizualizare n cazul proieciei perspectiv, n OpenGL, este un trunchi de
piramid, ABCDABCD . Trunchiul de piramid de vizualizare (frustum), este determinat de
intersecia a dou plane de vizualizare, planul apropiat i planul deprtat, cu patru plane
laterale. Planul de vizualizare apropiat este i planul n care sunt proiectate toate obiectele
vizibile ale scenei. Suprafaa ABCD din planul de vizualizare apropiat (planul de proiecie)
constituie fereastra de vizualizare (view plane window). Prin urmare, trunchiul de piramid de
vizualizare este orientat spre zv i este fi definit prin urmtoarele valori:
(left, bottom) i (right, top): coordonatele colurilor ferestrei din planul din fa (ale
ferestrei de vizualizare);
znear: distana (ca valoare pozitiv) de la poziia observatorului la planul din fa;
zfar: distana (ca valoare pozitiv) de la poziia observatorului la planul din spate.
Funcia OpenGL care definete o proiecie perspectiv ca cea din figura 1 este:
void glFrustum(GLdouble left, GLdouble right, GLdouble bottom,
GLdouble top, GLdouble znear, GLdouble zfar);

Colurile ferestrei 2D din planul de proiecie, (left, bottom, -znear) i (right, top, -zfar)
sunt mapate pe colurile stnga-jos i dreapta-sus ale ferestrei 2D din sistemul coordonatelor
de decupare, adic (1,1,1) i (1,1,1) . Matricea de proiecie este urmtoarea:
2 znear
right left

0
MP =

0
2 znear
top bottom
0
0

right + left
right left
top + bottom
top bottom
zfar + znear

zfar znear
1

0
.
2 zfar znear

zfar znear
0

(2)

O alt funcie care poate fi folosit pentru definirea proieciei perspectiv este:
void gluPerspective(GLdouble fovy, GLdouble aspect,
GLdouble znear, GLdouble zfar);

Funcia gluPerspective() creeaz un volum de vizualizare la fel ca i funcia glFrustum(),


dar specificarea se face n alt mod. n cazul acestei funcii volumul de vizualizare se specific
prin unghiul de vizualizare n planul Ov xv yv (deschiderea camerei de luat vederi), raportul
dintre limea i nlimea ferestrei definite n planul apropiat i distanele la planul apropiat,
respectiv deprtat (ca valori pozitive). Deci parametrii funciei sunt:
fovy: unghiul de vizualizare n planul Ov xv yv , care trebuie s fie n intervalul

[0.0,180.0] ;

aspect: raportul lime/nlime al laturilor ferestrei din planul apropiat; acest raport
trebuie s corespund raportului lime/nlime asociat porii de afiare. De exemplu,
dac aspect = 2 , atunci unghiul de vizualizare pe direcia axei xv este de dou ori mai
mare dect cel pe direcia axei yv . Dac poarta de afiare are limea de dou ori mai
mare dect nlimea, atunci imaginea va fi afiat nedistorsionat.

Grafic pe calculator n C i OpenGL


znear, zfar: distanele ntre observator i planele de decupare de-a lungul axei z v
negative (se iau ca valori pozitive).

2. Compunerea transformrilor geometrice


Pentru a efectua transformri geometrice compuse nu este eficient s se calculeze
produsul dintre matricea de reprezentare a fiecrui punct i matricele de transformri
succesive. Este de preferat s se calculeze o matrice de transformare compus, care se poate
aplica unuia sau mai multor obiecte. Pentru calculul matricelor de transformare compuse (prin
produs de matrice) se folosete o matrice de transformare curent C i operaii de acumulare
n matricea curent prin nmulire la dreapta. Rezultatul nmulirii nlocuiete coninutul
matricei curente.
De exemplu, pentru secvena de transformri n ordinea M1, M 2 ,K, M n , aplicate
obiectelor scenei, mai nti se iniializeaz matricea curent C cu matricea identitate, dup
care se calculeaz matricea compus prin postmultiplicare (nmulire la dreapta) n ordine
invers celei n care se aplic matricele componente.
C=I
C = C Mn = Mn

C = C M n 1 = M n M n 1
.........................................
C = C M1 = M n M n 1 K M 2 M1

(3)

C = M = M n M n 1 K M 2 M1
P = M P = M n M n 1 K M1 P

n aceast transformare, se aplic mai nti matricea M 1 punctului P . Punctului astfel rezultat
i se aplic transformarea M 2 .a.m.d . Acest mod de calcul al matricelor compuse este folosit
n OpenGL.
Matricea curent se poate iniializa cu matricea identitate prin funcia
glLoadIndentity() sau cu o matrice oarecare, dat de un pointer la un vector de 16 valori
consecutive, prin funcia glLoadMatrix#().
glLoadMatrixd( const GLdouble *m);
glLoadMatrixf( const GLfloat *m);

Valorile din vectorul GLdouble *m (respectiv GLfloat *m) sunt atribuite n ordinea
coloan major matricei curente.
Coninutul matricei curente poate fi modificat prin multiplicare (la dreapta) cu o alt
matrice, dat printr-un vector de 16 valori de tip double sau float utiliznd funcia
glMultMatrix#().
glMultMatrixd( const GLdouble *m);

Lucrarea 5
glMultMatrixf( const GLfloat *m);

Matricea iniial C este astfel nlocuit cu produsul C M , unde M este matricea


corespunztoare vectorului dat de pointerul m. Crearea unei matrice pentru o transformare
elementar (translaie, scalare etc.) i nmulirea ei cu matricea curent se poate face prin
apelul unei singure funcii OpenGL.
Transformrile compuse se efectueaz prin acumularea produsului matricelor
componente n matricea curent. De exemplu, transformrile de modelare din lucrarea
precedent au fost implementate n OpenGL dup cum urmeaz:
Transformarea M 2 = T (0,8,0) S (2,2,2) :
glTranslated(0,-8,0);
glScaled(2,2,2);

Transformarea M 3 = T (8,0,0) Rz ( / 4) S (2,1,2) :


glTranslated(8,0,0);
glRotated(45,0,0,1);
glScaled(2,1,2);

Transformarea M 4 = T (8,0,0) Rz ( / 4) S (2,1,2)


glTranslated(-8,0,0);
glRotated(-45,0,0,1);
glScaled(2,1,2);

3. Stivele matricelor de transformare utilizate n OpenGL


Transformarea unui obiect din sistemul de referin local n sistemul de referin
normalizat este compus din succesiunea transformrilor de modelare (instaniere) M i , de
observare M v i de normalizare M n :

M = M n M v Mi

(4)

Transformarea de instaniere M i este, n general, specific fiecrui obiect, deci se


calculeaz pentru fiecare obiect n parte.
Pentru cele mai multe din aplicaiile grafice, n care scena este observat dintr-un
singur punct de observare, matricea de observare M v este unic pentru toate obiectele dintrun cadru dat, dar se modific n cadrul urmtor (imaginea urmtoare), dac observatorul i-a
schimbat poziia de observare (situaie ntlnit n grafica interactiv).
Matricea de normalizare M n este definit de parametrii de proiecie care corespund
sistemului grafic. Aceast matrice este o caracteristic constructiv a sistemului grafic i
rmne constant pe toat perioada desfurrii programului, pentru toate obiectele i pentru
toate imaginile generate. n concluzie, sunt necesare urmtoarele matrice de transformare n
cursul generrii imaginilor succesive, la momentele (cadrele) i, i + 1, i + 2,K .
M = M n M vi M i1 ,
pentru obiectul 1
Cadrul i :

Grafic pe calculator n C i OpenGL


M = M n M vi M i 2 ,
pentru obiectul 2
................................
M = M n M vi M ik ,
pentru obiectul k
................................
Cadrul i + 1 : M = M n M vi +1 M i1 ,
pentru obiectul 1
M = M n M vi +1 M i 2 ,
pentru obiectul 2
................................
M = M n M vi +1 M ik , pentru obiectul k
................................
Pentru a eficientiza organizarea acestor operaii de transformri succesive, n OpenGL se
folosesc mai multe stive de matrice de transformare, n care sunt reinute i reutilizate
matricele intermediare de transformare.
Transformrile de modelare i de observare sunt efectuate ntr-o stiv de matrice,
numit stiva matricelor de modelare-vizualizare (modelview matrix stack). Transformarea de
normalizare este prelucrat ntr-o stiv de matrice separat, numit stiva matricelor de
proiecie (projection matrix stack). Mai exist nc o stiv de matrice pentru operaiile de
texturare, numit stiva matricelor de texturare (texture matrix stack). Separarea matricelor de
modelare-vizualizare i de proiecie permite execuia n paralel a operaiilor din pipeline-ul
grafic al acceleratoarelor hardware care au prevzute resurse pentru astfel de prelucrri.
Fiecare stiv de matrice se comport asemntor cu o stiv obinuit asupra creia se
opereaz prin funcii de introducere (push) i extragere (pop). Aceste funcii difer foarte
puin de funciile push i pop folosite n general n programare.
n orice moment, una din cele trei stive de matrice este declarat ca stiv curent i
toate operaiile cu matricele de transformare sunt adresate stivei curente. Setarea unei stivei
curente se face prin apelul funciei:
void glMatrixMode(GLenum mode);

unde

argumentul mode poate fi una din constantele simbolice GL_MODELVIEW,


GL_PROJECTION sau GL_TEXTURE pentru setarea ca stiv curent a stivei de modelarevizualizare, a stivei de proiecie sau a stivei de texturare.
Matricea din vrful stivei curente este matricea curent C , cu care se efectueaz
operaiile cu matrice (glLoadIdentitz(), glTranslate#(), glLoadMatrix#(),
glMultMatrix#(), etc.). Operaiile efectuate cu o stiv se realizeaz prin intermediul
funciilor:
- glPushMatrix() care se apeleaz atunci cnd o matrice aflat n capul stivei trebuie
salvat pentru a fi utilizat ulterior;
- glPopMatrix() care se apeleaz atunci cnd operaiile de compunere a matricelor
trebuie s continue cu o matrice aflat sub capul stivei.
n figura 2 este ilustrat modul de acionare a funciilor glPushMatrix() i glPopMatrix().

Lucrarea 5

glPushMatrix()

glTranslate#()

glPopMatrix()

C = M
M

C = M
M
M

C = MT
M
M

C = M
M

Fig. 2 Operaii cu stiva matricelor de transformare

Stivele matricelor de transformare sunt deosebit de utile pentru redarea scenelor i a


obiectelor modelate ierarhic, n care scena sau fiecare obiect este compus din mai multe
subobiecte, pe mai multe nivele de ierarhie. Fiecare obiect component este definit printr-o
matrice de localizare relativ la obiectul cruia i aparine (obiect printe), i instanierea
acestuia se obine prin compunerea matricei de localizare proprii cu matricea de localizare a
obiectului printe.
n continuare prezentm modalitatea de adugare a noi obiecte a cror micare trebuie
descris n raport de un obiect precedent. Presupunem c scena conine obiectele o1, o2 ,K, on ,
aflate n micare unele fa de altele. Dorim s adugm obiectul on +1 , care se va mica n
raport cu obiectul on (fig. 3). Considerm c matricea de transformare care permite
localizarea i orientarea obiectului on n raport cu sistemul universal este M n , iar localizarea
i orientarea obiectului on +1 este dat de matricea M n +1 .

M n +1

on +1

yn
on

o1

Mn

M n, n +1

yn +1

xn +1

zn

x
z

Fig. 3 Modelarea obiectelor definite ierarhic


6

Grafic pe calculator n C i OpenGL

Putem scrie:
M n +1 = M n M n,n +1 ,

(5)

unde M n,n +1 este matricea care realizeaz poziionarea obiectului on +1 n raport cu on .


innd cont de cele de mai sus, rezult c se poate adopta urmtoarea strategie:
la adugarea obiectului on se va memora (glPushMatrix()) matricea de transformare
M n (fr a fi inclus i scalarea);
se reface M n (glPopMatrix()) i se poziioneaz obiectul on +1 relativ la obiectul on
(eventual se va memora matricea M n +1 , fr includerea scalrii, pentru adugarea unui
nou obiect).

3. Aplicaii
n aplicaiile urmtoare se urmrete utilizarea stivelor matricelor de transformri geometrice.
Exemplul 1

S se construiasc un bra articulat de robot, constituit din patru segmente: bra,


antebra i dou degete (fig. 4).

Fig. 4 Bra de robot

Braul trebuie s se roteasc n jurul umrului (captul din stnga al primului segment) i
cotului. Micrile de rotaie au loc att timp ct sunt apsate anumite taste.

Lucrarea 5

Indicaii. Pentru construirea celor patru segmente (bra, antebra i cele dou degete) se poate
folosi scalarea unui cub, dar mai nti trebuie aplicat o transformare care s orienteze
corespunztor fiecare segment. Deoarece sistemul de coordonate local al modelului (cubului)
este iniial n centrul cubului, trebuie translat sistemul de coordonate local pe o muchie a
cubului (sau pe una din feele cubului), altfel, rotaiile cubului se vor face fa de centrul lui i
nu fa de punctul de pivotare. Dup apelul lui glTranslate#() (pentru stabilirea punctului
de pivotare) i glRotate#() (pentru a pivota cubul), se va efectua translaia sistemului de
coordonate n vechiul punct. Apoi cubul este scalat i trasat, n felul acesta construind primul
segment (braul). Codul pentru primul segment este:
glTranslatef (-1.0, 0.0, 0.0);
glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0);
glTranslatef (1.0, 0.0, 0.0);
glPushMatrix();
glScalef (2.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();

Pentru construirea celui de-al doilea segment, trebuie mutat sistemul de coordonate
local n urmtorul punct de pivotare (rotaie). Deoarece sistemul de coordonate local al
obiectului precedent a fost rotit anterior, axa x este deja de-a lungul braului. De aceea
translarea de-a lungul axei x deplaseaz sistemul de coordonate n urmtorul punct de rotaie
(ncheietura braului). Odat stabilit punctul de rotaie se poate utiliza acelai cod pentru
trasarea celui de-al doilea segment ca i pentru primul segment. Acest procedeu poate continua
pentru un numr oarecare de elemente (bra, antebra, mn, degete).
glTranslatef (1.0, 0.0, 0.0);
glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0);
glTranslatef (1.5, 0.0, 0.0);
glPushMatrix();
glScalef (3.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();

Folosind indicaiile de mai sus s se completeze programul de mai jos astfel nct s se
realizeze funciile cerute.
static int shoulder = 0, elbow = 30, finger=15; //unghiuri de rotatie
GLfloat x1 = 3, x2 = 5, x3 = 1; //dimensiuni segmente
GLfloat xp1 = -5; //pozitia pe x a primului punct de pivotare
void init(void)
{
..........
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();

Grafic pe calculator n C i OpenGL


//primul obiect (brat)
..........
//al doilea obiect (antebrat)
..........
//deget superior
..........
//deget inferior
..........
glPopMatrix();
glutSwapBuffers();
glFlush();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//transformarea de proiectie
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
//transformarea de observare
..........
}
void keyboard (unsigned char key, int x, int y)
{
..........
glutPostRedisplay();
}

Probleme propuse
1. Modificai problema din exemplul 1 adugnd i alte segmente la bra. De exemplu,
adugai cteva degete la mn ca n fig. 5. Pivotarea se va face n jurul muchiei marginale a
unui segment.

Lucrarea 5

Fig. 5 Bra de robot cu degete

2. S se modifice problema anterioar adugnd articulaii sferice n jurul crora s se


efectueze micarea de rotaie.

Observaie. n vederea adugrii de pri suplimentare la braul de robot (degete, eventual


articulaii sferice pentru micarea de rotaie n jurul lor) se poate consulta programul
"glutmech.cpp" sau "glutmech.exe".

10

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