OpenGL e Glut ============= INTRODUZIONE OpenGL assume di avere a disposizione una finestra grafica su cui disegnare. Lo standard di OpenGL non specifica nulla su come una tale finestra viene ottenuta, ne' su come viene gestita; in una parola, OpenGL non fornisce funzionalita' per l'interazione tra OpenGL e il window system / window manager. Per usare OpenGL in pratica, bisogna affiancargli un toolkit che funga da interfaccia tra OpenGL e il window system / window manager. Assieme a OpenGL (ma non parte stretta di esso) e' fornito GLX, un piccolo insieme di routines per interfacciare OpenGL direttamente con lo strato piu' basso di X Window System, Xlib. Noi non useremo questo perche' troppo di basso livello. Noi useremo Glut, un toolkit prototipale scritto allo scopo di fornire un'interfaccia di alto livello tra OpenGL e X window system. Glut non e' un pacchetto per la realizzazione di interfacce grafiche. Non fornisce sofisticati componenti di interfaccia (menu', bottoni, browser, etc.) e meccanismi per assemblarli. E' semplicemente uno strumento semplice per fare della grafica in OpenGL in ambiente X. Le funzionalita' offerte sono quelle di mediazione con X e il window manager per: - ottenere finestre (in cui OpenGL possa fare rendering) - gestire tali finestre: - redisegnamento del contenuto grafico della finestra quando essa viene nascosta da un'altra, oppure iconificata, e poi torna ad essere visibile - supporto per animazione (aggiornamento in continuo dell'immagine visualizzata) in una finestra - cattura di eventi generati dall'utente all'interno della finestra (pressione di tasti della tastiera, movimento e click del mouse) - gestione del cursore (forma...) - rendering di testo nella finestra Inoltre fornisce: - un rudimentale meccanismo per immettere opzioni, tramite menu' pop-up. - alcuni oggetti OpenGL predefiniti (sfera, toro, teapot...) - gestione di sottofinestre, piani di overlay, ... APRIRE UNA FINESTRA DI RENDERING CON GLUT Sequenza di istruzioni (tipicamente nel main): glutInit(...); glutInitDisplayMode(...); glutInitWindowSize(...); win = glutCreateWindow(...); Spiegazioni: glutInit(&argc, argv); Da chiamarsi prima di ogni altra funzione Glut, stabilisce connessione con X server e si assicura che l'X server supporti OpenGL. Chiamata con gli stessi argomenti con cui il main program e' invocato da command line. Processa tutti gli argomenti che corrispondono a opzioni di X (es: -geometry, -display), e li cancella, lasciando i rimanenti, che possono essere poi processati dal programma. glutInitDisplayMode(); Stabilisce i requisiti della finsetra che si vuole aprire. esempio: = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH richiede che la finestra abbia double buffer, supporti RGBA color mode, e abbia z buffer. glutInitWindowSize(,); Stabilisce le dimensioni della finsetra che si vuole aprire (in pixel). win = glutCreateWindow(); Stabilisce l'etichetta che comparira' come titolo della finestra ( e' una stringa), crea la finestra, e ritorna in win un identificatore intero di tale finestra. L'identificatore serve se un programma OpenGL ha piu' finestre aperte, per stabilire di volta in volta la finestra corrente su cui viene mandato l'output grafico (con glutSetWindow). Se vi e' una sola finsetra, essa e' automaticamente la finestra corrente. Una volta creata, la finestra e' pronta per essere usata da OpenGL. GESTIRE UNA FINESTRA Glut permette al programma di associare ad una finestra funzioni (dette callback) che vengono chiamate automaticamente quando avvengono certe condizioni predefinite. Alcune di tali funzioni accettano argomenti, che sono passati automaticamente dal sistema alla funzione chiamata. - Display function: chiamata quando la finestra viene redisegnata dal window manager (es: quando diventa nuovamente visibile dopo essere stata iconificata o nascosta da un'altra finestra); tipicamente, contiene le istruzioni OpenGL per redisegnare il contenuto grafico della finestra (necessario farlo da programma perche' il window manager redisegna solo il contorno della finestra, non il suo contenuto). - Idle function: chiamata "continuamente"; utile per animazione: la idle function sposta l'oggetto e lo redisegna, essendo chiamata continuamente, produce l'immagine di un oggetto in movimento. - Keyboard function: chiamata quando utente preme un tasto ASCII avendo il keyboard focus sulla finestra. - Special key function: chiamata quando utente preme un tasto speciale avendo il keyboard focus sulla finestra (tasti funzione...). - Mouse function: chiamata quando utente preme o rilascia un tasto del mouse nella finestra. - Motion function: chiamata quando utente muove il mouse tenendo un tasto premuto. - Passive motion function: chiamata quando utente muove il mouse senza tenere tasti premuti. - Visibility function: chiamata quando lo stato della finestra passa da visibile a non visibile o viceversa; tipicamente usata da programmi di animazione per disattivare animazione quando la finestra non e' visibile. - Timer function: chiamata ogni tot millisecondi. - Menu state function: chiamata quando un menu' pop-up e' attivato o disattivato; tipicamente usata per sospendere attivita' come animazione mentre l'utente sta introducendo opzioni. Le funzioni vengono registrate con glutXXXXXFunc(); e deregistrate con glutXXXXXFunc(NULL); dove XXXXX e' il nome della funzione che si sta registrando. Esempi: glutDisplayFunc(); dove e' del tipo void f(void). glutIdleFunc(); dove e' del tipo void f(void). Esempio: void f(void) { glutPostRedisplay(); } Nota: non esegue il rendering, si limita a rendere noto a glut che la scena necessita redisegnamento; questo meccanismo permette di redisegnare una volta sola nel caso che il redisegmaneto sia necessario anche per altre cause. glutVisibilityFunc(); dove e' del tipo void f(int); il parametro e' lo stato attuale (GLUT_VISIBLE o GLUT_NOT_VISIBLE), e viene passato automaticamente alla funzione da Glut. Esempio (sospende animazione se finestra non visibile): void f(int status) { if (status==GLUT_VISIBLE) glutIdleFunc(); else glutIdleFunc(NULL); /* nessuna funzione idle */ } Per adesso non ci occupiamo delle funzioni relative alla cattura di input da parte dell'utente. IL MAIN LOOP Dopo aver aperto la finestra, definito e registrato le funzioni che interessano su di essa (e i menu' - cosa che dobbiamo ancora vedere), il programma entra in un ciclo senza fine, interamente gestito da Glut, nel quale - attende il verificarsi delle condizioni associate all'attivazione di una delle funzioni registrate come callback - attiva la callback - torna in attesa Il loop non termina mai. Il programma puo' terminare eseguendo exit all'interno di una funzione callback. Nota: se e' stata registrata una Idle callback, questa e' chiamata ad ogni ciclo. istruzione: glutMainLoop();