Le bouton gauche permet de déplacer la scène.
Le bouton droit permet de zoomer la scène par détection des mouvements verticaux de la
souris.
Le zoom est géré par paramètrage d'un gluLookAt.
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Septembre 2008 */
/* OpenGL et GLUt */
/* Gestion d'un zoom a la souris */
/* par parametrage d'un gluLookAt */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
/* Variables et constantes globales */
static const float blanc[] = { 1.0F,1.0F,1.0F,1.0F };
static const float vert[] = { 0.0F,1.0F,0.0F,1.0F };
static const float bleu[] = { 0.0F,0.0F,1.0F,1.0F };
static const float rouge[] = { 1.0F,0.0F,0.0F,0.5F };
static const float jaune[] = { 1.0F,1.0F,0.0F,0.5F };
static float rx = -50.0F;
static float r1 = 0.0F;
static float r2 = 0.0F;
static float dr1 = 0.31F;
static float dr2 = 1.81F;
static int anim = 1;
static int mouvement = 0 ;
static int button = 0 ;
static int px ;
static int py ;
static float zoom = 1.0F;
static float transx = 0.0F;
static float transy = 0.0F;
/* Fonction d'initialisation des parametres */
/* OpenGL ne changeant pas au cours de la vie */
/* du programme */
void init(void) {
const GLfloat mat_shininess[] = { 50.0 };
glMaterialfv(GL_FRONT,GL_SPECULAR,blanc);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
glLightfv(GL_LIGHT1,GL_DIFFUSE,blanc);
glLightfv(GL_LIGHT2,GL_DIFFUSE,blanc);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_CULL_FACE);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
/* Scene dessinee */
void scene(void) {
glPushMatrix();
glRotatef(r1,0.0F,0.0F,1.0F);
glTranslatef(10.0F,0.0F,0.0F);
glPushMatrix();
glRotatef(r2,0.0F,1.0F,0.0F);
glTranslatef(0.15F,0.0F,0.0F);
glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
glutSolidSphere(0.1F,36,36);
glPopMatrix();
glPushMatrix();
glRotatef(r2+120.0F,0.0F,1.0F,0.0F);
glTranslatef(0.15F,0.0F,0.0F);
glMaterialfv(GL_FRONT,GL_DIFFUSE,vert);
glutSolidSphere(0.1F,36,36);
glPopMatrix();
glPushMatrix();
glRotatef(r2+240.0F,0.0F,1.0F,0.0F);
glTranslatef(0.15F,0.0F,0.0F);
glMaterialfv(GL_FRONT,GL_DIFFUSE,bleu);
glutSolidSphere(0.1F,36,36);
glPopMatrix();
glPopMatrix();
glMaterialfv(GL_FRONT,GL_DIFFUSE,rouge);
glutSolidTorus(0.3,10.0,36,180);
glMaterialfv(GL_FRONT,GL_DIFFUSE,jaune);
glPushMatrix();
for( int i = 0 ; i < 10 ; i++ ) {
glPushMatrix();
glRotatef(36.0F*i,0.0F,0.0F,1.0F);
glTranslatef(10.0F,0.0F,0.0F);
glutSolidCube(1.0F);
glPopMatrix(); }
glPopMatrix();
}
/* Fonction executee lorsqu'aucun evenement */
/* n'est en file d'attente */
void idle(void) {
r1 += dr1;
r2 += dr2;
glutPostRedisplay();
}
/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin */
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
const GLfloat light0_position[] = { 1.0,1.0,1.0,0.0 };
const GLfloat light1_position[] = { -1.0,1.0,1.0,0.0 };
const GLfloat light2_position[] = { 1.0,-1.0,1.0,0.0 };
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
glPushMatrix();
gluLookAt(0.0,-7.0*zoom,25.0*zoom,
0.0,-2.0*zoom,0.0,
0.0,1.0,0.0);
glTranslatef(transx,transy,0.0F);
glRotatef(rx,1.0F,0.0F,0.0F);
scene();
glPopMatrix();
glFlush();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Attention, erreur OpenGL %d\n",error);
}
/* Fonction executee lors d'un changement */
/* de la taille de la fenetre OpenGL */
void reshape(int x,int y) {
glViewport(0,0,x,y);
glMatrixMode(GL_PROJECTION) ;
glLoadIdentity() ;
gluPerspective(30.0F,(float) x/y,1.0,1000.0) ;
glMatrixMode(GL_MODELVIEW) ;
glLoadIdentity() ;
}
/* Fonction executee lors de l'appui */
/* d'une touche du clavier */
void keyboard(unsigned char c,int x,int y) {
switch (c) {
case 43 :
dr1 *= 1.01F;
break;
case 45 :
dr1 /= 1.01F;
break;
case 0x1B :
exit(0);
break;
case 0x0D :
dr1 = -dr1;
break;
case 0x20 :
anim = !anim;
glutIdleFunc((anim) ? idle : NULL);
break; }
}
/* Fonction executee lors de l'appui */
/* d'une touche speciale du clavier */
void special(int c,int x,int y) {
switch (c) {
case GLUT_KEY_UP :
rx += 1.0F;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN :
rx -= 1.0F;
glutPostRedisplay();
break; }
}
/* Fonction executee lors de l'appui */
/* d'une touche de la souris */
void mouse(int bouton,int etat,int x,int y) {
button = bouton;
px = x ;
py = y ;
if ( etat == GLUT_DOWN ) {
mouvement = 1 ; }
if ( etat == GLUT_UP ) {
mouvement = 0 ; }
}
/* Fonction executee lors du deplacement */
/* de la souris devant la fenetre */
/* avec le bouton appuye */
void motion(int x,int y) {
switch ( button ) {
case GLUT_LEFT_BUTTON :
if ( mouvement == 1 ) {
transx += (x-px)/20.0F ;
transy += (py-y)/20.0F ;
px = x;
py = y;
glutPostRedisplay(); }
break;
case GLUT_RIGHT_BUTTON :
if ( mouvement == 1 ) {
int dy = py-y;
int i;
for ( i = 0 ; i < -dy ; i++ )
zoom *= 1.01F ;
for ( i = 0 ; i < dy ; i++ )
zoom /= 1.01F ;
px = x;
py = y;
glutPostRedisplay(); }
break; }
}
/* Fonction principale */
int main(int argc,char **argv) {
/* Initialisation de l'affichage */
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(450,250);
glutInitWindowPosition(50,50);
glutCreateWindow("Programmation événementielle avec GLUt");
/* Initialisation d'un certain nombre */
/* de parametres d'OpenGL */
init();
/* Specification des fonctions de gestion */
/* evenementielle */
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc(display);
/* Boucle principale d'affichage */
/* et de gestion des evenements */
glutMainLoop();
return(0);
}