Gestione di Interfacce con OpenGL Claudio Rocchini
Aspetti di OpenGL 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. 13/11/2018 Claudio Rocchini
Picking di un Punto 3D 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 13/11/2018 Claudio Rocchini
Picking di un Punto 3D 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; 13/11/2018 Claudio Rocchini
Picking di un Punto 3D // Lettura z buffer GLfloat qz; // Seleziono il buffer corretto glReadBuffer(GL_FRONT); glReadPixels(sx,sy,1,1,GL_DEPTH_COMPONENT, GL_FLOAT,&qz); 13/11/2018 Claudio Rocchini
Picking di un Punto 3D 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; } 13/11/2018 Claudio Rocchini
Picking di un Punto 3D 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). 13/11/2018 Claudio Rocchini
Picking di un Punto 3D 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). 13/11/2018 Claudio Rocchini
Selezione 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. 13/11/2018 Claudio Rocchini
Selezione 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. 13/11/2018 Claudio Rocchini
Selezione 1 // 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 13/11/2018 Claudio Rocchini
Selezione 2 // 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 ); 13/11/2018 Claudio Rocchini
Selezione 3 glInitNames(); glLoadName(0); // Rendering con nome … // Chiusura modalita' selezione buflen = glRenderMode( GL_RENDER ); // Interpretazione dei risultati 13/11/2018 Claudio Rocchini
Selezione 4 // 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(); 13/11/2018 Claudio Rocchini
Selezione 5 // 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(); 13/11/2018 Claudio Rocchini
Selezione 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++]; } 13/11/2018 Claudio Rocchini
Dragging in OpenGL 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) 13/11/2018 Claudio Rocchini
Dragging 1 // 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 ); 13/11/2018 Claudio Rocchini
Dragging 2 glDrawBuffer( GL_FRONT ); // Modalita’ disegno glDepthFunc( GL_ALWAYS ); glLineStipple( 1, 0xF6F6 ); glMatrixMode( GL_MODELVIEW ); // Vista glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); // Proiezione glOrtho( 0, vport[2], 0, vport[3], 0, 1 ); 13/11/2018 Claudio Rocchini
Dragging 3 // 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 ); 13/11/2018 Claudio Rocchini
Dragging 4 // 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; glFinish(); 13/11/2018 Claudio Rocchini
Dragging 5 // 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 ); 13/11/2018 Claudio Rocchini
Stampa di testi 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); 13/11/2018 Claudio Rocchini
Librerie OpenGL ad alto livello 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. 13/11/2018 Claudio Rocchini
Pregi e difetti Tutte le librerie HL OpenGL hanno pregi e difetti: 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. 13/11/2018 Claudio Rocchini
Storiografia 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,…) 13/11/2018 Claudio Rocchini
Storiografia 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. 13/11/2018 Claudio Rocchini
Un esempio di HL OpenGL 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 13/11/2018 Claudio Rocchini
Contatti 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 13/11/2018 Claudio Rocchini