[OpenGL/SDL] Explosion avec particules Difficulté : 35/100
Publié le 06/02/2008 à 12h 32min par Marco565



Une simulation d'une explosion a l'aide d'un generateur à particules




Cet exercices vous feras travailler sur la génération des particules et des différents paramètres a régler pour arriver a faire une explosion.


Requis
Une assez bonne maîtrise de OpenGl et un peu de SDL puis savoir comment fonctionne les particules

Aide
Plus la vitesse initiale des particules est importante, plus leur trajectoire ressembleras a une explosion

Correction
Avec le tuto sur le site du zero, rien de compliquer.


Code : c
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <SDL/SDL.h>
  5. #include <GL/gl.h>
  6. #include <GL/glu.h>
  7.  
  8.  
  9.  
  10. #define LARGEUR 640
  11. #define HAUTEUR 480
  12. #define REFRESH_DELAY 20
  13. #define MAX_PARTICLES 50000
  14.  
  15.  
  16. //Prototypes des fontions
  17. double myRand(double min, double max);
  18. void dessinerScene();
  19. int initParticles();
  20. int dessinerParticules();
  21.  
  22. //Creation d'une structure pour stoker les donnees naicessaire aux particules
  23. typedef struct particles
  24. { bool active; // Active (1=Oui/0=Non)
  25. double life; // Durée de vie
  26. double fade; // Vitesse de disparition
  27. double r, g, b; // Valeurs RGB pour la couleur
  28. double x, y, z; // Position
  29. double xi, yi, zi; // Vecteur de déplacement
  30. double xg, yg, zg; // Gravité
  31. };
  32.  
  33. //Tableau de stockage des particules
  34. particles particle[MAX_PARTICLES];
  35.  
  36. //Bolean pour initialiser les particules
  37. int particleStarted = 0;
  38. int particleReset = 0;
  39.  
  40.  
  41.  
  42.  
  43.  
  44. int main(int argc, char *argv[])
  45. { SDL_Surface *ecran = NULL;
  46. SDL_Event event;
  47. int continuer = 1;
  48. int previousTime = SDL_GetTicks();
  49. int elapsedTime = 0;
  50. int lastTime = SDL_GetTicks();
  51.  
  52. //On initialise le tout
  53. SDL_Init(SDL_INIT_VIDEO);
  54. SDL_WM_SetCaption("Particle Engine", NULL);
  55. ecran = SDL_SetVideoMode(LARGEUR, HAUTEUR, 32, SDL_OPENGL);
  56.  
  57. // Initialisation du mode 3D
  58. glMatrixMode(GL_PROJECTION);
  59. glLoadIdentity();
  60. gluPerspective(70,(float)LARGEUR/HAUTEUR,1,1000);
  61.  
  62. glEnable(GL_DEPTH_TEST); /* Initialisation du Z-Buffer */
  63. glEnable(GL_BLEND); // Autoriser la transparence
  64. glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Type de transparence
  65.  
  66.  
  67. //On netoy l'ecran
  68. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  69. glFlush();
  70. SDL_GL_SwapBuffers();
  71.  
  72. //On initialise nos petites particules
  73. initParticles();
  74.  
  75. while (continuer)
  76. { SDL_PollEvent(&event);
  77. switch(event.type)
  78. { case SDL_QUIT:
  79. continuer = 0;
  80. break;
  81. case SDL_KEYDOWN:
  82. switch(event.key.keysym.sym)
  83. { case SDLK_SPACE:
  84. particleStarted = 1;
  85. break;
  86. case SDLK_r:
  87. particleReset = 1;
  88. break;
  89. default:break;
  90. }
  91. break;
  92. }
  93.  
  94. //On dessine la scene
  95. dessinerScene();
  96.  
  97. //On regle le fremate
  98. elapsedTime = SDL_GetTicks() - previousTime;
  99. if (elapsedTime < REFRESH_DELAY)
  100. {
  101. SDL_Delay(REFRESH_DELAY - elapsedTime);
  102. }
  103. previousTime = SDL_GetTicks();
  104.  
  105.  
  106. }
  107.  
  108. SDL_Quit();
  109.  
  110. return EXIT_SUCCESS;
  111. }
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118. //Fontion qui renvoi un nombre alléatoire
  119. double myRand(double min, double max)
  120. { return (double) (min + ((float) rand() / RAND_MAX * (max - min + 1.0)));
  121. }
  122.  
  123. void dessinerScene()
  124. {
  125. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  126. glMatrixMode(GL_MODELVIEW);
  127. glLoadIdentity();
  128.  
  129. //On regle la cam
  130. gluLookAt(2,2,0, 0,0,0, 0,0,1);
  131.  
  132.  
  133. //On affiche nos particules si l'utilisateur a apuié sur espace
  134. if(particleStarted)
  135. dessinerParticules();
  136.  
  137. //On reset les particules si l'utilisateur appui sur r
  138. if(particleReset)
  139. initParticles();
  140.  
  141.  
  142. //On met a jour l'ecran
  143. glFlush();
  144. SDL_GL_SwapBuffers();
  145. }
  146.  
  147.  
  148. int initParticles()
  149. { for(int i=0; i<MAX_PARTICLES; i++) //On parcourt toutes les particules
  150. { particle[i].active = 1; //on active la particule
  151. particle[i].life = 1.0; //On lui donne de la vie
  152.  
  153. particle[i].fade = myRand(0.005,0.01); // Vitesse de disparition
  154.  
  155. //On lui met une couleur
  156. particle[i].r=myRand(0.7,1.0);
  157. particle[i].g=myRand(0.6,1.0);
  158. particle[i].b= myRand(0.0,0.0);
  159.  
  160. //On leur donne une vitesse
  161. particle[i].xi = myRand(-100.0,100.0);
  162. particle[i].yi = myRand(-100.0,100.0);
  163. particle[i].zi = myRand(-100.0,100.0);
  164.  
  165. //On ajoute de la gravité
  166. particle[i].xg = 0.0;
  167. particle[i].yg = 0.0;
  168. particle[i].zg = -2.0;
  169.  
  170. //On leur met une position de départ
  171. particle[i].x = 0;
  172. particle[i].y = 0;
  173. particle[i].z = 0;
  174. }
  175.  
  176. //On reset les particules
  177. particleReset = 0;
  178.  
  179. return 0;
  180. }
  181.  
  182. int dessinerParticules()
  183. { for(int i=0; i<MAX_PARTICLES; i++)
  184. { if(particle[i].active) //Si elle est active
  185. {
  186. //On récupère sa position
  187. float x = particle[i].x;
  188. float y = particle[i].y;
  189. float z = particle[i].z;
  190.  
  191. // Couleur de la particule; transparence = vie
  192. glColor4d(particle[i].r, particle[i].g, particle[i].b, particle[i].life);
  193.  
  194. // Dessin de carrés à partir de deux triangles (plus rapide pour la carte video)
  195. glBegin(GL_TRIANGLE_STRIP);
  196. glVertex3d(x+0.015,y,z+0.015); // Nord-Ouest
  197. glVertex3d(x-0.015,y,z+0.015); // Nord-Est
  198. glVertex3d(x+0.015,y,z-0.015); // Sud-Ouest
  199. glVertex3d(x-0.015,y,z-0.015); // Sud-Est
  200. glEnd();
  201.  
  202. //On fait bouger les particules
  203. particle[i].x += particle[i].xi/1000;
  204. particle[i].y += particle[i].yi/1000;
  205. particle[i].z += particle[i].zi/1000;
  206.  
  207. //on aplique la gravitée
  208. particle[i].xi += particle[i].xg;
  209. particle[i].yi += particle[i].yg;
  210. particle[i].zi += particle[i].zg;
  211.  
  212. //On fait veillir la particule
  213. particle[i].life -= particle[i].fade;
  214.  
  215.  
  216. }
  217. }
  218. return 0;
  219. }
  220.  
  221.