Altre informazioni su OpenGL e Glut

CALLBACK ASSOCIATE AD UNA FINESTRA

La lista delle callback disponibili per una finestra e' nel file precedente. Qui si fanno alcuni esempi di come registrare callback associate a una finestra e che cosa devono fare tali funzioni.

Display callback

Chiamata dal sistema quando viene ridisegnata la finestra:
  /* definizione della funzione */
  void f(void)
  {
     comandi OpenGL per ritracciare contenuto grafico della finestra
  }
  
  /* associazione di f come display callback della finestra corrente */
  glutDisplayFunc(f);

Idle callback

Chiamata dal sistema "continuamente":
  /* definizione della funzione */
  void f(void)
  {  
     glutPostRedisplay();
  }  
  
  /* associazione di f come idle callback della finestra corrente */
  glutIdleFunc(f);
Nota: f non esegue il rendering, si limita a rendere noto a glut che la scena necessita redisegnamento; la scena sara' ridisegnata da glut chiamando la display callback. Questo meccanismo permette di redisegnare una volta sola nel caso che il redisegmaneto sia necessario anche per altre cause.

Keyboard callback

Chiamata dal sistema quando premo un tasto della tastiera sulla finsetra:
  /* definizione della funzione.
     c = carattere premuto, x,y = posizione
     del cursore quando e' stato premuto (in pixel) */
  void f(unsigned char c, int x, int y) 
  {  
    printf("key %c pressed at (%d,%d)\n",c,x,y);
  }

  /* associazione di f come keyboard callback della finestra corrente */
  glutKeyboardFunc(f);

Special callback

Chiamata dal sistema quando premo un tasto speciale sulla finestra.
  /* definizione della funzione.
     k = codice del tasto speciale premuto 
     x,y = posizione del cursore quando e' stato premuto */
  void f(int k, int x, int y) 
  {  
    if (k == GLUT_KEY_INSERT)
    printf("INSERT key pressed at (%d,%d)\n",x,y);
  }

  /* associazione di f come special callback della finestra corrente */
  glutSpecialFunc(f);

Glut ha una serie di #define che danno nomi simbolici ai tasti speciali. In alternativa posso usare i numeri (farsi stampare k per vederli).

Mouse callback

Chiamata da Glut quando schiaccio o rilascio un bottone del mouse:
  /* definizione della funzione.
     b = numero del bottone interessato, s = stato
     (giu' o su), x,y = posizione del mouse */
  void f(int b, int s, int x, int y)
  {
    printf("Button %d is %s at (%d,%d)\n",
       b, ((s==GLUT_DOWN) ? "down" : "up"), x, y);
  }
    
  /* associazione di f come mouse callback della finestra corrente */
  glutMouseFunc(f);

Motion e Passive Motion callback

Chiamata da Glut quando muovo il mouse tenendo il bottone premuto o rilasciato, rispettivamente:
  /* definizione della funzione */
  void f(int x, int y)
  {
    printf("Button motion at (%d,%d)\n", x, y);
  }

  /* associazione di f come motion o passive motion callback */
  glutMotionFunc(f);  oppure glutPassiveMotionFunc(f);

Visibility callback

Chiamata da Glut quando lo stato della finestra passa da visibile a invisibile o viceversa. Tipicamente usata per fermare e riavviare la idle callback:
  /* definizione della funzione. 
     s e' lo stato attuale (GLUT_VISIBLE o GLUT_NOT_VISIBLE). */
  void f(int s)
  {
    if (s==GLUT_VISIBLE) glutIdleFunc(funzione idle callback);
    else glutIdleFunc(NULL); /* nessuna funzione idle */
  } 
  
  /* associazione di f come visibility callback */
  glutVisibilityFunc(f);

Timer callback

Chiamata da Glut dopo intervallo di tempo prestabilito:
  /* definizione della funzione.
     v = valore che specifico quando associo la callback */
  void f (int v)
  
  /* associazione di f come timer callback. k (in millisecondi) = 
     intervallo di tempo dopo il quale deve essere chiamata f,
     v = valore che viene passato da Glut a f quando la chiama */
  glutTimerFunc(k,f,v);

Entry callback

Chiamata da Glut quando il mouse entra od esce dalla finestra:
  /* definizione della funzione.
     s = stato attuale (GLUT_ENTERED o GLUT_LEFT) */
  void f (int s)
  {
    if (s==GLUT_ENTERED) azione da fare quando mouse entra
    else azione da fare quando mouse esce
  }

  /* associazione di f come entry callback */
  glutEntryFunc(f);

GESTIONE DI MENU'

Glut fornisce supporto per gestione di menu' pop-up a cascata.

Pop-up: menu' che appare sovrapposto alla finestra quando premo un tasto del mouse sullo sfondo della finestra, e scompare quando rilascio il bottone. Seleziono le voci scorrendo con il mouse premuto.

A cascata: ad una voce di un menu' puo' essere associato un sottomenu' che appare quando scorro con il mouse su quella voce.

Per creare un menu'

  my_menu = glutCreateMenu (f);
  glutAddMenuEntry("voce 1", 1);
  glutAddMenuEntry("voce 2", 2);
  glutAttachMenu(GLUT_RIGHT_BUTTON);
dove la funzione f e' definita a parte come:
  void f (int v)
  {
    switch (v)
    {  case 1: 
       case 2: 
    }
  }
ed e' quella che viene chiamata automaticamente da Glut quando l'utente seleziona una delle voci del menu', passando come valore il numero d'ordine della voce selezionata.

Spiegazione delle istruzioni:

Callback per i menu'

E' utile sapere se l'utente sta utilizzando i menu' pop-up, in modo da disattivare funzioni costose (es. animazione) mentre l'utente li usa. La Menu Status callback e' chiamata da Glut quando visualizza o devisualizza un menu' pop-up.

Esempio di funzione callback che sospende la idle callback (animazione) mentre qualche menu' e' in uso:

  /* status = GLUT_MENU_IN_USE se qualche 
    menu' e' popped-up, altrimenti GLUT_MENU_NOT_IN_USE,
    x,y = coordinate del mouse quando il menu' e' stato invocato
    o rilasciato */
  void f(int status, int x, int y)
  {
    if (status==GLUT_MENU_IN_USE) glutIdleFunc(NULL);
    else glutIdleFunc(funzione di animazione); 
  }

  /* associazione di f come menu status callback */
  glutMenuStatusFunc(f);

Menu' annidati

In alternativa a voci di menu' associate a valori interi (che saranno passati alla funzione di gestione del menu'), posso definire voci di menu' con associati sottomenu', che appariranno quando scorro col mouse su quella voce. void glutAddSubMenu(etichetta,menu);
aggiunge al menu' corrente una voce che mostra la stringa etichetta e invoca il sottomenu' menu quando selezionata (menu e' l'identificatore ritornato da glutCreateMenu quando ho creato il sottomenu')

Se un menu' e' attaccato come sottomenu' di un altro, non ha bisogno di essere associato ad un bottone del mouse con glutAttachMenu.

Esempio:

  submenu = glutCreateMenu(f1);
  glutAddMenuEntry(...) /* aggiunge entry a submenu */
  mainmenu = glutCreateMenu(f2);
  glutAddMenuEntry(...) /* aggiunge entry a mainmenu */
  glutAddSubMenu("chiama sottomenu",submenu);
  glutAttachMenu(GLUT_LEFT_BUTTON);

VISUALIZZAZIONE DI TESTO

In OpenGL e' possibile rendere testo, ma non direttamente, bensi' usando primitive grafiche per realizzare i vari caratteri: E' compito del programmatore definire le font, posizionare le i caratteri di una parola uno di seguito all'altro ecc.

Glut fornisce font sia stroke che bitmap predefinite e funzioni di piu' alto livello per rendere testo. Entrambe sono realizzate internamente mediante primitive OpenGL e quindi il modo in cui sono rese dipende dallo stato corrente di OpenGL (es. posso cambiarne il colore con glColor...).

Una font stroke e' "geometria", immersa nella scena modellata e soggetta alle stesse trasformazioni (puo' scalata, essere ruotata ecc.). Adatta per rendere scritte che sono parte della scena (l'insegna sulla porta...). E' piu' lenta.

Una font bitmap viene resa sempre rivolta verso l'utente, colorando i pixel della finestra in accordo allo schema definito dalla bitmap. E' veloce. Adatto per annotare l'immagine della scena (es. mostrare una didascalia...).

Testo stroke

  GlutStrokeCharacter(font,carattere);  

Teso bitmap

  glutBitMapCharacter(font,carattere);
Scrive il carattere alla posizione attuale sulla finestra, che puo' essere settata con glRasterPos2i(x,y) con x,y = coordinate in pixel. Glut avanza automaticamente la posizione dopo ogni carattere.

Esempio per scrivere stringa s:

  glRasterPos2i(x,y);
  for (i=0;s[i]!='\0';i++)   {  glutBitMapCharacter(,s[i]);  }