Corso di Programmazione Graficaper il Tempo Reale Display list e picking Daniele Marini Disegnare e cancellare • Il problema più complesso nel disegno interattivo è cancellare • Tenere memoria di quanto disegnato • Due soluzioni: – Display list – Hit list PGTR aa 2010/2011 2 Display list • Separare la costruzione del disegno dalle istruzioni per eseguirlo a monitor • Il display processor all’origine conteneva una lista di istruzioni elementari per tracciare linee • In un’architettura client-sever la display list consente di sgravare il client dal compito di disegnare, affidato al server grafico PGTR aa 2010/2011 3 Due modalità di esecuzione • Immediate mode appena il programma esegue una istruzione che definisce una primitiva, essa viene inviata al server grafico per disegno immediato • Retained mode la descrizione della primitiva viene inviata e memorizzata nella display list, ma verrà tracciata solo al momento voluto PGTR aa 2010/2011 4 Funzioni fondamentali • La display list viene trattata come le altre primitive: glNewList(BOX, GL_COMPILE); glBegin(GL_POLYGON); glColor3f(1.0,0.0,0.0); glVertex2f(-1.0,-1.0); glVertex2f(1.0,-1.0); glVertex2f(-1.0,1.0); glVertex2f(-1.0,1.0); glEnd(); glEndList(); PGTR aa 2010/2011 5 Flag • Il flag GL_COMPILE indica al sistema di spedire la lista al server ma di non disegnarne il contenuto, retained mode • Immediate mode: GL_COMPILE_AND_EXECUTE • Quando si desidera tracciare il disegno si chiama la funzione glCallList(BOX) • Se si desiderano gestire più liste si può generarne il numero in modo automatico: glGenLists(number) • Per eseguire tutte le display list: glCallLists() PGTR aa 2010/2011 6 Picking • Selezionare un elemento grafico sul monitor • In origine, con le light pen l’esistenza della display list permetteva di risalire all’oggetto puntato rilevando l’istante di tempo durante il ridisegno della scena in cui il segnale di interrupt della light pen veniva rilevato, mettendolo in corrispondenza con il contenuto della display list PGTR aa 2010/2011 7 Oggi? • Nei sistemi attuali la primitiva grafica ha subito numerose operazioni prima di venire convertita in pixel • Per risalire all’oggetto cui il pixel appartiene ci sono varie soluzioni: – Boundig box (allineate agli assi) – Back buffer – Selection PGTR aa 2010/2011 8 Bounding box • Chiamati anche extents • È il più piccolo rettangolo che contiene l’oggetto • Mettere in relazione il rettangolo nello spazio immagine con il rettangolo nello spazio mondo di cui è la proiezione • Occorre mantenere una struttura dati in memoria che associa extents con oggetti PGTR aa 2010/2011 9 Back buffer • Usando il double buffering si mantengono due buffer: il front buffer contiene il disegno visualizzato, nel back buffer si ridisegna la scena per il picking e si interroga: – Si disegna un oggetto nel back buffer con un colore di picking – Si rileva la posizione del mouse sul piano immagine – Si legge il contenuto di colore del back buffer con glReadPixels() – Si cerca in una tavola di colori di picking l’oggetto con il colore letto PGTR aa 2010/2011 10 Selection • In OGL è difficile ripercorre all’indietro la pipeline di rendering per identificare l’oggetto che si desidera individuare • È perciò disponibile una modalità di rendering chiamata selection mode • Questo richiede un extra rendering ogni volta che eseguiamo il picking PGTR aa 2010/2011 11 Volume di clipping • OGL permette di conservare informazione su un volume di clipping specifico di ciascun oggetto, diverso dal volume di clipping complessivo • La funzione glRenderMode offre tre opzioni: – GL_RENDER, rendering normale nel color buffer – GL_SELECT, modalità di selezione – GL_FEEDBACK, per ottenere una lista degli oggetti renderizzati PGTR aa 2010/2011 12 Selezione • Quando si entra in modalità selection e si renderizza una scena ogni primitiva che entra nel volume di clipping genera un messaggio di hit che è memorizzato in un buffer chiamato name stack • Per identificare un array contenente il dato selezionato si usa la funzione glSelectBuffer PGTR aa 2010/2011 13 Name stack • Per la gestione del name stack ci sono le funzioni: – glSelectBuffer per specificare l’array in cui raccogliere i dati – glInitNames per inizializzare il nome dello stack – glPushName e glPopoName per inserire e togliere nomi nello stack – glLoadName per cambiare il nome dell’elemento che si trova in cima allo stack PGTR aa 2010/2011 14 Gestione • Prima di rendere un oggetto si carica il suo nome nel name stack • Lo stack va inizializzato con: – glInitNames(); glPushName(0); • La modalità di selezione viene modificata nella callback del mouse • Quando si ritorna al modo di rendering la glRenderMode restituisce il numero di hit che sono stati processati e si esamina la hit list PGTR aa 2010/2011 15 Gestione • Se vogliamo selezionare gli oggetti in una regione occorre ridefinire una finestra di clipping entro la quale ridisegnare gli oggetti selezionati • Nella mouse callback si modifica anche il volume di clipping per ottenere gli hit nella regione considerata PGTR aa 2010/2011 16 Esempio • La funzione gluPickMatrix(x,y,w,h,*vp) permette di creare una nuova matrice di proiezione centrata in x,y di ampiezza w,h relativa alla viewport vp • I parametri sono restituiti dalla callback mouse quando indichiamo la posizione del cursore sul monitor PGTR aa 2010/2011 17 Mouse callback #define N 2 /*area sensibile attorno al cursore void mouse(int button, int state, in x, int y); { Gluint nameBuffer[SIZE]; Glint hits; Glint viewport[4]; if (button==GLUT_LEFT_BUTTON && state==GLUT_DOWN) { glInitNames(); glPushNames(0); glSelectBuffer(SIZE,nameBuffer); glGetInteger(GL_VIEWPORT, viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); PGTR aa 2010/2011 18 /*area di selezione NxN attorno al cursore, flipping della y gluPickMatrix((Gldouble)x,(Gldouble)(viewport[3]-y, N,N,viewport); gluOrtho2D(xmin,xmax,ymin,ymax) /*window di clipping della reshape draw_objects(GL_SELECT); glMatrixMode(GL_PROJECTION); /*recupera la matrice di vista glPopMatrix(); glFlush(); /*ritorna al rendering normale con gli hits hits=glRenderMode(GL_RENDER); process_hits(hits, nameBuffer); glutPostRedisplay(); } } void display(); { glClear(GL_COLOR_BUFFER_BIT); draw_objects(GL_RENDER); glFLush(); } PGTR aa 2010/2011 19