Aller au menu - Aller au contenu

Icône Systèmes de particules

Avatar
Mise à jour : 23/03/2011
Difficulté : Facile Facile Creative Commons BY-SA
1 621 visites depuis 7 jours, dont 32 sur ce chapitre classé 80/786
Les systèmes de particules sont un grand incontournable des scènes 3D. Principalement car ils sont un excellent moyen de représenter des phénomènes naturels courants; tels que la neige, le feu, la pluie, la fumée d'une trainée de roquette et l'explosion qui suit... :-°

Ce n'est malheureusement pas pour autant qu'ils sont simples à manipuler. Mais par chance nous allons voir dans ce chapitre qu'Irrlicht fait quasiment tout le boulot. Tout ce qu'il nous reste à faire est de bien comprendre comment pour arriver à en tirer le meilleur.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Comment ça marche ?

Avant de se lancer vaillamment dans l'étude de la documentation, puis du code qui en découle, il est important de revoir nos bases et de bien comprendre comment fonctionne un générateur de particules.

Ce qui suit est valable pour Irrlicht et pas forcément dans tous les cas où le code est orienté objet.


Par souci de simplicité et comme tout le moteur est codé comme ça, tout ce qui concerne un système de particules est regroupé dans la classe IParticleSystemSceneNode. C'est elle qui va regrouper et gérer toutes les composantes du système. Composantes que nous allons d'ailleurs énumérer :

Je n'ai pas mis la classe correspondante à coté de l'émetteur et du modificateur car il en existe plusieurs différentes.


Emetteur :


Son rôle est comme son nom l'indique, d'émettre des particules. C'est lui qui les génère. Et c'est donc lui qui détermine leurs paramètres à ce moment-là. Un système de particule ne peut gérer qu'un seul émetteur à la fois. En revanche, un même émetteur peut être utilisé pour deux systèmes différents.

Tous les émetteurs de particules d'Irrlicht permettent de contrôler les éléments suivants :
  • la propagation des particules (départ, direction)
  • le nombre de particules émises par seconde
  • la couleur des particules
  • la taille des particules
  • la durée de vie des particules

La propagation des particules est le seul critère qui varie d'un type d'émetteur à l'autre, comme nous le verrons plus tard en les passant tous en revue.



Modificateur :


Les modificateurs permettent d'agir sur les particules émises par un émetteur. En effet, sans modification celles-ci seraient bien mornes : pas de changement de couleur, de direction, etc... Contrairement à ce qu'on pourrait penser, un modificateur s'associe au scene node concernant le système de particules, pas à l'émetteur. On peut utiliser plusieurs modificateurs sur un seul système, mais on ne peut pas utiliser un seul modificateur sur plusieurs systèmes.



Pour résumer le tout : il va s'agir de créer un système de particules grâce au scene node approprié. Puis de choisir un type d'émetteur et de l'associer au système. Et enfin de créer un ou plusieurs modificateurs qui vont affecter les particules émises.

Le système global

Attardons-nous maintenant sur les paramètres modifiables de ces trois éléments et sur le code qui va avec. En commençant par le système global.

Nous avons déjà vu que la classe correspondante est IParticleSystemSceneNode

On peut en obtenir une instance à partir du scene manager :

Code : C++
1
irr::scene::IParticleSystemSceneNode* particleSystem = sceneManager->addParticleSystemSceneNode(false);


Le premier paramètre de la fonction est un booléen permettant de déterminer s'il y a un émetteur par défaut ou non. C'est uniquement utile à des fins de test ou de débogage étant donné qu'on ne peut pas le paramétrer. Il va néanmoins nous être utile tout de suite, pour vérifier que ça marche. :)

En incluant la ligne d'au-dessus dans un code de base :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <IRR/irrlicht.h>


int main(void)
{
    //Device, driver et graphe de scene.
    irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL,
        irr::core::dimension2d<irr::u32>(800,800),32,false,false,false);
    irr::video::IVideoDriver* driver = device->getVideoDriver ();
    irr::scene::ISceneManager *sceneManager = device->getSceneManager ();

     //On rend invisible le curseur.
    device->getCursorControl ()-> setVisible (false);

    //La camera
    irr::SKeyMap keyMap[5];
    keyMap[0].Action = irr::EKA_MOVE_FORWARD;
    keyMap[0].KeyCode = irr::KEY_KEY_Z;
    keyMap[1].Action = irr::EKA_MOVE_BACKWARD;
    keyMap[1].KeyCode = irr::KEY_KEY_S;
    keyMap[2].Action = irr::EKA_STRAFE_LEFT;
    keyMap[2].KeyCode = irr::KEY_KEY_Q;
    keyMap[3].Action = irr::EKA_STRAFE_RIGHT;
    keyMap[3].KeyCode = irr::KEY_KEY_D;
    keyMap[4].Action = irr::EKA_JUMP_UP;
    keyMap[4].KeyCode = irr::KEY_SPACE;
    irr::scene::ICameraSceneNode *camera;
    camera = sceneManager->addCameraSceneNodeFPS (0,100.0f,0.02f, -1, keyMap, 5, false, 0.4);
    camera->setPosition(irr::core::vector3df(0.0f, 0.0f, 0.0f));

    //La chaine pour le titre de la fenetre
    irr::core::vector3df posCam;
    wchar_t titre[100];


    irr::scene::IParticleSystemSceneNode* particleSystem = sceneManager->addParticleSystemSceneNode(true);


    //La boucle de rendu
    while (device->run())
    {
        posCam = camera->getPosition();
        swprintf(titre, 100, L"FPS : %d (mode debug) |  PosCam :  "
        "X : %f Y : %f Z : %f", driver->getFPS(), posCam.X, posCam.Y, posCam.Z);
        device->setWindowCaption(titre);
        //On utilise un fond blanc pour voir les particules
        driver->beginScene(true, true, irr::video::SColor(0,255,255,255));
        sceneManager->drawAll ();
        driver->endScene ();
    }

    device->drop();
    return 0;
}

Image utilisateur

Et vous devriez voir apparaître de gros carrés noirs bien moches sur un fond blanc (comme sur le screen à droite).

Mais le IParticleSystemSceneNode permet également de gérer d'autres choses (comme l'indique la page de documentation). Etant donné qu'il est dérivé de ISceneNode, il possède notamment un material. Pour ceux qui auraient oublié de quoi il s'agit; relisez le chapitre correspondant. ;)

Les émetteurs

Comme je le disais plus haut, il y a plusieurs types d'émetteur. En voici la liste :
  • IParticleBoxEmitter
  • IParticleCylinderEmitter
  • IParticleMeshEmitter
  • IParticlePointEmitter
  • IParticleRingEmitter
  • IParticleSphereEmitter

J'imagine que les noms sont suffisamment explicites. Néanmoins si vous voulez en savoir plus, la documentation est là pour ça.

Commençons par un facile, le IParticleBoxEmitter. Comme son nom l'indique, il va générer des particules à partir d'une boite. La position de cette boite étant relative à la position du noeud particle system, les coordonnées que nous allons renseigner aussi. 0 correspond donc à la position du noeud particle system.

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
camera->setPosition(irr::core::vector3df(60.0f, 60.0f, 0.0f));
camera->setTarget(irr::core::vector3df(0.0f, 20.0f, 0.0f));

irr::scene::IParticleSystemSceneNode* particleSystem =
    sceneManager->addParticleSystemSceneNode(false);

irr::scene::IParticleEmitter* emitter = particleSystem->createBoxEmitter(
    irr::core::aabbox3d<irr::f32>(-3,0,-3,3,1,3), // coordonnees de la boite
    irr::core::vector3df(0.0f,0.06f,0.0f),        // direction de diffusion
    80,100,                                       // nb particules emises a la sec min / max
    irr::video::SColor(0,0,0,0),                  // couleur la plus sombre
    irr::video::SColor(0,255,255,255),            // couleur la plus claire
    600, 1000,                                    // duree de vie min / max
    0,                                            // angle max d'ecart / direction prevue
    irr::core::dimension2df(6.0f,6.0f),           // taille minimum
    irr::core::dimension2df(8.0f,8.0f));          // taille maximum

particleSystem->setEmitter(emitter);                               // on attache l'emetteur
emitter->drop();                                                   // plus besoin de ca
particleSystem->setMaterialFlag(irr::video::EMF_LIGHTING, false); // insensible a la lumiere

Image utilisateur

Si tant est que vous codez sur un matériel un peu performant, vous devriez voir que ça va vite, très vite. C'est du au fait que nous n'avons pas imposé de limite de framerate. Comme il y a très peu de choses à calculer et à afficher, le nombre de FPS est très élevé. Vous remarquerez aussi qu'on a modifié le material du particle system pour le rendre insensible à la lumière. Ce qui est indispensable pour y voir quelque chose, sachant que la scène ne contient aucune source de lumière.

Poussons l'expérience un peu plus loin et tentons de reproduire un feu (pour être original) à l'aide du material du particle system. Avant tout, nous allons avoir besoin de la texture "fire.bmp", qui se trouve dans le dossier media du SDK. Ensuite, regardez le code qui suit et faites fonctionner vos méninges. :)

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
camera->setPosition(irr::core::vector3df(60.0f, 60.0f, 0.0f));
camera->setTarget(irr::core::vector3df(0.0f, 40.0f, 0.0f));

irr::scene::IParticleSystemSceneNode* particleSystem =
    sceneManager->addParticleSystemSceneNode(false);

irr::scene::IParticleEmitter* emitter = particleSystem->createBoxEmitter(
    irr::core::aabbox3d<irr::f32>(-6,0,-6,6,1,6), // coordonnees de la boite
    irr::core::vector3df(0.0f,0.06f,0.0f),        // direction de diffusion
    80,100,                                       // nb particules emises a la sec min / max
    irr::video::SColor(0,255,255,255),            // couleur la plus sombre
    irr::video::SColor(0,255,255,255),            // couleur la plus claire
    600, 1200,                                    // duree de vie min / max
    0,                                            // angle max d'ecart / direction prevue
    irr::core::dimension2df(8.0f,8.0f),           // taille minimum
    irr::core::dimension2df(14.0f,14.0f));        // taille maximum

particleSystem->setEmitter(emitter);              // on attache l'emetteur
emitter->drop();                                  // plus besoin de ca

particleSystem->setMaterialFlag(irr::video::EMF_LIGHTING, false);          // insensible a la lumiere
particleSystem->setMaterialFlag(irr::video::EMF_ZWRITE_ENABLE, false);     // desactive zbuffer pour surfaces derriere
particleSystem->setMaterialTexture(0, driver->getTexture("fire.bmp"));     // on colle une texture
particleSystem->setMaterialType(irr::video::EMT_TRANSPARENT_VERTEX_ALPHA); // application transparence


Image utilisateurImage utilisateurImage utilisateur

Les seules nouveautés sont les trois dernière lignes qui collent une texture sur chaque particule et activent la transparence. De fait, si vous compilez tout ça vous verrez apparaitre un joli feu (comme à droite), et pas un amas immonde de particules carrées. Faites le test de retirer la transparence pour voir la différence. ;)

L'ajout de texture est fondamental pour reproduire des phénomènes physiques naturels. A vrai dire les générateurs de particules sont (de manière générale) tellement souples et efficaces qu'ils permettent par exemple de générer une pelouse. Il suffit de ne pas re-générer les particules et de leur mettre une texture de brin d'herbe. Les possibilités sont énormes...

Les modificateurs

Notre feu a donc un aspect plutôt réaliste, mais quelques détails sont néanmoins gênants. Le fait que les particules ne baissent pas "d'intensité" par exemple. En effet, le haut des flammes produit théoriquement moins de lumière que le gros du brasier. Nous allons donc utiliser un modificateur qui change progressivement la couleur des particules. Mais avant cela, passons en revue les différents types de modificateur :
  • IParticleAttractionAffector
  • IParticleFadeOutAffector
  • IParticleGravityAffector
  • IParticleRotationAffector

Nous allons donc utiliser un IParticleFadeOutAffector qui va diminuer progressivement la couleur de la texture et la rendre ainsi transparente.

Code : C++
1
2
3
4
5
6
irr::scene::IParticleAffector* affector =    // creation du modificateur
    particleSystem->createFadeOutParticleAffector(
    irr::video::SColor(0,0,0,0),             // la couleur finale
    1200);                                   // temps necessaire a la modification
particleSystem->addAffector(affector);       // ajout du modificateur au particle system
affector->drop();                            // plus besoin de ca


Image utilisateurImage utilisateurImage utilisateur

Vous pouvez voir sur les screens à droite que les particules disparaissent maintenant progressivement, ce qui donne l'impression que les flammes sont plus fortes en bas du brasier qu'en haut (logique).

Les autres modificateurs sont peut être un peu plus spécialisés, IParticleRotationAffector par exemple propose un effet sympathique mais peu commun dans le monde réel. A l'inverse, certains modificateurs évidents ne sont pas présents dans le moteur. Le vent par exemple ne peut pas être simulé avec ceux listés au dessus. Quoi qu'il en soit ce n'est pas un problème très gênant puisqu'il est bien sûr possible de créer ses propres modificateurs et de les utiliser sans même avoir à recompiler le moteur. Magie de la POO. :magicien:



Exercice :


Quoi de mieux qu'un exercice pour s'assurer qu'on a tout compris ? Je vous propose donc de créer une petite scène représentant une chute de neige. Voici d'ailleurs quelques images de ce que j'ai fait pour vous donner une idée du rendu :

Image utilisateurImage utilisateurImage utilisateur


L'important ici sont les particules de neige. Inutile de faire un sol ou une interface si ça ne vous intéresse pas. Pour la texture des flocons, j'ai juste repris le fichier "fire.bmp" qu'on a déjà utilisé plus haut, auquel j'ai changé les couleurs. Pour comparer votre code avec le mien ou si vous êtes bloqués, vous pouvez

La gestion des particules par Irrlicht est suffisante pour créer de jolis effets et produire des scènes relativement réalistes, mais elle est tout de même assez rudimentaire dans l'absolu. Par exemple, il n'y a pas de gestion des particules en 3 dimensions. Alors que c'est incontournable pour reproduire certaines choses.

Aussi, le moteur montre assez rapidement ses limites par rapport au nombre de particules à gérer simultanément. En effet, si vous faites le test de prendre un générateur tout bête et d'augmenter la durée de vie des particules, ça va rapidement ramer.

Mais après tout, tous ces défauts n'en sont pas. Car il est tout à fait possible de modifier cette partie du moteur. Soit en l'améliorant, soit en la recodant totalement. "Il n'y a de limite que celle qu'on s'impose" comme dirait l'autre. ;)
Chapitre précédent Sommaire Chapitre suivant

Partager

7 commentaires pour "Systèmes de particules"
Note moyenne : 3.60 / 4 (122 votes)
Pseudo Commentaire
Hors ligne mogolecho # Posté le 16/09/2009 à 16:14:10
Encore une p'tite question...
Avatar

Ville : Strasbourg
Pays : France métropolitaine

Tu vas encore continuer d'ici.. bientôt ?
Ca devient franchement intéressant. Pressé de voir la suite !!!!!!!!!!!!!!!!!

Image utilisateur
Serveur Minecraft gratuit - Forum - Page Facebook
Je recherche des antiquités de l'informatique (<1995), contactez-moi si vous en avez !
« Le lol est aux Kevins ce que le point-virgule est aux programmeurs » GUITRY
« Un homme azerty en vaut deux. » GOURCUFF
« Code-moi un mouton » LE PETIT-FILS DU PETIT PRINCE
Image utilisateur







Image utilisateur Image utilisateur Image utilisateur








Un tram sur fer pour Koenigshoffen
Site de presse amateur l'Orateur
 
Hors ligne titz # Posté le 10/11/2009 à 12:20:50
Avatar

Avis : Très bon

Ville : Vernon
Pays : France métropolitaine

Je viens de voir ton tutoriel.
Sa doit être vachement décevement de n' avoir que 135 visualitation :p

Tu mérite plus c'est un tuto pas mal !
:D
 
Hors ligne Kts # Posté le 26/05/2010 à 20:24:35
Avatar

Études : IUT Bordeaux 1

J'avoue que passer de quelque 20 000 visualisations aux premiers chapitres à 1xx c'est dommage... surtout vu ce qu'on apprend... Tant pis pour eux, y en aura plus pour nous :p

Sinon bravo, très bon tuto comme les autres ^^
J'ai beaucoup aimé :) on peut faire des choses très sympa avec ces particules !

Content d'avoir eus un petit exercice :D J'ai réussi à faire neiger dans la room.3ds avec le feu sur la marche du haut \o/
Mais j'ai encore des difficultés avec les aabbox3d è_é j'ai beaucoup de mal à positionner le rectangle de mon emetteur dans cet espace en 3D... ça viendra j'espère :p

"La possibilité de déplacer une forte proportion de composantes libidinales, composantes narcissiques, agressives et même érotiques, sur le travail professionnel et sur les relations humaines qui s'y rattachent, confère à celui ci une valeur qui ne le cède en rien à son indispensabilité pour chacun aux fins d'affirmer et justifier son existence dans la société"
Sigmund Freud
:euh: vive la philo :lol:
 
Hors ligne mr.xyz # Posté le 10/06/2010 à 21:32:57
Avatar

Ville : Bordeaux
Pays : France métropolitaine
Études : Université de Bordeaux

Tout d'abord merci beaucoup pour ce tutoriel :)

Par contre j'ai un petit soucis, j'ai testé le début du tuto sa marche bien. Mais la fin avec les textures ne marche pas. Déjà erreur de compilation sur les paramètres de swprintf, et si je mets un titre banal, sa compile bien mais les textures ne sont pas chargées à l'exécution. Pourriez-vous m'aider ? (je précise que j'ai bien placé mes ressources dans le bon rep..).. Merci d'avance ;)
 
Hors ligne vorpal # Posté le 29/12/2011 à 02:50:32

j'ai trouver un problème avec les particules de feu vers la fin du tuto.
j'ai juste tester le code donner par Kevin Leonhart.

Lorsque j’exécute l’exécutable du projet pour texte le résultat tout va bien l'animation du feu tout est correct.

Mais quand je recule je voie juste des particules blanc comme sur cette image.
Image utilisateur

Quelqu’un aurait la solution? Merci d'avance.

Voir tous les commentaires