Code
Source
#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));
}
}