/* Auteur: Nicolas JANEY */ /* Avril 2001 */ /* Illustration de l'animation */ /* en OpenGL */ #include "windows.h" #include #include #include #include #include struct boule { float x ; float y ; float dx ; float dy ; float couleur[4] ; } ; #define N 10 static boule boules[N] = { { -50.0F, 10.0F,-0.4F,0.8F,{1.0F,0.0F,0.0F,1.0F} }, { 20.0F, 0.0F,-1.0F,-0.3F,{0.0F,0.0F,1.0F,1.0F} }, { -130.0F,-120.0F,0.23F,-1.57F,{0.0F,1.0F,0.0F,1.0F} }, { 115.0F, 60.0F,-0.73F,0.77F,{1.0F,1.0F,1.0F,1.0F} }, { -125.0F, 100.0F,-1.53F,-0.27F,{0.0F,1.0F,1.0F,1.0F} }, { 120.0F, 120.0F,1.53F,-0.33F,{1.0F,0.0F,1.0F,1.0F} }, { 80.0F, -20.0F,-0.23F,1.47F,{1.0F,1.0F,0.0F,1.0F} }, { -90.0F, -90.0F,-0.56F,0.97F,{0.5F,1.0F,1.0F,1.0F} }, { 110.0F, -70.0F,0.59F,1.67F,{1.0F,0.5F,1.0F,1.0F} }, { -90.0F, -34.0F,0.52F,-1.07F,{1.0F,1.0F,0.5F,1.0F} } } ; static int w = 0 ; static int h = 0 ; void myinit(void) { GLfloat light_ambient[] = { 0.0F,0.0F,0.0F,1.0F }; GLfloat light_diffuse[] = { 1.0F,1.0F,1.0F,1.0F }; GLfloat light_specular[] = { 1.0F,1.0F,1.0F,1.0F }; GLfloat light_position[] = { 1.0F,1.0F,1.0F,0.0F }; glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); glLightfv(GL_LIGHT0,GL_POSITION,light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } void afficheBoule(struct boule *b) { glPushMatrix(); glMaterialfv(GL_FRONT,GL_DIFFUSE,b->couleur) ; glTranslatef(b->x,b->y,0.0F); auxSolidSphere(10.0); glPopMatrix(); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for ( int i = 0 ; i < N ; i++ ) afficheBoule(&boules[i]); glFlush(); auxSwapBuffers(); } void adapteBoule(struct boule *b,int w,int h) { if ( b->x < -w/2+10 ) { b->x = -w/2+11.0F ; } if ( b->y < -h/2+10 ) { b->y = -h/2+11.0F ; } if ( b->x >= w/2-10 ) { b->x = w/2-11.0F ; } if ( b->y >= h/2-10 ) { b->y = h/2-11.0F ; } } void CALLBACK myReshape(int ww,int hh) { w = ww ; h = hh ; glViewport(0,0,ww,hh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-w/2,w/2,-h/2,h/2,-10.0,10.0); glMatrixMode(GL_MODELVIEW); for ( int i = 0 ; i < N ; i++ ) adapteBoule(&boules[i],w,h); } void interioriseBoule(struct boule *b,int w,int h) { if ( b->x < -w/2+10 ) { b->dx = -b->dx ; } if ( b->y < -h/2+10 ) { b->dy = -b->dy ; } if ( b->x >= w/2-10 ) { b->dx = -b->dx ; } if ( b->y >= h/2-10 ) { b->dy = -b->dy ; } adapteBoule(b,w,h) ; } void bougeBoule(struct boule *b,int w,int h) { b->x += b->dx ; b->y += b->dy ; interioriseBoule(b,w,h) ; } float produitScalaire(float ix,float iy,float nx,float ny) { return(ix*nx+iy*ny) ; } float norme(float x,float y) { return((float) sqrt(x*x+y*y)) ; } void normalise(float *x,float *y) { float n = norme(*x,*y); *x /= n ; *y /= n ; } float distance(struct boule *b1,struct boule *b2) { float dx = b1->x - b2->x ; float dy = b1->y - b2->y ; return((float) sqrt(dx*dx+dy*dy)) ; } float distance(struct boule *b,int i,int j) { float dx = b[i].x - b[j].x ; float dy = b[i].y - b[j].y ; return((float) sqrt(dx*dx+dy*dy)) ; } int rapprochement(struct boule *b,int i,int j) { float d = distance(b,i,j) ; boule bb = b[i] ; bb.x += b[i].dx ; bb.y += b[i].dy ; float di = distance(&bb,&b[j]) ; bb = b[j] ; bb.x += b[j].dx ; bb.y += b[j].dy ; float dj = distance(&bb,&b[i]) ; if ( di > d ) return(1) ; if ( dj > d ) return(2) ; return (0) ; } void rebond(boule *b,float px,float py) { float ix = -b->dx ; float iy = -b->dy ; float d = norme(ix,iy) ; float nx = b->x - px ; float ny = b->y - py ; normalise(&ix,&iy) ; normalise(&nx,&ny) ; float s = produitScalaire(ix,iy,nx,ny) ; float rx = (2*nx*s-ix)*d ; float ry = (2*ny*s-iy)*d ; b->dx = rx ; b->dy = ry ; } void rebond2(boule *b,float px,float py) { float ix = -b->dx ; float iy = -b->dy ; float d = norme(ix,iy) ; float nx = b->x - px ; float ny = b->y - py ; normalise(&ix,&iy) ; normalise(&nx,&ny) ; float s = produitScalaire(ix,iy,nx,ny) ; float rx = (2*nx*s-ix)*d ; float ry = (2*ny*s-iy)*d ; b->dx = rx ; b->dy = ry ; } void CALLBACK idle(void) { for ( int i = 0 ; i < N ; i++ ) { boule aux = boules[i] ; bougeBoule(&boules[i],w,h); for ( int j = 0 ; j < N ; j++ ) if ( i != j ) { if ( distance(boules,i,j) < 20 ) { boules[i] = aux ; float px = (boules[i].x+boules[j].x)/2.0F ; float py = (boules[i].y+boules[j].y)/2.0F ; int c = rapprochement(boules,i,j) ; if ( !c ) { rebond(&boules[i],px,py) ; rebond(&boules[j],px,py) ; } else { switch ( c ) { case 1 : rebond2(&boules[j],px,py) ; rebond(&boules[i],px,py) ; break ; case 2 : rebond(&boules[j],px,py) ; rebond2(&boules[i],px,py) ; break ; } } } } } display() ; } void main(void) { auxInitDisplayMode(AUX_DOUBLE|AUX_RGB|AUX_DEPTH); auxInitPosition(0,0,300,300); auxInitWindow("10 sphères s'entrechoquant"); myinit(); auxIdleFunc(idle); auxReshapeFunc(myReshape); auxMainLoop(display); }