/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Decembre 2004 */ /* Calcul d'une courbe parametrique cubique */ /* avec affichage de sa tangente */ #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,y,z,t ; } ; struct polygone { int n ; coord_3D *p ; } ; typedef float vecteur[4] ; typedef float matrice[4][4] ; static int f1; static int f2; static coord_3D pts[4] = { { 0.8F,-1.5F,-1.5F,1.0F}, { 1.0F, 1.3F,-0.8F,1.0F}, { -1.3F, 0.0F, 0.5F,1.0F}, { -1.0F,-1.6F, 1.0F,1.0F} }; static int aff = 2 ; static int pt = 0 ; static int mode = 0 ; static int ttan = 1 ; static float t = 0.5F ; static int disc = 30 ; static polygone pl = { 4,pts } ; static coord_3D pnt; static coord_3D tgt; 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 pixel(coord_3D *pt) { glVertex3fv((float *) pt); } void pixelIndividuel(coord_3D *pt,coord_3D *tg) { glBegin(GL_POINTS); glVertex3fv((float *) pt); glEnd(); glPushMatrix(); glTranslatef(pt->x,pt->y,pt->z); glEnable(GL_LIGHTING); flecheEnVolume(tg->x,tg->y,tg->z,0.04F,0.3F,0.01F) ; glDisable(GL_LIGHTING); glPopMatrix(); } float produitVecteurVecteur(vecteur v1,vecteur v2) { float r = 0 ; for ( int i = 0 ; i < 4 ; i++ ) r += v1[i]*v2[i]; return(r) ; } void produitVecteurMatrice(vecteur v,matrice m,vecteur r) { vecteur vt; int i; for ( i = 0 ; i < 4 ; i++ ) { vt[i] = 0 ; for ( int j = 0 ; j < 4 ; j++ ) vt[i] += v[j]*m[j][i]; } for ( i = 0 ; i < 4 ; i++ ) { r[i] = vt[i]; } } void calcul(float *tt,matrice m,coord_3D *p,coord_3D *pt) { vecteur vx ; vecteur vy ; vecteur vz ; for ( int i = 0 ; i < 4 ; i++ ) { vx[i] = p[i].x ; vy[i] = p[i].y ; vz[i] = p[i].z ; } produitVecteurMatrice(tt,m,tt) ; pt->x = produitVecteurVecteur(tt,vx) ; pt->y = produitVecteurVecteur(tt,vy) ; pt->z = produitVecteurVecteur(tt,vz) ; } void lisse(coord_3D *p,int n,matrice m) { float tt[4] ; coord_3D pt ; 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,&pt); pixel(&pt) ; } } void normalize(struct coord_3D *n) { float d =(float) sqrt(n->x*n->x+n->y*n->y+n->z*n->z); if ( d != 0.0F) { n->x /= d; n->y /= d; n->z /= d;} } void tangente(coord_3D *p,matrice m,float t) { float tt[4] ; tt[0] = t*t*t ; tt[1] = t*t ; tt[2] = t ; tt[3] = 1.0F ; calcul(tt,m,p,&pnt); tt[0] = 3*t*t ; tt[1] = 2*t ; tt[2] = 1.0F ; tt[3] = 0.0F ; calcul(tt,m,p,&tgt); normalize(&tgt); pixelIndividuel(&pnt,&tgt) ; } 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((float *) &pts[i]); glEnd(); glPointSize(5.0); glBegin(GL_POINTS); for ( i = 0 ; i < 4 ; i++ ) { glColor4fv((i == pt) ? couleurRouge() : couleurJaune()); glVertex3fv((float *) &pts[i]); } 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,*m,t) ; } else for ( i = 0 ; i < disc ; i++ ) { float t =(float) i/(disc-1); tangente(pl.p,*m,t) ; } glDisable(GL_DEPTH_TEST); for ( i = 0 ; i < 4 ; i++ ) { glColor4fv((i == pt) ? couleurRouge() : couleurJaune()); placeFontCursor(pts[i].x+0.1F,pts[i].y+0.1F,pts[i].z+0.1F); simpleBitmapOutput("%d",i); } glPopMatrix(); glFlush(); glutSwapBuffers(); glutPostWindowRedisplay(f2); } void myinit(void) { glClearColor(0.0,0.0,0.0,1.0); glMap1f(GL_MAP1_VERTEX_3,0.0,1.0,3,6,(float *) &pts[0]); glEnable(GL_MAP1_VERTEX_3); glShadeModel(GL_FLAT); 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_AUTO_NORMAL); glEnable(GL_NORMALIZE); } void redisplay(void) { glutPostWindowRedisplay(f1); } void special(int k, int x, int y) { switch (k) { case GLUT_KEY_LEFT : pts[pt].x -= 0.1F; redisplay(); break; case GLUT_KEY_RIGHT : pts[pt].x += 0.1F; redisplay(); break; case GLUT_KEY_UP : pts[pt].y += 0.1F; redisplay(); break; case GLUT_KEY_DOWN : pts[pt].y -= 0.1F; redisplay(); break; case GLUT_KEY_PAGE_UP : pts[pt].z += 0.1F; redisplay(); break; case GLUT_KEY_PAGE_DOWN : pts[pt].z += 0.1F; redisplay(); break; } } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else switch ( key ) { case 43 : disc++ ; redisplay(); break; case 45 : disc-- ; if ( disc < 3 ) disc = 3 ; redisplay(); break; case 0x0D : aff = (aff+1)%3 ; redisplay(); break; case 't' : t += 0.01F ; if ( t > 1.0F ) t = 1.0F; redisplay(); break; case 'T' : t -= 0.01F ; if ( t < 0.0F ) t = 0.0F; redisplay(); break; case 'm' : mode = (mode+1)%3 ; redisplay(); break; case 'a' : ttan = !ttan ; redisplay(); break; case ' ' : pt = (pt+1)%4 ; redisplay(); break; } } void select1(int selection) { switch (selection) { case 1 : aff = 0; redisplay(); break; case 2 : aff = 1; redisplay(); break; case 3 : aff = 2; redisplay(); break; } } void select2(int selection) { switch (selection) { case 4 : pt = (pt+1)%4; redisplay(); break; case 5 : mode = 0; redisplay(); break; case 6 : mode = 1; redisplay(); break; case 7 : mode = 2; redisplay(); break; case 8 : ttan = 1; redisplay(); break; case 9 : ttan = 0; redisplay(); break; } } void select3(int selection) { switch (selection) { case 10 : disc = 3; redisplay(); break; case 11 : disc = 10; redisplay(); break; case 12 : disc = 30; redisplay(); break; case 13 : disc = 50; redisplay(); break; case 14 : disc = 100; redisplay(); break; case 6 : disc++; redisplay(); break; case 7 : disc--; if ( disc < 3 ) disc = 3; redisplay(); 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); } void reshape2(int w,int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,w,-h,0,-1.0,1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void display2() { glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glClearColor(0.0F,0.0F,0.0F,1.0F) ; glPushMatrix(); glColor4fv(couleurBlanc()); float pos = 1.0F; placeFontCursor(5.0F,-pos*20.0F,0.0F) ; switch (aff) { case 0 : simpleBitmapOutput(1,REGULAR8x13,"NRUBS"); break; case 1 : simpleBitmapOutput(1,REGULAR8x13,"Catmull Rom"); break; case 2 : simpleBitmapOutput(1,REGULAR8x13,"Bezier"); break; } if ( ttan ) { pos += 1.0F; placeFontCursor(5.0F,-pos*20.0F,0.0F) ; simpleBitmapOutput(1,REGULAR8x13,"t :%7.3f",t) ; pos += 1.0F; placeFontCursor(5.0F,-pos*20.0F,0.0F) ; simpleBitmapOutput(1,REGULAR8x13,"Position :%7.3f%7.3f%7.3f",pnt.x,pnt.y,pnt.z) ; pos += 1.0F; placeFontCursor(5.0F,-pos*20.0F,0.0F) ; simpleBitmapOutput(1,REGULAR8x13,"Normale :%7.3f%7.3f%7.3f",tgt.x,tgt.y,tgt.z) ; } glPopMatrix(); glutSwapBuffers(); } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(250,250); glutInitWindowPosition(50,50); f1 = glutCreateWindow("Courbe cubique avec tangente"); myinit(); creationMenu(); setParametresOrthoBasique(-2.0,2.0,-2.0,2.0,-10.0,10.0); setManipulateurDistance(1.0F); glutReshapeFunc(reshapeOrthoBasique); glutKeyboardFunc(key); glutSpecialFunc(special); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutDisplayFunc(display); glutInitWindowSize(320,90); glutInitWindowPosition(60,330); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); f2 = glutCreateWindow("Valeurs"); creationMenuBasique(); glutDisplayFunc(display2); glutReshapeFunc(reshape2); glutKeyboardFunc(key); glutSpecialFunc(special); glutMainLoop(); return(0); }