/* 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 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 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;
}
/* 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
/* 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
/* 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];
}
/* 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
/* 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) {
}
/* 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
/* 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);
}