Programmazione grafica:
l’Interazione
Daniele Marini
1
Generalità
• L’interazione dipende dalle caratteristiche dei
dispositivi fisici e del sistema operativo
• OpenGL si appoggia sul window manager (XWindow, Microsoft Windows, Mac, ..)
• Per interfacciare OpenGL al window manager
faremo uso di GLUT, indipendente dallo
specifico WM
2
Dispositivi di input
Dispositivi logici e dispositivi fisici: analogo al rapporto
indotto da funzioni come: printf, scanf, getchar,
putchar: si puo’ leggere o scrivere su file, stampante,
display, tastiera ecc.
Nella grafica è più complesso: non sono solo caratteri!
3
Dispositivi di input
• Dispositivi di puntamento: per indicare una
posizione su uno schermo, comprende bottoni
per inviare interrupt o segnali
•
•
•
•
•
•
Mouse
Trackball
Tablet
Light pen
Joystick
Spaceball
• Tastiera: invia caratteri
4
Mouse/trackball
• Non trasmettono posizione ma velocità
• I due valori rilevati dal movimento della sferetta
sono incrementi relativi, posti in relazione
all’intervallo di tempo danno luogo al calcolo di
una velocità, la cui integrazione restituisce una
posizione relativa
• Permette di ottenere movimenti lenti o veloci
del cursore
5
tablet
• Fornisce posizione assoluta
• La posizione viene rilevata con interazione
elettromagnetica della punta di una penna
speciale con una maglia di fili annegati nella
superficie
• Touch screen ha funzioni analoghe
6
lightpen
• Un sensore ottico rileva la presenza di luce dal display,
invia un interrupt all’host, che ricava la posizione
conoscendo l’istante di rilevazione dell’interrupt e il
tempo di scansione della figura; identifica l’oggetto
grafico indicato conoscendo l’intera struttura dati e il
modo di attraversamento della struttura
• Limiti dovuti alla complessità e alla soglia di
illuminazione: se punta lo sfondo non rileva luce!
7
Joystick
• Anche il joystick rileva velocità, che vengono integrate
per calcolare posizioni relative
• Può avere componenti meccaniche che simulano effetti
di resistenza con stimolazione “cinestesica”
8
Spaceball
• Dotata di sensori di pressione, ha sei gradi di
libertà ed è adatta ad input 3D:
• Front-back left-right top-bottom
• Rotazioni su tre assi
9
Dispositivi logici - classificazione
GKS e PHIGS
• Secondo lo standard GKS e PHIGS sei logical devices:
• String - es. tastiera
• Locator - fornisce coordinate mondo (WC) es. mouse
con conversione da SC (ccordinate schermo) a WC
• Pick - restituice l’identificatore di un oggetto
• Choice - seleziona una opzione
• Dial - input analogico (potenziometri)
• Stroke - array di locazioni
10
Logical devices - OpenGL
• string - supportata dal Window Manager (WM), OGL
non distingue tra dispositivo fisico e logico (tastiera)
• locator - OGL converte da SC a WC con dati da mouse
ecc.
• Pick - OGL usa il processo selection
• choice - OGL usa widgets (gadget: congegno, dispositivo;
aggeggio, arnese) del WM (menu, scrollbar, bottoni ecc.)
• dial - OGL usa widgets del WM (sliders)
• stroke - OGL simula l’invio di sequenze di valori
attivando e terminando lo stream ad es. col bottone del
mouse
11
Misura e trigger
• L’input di un dispositivi fisico è caratterizzato
da misura e trigger
– Misura: è il valore restituito dal dispositivo
– Trigger: è un input fisico con cui l’utente invia un
segnale al sistema
• String: measure = caratteri battuti, trigger = CR
• Locator: measure = posizione, trigger = click su bottone
• Si può anche considerare un valore di stato (il
cursore è fuori dalla window …)
12
Modi di input
• Request mode
– La misura viene ritornata al sistema quando il
trigger viene attivato
request_locator(device_id, &measure)
• Sample mode
– Input immediato, non c’è trigger
sample_locator(device_id, &measure)
13
• Request mode - tipico di programmi non
grafici, es. input da tastiera con scanf
– Oppure per posizionare il cursore in WM e
selezionare con click
• Sample mode e request mode non sono adatti ad
applicazioni in cui l’utente determina il flusso
del programma, è piuttosto il programma che
guida l’utente (es. scelte di menu, word
processing)
• In un simulatore di volo possono esserci input
da moltissimi dispositivi
14
Event mode
• Permette di trattare situazioni complesse
• In ogni istante ogni dispositivo può generare un
evento
• Le measures del dispositivo, con identificatore
associato, sono poste in una coda di eventi
(event queue) indipendentemente da ciò che sta
eseguendo il programma - il programma
esamina la coda e decide che fare, se la coda è
vuota resta idle
15
Event mode
• Alternativamente si associa a ogni tipo di evento
una callback
• L’approccio con callback è il più usato nei
sistemi di WM e in OGL, e si presta a situazioni
client-server
16
Client-server
• Servizi distribuiti in LAN (printer, file, graphics, ..)
• Un programma applicativo OGL e’ un processo client
che usa un graphics server, i due processi possono
risiedere sul medesimo sistema o essere distribuiti
17
Programmazione dell’interazione
event driven
•
•
•
•
•
•
Uso del puntatore
Terminazione programma
Resize della finestra
Gestione della finestra
Menu
Picking
18
Uso puntatore
• Il puntatore può essere usato per la terminazione del
programma; distinguiamo tra
– move event: il mouse viene mosso col bottone premuto
– passive move event: mosso con bottone alzato
Dopo un move event la “measure” del device (posizione del mouse) è
resa disponibile
– mouse event - un bottone del mouse è premuto o rilasciato (il
bottone mantenuto premuto non genera eventi, è la
transizione che conta!)
19
Terminazione programma
glutMouseFunction(mouse_callback_func);
void mouse_callback_func(int button, int state, int x, int
y,);
int x, int y;
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
exit();
}
Altri bottoni o uno stato differente del mouse non provocano nulla, non
ci sono callback registrate col WM
20
main
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLLUT_RGB);
glutCreateWindow(“square”);
myinit();
glutReshapeFunc(myReshape);
glutMouseFunc(mouse);
glutDisplayFunc(display);
glutMainLoop();
}
Reshape è invocato quando la finestra viene modificata dall’utente
Ogni programma deve avere una display callback, anche vuota:
void display() {}
21
Disegnare un rettangolo al click del
mouse
void mouse(int button, int state, int x, int y);
{
if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
drawSquare(x,y);
if(button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN)
exit();
}
La drawSquare si limita a disegnare, gli attributi del disegno vanno definiti
altrove, nell’esempio in myinit
22
myinit
/* globals */
Glsizei wh = 500, ww = 500; /* dim finestra iniziale */
Glfloat size = 3.0; /* metà del lato del quadrato */
void myinit(void)
{
glViewport(0,0,ww,wh);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (GLdouble) ww , 0.0, (GLdouble) wh , -1.0,
1.0);
glMatrixModel(GL_MODELVIEW);
glClearColor (0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
23
Disegno del quadrato
L’origine del sistema di riferimento nel WM è in alto a sinistra,
con y verso il basso, in OGL è in basso a sinistra con y verso
l’alto - bisogna “flippare” la y ritornata dal mouse:
void drawSquare(int x, int y)
{
y=wh-y; /* flippa y */
glColor3ub( (char) random()%256, (char)
random()%256, (char) random()%256);
glBegin(GL_POLYGON);
glVertex2f(x+size, y+size);
glVertex2f(x-size, y+size);
glVertex2f(x-size, y-size);
glVertex2f(x+size, y-size);
glEnd();
}
24
Il programma è completo
• Inizializza una finestra, disegna un quadrato di
colore casuale nel punto selezionato dal mouse
col tasto di sinistra; termina premendo il tasto di
mezzo del mouse
• Non ha menu, se la finestra viene modificata
(resize) il programma non sa che fare
25
Window events
• Es: resize, che fare?
– Ridisegnare tutto?
– Che fare se l’aspect ratio cambia?
– Si cambiano le dimensioni degli oggetti se la
finestra cambia dimensioni?
• Nell’esempio si ridisegna tutto, mantenendo i
rapporti degli oggetti (quadrati restano quadrati)
e si applica il clipping
• L’evento di resize restituisce altezza e larghezza
26
della window
myReshape
void myReshape(GLsizei w, GLsizei h)
{
/* adjust clipping box */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* adjust viewport and
clear */
glViewport(0,0,w,h);
glClearColor (0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
display();
glFlush();
}
27
Display callback
La glutDisplayFunc(display) viene eseguita quando GLUT
determina che la finestra va ridisegnata, certamente alla prima
apertura; in questo caso è utile disegnare le parti statiche della
finestra
La display callback può essere usata per animazione, quando
cambiano parametri nel programma
Per iconizzare una finestra si usa la glutPostDisplay()
Per disabilitare una callback si può settare la sua callback function
a NULL
28
Finestre multiple
id=glutCreateWindow(“second window”);
L’intero ritornato permette di attivare la prima o la seconda finestra:
glutSetWindow(id);
Si possono modificare parametri e proprietà della seconda finestra prima di
definirla:
glutInitDisplayMode( …);
id=glutCreateWindow(“third window”);
29
Menu
Pull-down e pop-up menus
glutCreateMenu(demo_menu);
glutAddMenuEntry(“quit”,1);
glutAddMenuEntry(“increase square size”,2);
glutAddMenuEntry(“decrease square size”,3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
void demo_menu(int id);
{
if(id==1) exit();
else if (id==2) size = 2*size;
else if (id==3) size=size/2;
glutPostRedisplay();
}
30
Menu pull-down gerarchici
sub_menu = glutCreateMenu(size_menu);
glutAddMenuEntry(“increase square size”,2);
glutAddMenuEntry(“decrease square size”,3);
glutCreateMenu(top_menu);
glutAddMenuEntry(“quit”,1);
alutAddSubMenu(“Resize”, sub_menu);
glutAttachMenu(GLUT_RIGHT_BUTTON);
Esercizio: scrivere le callback function di:
size_menu
top_menu
31
Scarica

06_Programmazione grafica - Università degli Studi di Milano