OpenGL avec GtkGLArea Par Xavier Michelon |
#include <stdio.h> #include <stdlib.h> #include <gtk/gtk.h> #include <gtkgl/gtkglarea.h> #include <GL/gl.h> #include <GL/glu.h> #define DISTANCE_INIT 6.0 #define DISTANCE_MIN 4.5 #define DISTANCE_MAX 25.0 GtkWidget *fenetre,*glarea,*boiteh,*boitev,*boitev2,*bouton,*frame; GSList *groupe; int listeAttributs[] = { GDK_GL_RGBA, GDK_GL_DOUBLEBUFFER, GDK_GL_DEPTH_SIZE, 1, GDK_GL_NONE }; int theta=-35,phi=20,xprec,yprec; float distance=DISTANCE_INIT; /* Parametres d'éclairage */ GLfloat L0pos[]={ 0.0,2.0,1.0}; GLfloat L0dif[]={ 0.3,0.3,0.8}; GLfloat L1pos[]={ 2.0,2.0,2.0}; GLfloat L1dif[]={ 0.5,0.5,0.5}; GLfloat Mspec[]={0.5,0.5,0.5}; GLfloat Mshiny=50; /* Prototypes des fonctions */ void creeInterface(); void affichage(GtkWidget *widget,GdkEventExpose *evenement); void initGlarea(GtkWidget* widget); void redimGlarea(GtkWidget* widget, GdkEventConfigure* evenement); void mouvementSouris(GtkWidget* widget, GdkEventMotion* evenement); void rappelMap(GtkWidget* widget, GdkEventAny* evenement); void modeAffichage(GtkWidget* widget, char *chaine); void basculeEclairage(GtkWidget* widget,gpointer donnee); void basculeFacesArrieres(GtkWidget *widget,gpointer donnee); int main(int argc,char **argv) { gtk_init(&argc,&argv); creeInterface(); /* affichage de l'interface */ gtk_widget_show_all(fenetre); gtk_main(); return 0; } /* Fonction de creation de l'interface graphique */ void creeInterface() { /* la fenetre principale */ fenetre=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(fenetre),"Example GtkGLArea"); gtk_signal_connect(GTK_OBJECT(fenetre),"destroy",GTK_SIGNAL_FUNC(gtk_main_quit),NULL); gtk_signal_connect(GTK_OBJECT(fenetre),"delete_event",GTK_SIGNAL_FUNC(gtk_main_quit),NULL); /* un boite verticale */ boiteh=gtk_hbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(fenetre),boiteh); /* une glarea */ if(gdk_gl_query() == FALSE) { fprintf(stderr,"Impossible d'utiliser OpenGL\n"); exit(1); } glarea = gtk_gl_area_new(listeAttributs); gtk_widget_set_events(GTK_WIDGET(glarea), GDK_EXPOSURE_MASK| GDK_BUTTON_PRESS_MASK| GDK_BUTTON_RELEASE_MASK| GDK_POINTER_MOTION_MASK| GDK_POINTER_MOTION_HINT_MASK); gtk_widget_set_usize(GTK_WIDGET(glarea),300,300); gtk_box_pack_start(GTK_BOX(boiteh),glarea,TRUE,TRUE,0); gtk_signal_connect (GTK_OBJECT(glarea), "realize", GTK_SIGNAL_FUNC(initGlarea), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "expose_event", GTK_SIGNAL_FUNC(affichage), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "configure_event", GTK_SIGNAL_FUNC(redimGlarea), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "motion_notify_event", GTK_SIGNAL_FUNC(mouvementSouris), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "map_event", GTK_SIGNAL_FUNC(rappelMap), NULL); /* une boite verticale */ boitev=gtk_vbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(boiteh),boitev,FALSE,FALSE,0); /* une frame */ frame=gtk_frame_new("Mode d'affichage"); gtk_box_pack_start(GTK_BOX(boitev),frame,FALSE,FALSE,0); /* un boite verticale pour la frame */ boitev2=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(frame),boitev2); /* un groupe de bouton radio */ bouton=gtk_radio_button_new_with_label(NULL,"Plein"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bouton),TRUE); gtk_box_pack_start(GTK_BOX(boitev2),bouton,FALSE,FALSE,0); gtk_signal_connect(GTK_OBJECT(bouton),"toggled",GTK_SIGNAL_FUNC(modeAffichage),"a"); groupe=gtk_radio_button_group(GTK_RADIO_BUTTON(bouton)); bouton=gtk_radio_button_new_with_label(groupe,"Fil de fer"); gtk_box_pack_start(GTK_BOX(boitev2),bouton,FALSE,FALSE,0); gtk_signal_connect(GTK_OBJECT(bouton),"toggled",GTK_SIGNAL_FUNC(modeAffichage),"b"); groupe=gtk_radio_button_group(GTK_RADIO_BUTTON(bouton)); bouton=gtk_radio_button_new_with_label(groupe,"Points"); gtk_box_pack_start(GTK_BOX(boitev2),bouton,FALSE,FALSE,0); gtk_signal_connect(GTK_OBJECT(bouton),"toggled",GTK_SIGNAL_FUNC(modeAffichage),"c"); /* un bouton pour bascule pour l'éclairage */ bouton=gtk_check_button_new_with_label("Eclairage"); gtk_box_pack_start(GTK_BOX(boitev),bouton,FALSE,FALSE,0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bouton),TRUE); gtk_signal_connect(GTK_OBJECT(bouton),"toggled",GTK_SIGNAL_FUNC(basculeEclairage),NULL); /* un bouton pour le masquage des faces arrieres*/ bouton=gtk_check_button_new_with_label("Masquage des face arrières"); gtk_box_pack_start(GTK_BOX(boitev),bouton,FALSE,FALSE,0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bouton),TRUE); gtk_signal_connect(GTK_OBJECT(bouton),"toggled",GTK_SIGNAL_FUNC(basculeFacesArrieres),NULL); /* un bouton Quitter */ bouton=gtk_button_new_with_label("Quitter"); gtk_box_pack_end(GTK_BOX(boitev),bouton,FALSE,FALSE,0); gtk_signal_connect(GTK_OBJECT(bouton),"clicked",GTK_SIGNAL_FUNC(gtk_main_quit),NULL); } /* Fonction de rappel pour l'affichage */ void affichage(GtkWidget *widget,GdkEventExpose *evenement) { if (evenement->count > 0) return; if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0,0.0,distance,0.0,0.0,0.0,0.0,1.0,0.0); glRotatef(phi,1.0,0.0,0.0); glRotatef(theta,0.0,1.0,0.0); glBegin(GL_POLYGON); glNormal3d(0,0,1); glColor3d(1,0,0); glVertex3d(-1,1,1); glVertex3f(-1,-1,1); glVertex3f(1,-1,1); glVertex3f(1,1,1); glEnd(); glBegin(GL_POLYGON); glNormal3d(1,0,0); glColor3d(0,1,0); glVertex3d(1,1,1); glVertex3f(1,-1,1); glVertex3f(1,-1,-1); glVertex3f(1,1,-1); glEnd(); glBegin(GL_POLYGON); glNormal3d(0,0,-1); glColor3d(0,0,1); glVertex3d(1,1,-1); glVertex3f(1,-1,-1); glVertex3f(-1,-1,-1); glVertex3f(-1,1,-1); glEnd(); glBegin(GL_POLYGON); glNormal3d(-1,0,0); glColor3d(1,1,0); glVertex3d(-1,1,-1); glVertex3f(-1,-1,-1); glVertex3f(-1,-1,1); glVertex3f(-1,1,1); glEnd(); glBegin(GL_POLYGON); glNormal3d(0,1,0); glColor3d(1,0,1); glVertex3d(-1,1,-1); glVertex3f(-1,1,1); glVertex3f(1,1,1); glVertex3f(1,1,-1); glEnd(); glBegin(GL_POLYGON); glNormal3d(0,-1,0); glColor3d(0,1,1); glVertex3d(-1,-1,1); glVertex3f(-1,-1,-1); glVertex3f(1,-1,-1); glVertex3f(1,-1,1); glEnd(); gtk_gl_area_swapbuffers(GTK_GL_AREA(widget)); } } /* fonction d'initialisation d'OpenGL*/ void initGlarea(GtkWidget* widget) { if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) { glClearColor(0.4,0.4,0.4,1.0); glColor3d(1,0,0); glPointSize(4.0); glLineWidth(2.0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); /* Mise en place de la perspective */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0,1.0,0.1,DISTANCE_MAX+2); glMatrixMode(GL_MODELVIEW); /* Parametrage de l'éclairage */ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glLightfv(GL_LIGHT0,GL_DIFFUSE,L0dif); glLightfv(GL_LIGHT0,GL_SPECULAR,L0dif); glLightfv(GL_LIGHT1,GL_DIFFUSE,L1dif); glLightfv(GL_LIGHT1,GL_SPECULAR,L1dif); /* Paramétrage du matériau */ glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,Mspec); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,Mshiny); } } /* Fonction de rappel pour le redimensionnement du widget OpenGL */ void redimGlarea(GtkWidget* widget, GdkEventConfigure* evenement) { int l = widget->allocation.width; int h = widget->allocation.height; if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) { if (l<h) glViewport(0,(h-l)/2,l,l); else glViewport((l-h)/2,0,h,h); } } /* fonction de rappel pour les mouvements de la souris */ void mouvementSouris(GtkWidget* widget, GdkEventMotion* evenement) { int x,y; GdkModifierType etat; if (evenement->is_hint) gdk_window_get_pointer(evenement->window,&x,&y,&etat); else { x=evenement->x; y=evenement->y; etat=evenement->state; } /* bouton gauche = rotation */ if (etat & GDK_BUTTON1_MASK){ theta+=x-xprec; phi+=y-yprec; gtk_widget_queue_draw(widget); } /* bouton droit = Zoom */ if (etat & GDK_BUTTON3_MASK){ distance+=((float)(y-yprec))/20.0; if (distance<DISTANCE_MIN) distance=DISTANCE_MIN; if (distance>DISTANCE_MAX) distance=DISTANCE_MAX; gtk_widget_queue_draw(widget); } xprec=x;yprec=y; } /* Fonction de rappel pour le mapping du widget */ void rappelMap(GtkWidget* widget, GdkEventAny* evenement) { int x,y; gdk_window_get_pointer(glarea->window,&x,&y,NULL); xprec=x; yprec=y; } /* Fonction de bascule du mode d'affichage */ void modeAffichage(GtkWidget* widget, char *chaine) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) if (gtk_gl_area_make_current(GTK_GL_AREA(glarea))) { switch (chaine[0]) { case 'a': glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; case 'b': glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; case 'c': glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break; } gtk_widget_queue_draw(GTK_WIDGET(glarea)); } } /* Fonction de bascule du mode d'eclairage */ void basculeEclairage(GtkWidget* widget,gpointer donnee) { if (gtk_gl_area_make_current(GTK_GL_AREA(glarea))) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) glEnable(GL_LIGHTING); else glDisable(GL_LIGHTING); gtk_widget_queue_draw(GTK_WIDGET(glarea)); } } /* Fonction de bacule pour le masquage des faces arrieres */ void basculeFacesArrieres(GtkWidget *widget,gpointer donnee) { if (gtk_gl_area_make_current(GTK_GL_AREA(glarea))) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); gtk_widget_queue_draw(GTK_WIDGET(glarea)); } }