L'exécutable

Le source: BoulesRebondissantes.cpp

#include "windows.h"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

#include <stdio.h>
#include <math.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_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);
}
 RETOUR