Esempio di scritto di IG - parte pratica
Esercizio su OpenGL
Testo
Supponendo di avere a disposizione la display list "cubo", che
disegna un cubo con facce parallele ai piani coordinati e diagonale
(0,0,0) - (1,1,1), si consideri il seguente frammento di codice:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslate(2.0, 2.0, 0.0);
glScalef(1.0, 1.0, 10.0);
glCallList(cubo);
glPopMatrix();
glPushMatrix();
glTranslate(0.0, 0.0, 10.0);
glScalef(5.0, 5.0, 1.0);
glCallList(cubo);
glPopMatrix();
Domande
- Come e' fatta la scena risultante? a quali trasformazioni e'
sottoposta e in che ordine ciascuna delle due istanze del cubo?
- Che cosa succederebbe se eliminassimo le chiamate a glPushMatrix e
glPopMatrix?
- Modificare il codice per formare una scena che rappresenta un
tavolo fatto da un piano e 4 gambe (le dimensioni a piacere).
Soluzione
- La prima istanza del cubo e' soggetta nell'ordine ad una scalatura
di fattori (1,1,10) sui tre assi, che lo porta ad essere un
parallelepidedo con angoli (0,0,0)-(1,1,10) e poi ad una
traslazione con vettore di traslazione (2,2,0).
La seconda istanza del cubo e' soggetta nell'ordine ad una scalatura
di fattori (5,5,1), che lo porta ad essere un
parallelepidedo con angoli (0,0,0)-(5,5,1) e poi ad una
traslazione con vettore di traslazione (0,0,10).
La scena mostra due parallelepipedi con facce parallele ai piani
coordinati, uno di diagonale (2,2,0)-(3,3,10) e l'altro di
diagonale (0,0,10)- (5,5,11).
- Se eliminassimo glPushMatrix e glPopMatrix, la seconda istanza del
cubo sarebbe sottoposta anche alle trasformazioni della prima,
cioe' subirebbe nell'ordine le trasformazioni:
scalatura con fattori (5,5,1), traslazione di vettore (0,0,10),
scalatura con fattori (1,1,10), traslazione di vettore (2,2,0).
[Osservazione facoltativa:
Notare che entrambe le scalature tengono ferma l'origine, ma
nella prima l'origine e' uno dei vertici dell'oggetto,
mentre nella seconda l'origine e' un punto esterno all'oggetto,
quindi come effetto collaterale della scalatura l'oggetto viene
anche spostato aumentando di 10 volte la sua distanza dall'origine
lungo l'asse z.]
- Il mio tavolo ha gambe a base quadrata di lato 1x1 unita', alte
4 unita', il piano del tavolo e' quadrato di lato 6x6 unita' ed
e' spesso 1 unita'. Il tavolo e' posizionato in modo tale che
il suo bounding box abbia diagonale (0,0,0)-(6,6,5)
[La descrizione del tavolo deve preferibilmente essere corredata
da una figura esplicativa; la figura puo' sostituire la
descrizione se tutte le misure sono riportate in modo chiaro]
Costruisco il tavolo posizionando 5 istanze del cubo nel modo
seguente:
glPushMatrix();
glTranslate(0,0,4);
glScalef(6,6,1);
glCallList(cubo); /* piano del tavolo */
glPopMatrix();
glPushMatrix();
glScalef(1,1,4);
glCallList(cubo); /* prima gamba */
glPopMatrix();
glPushMatrix();
glTranslate(5,0,0);
glScalef(1,1,4);
glCallList(cubo); /* seconda gamba */
glPopMatrix();
glPushMatrix();
glTranslate(0,5,0);
glScalef(1,1,4);
glCallList(cubo); /* terza gamba */
glPopMatrix();
glPushMatrix();
glTranslate(5,5,0);
glScalef(1,1,4);
glCallList(cubo); /* quarta gamba */
glPopMatrix();
Esercizio su interfacce
Testo
Consideriamo un'interfaccia per la scelta del colore da usare in
una applicazione grafica.
L'applicazione e' una scatola nera con la quale l'interfaccia comunica
attraverso due funzioni:
-
sendColorToApplication(r,g,b);
invia il colore (r,g,b) all'applicazione, che da ora in poi lo
usera' come suo colore corrente
-
(r,g,b) = getColorFromApplication();
si fa restituire dall'applicazione il colore corrente e lo memorizza in
(r,g,b)
In entrambi i casi i tre valori (r,g,b) sono float compresi
nell'intervallo [0,1].
Un'interfaccia testuale si comporterebbe come segue (scritto in
pseudo-codice):
1 float r, g, b;
2 (r,g,b) = getColorFromApplication();
3 output "Colore corrente:"
4 output " rosso = ";
5 output r;
7 output " verde = ";
8 output g;
9 output " blu = ";
10 output b;
11 output "Nuovo colore:"
12 output "immetti il valore di rosso (in [0,1]):
13 input r;
14 if r not in [0,1] { output "errore"; goto 12; }
15 output "immetti il valore di verde (in [0,1]):
16 input g;
17 if r not in [0,1] { output "errore"; goto 15; }
18 output "immetti il valore di blu (in [0,1]):
19 input b;
20 if r not in [0,1] { output "errore"; goto 18; }
21 sendColotToApplication (r,g,b);
Supponiamo di organizzare un'interfaccia grafica nel seguente modo:
-
tre slider r_slider, g_slider e b_slider
per i tre valori di colore r, g, b
-
un'area grafica 2d preview_area
che traccia un rettangolo del colore attualmente indicato dagli slider
-
un bottone apply_but, etichettato "Apply",
premendo il quale il colore indicato dagli slider e
dal rettangolo diventera' il colore corrente dell'applicazione
-
un bottone reset_but, etichettato "Reset",
che reinizializza il colore degli slider e del rettangolo
rendendolo uguale a quello corrente dell'applicazione
Domande
-
Determinare quali abilitazioni e disabilitazioni sono opportune
(es. se gli slider non sono stati spostati non ha senso fare apply).
-
Scrivere in pseudocodice
il contenuto delle callback (o event handler) dei tre slider
e dei due bottoni, ricordando anche di gestire l'abilitazione e
disabilitazione.
Supporre che il toolkit utilizzato per creare l'interfaccia ammetta
le funzioni usuali per manipolare i vari tipi di dispositivi
(es: assegnare e leggere il valore di uno slider,
assegnare e leggere il colore di disegno per l'area grafica ecc.) e che
preveda funzioni per abilitare e disabilitare un dispositivo.
Nello pseudocodice scrivere queste funzioni
in linguaggio naturale oppure con nomi
significativi, indicando chiaramente i loro parametri di ingresso e uscita.
Soluzione
-
Inizialmente nessuna modifica e' stata ancora apportata al colore,
il colore mostrato nell'interfaccia e' uguale a quello usato
nell'applicazione. In questo stato sono abilitati solo gli slider,
i due bottoni sono disabilitati.
Non appena uno degli slider viene mosso, i due bottoni sono abilitati.
La pressione di uno qualsiasi dei bottoni riporta ad uno stato
in cui il colore mostrato nell'interfaccia e' uguale a quello
dell'applicazione, dunque i due bottoni vengono nuovamente disabilitati.
-
Pseudocodice della callback dello slider r_slider
per il rosso (le altre due sono analoghe):
r := valore segnato dallo slider r_slider;
assegna colore di foreground di preview_area con (r,g,b);
abilita reset_but;
abilita apply_but;
Pseudocodice della callback del bottone reset_but:
(r,g,b) = getColorFromApplication();
assegna valore di r_slider con r;
assegna valore di g_slider con g;
assegna valore di b_slider con b;
assegna colore di foreground di preview_area con (r,g,b);
disabilita reset_but;
disabilita apply_but;
Pseudocodice della callback del bottone reset_but:
sendColotToApplication (r,g,b);
disabilita reset_but;
disabilita apply_but;