Laboratorio di Grafica Interattiva A.A. 2002-3
Esercizio 6
Argomento
Selezione interattiva di oggetti in OpenGL.
Files
Nessun nuovo file, si continua da quelli dell'esercitazione precedente.
Esercitazione guidata
Prima tappa
Date modo all'utente di selezionare il solido corrente (quello su
cui agiscono le operazioni di rotazione/traslazionecambio di attributi)
cliccandovi sopra con il mouse.
Usate il bottone destro del mouse per selezionare e mantenete il
bottone sinistro per ruotare/traslare.
Per adesso implementate la selezione tramite click solo sulla vista
prospettica.
Per selezionare il solido tramite click usate il selection mode
di OpenGL.
-
Il disegno della scena avviene normalmente nel modo consueto.
-
Quando l'utente clicca con il bottone destro sulla work area prospettica,
parte una procedura di disegno alternativa che esegue lo
stesso disegno di quella normale usando il selection buffer
invece del frame buffer, con un'area di selezione
ristretta a pochi pixel intorno al punto in cui e' stato cliccato il mouse.
-
Al termine di questa operazione si ricava dal selection buffer il nome
del solido che e' stato selezionato.
La funzione di disegno della work area prospettica esiste in due versioni
-
una che disegna nel frame buffer in drawing mode (quella solita,
chiamata nella display callback)
-
una che disegna nel selection buffer in selection mode (quella
alternativa che parte quando l'utente preme il bottone destro del mouse,
da chiamare nella mouse callback)
In pratica e' meglio avere un'unica funzione ed usare una
variabile di stato per sapere in quale caso siamo.
Nel secondo caso la funzione compie delle operazioni in piu'.
Dovete intervenire sulla mouse callback della work area prospettica e
sulla funzione di disegno della work area prospettica.
La mouse callback:
- crea il selection buffer
- entra in selection mode
- assegna alla variabile di stato il valore corrispondente a
modalita' di selezione
- CHIAMA la funzione di disegno della work area prospettica
- torna in rendering mode e
legge dal selection buffer il nome (numero) del solido selezionato
- riassegna alla variabile di stato il valore corrispondente a
modalita' di disegno normale
- chiama glutPostRedisplay per ridisegnare la scena
evidenziando il solido selezionato
La funzione di disegno della work area va chiamata qui con
viewport coincidente con la work area prospettica,
cosi' come avviene quando e' chiamata all'interno della display callback.
Non e' necessario chiamare le funzioni di disegno delle altre
aree perche' la selezione avviene solo nella work area prospettica.
La funzione di disegno della work area prospettica,
quando chiamata in modalita' di selezione,
oltre alle operazioni solite:
-
restringe l'area di selezione a pochi pixel attorno alla posizione
del mouse
- inizializza lo stack dei nomi
- assegna nomi alle primitive in modo che
si possano generare gli "hit"
Le variabili che tengono il selection buffer e l'informazione se siamo
in modalita' normale oppure in modalita' di selezione
devono essere globali
perche' sono usate sia nella mouse callback che nella
funzione di disegno.
Inoltre occorre passare le
le coordinate del punto cliccato dalla mouse callback alla
funzione di ridisegno. Anche questo si puo' fare con
variabili globali.
Ogni solido e' composto da varie primitive GL_POLYGON.
A tutte le primitive che compongono un solido va dato lo stesso
nome (identificatore numerico), che puo' essere per es. la
posizione del solido nell'array di solidi.
Quindi occorre:
-
inizializzare lo stack dei nomi prima di disegnare il primo solido,
usando glInitNames (crea lo stack vuoto) seguito
da glPushName (carica un primo nome fittizio, per es. 9999)
-
prima di disegnare ogni solido caricarne il nome
chiamando glLoadName
Il nome del solido selezionato (se il click e' avvenuto su un solido)
rimarra' nel selection buffer.
Compito
Implementate la selezione anche nelle tre viste ortografiche.
Evidenziate l'oggetto selezionato in modo opportuno,
per esempio marcando i suoi vertici con pallini.
Basta chiamare la stessa display list che disegna il
solido dopo aver impostato polygon mode a GL_POINT
e point size abbastanza grosso.