|
|
|
|
Vedremo alcuni aspetti di OpenGL che risultano
utili nello sviluppo di interfacce. |
|
|
|
Inoltre vedremo come si possono implementare
alcune funzioni utili per l’interazione con l’untente. |
|
|
|
|
|
Un’operazione tipica e’ la lettura delle
coordinate spaziali di un punto, ad esempio dopo che l’utente ha cliccato
sulla finestra OpenGL. |
|
Passi fondamentali: |
|
Recupero matrici di trasformazione correnti |
|
Lettura Z-Buffer |
|
Proiezione inversa |
|
|
|
|
GLdouble modelMatrix[16]; |
|
GLdouble projMatrix[16]; |
|
GLint viewport[4]; |
|
|
|
// Recupero matrici e viewport |
|
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix); |
|
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix); |
|
glGetIntegerv(GL_VIEWPORT,viewport); |
|
|
|
// ATTENZIONE: ribaltamento Y!!!!! |
|
sy = viewport[3]-1-sy; |
|
|
|
|
// Lettura z buffer |
|
GLfloat
qz; |
|
// Seleziono il buffer corretto |
|
glReadBuffer(GL_FRONT); |
|
|
|
glReadPixels(sx,sy,1,1,GL_DEPTH_COMPONENT, |
|
GL_FLOAT,&qz); |
|
|
|
|
if(qz==1.0){ // Proiezione inversa |
|
x = y = z = 0.0; |
|
return false; |
|
} else { |
|
GLdouble objz = qz; |
|
GLdouble tx,ty,tz; |
|
gluUnProject( GLdouble(sx), GLdouble(sy), objz, |
|
modelMatrix, projMatrix, viewport, |
|
&tx, &ty, &tz); |
|
return true; |
|
} |
|
|
|
|
|
Il codice di picking puo’ essere ottimizzato
leggendo le matrici di proiezione e la viewport solo nel momento in cui
cambiano: |
|
La viewport e la projection matrix, di solito,
vengono aggiornate solo al resize della finestra |
|
La modelview viene aggiornata quando si cambia
punto di visuale (rotazione, zoom, etc). |
|
|
|
|
In alcuni casi e’ impossibile eseguire il
picking: |
|
Se non si usa lo z-buffer |
|
(Solo per le schede 3D di ultima generazione),
se si e’ attivato l’antialiasing delle immagini (lo z-buffer e’
incosistente). |
|
|
|
|
Per selezione si intende l’identificazione di un
oggetto OpenGL a partire dalla sua visualizzazione. |
|
Per realizzarla si usano le funzionalita’ native
di OpenGL. |
|
Utilizzo tipico: dopo il click dell’utente e’
necessario identificare l’oggetto puntato. |
|
|
|
|
|
Il Meccanismo della selezione OpenGL e’ il
seguente: |
|
Si sceglie la zona su cui operare la selezione
(tipicamente un cono di vista centrato sulla posizione di click del mouse). |
|
Si renderizza solo la zona interessata, badando
a dare un nome ad ogni oggetto renderizzato. |
|
Tutti i nome degli oggetti renderizzati nella
zona selezionata sono memorizzati in un buffer. |
|
|
|
|
// Definizione del buffer di selezione |
|
const GLsizei MAXSBUF = 512; |
|
GLuint sbuf[MAXSBUF]; |
|
GLint
buflen; |
|
|
|
// Preparativi generali |
|
// Seleziona il buffer di picking |
|
glSelectBuffer( MAXSBUF, sbuf ); |
|
glRenderMode( GL_SELECT ); // Modalita' select |
|
|
|
|
// Rovesciamento coordinate |
|
y =
viewport[3] - viewport[1] - 1 - y; |
|
|
|
// Preparazione matrice di selezione |
|
glMatrixMode( GL_PROJECTION ); |
|
glLoadIdentity(); |
|
gluPickMatrix(x, y, wx,wy, wextra.viewport); |
|
gluPerspective(prospAngle,aspect,nearPlane,farPlane); |
|
glMatrixMode( GL_MODELVIEW ); |
|
|
|
|
glInitNames(); |
|
glLoadName(0); |
|
// Rendering con nome |
|
… |
|
// Chiusura modalita' selezione |
|
buflen = glRenderMode( GL_RENDER ); |
|
|
|
// Interpretazione dei risultati |
|
… |
|
|
|
|
|
|
// Esempio di rendering con nome (oggetto) |
|
Int name = 7; |
|
glPushName(name); |
|
glBegin(GL_TRIANGLES); |
|
glVertex3fv(v[0]); |
|
glVertex3fv(v[1]); |
|
glVertex3fv(v[2]); |
|
glEnd(); |
|
glPopName(); |
|
|
|
|
// Esempio di rendering con nome (triangoli) |
|
glBegin(GL_TRIANGLES); |
|
for(int I=0;I<v.size();++I) |
|
{ |
|
glPushName(I+1); |
|
glVertex3fv(v[I][0]); |
|
glVertex3fv(v[I][1]); |
|
glVertex3fv(v[I][2]); |
|
glPopName(); |
|
} |
|
glEnd(); |
|
|
|
|
Intepretazione del buffer risultato: |
|
// Parsing dello stack |
|
pr.resize(buflen); |
|
int j = 0; |
|
for(int i=0;i<buflen;++i){ |
|
int n = sbuf[j++]; // Namestack size |
|
pr[i].minDepth = sbuf[j++]/double(UINT_MAX); |
|
pr[i].maxDepth = sbuf[j++]/double(UINT_MAX); |
|
pr[i].nameStack.resize(n); |
|
for(int k=0;k<n;++k) |
|
pr[i].nameStack[k] = sbuf[j++]; |
|
} |
|
|
|
|
E’ utile implementare la funzione di dragging,
passi fondamentali: |
|
Salvare lo stato OpenGL attuale |
|
Selezionare la modalita’ di disegno diretta
(front buffer) e in modalita’ xor |
|
Selezionare modalita’ di proiezione diretta
(coordinate 2d = coordinate pixel) |
|
Eseguire il disegno del drag senza glClear (lo
sfondo e’ disegnato una sola volta) |
|
|
|
|
// Salvataggio stato opengl |
|
glGetIntegerv( GL_DRAW_BUFFER,
&oldDrawBuffer ); |
|
glGetIntegerv( GL_DEPTH_FUNC, &oldDepthFunc
); |
|
glGetIntegerv( GL_LINE_STIPPLE_PATTERN, |
|
&oldLineStippleP ); |
|
glGetIntegerv( GL_LINE_STIPPLE_REPEAT , |
|
& oldLineStippleR ); |
|
|
|
|
glDrawBuffer( GL_FRONT ); // Modalita’ disegno |
|
glDepthFunc( GL_ALWAYS ); |
|
glLineStipple( 1, 0xF6F6 ); |
|
|
|
glMatrixMode( GL_MODELVIEW ); // Vista |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
|
|
glMatrixMode( GL_PROJECTION ); // Proiezione |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
glOrtho( 0, vport[2], 0, vport[3], 0, 1 ); |
|
|
|
|
// Colore disegno: bianco |
|
glGetMaterialfv( GL_FRONT, GL_EMISSION
,oldEColor ); |
|
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION,
white ); |
|
|
|
// Abilitazione motalita’ xor tramite la
funzione |
|
// blending: colore = 1 – colore_sfondo; |
|
BlendingIsE = glIsEnabled( GL_BLEND ); |
|
glEnable( GL_BLEND ); |
|
glGetIntegerv( GL_BLEND_SRC, & BlendFun1 ); |
|
glGetIntegerv( GL_BLEND_DST, & BlendFun2 ); |
|
glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO ); |
|
|
|
|
// Dragging vero e proprio |
|
glBegin(GL_LINE_LOOP); |
|
glVertex2i( ox,oy ); glVertex2i( ox,dy ); |
|
glVertex2i( dx,dy ); glVertex2i( dx,oy ); |
|
glEnd(); |
|
dx = x; |
|
dy = y; |
|
glBegin(GL_LINE_LOOP); |
|
glVertex2i( ox,oy ); glVertex2i( ox,dy ); |
|
glVertex2i( dx,dy ); glVertex2i( dx,oy ); |
|
glEnd(); |
|
glFinish(); |
|
|
|
|
// End drag: ripristino stato OpenGL |
|
glDrawBuffer( oldDrawBuffer ); |
|
glDepthFunc( oldDepthFunc ); |
|
glLineStipple( oldLineStippleR, oldLineStippleP
); |
|
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION,
oldEC ); |
|
if( !BlendingIsE ) glDisable( GL_BLEND ); |
|
glBlendFunc( BlendFun1, BlendFun2 ); |
|
|
|
glPopMatrix(); |
|
glMatrixMode( GL_MODELVIEW ); |
|
glPopMatrix(); |
|
|
|
|
Per visualizzare stringhe sul render OpenGL: |
|
Se si utilizza glut c’e’ la funzione apposita |
|
In MFC, si puo’ utilizzare il codice: |
|
|
|
SelectObject(we.ghDC, GetStockObject
(SYSTEM_FONT)); |
|
wglUseFontBitmaps(we.ghDC, 0, 256, FONT_BASE); |
|
… |
|
glListBase(FONT_BASE); |
|
CallLists (strlen(str), GL_UNSIGNED_BYTE,str); |
|
|
|
|
Nel corso degli anni sono state sviluppate una
serie di librerie ad alto livello per l’utilizzo di OpenGL. |
|
Quasi tutte si basano sulla definizione di un
grafo di scena, che rappresenta gli oggetti da visualizzare, le loro
propieta’ ed eventuali azioni su di essi. |
|
Lo sviluppatore storico di queste librerie e la
Silicon Graphics. Negli ultimi tempi la crisi finanziaria della SGI ha
lascito aperto il campo. |
|
|
|
|
Tutte le librerie HL OpenGL hanno pregi e
difetti: |
|
Pregi: |
|
Sviluppo veloce di applicazioni complesse |
|
Presenza di tool non banali da implementare
(manipolatori tridimensionali, semplificatori automatici di geometrie, …) |
|
Difetti: |
|
Incremento della memoria utilizzata (Per SGI
forte incremento!) |
|
Scarsa flessibilita’: difatto per lo sviluppo di
applicazioni commerciali, risulta spesso piu’ semplice ripartire da OpenGL. |
|
|
|
|
|
Sviluppo SGI: |
|
OpenInventor ( -> VRML 1.0 -> VRML 2.0) |
|
CosmoSoftware (CosmoPlayer) |
|
SGI Performer |
|
SGI Optimizer |
|
SGI Volumizer |
|
… |
|
Vari tentativi da parte di altre ditte di
porting o risviluppo del codice (TGS,…) |
|
|
|
|
Sviluppi OpenSource, Shareware: infiniti. |
|
Google: “opengl scene graph”: 7500 hits |
|
|
|
Solo su sourceforge ci sono decine di progetti
in corso di sviluppo. |
|
|
|
In realta’ realizzare una libreria decente
comporta una grossa mole di lavoro. |
|
|
|
|
|
GCR: libreria grafica OpenGL ad alto livello. |
|
Implementa uno scene graph simile ad
OpenInventor |
|
Caratteristiche salienti: |
|
E’ freeware, open source, ed e’ a disposizione
di questo corso per studio o modifica |
|
E’ parzialmente implementata |
|
E’ infinitamente rozza |
|
|
|
|
Claudio Rocchini |
|
Visual Computing Group |
|
ISTI-CNR, |
|
Area della Ricerca di Pisa |
|
Email: rocchini@iei.pi.cnr.it |
|
Web: http://vcg.iei.pi.cnr.it/~rocchini |
|