#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#define LARGEUR 640
#define HAUTEUR 480
#define REFRESH_DELAY 20
#define MAX_PARTICLES 50000
//Prototypes des fontions
double myRand(double min, double max);
void dessinerScene();
int initParticles();
int dessinerParticules();
//Creation d'une structure pour stoker les donnees naicessaire aux particules
typedef struct particles
{ bool active; // Active (1=Oui/0=Non)
double life; // Durée de vie
double fade; // Vitesse de disparition
double r, g, b; // Valeurs RGB pour la couleur
double x, y, z; // Position
double xi, yi, zi; // Vecteur de déplacement
double xg, yg, zg; // Gravité
};
//Tableau de stockage des particules
particles particle[MAX_PARTICLES];
//Bolean pour initialiser les particules
int particleStarted = 0;
int particleReset = 0;
int main(int argc, char *argv[])
{ SDL_Surface *ecran = NULL;
SDL_Event event;
int continuer = 1;
int previousTime = SDL_GetTicks();
int elapsedTime = 0;
int lastTime = SDL_GetTicks();
//On initialise le tout 
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetCaption("Particle Engine", NULL);
ecran = SDL_SetVideoMode(LARGEUR, HAUTEUR, 32, SDL_OPENGL);
// Initialisation du mode 3D
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70,(float)LARGEUR/HAUTEUR,1,1000);
glEnable(GL_DEPTH_TEST); /* Initialisation du Z-Buffer */
glEnable(GL_BLEND); // Autoriser la transparence
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Type de transparence
//On netoy l'ecran
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFlush();
SDL_GL_SwapBuffers();
//On initialise nos petites particules
initParticles();
while (continuer)
{ SDL_PollEvent(&event);
switch(event.type)
{ case SDL_QUIT:
continuer = 0;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{ case SDLK_SPACE:
particleStarted = 1;
break;
case SDLK_r:
particleReset = 1;
break;
default:break;
}
break;
}
//On dessine la scene
dessinerScene();
//On regle le fremate
elapsedTime = SDL_GetTicks() - previousTime;
if (elapsedTime < REFRESH_DELAY)
{
SDL_Delay(REFRESH_DELAY - elapsedTime);
}
previousTime = SDL_GetTicks();
}
SDL_Quit();
return EXIT_SUCCESS;
}
//Fontion qui renvoi un nombre alléatoire
double myRand(double min, double max)
{ return (double) (min + ((float) rand() / RAND_MAX * (max - min + 1.0)));
}
void dessinerScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//On regle la cam
gluLookAt(2,2,0, 0,0,0, 0,0,1);
//On affiche nos particules si l'utilisateur a apuié sur espace
if(particleStarted)
dessinerParticules();
//On reset les particules si l'utilisateur appui sur r
if(particleReset)
initParticles();
//On met a jour l'ecran
glFlush();
SDL_GL_SwapBuffers();
}
int initParticles()
{ for(int i=0; i<MAX_PARTICLES; i++) //On parcourt toutes les particules
{ particle[i].active = 1; //on active la particule
particle[i].life = 1.0; //On lui donne de la vie
particle[i].fade = myRand(0.005,0.01); // Vitesse de disparition
//On lui met une couleur
particle[i].r=myRand(0.7,1.0);
particle[i].g=myRand(0.6,1.0);
particle[i].b= myRand(0.0,0.0);
//On leur donne une vitesse
particle[i].xi = myRand(-100.0,100.0);
particle[i].yi = myRand(-100.0,100.0);
particle[i].zi = myRand(-100.0,100.0);
//On ajoute de la gravité
particle[i].xg = 0.0;
particle[i].yg = 0.0;
particle[i].zg = -2.0;
//On leur met une position de départ
particle[i].x = 0;
particle[i].y = 0;
particle[i].z = 0;
}
//On reset les particules
particleReset = 0;
return 0;
}
int dessinerParticules()
{ for(int i=0; i<MAX_PARTICLES; i++)
{ if(particle[i].active) //Si elle est active
{
//On récupère sa position
float x = particle[i].x;
float y = particle[i].y;
float z = particle[i].z;
// Couleur de la particule; transparence = vie
glColor4d(particle[i].r, particle[i].g, particle[i].b, particle[i].life);
// Dessin de carrés à partir de deux triangles (plus rapide pour la carte video)
glBegin(GL_TRIANGLE_STRIP);
glVertex3d(x+0.015,y,z+0.015); // Nord-Ouest
glVertex3d(x-0.015,y,z+0.015); // Nord-Est
glVertex3d(x+0.015,y,z-0.015); // Sud-Ouest
glVertex3d(x-0.015,y,z-0.015); // Sud-Est
glEnd();
//On fait bouger les particules
particle[i].x += particle[i].xi/1000;
particle[i].y += particle[i].yi/1000;
particle[i].z += particle[i].zi/1000;
//on aplique la gravitée
particle[i].xi += particle[i].xg;
particle[i].yi += particle[i].yg;
particle[i].zi += particle[i].zg;
//On fait veillir la particule
particle[i].life -= particle[i].fade;
}
}
return 0;
}