1
Marco Tarini Università dell’Insubria
Facoltà di Scienze MFN di Varese Corso di Laurea in Informatica Anno Accademico 2012/13
Computer Graphics Lab
Notes 3: event based prog
Struttura programma tradizionale
• Struttura classica dei programmi a linea di comando:
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
main() {
init();
do_my_beautiful_algorithm();
exit();
}
non va bene per applicazioni
interattive interattive interattive interattive !
Struttura programma nel paradigma Event Event Event Event----Based Based Based Based
• Sistema a eventi
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
main() {
init();
while (true) { get_event() ; process_event();
}
} eventi tipo:
• mouse, tastiera...
• sistema di finistre
• reshape, minimizzazione...
• generati dall'applicazione stessa
• o da thread differenti
{
ciclo degli eventi
Esempio: applicazione con lib SDL SDL SDL SDL
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
bool done= false;
while ( ! done) /* ciclo degli eventi */
{
SDL_Event event;
SDL_WaitEvent(&event);
switch(event.type) {
case SDL_VIDEOEXPOSE: /* evento "ridisegnati" */
myRendering(); /* riempi screen buffer*/
break;
case SDL_QUIT:
done= true; break ; case SDL_KEYDOWN:
if ( event.key.keysym.sym== SDLK_ESCAPE) done= true;
break;
} } SDL_Quit();
return 1;
}
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
c i c l o d e g l i e v e n t i
Programmare un Event-Based con CallBack
• CallBack CallBack CallBack CallBack:
– funzione preposta alla gestione di un evento evento evento evento – in (free)glut,
un funtore da registrare per ogni evento
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
void myRendering() // la mia callback per l’evento “disegnati”
{ ...
} void main(){
glutDisplayFunc ( myRendering ); // registra la callback ...
glutMainLoop();
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("A test");
glutDisplayFunc( mia_display_callback );
glutMainLoop();
return 0;
}
void mia_display_callback(){
glClearColor( 0,0,0,0);
glClear( GL_COLOR_BUFFER_BIT );
glBegin(GL_TRIANGLES);
glVertex2d(-1,-1);
glVertex2d(0,1);
glVertex2d(1,0);
glEnd();
glutSwapBuffers(); // x double buffering
}
2
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("A test");
glutDisplayFunc( mia_display_callback );
glutReshapeFunc( mia_reshape_callback );
glutMainLoop();
return 0;
}
void mia_reshape_callback( int size_x, int size_y){
// la finestra e’ cambiata
// (ora e’ grande size_x X size_ypixel // ... che voglio fare?
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("A test");
glutDisplayFunc( mia_display_callback );
glutReshapeFunc( mia_reshape_callback );
glutKeyboardFunc( mia_keyboard_callback );
glutMainLoop();
return 0;
}
void mia_keyboard_callback( char c, int x, int y){
// l’utente ha premuto il tasto c
// (mentre il pointer era in pos x,y (viewport coords) // ... che voglio fare?
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("A test");
glutDisplayFunc( mia_display_callback );
glutReshapeFunc( mia_reshape_callback );
glutKeyboardFunc( mia_keyboard_callback );
glutMainLoop();
return 0;
}
void mia_keyboard_callback( char c, int x, int y){
// l’utente ha premuto il tasto c
// (mentre il pointer era in pos x,y (viewport coords) // ... che voglio fare?
}
Parentesi: Double buffering
• Piccolo trucco utile nelle applicazioni interattive – nascondere il frame buffer mentre viene riempito – evita “flickering” (“sfarfallio”)
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
fra m m en ti
(candidati pixels)frame buffer A
[ pronto ]
Ve rti ci pr oi et ta ti
(punti in R2)rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to set- up
rasterizer segmenti set- up
rasterizer punti set- up
frame buffer B
[ in costruzione ]
video al
A
Parentesi: Double buffering
• Piccolo trucco utile nelle applicazioni interattive – nascondere il frame buffer mentre viene riempito – evita “flickering” (“sfarfallio”)
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 2 / 1 3 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
fra m m en ti
(candidati pixels)frame buffer A
[ in costruzione ]
Ve rti ci pr oi et ta ti
(punti in R2)rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to set- up
rasterizer segmenti set- up
rasterizer punti set- up
frame buffer B
[ pronto ]