L'exécutable

Cascade-01.png (5688 octets) Cascade-02.png (9959 octets) Cascade-03.png (16090 octets)

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */
/*                                              */
/* Un programme OpenGL d'animation automatique  */
/* d'un ensemble de particules ponctuelles      */
/* modelisant une cascade                       */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

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

#include "Position3D.h"
#include "Direction3D.h"
#include "Particule.h"

static GLint win = 0;
static int program = 2;

static GLint cascadeArraySize = 25000;

static double inc = 0.02;
static double time = 0.0;

class Particule *particules; 

static void checkError(int line) {
  GLenum err = glGetError();
  if (err) {
    printf("GL Error %s (0x%x) at line %d\n",
           gluErrorString(err),(int) err,line); }
}

static void createCascade(GLint size) {
  particules = new Particule[cascadeArraySize]();
  for ( int i = 0 ; i < cascadeArraySize ; i++ ) {
    particules[i].init(i*15.0/cascadeArraySize);}
}

static void drawCascade(void) {
  glPointSize(1.0);
  glBegin(GL_POINTS);
  for ( int i = 0 ; i < cascadeArraySize ; i++ ) {
    if ( time >= particules[i].startIni ) {
      glVertex3dv((double *) &(particules[i].p)); } }
  glEnd();
  static int img = 0;
  printf("%8.2lf : %5d\n",time,img);
  img++;
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */

void reshape(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0F,(float) x/y,15.0,5000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(10.0,-20.0,50.0,10.0,-20.0,0.0,0.0,1.0,0.0);
}

static void display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  drawCascade();
  glTranslatef(0.0F,-20.0F,0.0F);
  glPopMatrix();
  glFlush();
  checkError(__LINE__);
  glutSwapBuffers();
}

static void cleanUp(void) {
  delete [] particules;
}

static void idle(void) {
  time += inc;
  for ( int i = 0 ; i < cascadeArraySize ; i++ ) {
    particules[i].update(time); }
  glutPostRedisplay();
}

/* Fonction executee lors de l'appui            */
/* d'une touche alphanumerique du clavier       */

void key(unsigned char key,int x,int y) {
  static int anim = 1;
  switch ( key ) {
    case 0x0D : anim = !anim;
                glutIdleFunc(anim ? idle : NULL);
                break;
    case 43   : time += inc;
                for ( int i = 0 ; i < cascadeArraySize ; i++ ) {
                  particules[i].update(time); }
                glutPostRedisplay();
                break;
    case 45   : time -= inc;
                if ( time < 0.0F )
                  time = 0.0F;
                for ( int i = 0 ; i < cascadeArraySize ; i++ ) {
                  particules[i].update(time); }
                glutPostRedisplay();
                break;
    case 0x1B : cleanUp();
                exit(0);
                break; }
}

static void init(void) {
  createCascade(cascadeArraySize);
  glClearColor(0.4F,0.4F,0.8F,0.0F);
  glEnable(GL_DEPTH_TEST);
  glColor3f(1.0F,1.0F,1.0F);
}

int main(int argc, char *argv[]) {
  glutInit(&argc,argv);
  glutInitWindowPosition(10,10);
  glutInitWindowSize(240,480);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  win = glutCreateWindow(argv[0]);
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutDisplayFunc(display);
  glutIdleFunc(idle);
  init();
  glutMainLoop();
  return(0);
}

Particule.h

/* Particule de systeme de particules           */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#ifndef ____PARTICULE____
#define ____PARTICULE____

#include "Position3D.h"
#include "Direction3D.h"

class Particule {

  public :
    double startIni;
    double start;
    double ax,bx;
    double ay,by,cy;
    double az,bz;
    Position3D p;
    Direction3D d;
    double v;
    double nextEvent;
    int rebond;

  public :
    Particule(void);
    ~Particule(void);
    void init(double t);
    void update(double pt);
    double getNextEvent(double y);
};

#endif

Particule.cpp

/* Particule de systeme de particules           */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "Position3D.h"
#include "Direction3D.h"
#include "Particule.h"

static float random(void) {
  return(((float) rand()/RAND_MAX));
}

Particule::Particule(void) {
}

Particule::~Particule(void) {
}

double Particule::getNextEvent(double y) {
  double nextEvent = 1000000.0;
  double delta = by*by+-4.0*ay*(cy-y);
  double r = (-by-sqrt(delta))/2.0/ay;
  if ( r > 0.0 )
    nextEvent = r+start;
    else {
    r = (-ay+sqrt(delta))/2.0/ay;
    if ( r > 0.0 )
      nextEvent = r+start; }
  return(nextEvent);
}

void Particule::init(double time) {
  rebond = 0;
  start = startIni = time;
  ax = 2.0*random()+1.0;
  bx = random();
  ay = -5.0;
  by = 0.0;
  cy = 2.0*random();
  az = 2.0*random()+1.0;
  bz = random();
  nextEvent = getNextEvent(-(20.0+2*random()));
  update(time);
}

void Particule::update(double time) {
  if ( time > nextEvent ) {
    rebond++;
    double t = nextEvent-start;
    Position3D pr;
    pr.c[0] = ax*t+bx;
    pr.c[1] = ay*t*t+cy;
    pr.c[2] = az*t+bz;
    Direction3D dr;
    dr.c[0] = ax;
    dr.c[1] = 2.0*ay;
    dr.c[2] = az;
    ax = dr.c[0];
    ay = -5.0;
    az = dr.c[2];
    t = dr.c[1]/((3.0+3.0*random())*ay);
    by = 0.0;
    bx = pr.c[0]+ax*t;
    cy = pr.c[1]-ay*t*t;
    bz = pr.c[2]+az*t;
    start = nextEvent+t;
    nextEvent = getNextEvent(-20.0-rebond*(10.0+random())); }
  double t = time-startIni;
  if ( t > 10.0 )
    init(time);
  t = time-start;
  p.c[0] = ax*t+bx;
  p.c[1] = ay*t*t+cy;
  p.c[2] = az*t+bz;
  d.c[0] = ax;
  d.c[1] = 2.0*ay;
  d.c[2] = az;
  v = sqrt(d.c[0]*d.c[0]+d.c[1]*d.c[1]+d.c[2]*d.c[2]);
  d.c[0] /= v;
  d.c[1] /= v;
  d.c[2] /= v;
}

TransformationGeometrique.h

/* Mathematiques de l'informatique graphique    */
/* Transformation geometrique 3D                */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#ifndef ____TRANSFORMATIONGEOMETRIQUE____
#define ____TRANSFORMATIONGEOMETRIQUE____

class CoordonneesHomogenes;

class TransformationGeometrique  {

  public :
    double c[4][4];

  public :
    TransformationGeometrique(void);
    TransformationGeometrique(double *t);
    TransformationGeometrique(double **t);
    ~TransformationGeometrique(void);
    void print(void);
    void produit(TransformationGeometrique *t1,TransformationGeometrique *t2);
    void transforme(CoordonneesHomogenes *ch);
};

#endif

CoordonneesHomogenes.h

/* Mathematiques de l'informatique graphique    */
/* Coordonnees homogenes en 3D                  */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#ifndef ____COORDONNEESHOMOGENES____
#define ____COORDONNEESHOMOGENES____

class TransformationGeometrique;

class CoordonneesHomogenes  {

  public :
    double c[4];

  public :
    CoordonneesHomogenes(void);
    CoordonneesHomogenes(double x,double y,double z,double t);
    CoordonneesHomogenes(CoordonneesHomogenes *c);
    ~CoordonneesHomogenes(void);
    void print(void);
    void transforme(TransformationGeometrique *t);
};

#endif

CoordonneesHomogenes.cpp

/* Mathematiques de l'informatique graphique    */
/* Coordonnees homogenes en 3D                  */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "CoordonneesHomogenes.h"
#include "TransformationGeometrique.h"

CoordonneesHomogenes::CoordonneesHomogenes(void) {
  c[0] = c[1] = c[2] = 0.0;
  c[3] = 1.0;
}

CoordonneesHomogenes::CoordonneesHomogenes(double x,double y, double z,double t) {
  c[0] = x;
  c[1] = y;
  c[2] = z;
  c[3] = t;
}

CoordonneesHomogenes::CoordonneesHomogenes(CoordonneesHomogenes *ch) {
  c[0] = ch->c[0];
  c[1] = ch->c[1];
  c[2] = ch->c[2];
  c[3] = ch->c[3];
}

CoordonneesHomogenes::~CoordonneesHomogenes(void) {
}

void CoordonneesHomogenes::print(void) {
  printf("%10.4lf %10.4lf %10.4lf %10.4lf",c[0],c[1],c[2],c[3]);
}

void CoordonneesHomogenes::transforme(TransformationGeometrique *t) {
  double c[4];
  for ( int i = 0 ; i < 4 ; i++ ) {
    c[i] = 0.0;
    for ( int j = 0 ; j < 4 ; j++ )
      c[i] += t->c[i][j] * this->c[j]; }
  for ( int i = 0 ; i < 4 ; i++ )
    this->c[i] = c[i];
}

Position3D.h

/* Mathematiques de l'informatique graphique    */
/* Position en 3D                               */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#ifndef ____POSITION3D____
#define ____POSITION3D____

#include "CoordonneesHomogenes.h"

class Position3D : public CoordonneesHomogenes {

  public :
    Position3D(void);
    Position3D(double x,double y,double z);
    Position3D(Position3D *c);
    ~Position3D(void);
};

#endif

Position3D.cpp

/* Mathematiques de l'informatique graphique    */
/* Position en 3D                               */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "CoordonneesHomogenes.h"
#include "Position3D.h"

Position3D::Position3D(void):CoordonneesHomogenes(0.0,0.0,0.0,1.0) {
}

Position3D::Position3D(double x,double y,double z):CoordonneesHomogenes(x,y,z,1.0) {
}

Position3D::Position3D(Position3D *p):CoordonneesHomogenes(p) {
}

Position3D::~Position3D(void) {
}

Direction3D.h

/* Mathematiques de l'informatique graphique    */
/* Direction en 3D                              */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#ifndef ____DIRECTION3D____
#define ____DIRECTION3D____

class Position3D;

#include "CoordonneesHomogenes.h"

class Direction3D : public CoordonneesHomogenes {

  public :
    Direction3D(void);
    Direction3D(double x,double y,double z);
    Direction3D(Direction3D *c);
    ~Direction3D(void);
    Direction3D::Direction3D(Position3D *p1,Position3D *p2);
    double normalise(void);
    void produitVectoriel(Direction3D *d1,Direction3D *d2);
    double produitScalaire(Direction3D *d);
    Direction3D *reflexion(Direction3D *n);
};

#endif

Direction3D.cpp

/* Mathematiques de l'informatique graphique    */
/* Direction en 3D                              */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2010                                 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "CoordonneesHomogenes.h"
#include "Direction3D.h"
#include "Position3D.h"

Direction3D::Direction3D(void):CoordonneesHomogenes(0.0,0.0,0.0,0.0) {
}

Direction3D::Direction3D(double x,double y,double z):CoordonneesHomogenes(x,y,z,0.0) {
}

Direction3D::Direction3D(Direction3D *p):CoordonneesHomogenes(p) {
}

Direction3D::Direction3D(Position3D *p1,Position3D *p2):CoordonneesHomogenes() {
  c[0] = p2->c[0]-p1->c[0];
  c[1] = p2->c[1]-p1->c[1];
  c[2] = p2->c[2]-p1->c[2];
  c[3] = 0.0;
}

Direction3D::~Direction3D(void) {
}

double Direction3D::normalise(void) {
  double d = sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]);
  if ( d != 0.0 ) {
    c[0] /= d;
    c[1] /= d;
    c[2] /= d; }
  return(d);
}

void Direction3D::produitVectoriel(Direction3D *d1,Direction3D *d2) {
  double x = d1->c[1]*d2->c[2] - d1->c[2]*d2->c[1];
  double y = d1->c[2]*d2->c[0] - d1->c[0]*d2->c[2];
  double z = d1->c[0]*d2->c[1] - d1->c[1]*d2->c[0];
  c[0] = x;
  c[1] = y;
  c[2] = z;
  c[3] = 0.0;
}

double Direction3D::produitScalaire(Direction3D *d) {
  return(c[0]*d->c[0]+c[1]*d->c[1]+c[2]*d->c[2]);
}

Direction3D *Direction3D::reflexion(Direction3D *n) {
  double ps = produitScalaire(n);
  if ( ps < 0.0 )
    return(NULL);
  Direction3D *r = new Direction3D();
  r->c[0] = 2.0*ps*n->c[0]-c[0];
  r->c[1] = 2.0*ps*n->c[1]-c[1];
  r->c[2] = 2.0*ps*n->c[2]-c[2];
  return(r);
}

RETOUR