Cette montagne a été construite par un petit programme OpenGl en C :
Je ne suis pas du tout un spécialiste en matière de programmation ( le code n'est surement pas parfait ...),
mais voici tout de même les sources, au cas où ça vous interesse... Si vous avez des remarques à faire qui me
permetrai de mieux connaitre OpenGl ou le C, n'hésitez pas !
Le .h :
#include<stdlib.h> #include<GL/glut.h> #include<stdio.h> #include<stdlib.h> #include<math.h> #include<time.h> #define LEFT 0x0010 #define MIDDLE 0x0020 #define RIGHT 0x0040 /* type pour definir l'etat des variables d'options du programme */ typedef enum { uniforme, normale }loi; typedef enum { on , off }etat_fog; typedef enum { golf_on , golf_off}etat_golf; /* ----- gestion de la souris */ struct { /* memoire des evenements souris + modifieurs */ float x ,y, /* position souris normalisee */ x0,y0, /* position precedente */ dx,dy; /* mouvement */ int left,middle,right; /* etat des boutons de la souris */ int state; /* etat global (cf flags dessus) */ } mouse; /* variables du programme */ float * Mxy , ** Mz, ** temp ; /* composantes en x, y , et z de la montagne et montagne tampon */ float *** point_color; /* couleur en un point */ float longueur = 15, hauteur = 5; /* etendu et hauteur par defaut de la montagne */ float perturb = 0; loi ma_loi = normale; etat_fog fog = off; etat_golf golf = golf_off; int taille = 1,taille_old = 1; int SIZEX, SIZEY; GLfloat diffuse_color[4] = { 1.5, 1.5, 1.5, 1.}; GLfloat light_pos[4] = { 0, 0., 30., 0.5}; /* à l'infini */ GLfloat fog_color[4] = {1.0,1.0,1.,0.5}; GLfloat Lphi = 0 , Ltheta = 0, rot = 0; /* orientation de la lampe et de la montagne */ GLfloat mer_ambient[4] = { 0., 0., 0.3 , 1. }; GLfloat mer_diffuse[4] = { 0.1, 0.3, 1., 1. }; GLfloat mer_specular[4] = { 0.8 , 0.8, 0.8, 1.}; GLfloat mon_ambient[4] = { 0., 0.1, 0. , 1. }; GLfloat mon_diffuse[4] = { 0.1, 1., 0., 1. }; GLfloat mon_specular[4] = { 0.3 , 0.3, 0.3, 0.}; GLUquadricObj *sphere; GLfloat mong_rot=0; /* les differentes fonctions */ void update();/* mise à jour de la ùonatgne */ void draw_scene();/* dessine la scene à l'ecran */ float new_z(int,int,int,int);/* calcul la nouvelle hauteur */ void calcul_couleur(int,int); void reshape(int x,int y); /* changer la taille de la fenetre */ void key_plan(unsigned char key, int x, int y);/* utilisation du clavier */ void parse_args(int, char **);/* traitement des parametres */ void init_interface();/* interface utilisateur */ void menu(); void undo(); void mouse_click(int button,int state,int x,int y); void mouse_motion(int x, int y); void initialisation(int argc, char ** argv);
Le .c :
/* gcc montagne.c -o montagne.exe -lglut -lMesaGLU -lMesaGL -lXmu -lXi -lX11 -lm */ /* ************************************************************************* * * * Montagne fractale par Yann Claudel et Thomas Cohu * * * * Projet GAG DESS IMOI * *************************************************************************/ #include "montagne.h" int main(int argc, char **argv) { initialisation(argc,argv); glutReshapeFunc(reshape); glutDisplayFunc(draw_scene); glutMouseFunc(mouse_click); glutMotionFunc(mouse_motion); glutKeyboardFunc(key_plan); init_interface(); glutMainLoop(); return 1; } void initialisation(int argc, char ** argv){ srand48(time(NULL)); /* initialisation du générateur de nombre aléatoire */ glutInit(&argc,argv); parse_args(argc,argv); /* position et taille de la fenetre */ glutInitWindowSize(920,640); glutInitWindowPosition(50,100); /* mode de la fenetre */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); /* creation de la fenetre */ glutCreateWindow("montagne fractale de yann et tom"); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glEnable(GL_NORMALIZE); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse_color); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); /* brouillard et matin .... */ glFogi(GL_FOG_MODE,GL_LINEAR); glFogi(GL_FOG_MODE,GL_NICEST); glFogf(GL_FOG_DENSITY,1); glFogi(GL_FOG_START,30); glFogi(GL_FOG_END,70); glFogfv(GL_FOG_COLOR,fog_color); /* pour la mongolfière */ sphere = gluNewQuadric(); } /* dessin de la scene ------------------------------------------------------ | |*/ void draw_scene(){ /* cette fonction affiche la scene à l'ecran ( comme son nom l'indique judicieusement ... */ int i ,j , i_p ,j_p ; float pas = 1./(taille-1) ,pas_c=pas*pas ; /* efface l'ecran */ glColor3f(0.,0.,0.); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(10., SIZEX/(float)SIZEY, 1, 100.); glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* position de la lumière */ glLoadIdentity(); glPushMatrix(); glRotatef(Ltheta*180/M_PI, 1., 0., 0.); glRotatef(Lphi*180/M_PI, 0., 1., 0.); glLightfv(GL_LIGHT0,GL_POSITION,light_pos); glPopMatrix(); /* position, target, up */ gluLookAt(50, 0, 0, 0, 0, 0, 0, 0, 1 ); glEnable(GL_DEPTH_TEST); /* affiche la montagne */ glMaterialfv (GL_FRONT_AND_BACK,GL_AMBIENT, mon_ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mon_diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mon_specular); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,100); /* une mongolfière */ if (golf == golf_on ){ glPushMatrix(); glRotatef(mong_rot*180/M_PI,0,0,1); glTranslatef(-longueur/3.,longueur/3.,3); glColor3f(0.6,0.4,0.8); gluSphere(sphere,0.5,100,100); glPushMatrix(); glTranslatef(0,0,-0.8); glColor3f(0.7,0.7,0.5); glutSolidCube(0.5); glPopMatrix(); glPopMatrix(); } glPushMatrix(); glRotatef(10.,0.,1,0.); glRotatef(rot*180/M_PI,0.,0,1); for(i=0;i<(taille-1);i++){ i_p = i + 1; for(j=0;j<(taille-1);j++){ j_p = j + 1; glBegin(GL_TRIANGLES); glNormal3f( pas*(Mz[i][j]-Mz[i_p][j]), -pas*(Mz[i_p][j_p]-Mz[i_p][j]), pas_c); glColor3fv(point_color[i][j]); glVertex3f(Mxy[i],Mxy[j],Mz[i][j]); glColor3fv(point_color[i_p][j]); glVertex3f(Mxy[i_p],Mxy[j],Mz[i_p][j]); glColor3fv(point_color[i_p][j_p]); glVertex3f(Mxy[i_p],Mxy[j_p],Mz[i_p][j_p]); glEnd(); glBegin(GL_TRIANGLES); glNormal3f(-pas*(Mz[i_p][j_p]-Mz[i][j_p]), pas*(Mz[i][j]-Mz[i][j_p]) ,pas_c); glColor3fv(point_color[i][j]); glVertex3f(Mxy[i] , Mxy[j] , Mz[i][j]); glColor3fv(point_color[i_p][j_p]); glVertex3f(Mxy[i_p] , Mxy[j_p] , Mz[i_p][j_p]); glColor3fv(point_color[i][j_p]); glVertex3f(Mxy[i] , Mxy[j_p] ,Mz[i][j_p]); glEnd(); }/* fin de la boucle en j */ } /* fin de la boucle en i */ glPopMatrix(); /* la mer ......(que l'on voit danser ...) */ glMaterialfv (GL_FRONT_AND_BACK,GL_AMBIENT, mer_ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mer_diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mer_specular); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20); glPushMatrix(); glRotatef(8,0,1,0); glBegin(GL_QUADS); glNormal3f(0.,0.,1.); glColor3f(1.,0.,1.); glVertex3f(-10.,-8.,-2.); glColor3f(0.8,0.3,1.); glVertex3f(12.,-8.,-2.); glColor3f(0.,0.,1.); glVertex3f(12.,14.,-2.); glColor3f(0.1,0.2,0.8); glVertex3f(-10,14.,-2.); glEnd(); glPopMatrix(); /* le ciel ... */ glBegin(GL_QUADS); glNormal3f(1,0,0); glColor3f(1,0,0); glVertex3f(-10,-8,-2.); glColor3f(1.,0.,0.); glVertex3f(-10,14,-2.); glColor3f(0.,0.,1.); glVertex3f(-10,14,8); glColor3f(0.,0.2,1.); glVertex3f(-10,-8,8); glEnd(); glPopMatrix(); glDisable(GL_DEPTH_TEST); glFlush(); glutSwapBuffers(); } void reshape(int x,int y) { /* modification de la taille de la fenètre */ SIZEX = x; SIZEY = y; glViewport(0,0,SIZEX,SIZEY); } /* calculs de la montagnes ----------------------------------------------- | |*/ void update(){ int i , i_p ,j , j_p,ind_i,ind_i_p,ind_j,ind_j_p ; float pas ; if (taille ==1){ taille = 3; taille_old = taille; pas = longueur / (taille -1); /* allocation des coordonnées et des couleurs......... les coordonnées en x et en y sont défini sur le caré de reference à l'altitude -2 ......*/ Mxy = (float *)malloc(taille * sizeof(float)); Mz = (float **)malloc(taille * sizeof(float*)); temp =(float **)malloc(taille*sizeof(float*)); point_color =(float ***)malloc(taille*sizeof(float**)); for (i=0;i<taille;i++){ Mz[i] =(float*)malloc(taille * sizeof(float)); temp[i]=(float*)malloc(taille*sizeof(float)); point_color[i]=(float**)malloc(taille*sizeof(float*)); point_color[i][0]=(float*)malloc(3*sizeof(float)); point_color[i][1]=(float*)malloc(3*sizeof(float)); point_color[i][2]=(float*)malloc(3*sizeof(float)); } Mxy[0] = -longueur/2.; for (i=1;i<taille;i++){ Mxy[i] = Mxy[i-1] + pas;} for (i=0;i<taille;i++){ for (j=0;j<taille;j++){ Mz[i][j] = -2.; temp[i][j]= -2.; calcul_couleur(i,j);}} Mz[1][1] = -2 + hauteur; calcul_couleur(1,1); temp[1][1] = -2 + hauteur; } else { for(i=0;i<taille_old;i++){ free(temp[i]); for (j=0;j<taille;j++){ free(point_color[i][j]);} free(point_color[i]); } free(temp); free(point_color); temp = (float **)malloc(taille * sizeof(float*)); for (i=0;i<taille;i++){ temp[i] = (float *)malloc(taille * sizeof(float));} for ( i=0;i<taille;i++){ for ( j=0;j<taille;j++){ temp[i][j] = Mz[i][j];}} for (i=0;i<taille;i++){ free(Mz[i]);} free(Mz); free(Mxy); taille_old = taille; taille= 2*taille -1; pas = longueur/(taille-1); Mxy =(float *)malloc(taille * sizeof(float)); Mz =(float **)malloc(taille * sizeof(float *)); point_color =(float ***)malloc(taille*sizeof(float**)); for (i=0;i<taille;i++){ Mz[i] =(float*)malloc(taille * sizeof(float)); point_color[i]=(float**)malloc(taille*sizeof(float*)); for (j=0;j<taille;j++){ point_color[i][j]=(float*)malloc(3*sizeof(float));}} Mxy[0] = -longueur/2.; for (i=1;i<taille;i++){ Mxy[i] = Mxy[i-1] + pas;} for (i =0; i < (taille_old-1);i++){ i_p = i + 1; ind_i = 2*i; ind_i_p = ind_i + 1; for (j=0;j<(taille_old-1);j++){ j_p = j+1 ; ind_j = 2*j; ind_j_p=ind_j+1; Mz[ind_i][ind_j] = temp[i][j]; Mz[ind_i_p][ind_j] = new_z(i,j,i_p,j); Mz[ind_i_p][ind_j_p] = new_z(i,j,i_p,j_p); Mz[ind_i][ind_j_p] = new_z(i,j,i,j_p); calcul_couleur(ind_i,ind_j); calcul_couleur(ind_i_p,ind_j); calcul_couleur(ind_i_p,ind_j_p); calcul_couleur(ind_i,ind_j_p); ;}/* fin de la boucle en j */ Mz[taille-1][ind_i] = -2.; Mz[taille-1][ind_i_p] = -2.; Mz[ind_i][taille-1] = -2.; Mz[ind_i_p][taille-1] = -2.; calcul_couleur(taille-1,ind_i); calcul_couleur(taille-1,ind_i_p); calcul_couleur(ind_i,taille-1); calcul_couleur(ind_i_p,taille-1); }/* fin de la boucle en i */ Mz[taille-1][taille-1] = -2.; calcul_couleur(taille-1,taille-1); }} void calcul_couleur(int i,int j){ float z = Mz[i][j],teta = 2 * M_PI*drand48() ,r = sqrt(-2 * log(drand48())); z += 0.3*r*cos(teta); if (z < -1.5 ) { point_color[i][j][0] = 0.5; point_color[i][j][1] = 0.3; point_color[i][j][2] = 0.2;} else if (z < -1){ point_color[i][j][0] = 0.4; point_color[i][j][1] = 0.4; point_color[i][j][2] = 0.2;} else if (z < -0.5){ point_color[i][j][0] = 0.3; point_color[i][j][1] = 0.5; point_color[i][j][2] = 0.3;} else if (z < 0){ point_color[i][j][0] = 0.2; point_color[i][j][1] = 0.6; point_color[i][j][2]=0.3;} else if ( z < 0.5){ point_color[i][j][0] = 0.3; point_color[i][j][1] = 0.7; point_color[i][j][2] = 0.3;} else if (z<1){ point_color[i][j][0] = 0.4; point_color[i][j][1] = 0.8; point_color[i][j][2] = 0.3; } else if (z < 1.5){ point_color[i][j][0] = 0.7; point_color[i][j][1] = 0.8; point_color[i][j][2] = 0.3;} else { point_color[i][j][0] = 0.7; point_color[i][j][1] = 0.8; point_color[i][j][2] = 0.9;} } void undo(){ /* annule le dernier update de la montagne */ int i , j; float pas = longueur/(taille_old-1); for (i=0;i<taille;i++){ free(Mz[i]); for (j=0;j<taille;j++){ free(point_color[i][j]);} free(point_color[i]);} free(Mz); free(Mxy); free(point_color); taille = taille_old; Mz =(float **)malloc(taille * sizeof(float *)); point_color = (float ***)malloc(taille * sizeof(float **)); for (i=0;i<taille;i++){ Mz[i] =(float*)malloc(taille * sizeof(float)); point_color[i]=(float**)malloc(taille*sizeof(float*)); for (j=0;j<taille;j++){ point_color[i][j]=(float*)malloc(3*sizeof(float));}} for (i=0;i<taille;i++){ for (j=0;j<taille;j++){ Mz[i][j] = temp[i][j]; calcul_couleur(i,j);}} Mxy = (float * )malloc(taille * sizeof(float)); Mxy[0] = -longueur/2; for (i=1;i<taille;i++){ Mxy[i] = Mxy [i-1] + pas;} } float new_z(int ia,int ja, int ib,int jb){ /* calcul de la hauteur d'un nouveau point */ float val_z = 0.5*(temp[ia][ja] + temp[ib][jb]); float r , teta , sigma ; if ((ib>taille_old-1)||(jb>taille_old-1)||(ib==0)||(jb==0)) return (-2); sigma = sqrt(fabs(temp[ia][ja]-temp[ib][jb])*0.66666); if (ma_loi==normale){ teta = 2 * M_PI*drand48(); r = sqrt(-2 * log(drand48())); val_z += sigma *r *cos(teta)* perturb;} else { val_z += drand48() * sigma * perturb;} return val_z; } /* gestion du clavier -------------------------------------------------------*/ void key_plan(unsigned char key, int x, int y) { switch (key) { case 27 : case 'q' : exit(0); case '0' : perturb =1./taille; update(); glutPostRedisplay(); break; case '+' : perturb =5./taille; update(); glutPostRedisplay(); break; case '-': perturb = -2.5/taille; update(); glutPostRedisplay(); break; case 'u' : ma_loi = uniforme; printf(" on passe en loi uniforme !\n"); break; case 'n' : ma_loi = normale; printf("on passe en loi normal !\n"); break; case 'i' : taille =1; srand48(time(NULL)); update(); glutPostRedisplay(); break; case 'r' : rot += 0.1 ; glutPostRedisplay(); break; case 'R' : rot -= 0.1; glutPostRedisplay(); break; case 'm' : mong_rot += 0.1; glutPostRedisplay(); break; case 'M' : mong_rot -= 0.1; glutPostRedisplay(); break; default: break; } } /* entrees du programme ----------------------------------------------*/ void parse_args(int argc, char **argv) { printf( "\n" " commandes: \n" " %s [-options_loi] [-l longeur] [-h hauteur]\n" " -n: utilisation de la loi normal \n" " -u: utilisation de la loi uniforme \n" " -l : longueur du coté du carré initiale\n" " -h : hauteur initiale \n\n" " touches: \n" " ESC,q: quit r,R: tourner la montagne\n" " 0 : pertubation simple \n" " + : grosse pertubation \n" " - : pertubation négative \n" " i: réinitialiser le dessin \n\n" " souris : \n" " - click gauche : faire tourner la montagne \n" " - click milieu : orienter la lumière \n" " - click droit : affiche le menu \n\n" " loi par défaut : normale \n" " longueur par défaut : 15 \n" " hauteur par defaut : 5 \n" ,argv[0]); argc--; argv++; while (argc && (*argv)[0]=='-') { switch((*argv)[1]) { case 'n': ma_loi = normale;printf(" loi normal utilisé !\n"); break; case 'u': ma_loi =uniforme; printf("loi uniforme utilisé ! \n"); break; case 'l': argc--; argv++; sscanf(*argv,"%f",&longueur);break; case 'h': argc--;argv++;sscanf(*argv,"%f",&hauteur);break; default : printf(" erreur de commande ! \n"); exit(0); } argc--; argv++; } } /* gestion de la souris -----------------------------------------*/ void menu(int v) { /* clic dans un menu */ switch (v) { case 1: perturb = 1/taille; update();glutPostRedisplay(); break; case 2: perturb =5./taille; update();glutPostRedisplay(); break; case 3: perturb = -2.5/taille; update();glutPostRedisplay(); break; case 4: taille = 1; srand48(time(NULL)); update();glutPostRedisplay(); break; case 5: if (fog == off) { fog = on; glEnable(GL_FOG);} else { fog = off; glDisable(GL_FOG);} glutPostRedisplay(); break; case 6: undo();glutPostRedisplay(); break; case 7: if (golf == golf_on) { golf = golf_off;} else { golf = golf_on;} glutPostRedisplay(); break; case 99: exit(0); } } void init_interface() { /* initialisation des menus */ glutCreateMenu(menu); glutAddMenuEntry("perurbation moyenne",1); glutAddMenuEntry("grosse pertubation",2); glutAddMenuEntry("pertubation négative",3); glutAddMenuEntry("reinitialiser",4); glutAddMenuEntry("brouillard on/off",5); glutAddMenuEntry("annuler",6); glutAddMenuEntry("mongolfière ?",7); glutAddMenuEntry("Quitter" ,99); glutAttachMenu(GLUT_RIGHT_BUTTON); } void mouse_motion(int x,int y) { /* mouvement de la souris */ float xx = mouse.x, yy = mouse.y; mouse.x = x /(float)SIZEX; mouse.y = (SIZEY-y)/(float)SIZEY; mouse.dx = mouse.x-xx; mouse.dy = mouse.y-yy; switch(mouse.state) { case LEFT: rot +=mouse.dx; break; case MIDDLE: Lphi +=mouse.dx;Ltheta+=mouse.dy;break; } glutPostRedisplay(); } void mouse_click(int button,int state,int x,int y) { /* clic de souris */ int alt; /* on stocke dans 'mouse' l'etat de tous les modifieurs */ switch(button) { case GLUT_LEFT_BUTTON: mouse.left = (state==GLUT_DOWN); break; case GLUT_MIDDLE_BUTTON: mouse.middle = (state==GLUT_DOWN); break; case GLUT_RIGHT_BUTTON: mouse.right = (state==GLUT_DOWN); break; } alt = glutGetModifiers(); mouse.state = LEFT*mouse.left | MIDDLE*mouse.middle | RIGHT*mouse.right; mouse.x0 = x /(float)SIZEX; mouse.x=mouse.x0; mouse.dx=0; mouse.y0 = (SIZEY-y)/(float)SIZEY; mouse.y=mouse.y0; mouse.dy=0; }