Interazione con la scena OpenGL

Note integrative al corso di Grafica Interattiva, corso di Laurea in Informatica, nuovo ordinamento.
A cura di Paola Magillo, DISI, Universita' degli Studi di Genova.

Immissione di punti tramite mouse

Consideriamo il seguente problema:

Il problema implica una traduzione fra sistemi di coordinate:

Traduzione di coordinate

Nel passare dagli oggetti all'immagine, le coordinate dei punti subiscono una serie di trasformazioni (pipeline): trasformazioni di modellazione, di vista, di proiezione, di workstation.

+--------+                                            +--------+
|coord.di| trasf.di   trasf.di   trasf.di   trasf.di  |coord.  |
|model-  | -------->  -------->  -------->  --------> |pixel   |
|lazione | modellaz.  vista      proiez.    workst.   |finestra|
+--------+                                            +--------+
Per risalire dall'immagine agli oggetti dobbiamo eseguire la serie di trasformazioni inversa.

In OpenGL i parametri di queste trasformazioni sono memorizzati in tre variabili di stato:

Traduzione diretta

Quando specifichiamo una primitiva con glBegin(...); glVertex(...) ... glEnd(); le coordinate dei vertici, scritte in coordinate di modellazione, vengono tradotte in coordinate di finestra da OpenGL usando la viewport e le matrici projection e modelview presenti nello stato corrente.

Traduzione inversa

OpenGL mette a disposizione la funzione gluUnProject che esegue la traduzione inversa da coordinate della finestra in coordinate di modellazione.
A questa funzione dobbiamo passare la viewport e le due matrici projection e modelview che sono state usate nella traduzione diretta.

gluUnProject(x, y, z, modelview_mat, projection_mat, viewport, &xx, &yy, &zz);

Attenzione: Le coordinate della finestra hanno y=0 in alto, mentre OpenGL le pensa con y=0 in basso. Quindi se la posizione del cursore e' (wx,wy) abbiamo x=wx e y=viewport[3]-wy.

Come ottenere la viewport e le matrici

La viewport e le due matrici projection e modelview sono parte dello stato di OpenGL. In generale lo stato di OpenGL si puo' interrogare con l'istruzione glGet che esiste in forme diverse a seconda del tipo dei parametri di stato che chiediamo.

Per variabili di stato a valori interi: glGetIntegerv(nome, ptr);

Esempio, per ottenere la viewport:
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

Per variabili di stato a valori double: glGetDoublev(nome, ptr);

Esempio, per ottenere la projection matrix (analogo per la modelview matrix):
GLdouble projection_mat[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection_mat);

Come organizzare il codice

Prevedere una struttura dati globale al programma, per esempio un array, in cui memorizzare i punti immessi.

La mia primitiva usera' i vertici presi dall'array.

Nel punto del codice in cui e' scritta la primitiva salvare la viewport e le matrici modelview e projection in variabili globali al programma.
Questo salva esattamente lo stato di trasformazioni in cui OpenGL si trova quando disegna la primtiva.

Definire una mouse callback che preleva le coordinate Glut del punto cliccato, le traduce in coordinate di modellazione usando la viewport e le matrici salvate, aggiunge il punto cosi' tradotto all'array, ed invoca tramite glutPostRedisplay il ridisegnamento della finestra.

Nel ridisegno dopo eseguita la mouse callback, la primitiva trovera' un vertice in piu' nell'array...