Laboratorio di Grafica Interattiva A.A. 2003-4
Esercizio 4
Argomento
Selezione di primitive in OpenGL.
Files
Nessun file nuovo. Si parte da quelli dell'esercitazione precedente.
Esercitazione guidata
Prima tappa
Date modo all'utente di selezionare la primitiva corrente (quella su cui
agiscono le operazioni di rotazione / traslazione / cambio di attributi)
cliccandovi sopra con il mouse.
Per esempio usate il bottone sinistro del mouse per selezionare e
il bottone destro per fare apparire il menu'.
Per selezionare la primitiva tramite click usate il selection mode
di OpenGL.
-
Il disegno della scena avviene normalmente nel modo consueto.
-
Quando l'utente clicca con il bottone sinistro sulla work area,
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
della primitiva che e' stata selezionata.
Il nome (identificatore numerico) di una primitiva
puo' essere per es. un numero da 1 a 5.
La funzione di disegno della work area 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 sinistro 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 e
sulla funzione di disegno della work area.
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
- torna in rendering mode e legge dal selection buffer
il nome (numero) della primitiva selezionata
- riassegna alla variabile di stato il valore corrispondente a
modalita' di disegno normale
- chiama glutPostRedisplay per ridisegnare la scena
evidenziando la primitiva selezionata
La funzione di disegno della work area va chiamata qui con
viewport coincidente con la work area,
cosi' come avviene quando e' chiamata all'interno della display callback.
Non e' necessario chiamare la funzione di disegno della toolbar
area perche' la selezione avviene solo nella work area.
La funzione di disegno della work area,
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.
Quindi occorre:
-
inizializzare lo stack dei nomi prima di disegnare la prima primitiva
usando glInitNames (crea lo stack vuoto) seguito
da glPushName (carica un primo nome fittizio, per es. 9999)
-
prima di disegnare ogni primitiva caricarne il nome
chiamando glLoadName
Il nome della primitiva selezionata (se il click e' avvenuto su una
primitiva) rimarra' nel selection buffer.
Seconda tappa
Permettere all'utente di selezionare i singoli vertici di una primitiva
e di spostarli trascinandoli con il mouse.
-
Il primo click su una primitiva la seleziona nella sua interezza,
provocando il disegnamento dei quadratini attorno ai suoi vertici
(come prima).
-
La pressione del mouse su un vertice della primitiva selezionata
(cioe' sul quadratino che lo evidenzia)
provoca la selezione del vertice.
Il vertice verra' evidenziato con un quadratino piu' grande
(o di altro colore, o pieno invece che vuoto... come volete).
Da questo momento fino a che l'utente non rilascia il mouse,
lo spostamento del mouse muovera' il punto.
NOTE:
Per monitorare lo spostamento del mouse (trascinamento del vertice),
si usa la mouse motion callback.
Occorre cambiare veramente le coordinate del vertice
nella struttura dati della primitiva.