/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2007 */ /* Trace de B-Splines */ #include #include #include #include #include /* Variables et constantes globales */ static int solution = 0; static int disc = 25; static int mode = 0; static int el = 0; static int mat = 2; /* Variables globales de gestion */ /* de l'interactivite clavier et souris */ static int clic = 0; static int mx; static int my; static float rx = 0.0F; static float ry = 0.0F; /* Type de stockage d'une position */ typedef struct position { double x; double y; double z; double t; } position; /* Type de stockage d'une matrice de base */ typedef double matriceDeBase[4][4]; /* Type de stockage d'une ligne polygonale */ typedef struct lignePolygonale { int n; position *pts; } lignePolygonale; /* Donnees statiques constantes */ static const float blanc[] = { 1.0F,1.0F,1.0F,1.0F }; static const float rouge[] = { 1.0F,0.0F,0.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 jaune[] = { 1.0F,1.0F,0.0F,1.0F }; static const float cyan[] = { 0.0F,1.0F,1.0F,1.0F }; static const float magenta[] = { 1.0F,0.0F,1.0F,1.0F }; static const float c1[] = { 0.3F,0.5F,0.7F,1.0F }; static const float c2[] = { 0.5F,0.7F,0.3F,1.0F }; static const float c3[] = { 0.7F,0.3F,1.5F,1.0F }; static const float *couleurs[10] = { rouge,vert, bleu,cyan, jaune,c3, magenta,c1, c2,blanc }; /* Donnees statiques */ static matriceDeBase mBNRU = { { -0.1666666F, 0.5F, -0.5F, 0.1666666F }, { 0.5F ,-1.0F, 0.5F, 0.0F }, { -0.5F , 0.0F, 0.5F, 0.0F }, { 0.1666666F, 0.6666666F, 0.1666666F,0.0F } }; static matriceDeBase mBCR = { { -0.5F, 1.5F,-1.5F, 0.5F }, { 1.0F,-2.5F, 2.0F,-0.5F }, { -0.5F, 0.0F, 0.5F, 0.0F }, { 0.0F, 1.0F, 0.0F, 0.0F } }; static matriceDeBase mBB = { { -1.0F, 3.0F,-3.0F, 1.0F }, { 3.0F,-6.0F, 3.0F, 0.0F }, { -3.0F, 3.0F, 0.0F, 0.0F }, { 1.0F, 0.0F, 0.0F, 0.0F } }; static matriceDeBase *mb = &mBB; static position p1[10] = { { -6.0,-1.0, 5.0, 1.0 }, { -1.0,-6.0,-4.0, 1.0 }, { 3.0,-4.0, 1.0, 1.0 }, { 6.0,-1.0, 0.0, 1.0 }, { 5.0, 3.0,-2.0, 1.0 }, { 1.0, 6.0, 4.0, 1.0 }, { -1.0, 2.0, 1.0, 1.0 }, { -4.0, 2.0, 2.0, 1.0 }, { -5.0, 6.0,-3.0, 1.0 }, { -2.0, 5.0,-6.0, 1.0 } }; static lignePolygonale lp = { 10,p1 }; /* Fonction de calcul du tableau de positions */ /* d'evaluation d'une B-Spline cree */ /* entre quatre positions */ position *calculBSpline(matriceDeBase m,position *pts,int n) { position *p =(position *) calloc(n,sizeof(position)); for ( int i = 0 ; i < n ; i++ ) { double t =(double) i/(n-1); double tt[4] = { t*t*t,t*t,t,1.0 }; double tn[4] = { 0.0,0.0,0.0,0.0 }; int j; for ( j = 0 ; j < 4 ; j++ ) for ( int k = 0 ; k < 4 ; k++ ) tn[j] += tt[k]*m[k][j]; for ( j = 0 ; j < 4 ; j++ ) { p[i].x += tn[j]*pts[j].x; p[i].y += tn[j]*pts[j].y; p[i].z += tn[j]*pts[j].z; } p[i].t = 1.0; } return(p); } /* Fonction d'initialisation des parametres */ /* OpenGL ne changeant pas au cours de la vie */ /* du programme */ void init(void) { glClearColor(0.0,0.0,0.0,0.0); } void dessine(position *p,int n) { glPushMatrix(); glBegin(GL_LINE_STRIP); for ( int i = 0 ; i < n ; i++ ) glVertex3dv((double *) &p[i]); glEnd(); glPopMatrix(); } void solutionQuestionA(void) { switch (mode) { case 0 : case 1 : case 2 : position *p = calculBSpline(*mb,&p1[el],disc); glColor4fv(vert); dessine(p,disc); free(p); glColor4fv(blanc); dessine(&p1[el],4); break; } } void solutionQuestionB(void) { int i; switch (mode) { case 0 : glColor4fv(blanc); dessine(lp.pts,lp.n); break; case 1 : glColor4fv(blanc); dessine(lp.pts,lp.n); glColor4fv(vert); for ( i = 0 ; i < lp.n-3 ; i++ ) { position *p = calculBSpline(*mb,&lp.pts[i],disc); dessine(p,disc); free(p); } break; case 2 : glColor4fv(blanc); dessine(lp.pts,lp.n); for ( i = 0 ; i < lp.n-3 ; i++ ) { glColor4fv(couleurs[i]); position *p = calculBSpline(*mb,&lp.pts[i],disc); dessine(p,disc); free(p); } break; } } /* Scene dessinee */ void scene(void) { glPushMatrix(); switch (solution) { case 0 : solutionQuestionA(); break; case 1 : solutionQuestionB(); break; } glPopMatrix(); } /* Fonction executee lors d'un rafraichissement */ /* de la fenetre de dessin */ void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rx,1.0F,0.0F,0.0F); glRotatef(ry,0.0F,1.0F,0.0F); scene(); glPopMatrix(); glFlush(); glutSwapBuffers(); } /* Fonction executee lors de la frappe */ /* d'une touche alphanumerique du clavier */ void key(unsigned char key,int x,int y) { switch ( key ) { case 43 : disc++; glutPostRedisplay(); break; case 45 : disc--; if ( disc < 2 ) disc = 2; glutPostRedisplay(); break; case 'a' : el = (el+1)%7; glutPostRedisplay(); break; case 'm' : mat =(mat+1)%3; switch ( mat ) { case 0 : mb = &mBCR; break; case 1 : mb = &mBNRU; break; case 2 : mb = &mBB; break;} glutPostRedisplay(); break; case 0x20 : mode = (mode+1)%3; glutPostRedisplay(); break; case 0x0D : solution = (solution+1)%2; glutPostRedisplay(); break; case 0x1B : exit(0); break; } } /* Fonction executee lors d'un clic de souris */ /* dans la fenetre */ void mouse(int bouton,int etat,int x,int y) { if ( bouton == GLUT_LEFT_BUTTON ) { if ( etat == GLUT_DOWN ) { clic = 1; mx = x; my = y; } if ( etat == GLUT_UP ) { clic = 0; } } } /* Fonction executee lors d'un deplacement */ /* de la souris sur la fenetre */ /* avec un bouton appuye */ void motion(int x,int y) { if ( clic ) { ry += (x-mx); rx += (y-my); mx = x; my = y; glutPostRedisplay(); } } /* 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(); glOrtho(-8.0,8.0,(double) -8.0*y/x,(double) 8.0*y/x,-8.0,8.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Fonction principale */ int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(300,300); glutInitWindowPosition(50,50); glutCreateWindow("Dessin de B-Splines"); init(); glutReshapeFunc(reshape); glutKeyboardFunc(key); glutMotionFunc(motion); glutMouseFunc(mouse); glutDisplayFunc(display); glutMainLoop(); return(0); }