/* Implantation mathematique */ /* du calcul d'une courbe de Bezier */ /* */ /* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2011 */ #include #include #include #include #include #include #include "Position3D.h" /* Variables et constantes globales */ /* pour les angles et les couleurs utilises */ static int f1; static int aff = 1; static int n = 20; static int m = 500; static float rx = 10.0F; static float ry = 30.0F; static float rz = 10.0F; static Position3D *ptCtrl1[21] = { new Position3D( 5.0, -10.0, 5.0), new Position3D(-5.0, -9.1, 5.0), new Position3D(-5.0, -7.8, -5.0), new Position3D( 5.0, -7.2, -5.0), new Position3D( 5.0, -5.8, 5.0), new Position3D(-5.0, -5.1, 5.0), new Position3D(-5.0, -4.0, -5.0), new Position3D( 5.0, -3.2, -5.0), new Position3D( 5.0, -1.7, 5.0), new Position3D(-5.0, -1.4, 5.0), new Position3D(-5.0, 0.0, -5.0), new Position3D( 5.0, 1.2, -5.0), new Position3D( 5.0, 2.0, 5.0), new Position3D(-5.0, 3.1, 5.0), new Position3D(-5.0, 4.3, -5.0), new Position3D( 5.0, 4.7, -5.0), new Position3D( 5.0, 6.2, 5.0), new Position3D(-5.0, 7.1, 5.0), new Position3D(-5.0, 8.1, -5.0), new Position3D( 5.0, 9.3, -5.0), new Position3D( 5.0, 10.0, 5.0) }; static Position3D *ptCtrl2[21] = { new Position3D( 5.0, -10.0, 5.0), new Position3D(-5.0, -9.1, 5.0), new Position3D(-5.0, -7.2,-15.0), new Position3D( 5.0, -7.8,-15.0), new Position3D(15.0, -5.1, 5.0), new Position3D(-5.0, -5.8, 5.0), new Position3D(-5.0, -4.0, -5.0), new Position3D( 5.0, -3.2, -5.0), new Position3D( 5.0, -1.7, 15.0), new Position3D(-5.0, -1.4, 5.0), new Position3D(-5.0, 0.0, -5.0), new Position3D( 5.0, 1.2, -5.0), new Position3D(15.0, 2.0, 15.0), new Position3D(-5.0, 4.1, 5.0), new Position3D(-5.0, 3.3,-15.0), new Position3D( 5.0, 4.7, -5.0), new Position3D(15.0, 7.2, 5.0), new Position3D(-5.0, 6.1, 15.0), new Position3D(-5.0, 8.1, -5.0), new Position3D( 5.0, 9.3, -5.0), new Position3D( 5.0, 10.0, 5.0) }; static Position3D **ptCtrl = ptCtrl1; static void postRedisplay(void) { glutPostWindowRedisplay(f1); } /* Fonction executee lors d'un changement */ /* de la taille de la fenetre (1) */ void reshape(int w,int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-14.0F,14.0,(float) h/w*-14.0,(float) h/w*14.0,-50.0,50.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Fonction executee lors d'un rafraichissement */ /* de la fenetre de dessin (1) */ long long factoriel(int n) { if ( n == 0 ) return(1L); else return(n*factoriel(n-1)); } long long c(int i,int n) { return(factoriel(n)/factoriel(i)/factoriel(n-i)); } double power(double x,double y) { if ( ( x == 0.0 ) && ( y == 0 ) ) return(1.0); else return(pow(x,y)); } void bezier(Position3D **ptCtrl,int n,int m,Position3D **b) { for ( int j = 0 ; j < m ; j++ ) { double t =(double) j/(m-1); b[j]->c[0] = b[j]->c[1] = b[j]->c[2] = 0.0; b[j]->c[3] = 1.0; for ( int i = 0 ; i <= n ; i++ ) { long long v = c(i,n); double v1 = power(t,i); double v2 = power(1.0-t,n-i); b[j]->c[0] += v*v1*v2*ptCtrl[i]->c[0]; b[j]->c[1] += v*v1*v2*ptCtrl[i]->c[1]; b[j]->c[2] += v*v1*v2*ptCtrl[i]->c[2]; } } } void display() { glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(rz,0.0F,0.0F,1.0F); glRotatef(ry,0.0F,1.0F,0.0F); glRotatef(rx,1.0F,0.0F,0.0F); glColor3f(1.0F,0.0F,0.0F); glPointSize(3.0F); glBegin(GL_LINE_STRIP); for ( int i = 0 ; i <= n ; i++ ) glVertex3d(ptCtrl[i]->c[0],ptCtrl[i]->c[1],ptCtrl[i]->c[2]); glEnd(); Position3D **b =(Position3D **) calloc(m,sizeof(Position3D *)); for ( int i = 0 ; i < m ; i++ ) b[i] = new Position3D(); bezier(ptCtrl,n,m,b); glColor3f(1.0F,1.0F,0.0F); glPointSize(1.0F); glBegin(GL_POINTS); for ( int i = 0 ; i < m ; i++ ) glVertex3d(b[i]->c[0],b[i]->c[1],b[i]->c[2]); glEnd(); for ( int i = 0 ; i < m ; i++ ) delete(b[i]); free(b); glPopMatrix(); glutSwapBuffers(); int error = glGetError(); if ( error != GL_NO_ERROR ) printf("Erreur OpenGL: %d\n",error); } void myinit(void) { glEnable(GL_DEPTH_TEST); } /* Fonction executee lors de la frappe */ /* d'une touche special du clavier: */ /* - touches de curseur */ /* - touches de fonction */ /* - ... */ void special(int code,int x,int y) { switch ( code ) { case GLUT_KEY_UP : rx += 1.0F; postRedisplay(); break; case GLUT_KEY_DOWN : rx -= 1.0F; postRedisplay(); break; case GLUT_KEY_RIGHT : ry += 1.0F; postRedisplay(); break; case GLUT_KEY_LEFT : ry -= 1.0F; postRedisplay(); break; case GLUT_KEY_PAGE_UP : rz += 1.0F; postRedisplay(); break; case GLUT_KEY_PAGE_DOWN : rz -= 1.0F; postRedisplay(); break; } } /* Fonction executee lorsqu'aucun evenement */ /* n'est en file d'attente */ void idle(void) { rx += 0.13355F; ry += 0.06117F; rz += 0.24174F; postRedisplay(); } /* Fonction executee lors de l'appui */ /* d'une touche alphanumerique du clavier */ void keyboard(unsigned char key,int x,int y) { switch (key) { case 'r' : rx = 0.0F; ry = 0.0F; rz = 0.0F; postRedisplay(); break; case 0x20 : aff = (aff+1)%2; if ( aff ) ptCtrl = ptCtrl1; else ptCtrl = ptCtrl2; postRedisplay(); break; case 0x0D : { static int anim = 0; anim = !anim; glutIdleFunc(( anim ) ? idle : NULL); } break; case 0x1B : exit(0); break; } } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitWindowSize(400,400); glutInitWindowPosition(50,50); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); f1 = glutCreateWindow("Courbe de Bezier"); myinit(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutMainLoop(); return(0); }