Le source: BoulesRebondissantes.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Avril 2001 */
/* Illustration de l'animation */
/* en OpenGL */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "ModuleCouleurs.h"
#include "ModuleMenus.h"
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_position[] = { 1.0F,1.0F,1.0F,0.0F };
glLightfv(GL_LIGHT0,GL_AMBIENT,couleurNoir());
glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc());
glLightfv(GL_LIGHT0,GL_SPECULAR,couleurBlanc());
glLightfv(GL_LIGHT0,GL_POSITION,light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glNewList(1,GL_COMPILE);
glutSolidSphere(10.0,16,16);
glEndList();
}
void afficheBoule(struct boule *b) {
glPushMatrix();
glMaterialfv(GL_FRONT,GL_DIFFUSE,b->couleur) ;
glTranslatef(b->x,b->y,0.0F);
glCallList(1);
glPopMatrix();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for ( int i = 0 ; i < N ; i++ )
afficheBoule(&boules[i]);
glFlush();
glutSwapBuffers();
}
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 reshape(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 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 ; } } } } }
glutPostRedisplay() ;
}
void key(unsigned char key,int x,int y) {
switch ( key ) {
case '\033' : exit(0);
break ; }
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
glutInitWindowPosition(50,50);
glutInitWindowSize(300,300);
glutCreateWindow("10 sphères s'entrechoquant");
myinit();
creationMenuBasique();
glutIdleFunc(idle);
glutKeyboardFunc(key);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return(0);
}