/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Fevrier 2019 */ /* Illustration de la generation */ /* d'une courbe B-Spline */ /* avec calcul des tangentes */ #include #include #include #include #include #include #include "ModuleCouleurs.h" #include "ModuleFont.h" #include "ModuleManipulateur.h" #include "ModuleMenus.h" #include "ModuleFleche.h" #include "ModuleReshape.h" struct coord_3D { GLfloat x = 0.0F; GLfloat y = 0.0F; GLfloat z = 0.0F; GLfloat w = 1.0F; }; struct polygone { int n = 0; coord_3D *p = NULL; }; typedef struct coord_3D coord_3D; typedef struct polygone polygone; typedef float matrice[4][4]; static GLfloat pts[4][4] = { { 1.0F,-3.0F,-3.0F, 1.0F }, { 2.0F, 3.0F,-2.0F, 1.0F }, { -4.0F, 0.0F, 2.0F, 1.0F }, { -1.0F,-4.0F, 4.0F, 1.0F } }; static int aff = 2; static int pt = 0; static int mode = 0; static int ttan = 1; static int np = 0; static int disc = 30; static polygone pl; static matrice m1 = { -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 matrice m2 = { -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 matrice m3 = { -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 }; void point(float x,float y,float z) { glVertex3f(x,y,z); } void pointIndividuel(float x,float y,float z,float vx,float vy,float vz) { glBegin(GL_POINTS); glVertex3f(x,y,z); glEnd(); glPushMatrix(); glTranslatef(x,y,z); glEnable(GL_LIGHTING); flecheEnVolume(vx,vy,vz,0.04F,0.3F,0.01F); glDisable(GL_LIGHTING); glPopMatrix(); } void calcul(float *tt,matrice m,coord_3D *p,float *x,float *y,float *z) { int j,k; float ttt[4]; for ( j = 0 ; j < 4 ; j++ ) for ( k = 0,ttt[j] = 0 ; k < 4 ; k++ ) ttt[j] += tt[k] * m[k][j]; *x = *y = *z = 0; for ( j = 0 ; j < 4 ; j++ ) { *x += ttt[j] * p[j].x; *y += ttt[j] * p[j].y; *z += ttt[j] * p[j].z; } } void lisse(coord_3D *p,int n,matrice m) { float tt[4],x,y,z; for ( int i = 0 ; i < n ; i++ ) { float t =(float) i/(n-1); tt[0] = t*t*t; tt[1] = t*t; tt[2] = t; tt[3] = 1.0F; calcul(tt,m,p,&x,&y,&z); point(x,y,z); } } void tangente(coord_3D *p,int n,matrice m,int pt) { float tt[4],x,y,z,vx,vy,vz; float t =(float) pt/(n-1); tt[0] = t*t*t; tt[1] = t*t; tt[2] = t; tt[3] = 1.0F; calcul(tt,m,p,&x,&y,&z); tt[0] = 3*t*t; tt[1] = 2*t; tt[2] = 1.0F; tt[3] = 0.0F; calcul(tt,m,p,&vx,&vy,&vz); float d = sqrt(vx*vx+vy*vy+vz*vz); vx /= d; vy /= d; vz /= d; pointIndividuel(x,y,z,vx,vy,vz); } void display(void) { int i; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glEnable(GL_DEPTH_TEST); manipulateurSouris(); manipulateurClavier(); glColor4fv(couleurBlanc()); glBegin(GL_LINE_STRIP); for ( i = 0 ; i < 4 ; i++ ) glVertex3fv(&pts[i][0]); glEnd(); glPointSize(5.0); glBegin(GL_POINTS); for ( i = 0 ; i < 4 ; i++ ) { glColor4fv((i == pt) ? couleurRouge() : couleurJaune()); glVertex3fv(&pts[i][0]); } glEnd(); glPointSize(3.0); matrice *m; switch (aff) { case 0 : m = &m1; break; case 1 : m = &m2; break; case 2 : m = &m3; break; } if ( ( mode == 0 ) || ( mode == 2 ) ) { glColor4fv(couleurCyan()); glBegin(GL_LINE_STRIP); lisse(pl.p,disc,*m); glEnd(); } if ( ( mode == 1 ) || ( mode == 2 ) ) { glColor4fv(couleurMagenta()); glBegin(GL_POINTS); lisse(pl.p,disc,*m); glEnd(); } if ( ttan ) { tangente(pl.p,disc,*m,np); } else for ( i = 0 ; i < disc ; i++ ) tangente(pl.p,disc,*m,i); glDisable(GL_DEPTH_TEST); for ( i = 0 ; i < 4 ; i++ ) { glColor4fv((i == pt) ? couleurRouge() : couleurJaune()); placeFontCursor(pts[i][0]+0.3F,pts[i][1]+0.3F,pts[i][2]+0.3F); simpleBitmapOutput("%d",i); } glPopMatrix(); glPushMatrix(); glColor4fv(couleurBlanc()); placeFontCursor(getXmin()+0.3F,getYmin()+0.6F,0.0F); switch (aff) { case 0 : simpleBitmapOutput("%s","NRUBS"); break; case 1 : simpleBitmapOutput("%s","Catmull Rom"); break; case 2 : simpleBitmapOutput("%s","Bezier"); break; } glPopMatrix(); glFlush(); glutSwapBuffers(); } void init(void) { glClearColor(0.0,0.0,0.0,1.0); glDepthFunc(GL_LESS); GLfloat shinines[] = { 50.0 }; GLfloat l_pos0[] = { -1.0,1.0,1.0,0.0 }; GLfloat l_pos1[] = { 1.0,1.0,1.0,0.0 }; glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurVert()); glMaterialfv(GL_FRONT,GL_SPECULAR,couleurBlanc()); glMaterialfv(GL_FRONT,GL_SHININESS,shinines); glLightfv(GL_LIGHT0,GL_POSITION,l_pos0); glLightfv(GL_LIGHT0,GL_POSITION,l_pos1); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_NORMALIZE); } void special(int k, int x, int y) { switch (k) { case GLUT_KEY_LEFT : pts[pt][0] -= 0.1F; glutPostRedisplay(); break; case GLUT_KEY_RIGHT : pts[pt][0] += 0.1F; glutPostRedisplay(); break; case GLUT_KEY_UP : pts[pt][1] += 0.1F; glutPostRedisplay(); break; case GLUT_KEY_DOWN : pts[pt][1] -= 0.1F; glutPostRedisplay(); break; case GLUT_KEY_PAGE_UP : pts[pt][2] += 0.1F; glutPostRedisplay(); break; case GLUT_KEY_PAGE_DOWN : pts[pt][2] += 0.1F; glutPostRedisplay(); break; } } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else switch ( key ) { case 43 : disc++; glutPostRedisplay(); break; case 45 : disc--; if ( disc < 3 ) disc = 3; np = np%disc; glutPostRedisplay(); break; case 0x0D : aff = (aff+1)%3; glutPostRedisplay(); break; case 'p' : np = (np+1)%disc; glutPostRedisplay(); break; case 'P' : np = np-1; if ( np < 3 ) np = 3; glutPostRedisplay(); break; case 'm' : mode = (mode+1)%3; glutPostRedisplay(); break; case 't' : ttan = (ttan+1)%2; np = 0; glutPostRedisplay(); break; case 32 : pt = (pt+1)%4; glutPostRedisplay(); break; } } void select1(int selection) { switch (selection) { case 1 : aff = 0; glutPostRedisplay(); break; case 2 : aff = 1; glutPostRedisplay(); break; case 3 : aff = 2; glutPostRedisplay(); break; } } void select2(int selection) { switch (selection) { case 4 : pt = (pt+1)%4; glutPostRedisplay(); break; case 5 : mode = 0; glutPostRedisplay(); break; case 6 : mode = 1; glutPostRedisplay(); break; case 7 : mode = 2; glutPostRedisplay(); break; case 8 : ttan = 1; glutPostRedisplay(); break; case 9 : ttan = 0; np = 0; glutPostRedisplay(); break; } } void select3(int selection) { switch (selection) { case 10 : disc = 3; np = np%disc; glutPostRedisplay(); break; case 11 : disc = 10; np = np%disc; glutPostRedisplay(); break; case 12 : disc = 30; np = np%disc; glutPostRedisplay(); break; case 13 : disc = 50; np = np%disc; glutPostRedisplay(); break; case 14 : disc = 100; np = np%disc; glutPostRedisplay(); break; case 6 : disc++; glutPostRedisplay(); break; case 7 : disc--; if ( disc < 3 ) disc = 3; np = np%disc; glutPostRedisplay(); break; } } void select(int selection) { switch (selection) { case 0 : exit(0); } } void creationMenu(void) { int menu1 = glutCreateMenu(select1); glutAddMenuEntry("NRUBS",1); glutAddMenuEntry("Catmull Rom",2); glutAddMenuEntry("Bezier",3); int menu2 = glutCreateMenu(select2); glutAddMenuEntry("Changer point",4); glutAddMenuEntry("Fil de fer",5); glutAddMenuEntry("Points",6); glutAddMenuEntry("Fil de fer et points",7); glutAddMenuEntry("Une tangente",8); glutAddMenuEntry("Toutes les tangentes",9); int menu3 = glutCreateMenu(select3); glutAddMenuEntry("3",10); glutAddMenuEntry("10",11); glutAddMenuEntry("30",12); glutAddMenuEntry("50",13); glutAddMenuEntry("100",14); glutAddMenuEntry("Augmenter",6); glutAddMenuEntry("Reduire",7); glutCreateMenu(select); glutAddSubMenu("Matrice",menu1); glutAddSubMenu("Affichage",menu2); glutAddSubMenu("Discretisation",menu3); glutAddMenuEntry("Quitter",0); glutAttachMenu(GLUT_RIGHT_BUTTON); } int main(int argc,char **argv) { pl.n = 4; pl.p =(coord_3D *) &pts[0][0]; glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(300,300); glutInitWindowPosition(50,50); glutCreateWindow("Courbe B-Spline avec tangentes"); init(); creationMenu(); setParametresOrthoBasique(-5.0,5.0,-5.0,5.0,-500.0,500.0); setManipulateurDistance(1.0F); glutReshapeFunc(reshapeOrthoBasique); glutKeyboardFunc(key); glutSpecialFunc(special); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutDisplayFunc(display); glutMainLoop(); return(0); }