begin process at 2008 07 20 09:24:08
1 213 150 membres
71 nouveaux aujourd'hui
14 166 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

PARTICLE ENGINE 2D OPENGL DEV-C++ - EFFETS DE FEU ETC [ MOTEUR DE PARTICULES ]


Information sur la source

Catégorie :OpenGL Niveau : Débutant Date de création : 14/06/2004 Date de mise à jour : 01/09/2005 19:42:31 Vu / téléchargé: 14 428 / 954

Note :
9,94 / 10 - par 17 personnes
9,94 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (139)
Ajouter un commentaire et/ou une note

Description

Le code se présente sous la forme d'un ensemble de classes C++ qui forment, au global, un système de particules en 2D pour OpenGL.

Le concept: on dessine un très grand nombre (des milliers) de "particules" (carrés colorés et texturés plus ou moins transparents selon un facteur hasard et leur "âge": les particules meurent quand leur Vie atteint 0, c'est-à-dire lorsqu'elle sont complètement transparentes) à l'écran. Ces particules qui sont projetées (vive la théorie vectorielle ^^) dans une certaine direction à une certaine vitesse donnent un joli effet de feu dans le cas présenté ici, mais selon les paramètres on peut obtenir une trainée de poussière derrière un obus, une nuée d'étoiles etc... C'est une technique très amusante car si vous bidouillez avec les paramètres, vous obtiendrez souvent des choses étonnantes :)

Les specs:

- Génération dynamique de la texture des particules -> on ne doit pas fournir d'image
- Possibilité de coincer l'orientation des particules entre deux angles en degrés ([0,360])
   A noter: 40->140 est l'inverse de 140->40, il ne faut pas écrire -220->40
- Vitesse paramétrable ainsi que le facteur de réduction/croissance de celle-ci
- séparation en classes claires (j'espère ^^)
- Couleur paramétrable (au singulier, contacter Wett pour le pluriel ^^)

Le point original:

La classe CLieu représente un lieu géométrique de points (cercle, disque, rectangle "plaquette", point, mais aussi droite, parabole etc si l'on veut les coder). Ainsi, en associant un CLieu à un CParticleEngine, on peut aisément déterminer l'aspect de l'animation. Le feu en bas d'écran est une plaquette "ligne" (je n'ai pas codé les lignes, mais ça revient à ça). Le cercle est un cercle aplati à un facteur de 0.5 pour donner l'effet de perspective, et le flambeau vert est un point avec des angles de projections [40,140]°.

Je ne pense pas que cela existait déjà, en tout cas je ne l'ai jamais vu. Changer le Lieu en pleine animation devrait donner lieu à une transition intéressante, je n'ai pas encore testé, mais cela devient très simple grâce à ce système.

Source

  • //Exemple de config:
  • Engine2.SetFourchetteAngles(80, 100);
  • Engine2.SetFourchetteVitesse(1, 15);
  • Engine2.Rayon = 8;
  • Engine2.Lieu.Type = liCercle;
  • Engine2.Lieu.SetCentreEtRayon(400, 325, 250, 0.5);
  • Engine2.FacteurVitesse = 0.95;
  • Engine2.Couleur = CParticleEngine::clrEnergieBleue;
  • Engine2.CreerParticules(NbPart2);
  • //Note: le 4ème paramètre de SetCentreEtRayon() est le facteur de compression du lieu selon l'axe Y (cercle -> ellipse)
  • //cf ZIP évidemment
//Exemple de config:

    Engine2.SetFourchetteAngles(80, 100);
    Engine2.SetFourchetteVitesse(1, 15);
    Engine2.Rayon = 8;
    Engine2.Lieu.Type = liCercle;
    Engine2.Lieu.SetCentreEtRayon(400, 325, 250, 0.5);
    Engine2.FacteurVitesse = 0.95;
    Engine2.Couleur = CParticleEngine::clrEnergieBleue;
    Engine2.CreerParticules(NbPart2);


//Note: le 4ème paramètre de SetCentreEtRayon() est le facteur de compression du lieu selon l'axe Y (cercle -> ellipse)

//cf ZIP évidemment

Conclusion

L'exemple du zip:

Dans l'exemple vous verrez un feu "classique" étendu en bas de l'écran et poussé par un vent vers la droite (jouez avec les flèches gauche/droite pour changer ça), un cercle énergétique bleu au centre de l'écran dont vous pouvez changer le rayon avec les touches haut/bas et une flamme/lampe/chalumeau verte au centre du cercle (j'avais plus de place ^^).
Si vous appuyez sur Enter, les particules cessent d'être régénérées, et les systèmes s'éteignent. Si vous rappuyez sur Enter, la régénération reprend son cours normal.


Ne regardez pas trop le main.cpp, c'est le bordel. Remarquez juste qu'il a fallu générer la texture en appelant Engine1.GenerateTexture(25) (25 = ID de la texture, arbitraire, oui c'est dégueulasse de faire ça comme ça) APRÈS avoir activé OpenGL et que les méthodes CreerParticules(x) sont appelées APRÈS les configurations des Engine_. Cela pour que les particules initiales respectent les contraintes du système.

Vous ne devrez créer que des objets CParticleEngine si vous utilisez ce code. Voyez le main.cpp pour la configuration de ces objets et leur utilisation (Objet.Deplacer(); Objet.Dessiner();).


TODO:

- implémenter une fonction Initialiser(type) pour paramétrer l'objet directement avec une configuration par défaut pour un feu, une lampe, des étoiles etc...
- utiliser une display list pour les particules d'un ParticleEngine [FAIT]
- rétablir un système d'axes non modifié (pour l'axe Y, s'entend)
- Passer en 3D?
- éliminer l'effet de discrétisation des positions des particules qui donne lieu à un effet de quadrillage indésiré dans certains cas.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

20 octobre 2004 16:19:40 :
Correction de (certaines ^^) fautes d'orthographe; plus de TODO;
01 septembre 2005 19:42:31 :
Suite à une mise à jour de G++, une liberté sur le standard que je m'étais permise n'est plus acceptée. C'est maintenant corrigé. Il y a trois exe dans le zip nommés nom.exe.cutable. Je vous laisse deviner comment les lancer :P. Merci à Florent Weillaert pour l'alerte ^^.
  • signaler à un administrateur
    Commentaire de BumpMANN le 14/06/2004 23:39:45

    10/10! sans contestes ! Bravo!

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 00:49:53

    10/10 bravo amigos

  • signaler à un administrateur
    Commentaire de BruNews le 15/06/2004 00:54:16 administrateur CS

    Kirua, c'est joli tout plein et pour une fois voila un opengl qui daigne tourner chez moi.

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 08:43:21

    viens d'avr une idée, je la poste ici pour que je m'en souvienne parce que là je peux pas coder. Pour faire une trainée derrière le centre de l'objet, il faut déplacer le point Lieu du moteur de particules, et pas effectuer une translation supplémentaire. Comme ça, les particules ne se déplacent pas avec la translation. (faites pas attention, je me parle tout seul, c'est un post-it ;-))

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 08:50:19

    Désolé pour le mail supplémentaire, je viens de coder ça et ça marche! Suis content ^^, ça prend quasi rien comme lignes!

    J'ai rajouté dans le zip un exécutable Win32 Particle2D_trainee.exe pour vous montrer l'effet, et un fichier main_trainee.cpp par lequel il faut remplacer main.cpp si vous voulez compiler cet exemple-là. Les seules modifs apportée au flambeau:


        //les particules vont vers l'arrière
        Engine3.SetFourchetteAngles(180-40, 180+40);
        //le centre du jet commence plus à gauche (100px)
        Engine3.Lieu.SetPoint(100, 335);

    et dans la boucle principale:

                Engine3.Lieu.Param1+=15;

    Ce qui déplace le centre du jet de 15 px vers la droite 30 fois par seconde!

  • signaler à un administrateur
    Commentaire de Cyberboy2054 le 15/06/2004 10:37:17

    Trop fort, j adore l effet de trainée :)
    On peut par dessus ton systeme de gestionnaire de particules imaginer un gestionnaire des gestionnaires. Pour quoi faire ? ben au lieu d avoir
    Engine1.Deplacer();
    Engine2.Deplacer();
    Engine3.Deplacer();
    dans ta boucle principale, tu cree un gestionnaire qui n est ni plus ni pour qu une liste des moteur de particules, et qui se chargerait de mettre a jour et afficher les systemes de particules, puis supprimer ceux qui sont morts. Chais pas si je suis clair, mais ca fait un truc comme ca
    class PartManager
    {
    std::list <CParticleEngine*> m_List;
    public:
    void AddSystem (CParticleEngine* pEngine)
    {
    m_List.push_back(pEngine);
    }
    void Update ()
    {
    // met a jour les systemes, supprime ceux qui sont usagés
    }
    void Draw ()
    {
    // dessine les systemes presents
    }
    };

    comme ca tu peut initialiser le manager
    PartManager g_Manager;
    g_Manager.AddSystem (&Engine1); g_Manager.AddSystem (&Engine2); g_Manager.AddSystem (&Engine3);

    puis dans la boucle principale
    g_Manager.Update ();
    g_Manager.Draw();

    Voili voulou :)

  • signaler à un administrateur
    Commentaire de Cyberboy2054 le 15/06/2004 10:53:56

    Au passage, si tu code un moteur 2D, on va problablement avoir plein de trucs a se raconter :)
    Meme si le mien utilise SDL pour le rendu a la place d opengl, les concepts restent les memes ...

  • signaler à un administrateur
    Commentaire de Funto66 le 15/06/2004 10:54:04

    L'effet est magnifique même sur ma carte graphique, même envoûtant des fois lol, bravo ;)

    J'ai recompilé sous Visual C++ en supprimant tous lles errors et warnings (y'en avait un paquet :(, mais c'était surtout des histoires de conversions de types implicites ) je t'enverrai ça.

    J'ai vu aussi dans ta génération de textures que tu utilisais un filtre GL_LINEAR; vu que les particules sont toutes petites on ne voit aucune différence lorsque l'on filtre en GL_NEAREST, et, chez moi en tous cas, les performances sont bien meilleures.

    Extrait de ton code : "texPixels = (GLubyte *) malloc(texSize);" -> et toi qui me reprochais d'utiliser malloc() au lieu de new[]....d'ailleurs dans ce cas l'allocation dynamique n'est pas obligatoire vu que la taille de la texture allouée ne change pas...
    Euh...d'ailleurs je viens de m'en rendre compte : si j'ai bien compris, ta texture est appliquée à chaque particule, chacune toute petite. Et ta texture fait 256x256??? C'est énorme !

    PS : "//quelques couleurs remarquables qui seront souvent utilisées
    static SRVB clrFeu, clrEnergieBleue, clrNauseabond;"

    Mdr la couleur clrNauseabond :p

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 11:02:27

    CyberBoy: C'est une bonne idée, et je fais ça assez souvent quand je code une classe. Si j'en ai l'utilité, je le coderai (faudra juste rajouter une méthode pour savoir si le système est mort). Pas compliqué, mais je pense pas le coder ici. Dans mon moteur de RPG plus tard oui ;)

    Funto: pourtant moi Dev m'embête déjà bcp pr que j'exprime les cast littéralement, comprends pas où il t'en a trouvé d'autres ton VC :(

    La partie du code de génération de la texture n'est pas de moi, je l'ai extrait d'un code, d'ailleurs je dois encore rajouter les crédits de l'auteur. J'ai juste cherché à l'inclure dans ma classe sans chercher plus loin, je vais modifier ça, en effet c'est un peu idiot. Quant au malloc/free, je trouve ça moche :p je devrasi récrire la fct en fait.

    j'adore ce vert ^^ autant que le bleu et le rouge/jaune en fait. Mais si l'animation n'est pas sur un fond noir, ça tue tout l'effet :( :( :(

  • signaler à un administrateur
    Commentaire de Funto66 le 15/06/2004 11:58:45

    Moi aussi j'adore ce vert ;)
    Pour les casts, en fait, c'est surtout avec l'usage de constantes; 1.0 est un double et 1.0f et un float.
    Y'avait aussi des erreurs dûes à l'inclusion de GL/gl.h sans inclusion de windows.h avant (je sais c'est stupide mais Visual C++ veut ça...), et aussi M_PI n'était pas défini dans math.h.
    Y'a aussi un truc qui est bizarre, c'est que ça compile impec sur les 2 compilos alors que tu fais des #include <cmath>, #include <cstdio>...etc sans aucun using namespace std...

    Je t'envoie le mail avec la version VC++ée.

    PS : à un moment dans un commentaire tu fais référence au RPG Engine, je sais pas si c volontaire ou si c un oubli...

  • signaler à un administrateur
    Commentaire de LordBob le 15/06/2004 11:59:20

    c'est tres jolie !!! :)

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 14:25:01

    je savais pas pour le f après un nombre, je pensais que c'était facultatif, mais sans incidence.
    je savais pas non plus que les libraires <c___> faisaient partie de l'espace de nom std, faudra que je modifie ça.

    ben oui je fais référence en RPG Engine, bien entendu ^^ c'est pour ça que je l'ai créé ce moteur de particules, pour faire les effets des combats. Mais ça va faire bizarre ce truc "moderne" avec les graphismes rétro (vieillot? :p) du rpg...

  • signaler à un administrateur
    Commentaire de gagah1 le 15/06/2004 14:44:21

    Magnifique effet! 10/10.
    J'ai recompilé la source en changeant la valeur du timer en 15ms et même avec des nombres de particules 3000, l'effet est plus naturel. Bravo!!!!!!!

  • signaler à un administrateur
    Commentaire de Funto66 le 15/06/2004 14:58:56

    Bah de toutes façons ils utilisent bien ça dans Final Fantaisy non?
    Bon c'est sûr je pense pas que ton RPG ressemblera niveaux graphismes à Final mais bon ça sera un 1er pas :p

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 15:03:10

    ils utilisent ça dans les final fantasy en 3D, qui n'ont rien de rétro depuis 6 ans ^^ regarde FF7, c'est une pure bombe, et ça date de ...

    je me demande juste ce que ça va faire ces grosses boules d'énergies dans les mains de mes sprites en 2D bien plate sur fond 2D bien plat ...

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 15:30:33

    pense tu pas creé un jeu like street fighter et utiliser les particule comme des bull ( Hadouken) ca serait super :)

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 15:37:02

    à part Tekken 3 et DOA 3 j'aime bof les jeux de combat, et puis, c'est pas parce que j'ai l'anim que je vais faire le jeu, ça me paraît rapide comme saut^^ Mais le code source est à toi, tu es libres d'en faire ce que tu veux ;-)

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 16:19:28

    Alors  tekken Vs Street :) :)

  • signaler à un administrateur
    Commentaire de BumpMANN le 15/06/2004 16:49:09

    Qui a osé mettre 9? O_o

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 17:03:33

    il ont pas posé 9 mais oui
    car il avait deja 10 + 8 / 2 = 9 mais c pas grave je vais faire en sorte que sa augmente regarde now

    Kiruna mirite un 10/10 et ca va rester

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 17:03:53

    il ont pas posé 9 mais oui
    car il avait deja 10 + 8 / 2 = 9 mais c pas grave je vais faire en sorte que sa augmente regarde now

    Kiruna mirite un 10/10 et je vais faire en sorte qu'il a

  • signaler à un administrateur
    Commentaire de xarier le 15/06/2004 17:10:25

    Bh ca na rien donner He j'ai mi la un 10/10 il ca n a fait aucun effet

  • signaler à un administrateur
    Commentaire de Wett le 15/06/2004 17:22:29

    Salut! Comme d'hab, excellente source ;)
    Je viens de voir qu'une particule est gérée à l'aide de vecteurs, mais dans ta classe moteur c'est avec des angles... O_o plutot space comme truc... encore que non c'est pas idiot tu peux donner une fourchette et c'est bien mieux!
    Simple question (pas trop le temps d'étudier ta source) le moteur est 2D ou 3D? On peut gérer un mouvement de caméra? Je pense à un exemple simple : une chute d'eau (vitesse initiale horizontale, acceleration verticale, couleur bleue-blanche (tu devrais mettre aussi des plages de couleur, genre possibilité de melanger selon des proportions + ou - alétoires plusieurs couleurs) ) ensuite on pourrait tourner autour, etc. Et donc l'intégrer dans un vrai moteur 3D! Meme en 2D ça peut toujours servir...
    Tu devrais aussir permettre de gérer la mortalité de tes particules de differentes manières : pourcentage de mort à chaque secondes (genre la radioactivité), distance du point initial, temps etc... Que le tout soit paramétrable et bien sur soit tout de meme plus ou moins aléatoire comme tu t'es attaché à la faire jusqu'à présent...
    Bon voila un peu à court d'idée là mais j'espere que ça t'aidera... Et en fait meme apres avoir regardé ta source je comprends pas bien comment tu gere la vitesse et l'accéleration d'une particule... Un mélange d'angles et de vecteurs ok je comprends mais... La vitesse ET l'accélération ont un angle bien distinct? Je repense toujours à mon exemple de chute d'eau : c'est réalisable? Désolé de poser des questions bêtes je peux pas compiler d'ici sinon j'aurais bien essayé voir ce que je pouvais faire ;)
    a+ et encore bravo!

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 17:41:25

    Salut Wett, thx pr le commentaire élaboré ^^

    Le moteur est 2D complètement, donc pour l'adapter à de la 3D, faudrait du travail, à commencer par récrire une classe CVecteur3D et à remplacer tous les calculs de position (récrire Lieu et ses paramètres aussi...).

    C'est vrai que la mortalité c'est le seul truc que j'ai pas rendu paramétrable, je devrais changer ça (juste quelques lignes mais dans plusieurs classes). Faut d'ailleurs aussi récrire la génération de texture.

    Le mouvement de caméra, ben c'est en 2D, y a pas moyen ;-) mais si tu déplaces le lieu du système, les particules mortes renaissent toujours dans le nouveau lieu, ce qui permet les effets de trainées, puisque les particules en vie continuent de se mouvoir selon leur mvmt originel, indépendemment du déplacement du système. Tu pourras aussi simplement faire des transitions d'un point à un cercle puis d'un cercle à une droite, le tout en changeant les couleurs, ce serait simple à coder.

    Pour les variations de couleurs d'ailleurs, c'est une idée... pas long à coder non plus mais il y a un problème: une particule ponctuelle doit garder la même couleur tout le temps, donc il faudrait donner une propriété Couleur à chaque particule (SRVB = 3*4 octets). Pour 10 000 particules ça fait 120 Ko de plus... c'est trop coûteux je trouve. A nouveau, c'est vrmt trivial à coder, donc si ça amuse qq un :)

    Quant au mvmt des particules, m'étais demandé d'abord: est-ce que je dois gérer la gravitation? -> c'est tt léger, ça n'a "pas" de masse, donc non. Donc, il s'agira d'un mvmt rectiligne uniforme? pas vrmnt, elles sont quand même freinées par leur milieu... donc j'ai opté (sur conseil d'un tuto ;-)) pour l'option suivante: à chaque déplacement, je me contente de multiplier le vecteur vitesse (pas accélération!) par le scalaire FacteurVitesse (ce qui aura pour effet de modifier le module de la vitesse et donc la valeur scalaire de la vitesse) et ensuite j'additionne le vecteur vitesse au vecteur position de la particule, ce qui a pour effet de bien déplacer la particule dans le sens et la direction du vecteur vitesse.

    Les composantes du vecteur, par trigonométrie élémentaire, sont calculées selon les sinus et cosinus de l'angle (cf. Cercle Trigonométrique) et le module, ben c'est du Pythagore :)


    PS: si vous avez la possibilité de compielr chez vous, essayez de remplacer dans le code "main_trainee.cpp" le code d'initialisation de l'engine3 (la boule qui se déplace) par ça:

        Engine3.SetFourchetteAngles(360-40, 0+40);
        Engine3.SetFourchetteVitesse(4, 25);
        Engine3.Rayon = 8;
        Engine3.Lieu.Type = liPoint;
        Engine3.Lieu.SetPoint(100, 335);
        Engine3.FacteurVitesse = 0.95;
        Engine3.Couleur = CParticleEngine::clrFeu; //CParticleEngine::clrNauseabond;
        Engine3.CreerParticules(NbPart3);

    ça fait un jet amusant ^^

  • signaler à un administrateur
    Commentaire de neo_00110010101 le 15/06/2004 20:35:26

    excellent, magnifique, beau ... comme la note :)

    tu n'as pas mis longtemps à sortir ta "petite" source que j'attendais :]

  • signaler à un administrateur
    Commentaire de gagah1 le 15/06/2004 20:49:08

    Salut!
    J'ai regardé la source. Si tu mets le rayon (taille de particule) en valeur aléatoire comprise dans une fourchette et si la texture au lieu de rond , tu mets en ovale comme suit:
    GLuint dist = (unsigned)hypot(float(i-(texHeight/2)),float(j-(texWidth)/2))*2.0); l'effet sera plus réel.
    Aussi, gère independamment le timer.
    Dans la texture un 64x64 sera suffit ,meme 32x32 ,car le particule est petit, là tu perds quelque ms en utilisant 256x256.
    A part celà c'est très bien.
    J'ai remarqué aussi la presence de glBegin(GL_TRIANGLE_STRIP) dans le boucle for(...), tu peut mettre cela en dehors du boucle en remplaçant par (gl_Begin(GL_QUADS)) et changer le 4e glTexCoord en 3e. On gagne aussi quelque ms. Voilà , bonne prog!

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 20:55:06

    le rayon des particules, tu suggères qu'une particule ait un rayon fixe généré aléatoirement, ou que le rayon de la particule soit redéfini à chaque frame? parce que dans le premier cas, c'est la même réponse qu'à Wett pr les couleurs: il faut minimiser les données nécessitées par les particules parce qu'il y en a bcp! faut être raisonnable dans la paramétrisation ^^

    pour le timer, je l'ai vrmnt écrit en 4 secondes ;) c'était seulement pour l'application de démo (et de test). dans mon rpg, ce sera le timer du jeu qui fera la loi, et dans vos applications (éventuellement), ce sera le vôtre, pas de souci.

    pour les triangles, j'ai suivi un conseil sur un site qui disait que les triangles étaient plus rapides à dessiner qu'un rectangle (même 4 triangles dans ce cas-ci! étonnant non?).

    quant à la texture, c'est un des points à changer en effet.

  • signaler à un administrateur
    Commentaire de djl le 15/06/2004 20:55:09

    exelent ! 10/10

  • signaler à un administrateur
    Commentaire de Kirua le 15/06/2004 21:03:41

    Voici le code pour des textures plus petites (j'ai juste dû apporter qq modifs pour qu'il ne faille (mtnt) plus que changer les deux premières lignes pour changer la définition de la texture:

    j'ai changé ça:
         float color = 255-(dist*1.8);
    en ça:
         float color = 255-(dist*1.8*(256./texWidth));


    //---------------------------------------------------------------
    void CParticleEngine::GenerateTexture(int id)
    {
    int texWidth = 64;
    int texHeight = 64;
    GLubyte *texPixels, *p;
    int texSize;
    int i, j;
    int radius;

    texSize = texWidth*texHeight*4*sizeof(GLubyte);
    texPixels = (GLubyte *) malloc(texSize);
    if (texPixels == NULL)
      return;

    p = texPixels;
    for (i=0; i<texHeight; ++i)
    {
       for (j=0; j<texWidth; ++j)
       {
         GLuint dist = (unsigned)hypot(float(i - (texHeight / 2)),float(j - (texWidth / 2)));
        
         float color = 255-(dist*1.8*(256./texWidth));
         if (color < 0) color = 0;
         p[0] = (char)color;
         p[1] = (char)color;
         p[2] = (char)color;
         p[3] = (char)color;  
         p+=4;
       }
    }

    glBindTexture (GL_TEXTURE_2D, id);
    //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texPixels);

    free(texPixels);

    TextureID = id;
    }
    //-------------------------------------------------------------

  • signaler à un administrateur
    Commentaire de Funto66 le 15/06/2004 23:47:16

    Tous les CParticuleEngine utilisent la même texture; ça serait pas mieux de créer son ID en static?
    Je veux dire, plutôt que de donner un ID de texture arbitraire à chaque CParticuleEngine, d'autant plus que cet ID est le même pour tous, je verrai la chose comme ça :
    - un membre de CParticleEngine : static GLuint IdTexture;
    - à l'appel du constructeur de CParticuleEngine :

    static bool PremierPassage= true;
    if(PremierPassage)
    {
    glGenTextures(1, &IdTexture); // Evite d'utiliser un ID arbitraire; par contre dans tout le programme faudra utiliser des glGenTextures au lieu d'IDs arbitraires, ce qui est beaucoup plus clair et fiable.

    // ICI : génération de la texture...
    PremierPassage = false;
    }

    - la méthode CParticuleEngine::Dessiner() utilise IdTexture.

  • signaler à un administrateur
    Commentaire de Xs le 16/06/2004 00:10:43

    Salut !

    Si tu veux t'en servir dans un ptit rpg 2D, j'ai trouvé ca (c'est a peu prêt comme ca que je m'en servirai dans le mien) :

    Engine3.SetFourchetteAngles(80, 100);
    Engine3.SetFourchetteVitesse(4, 15);
    Engine3.Rayon = 8;
    Engine3.Lieu.Type = liPoint;
    Engine3.Lieu.SetPoint(400, 335);
    Engine3.FacteurVitesse = 0.95;
    Engine3.Couleur = CParticleEngine::clrFeu;
    Engine3.CreerParticules(50);

    50 particules seulement pour un truc assez sympa.

    Sinon, je suis pas habitué à l'openGL (je fais du DX9) donc je me pose une qustion : tes particules, ce sont bien des triangles ? Je veux dire, qu'est ce que tu dessines ? Un carré ou un triangle ? ou autre chose ?

    merci

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 00:24:42

    bh jj'ai pas vue mais la plus part des fois en utilise des carré la aussi je pense qu'il utilisé des carré

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 00:25:31

    bh jj'ai pas vue mais la plus part des fois en utilise des carré la aussi je pense qu'il utilisé des carré

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 07:59:44

    Funto, ton postulat de départ est erroné: tous les CParticleEngine's n'utilisent pas la même texture, et c'est bien pour ça que j'ai opté pour ce système. Ce qui est vrai, c'est que je pourrais avoir un flag qui détermine si la texture a déjà été générée, et j'y ai pensé. Mais on ne veut pas forcément créer la texture! Donc je laisse ça au gestionnaire de CParticleEngine's (je dois lui trouver un nom ;-))

    Salut Xs. Ton effet esxt OK pour un petit flambeau ou qqch du genre, en effet, faudra que je pense à le mettre dans les donjons :p
    Si tu veux convertir le code pour DirectX, c'est vraiment, vraiment easy. Tu ne dois changer que la méthode de Dessiner de CParticleEngine ainsi que la fonction GenerateTexte. C'est tout!
    Je dessine en fait 4 triangles qui forment un carré. J'ai lu que c'était "mieux", et en général je fais confiance ;-)

  • signaler à un administrateur
    Commentaire de Wett le 16/06/2004 10:53:11

    Kirua pour les couleurs, il ne faudrait pas conserver les couleurs pour chaque particule, simplement conserver par ex 255 couleurs differentes max et de conserver uniquement l'indice de la couleur dans chaque particule... ça reduit à un octet.. et on se reduit à meme pas 10Ko en plus, ça se tiens je trouve...
    Sinon c'est dommage que tout soit en 2D pure meme si je comprends que ça te simplifie grandement la tache... Je verrais si je peux pas trafiquer un peu ça des que j'aurais à nouveau acces à internet depuis mon pc ;) idem pour les couleurs ^^

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 10:59:24

    la 3D serait pas plus dure à coder (effectuer la modif mtnt est lourd, mais si depuis le début j'avais tout orienté 3D, ça n'aurait pas été sensiblement plus compliqué). je l'ai fait en 2D parce que mon moteur de jeu est en 2D et que donc, ben pas besoin de 3D ^^

  • signaler à un administrateur
    Commentaire de Xs le 16/06/2004 11:12:52

    Merci pour l'info Kirua mais : 4 triangles pour un carré ? Un carré moi je le divise en 2 triangles non :S ?

    Sinon, je vois pas trop pourquoi vous vous prenez la tête avec des 120Ko, 10Ko, etc... : je vous rappel qu'un jeu (2D qui plus est) doit être 100% orienté vitesse : donc vaut mieux stocker quelques données pour gagner quelques fps (multipliés par le nombre de particules) que quelques kilo.. A moins que vous soyez restés à l'époque des HDD de 3Mo : Ce ne sont pas quelques centaines de kilo qui vont surcharger un HDD d'une 50aine de gigas (Les nouveaux jeux se fichent de leur consommation en place : ils veulent juste aller vite : quake3, ut2k4..) !

    cordialement

  • signaler à un administrateur
    Commentaire de Wett le 16/06/2004 11:18:35

    Ici il n'est pas du tout question de HDD ou de sacrifier de la vitesse pour conserver de la mémoire (c'est fini l'époque des 512Ko de ram... On en est conscient t'inquiete!), simplement d'optimisations et d'éviter de bouffer trop de ram pour un simple moteur de particules, qui n'est qu'un supplément dans un moteur et non un programme à lui tout seul... Donc plus il est léger (autant en mémoire qu'en temps machine) mieux c'est!

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 11:20:24

    les 120 Ko ils vont ds les gencives de la RAM, et c'est pas parce que t'as 1024 Mo de RAM que 120 Ko ça ne représente rien. La fonction new d'allocation mémoire est très lente, elle doit chercher des plages mémoire continues dans la mémoire vive. Si tu cherches un tronçon continu de 120Ko tu risque de plus t'amuser que si tu cherches 4 octets pour stocker ton int. Le résultat il est clair: vitesse d'exécution en chûte. Puis je vois pas le rapport avec un disque dur ^^ si tu stockes ces données ds le DD t'es parti pour la gloire avec ta vitesse d'exécution ;-)

  • signaler à un administrateur
    Commentaire de Xs le 16/06/2004 11:23:43

    Arg :D

    Vous avez tout les deux raisons et Kirua a un excellent argument que je ne connaissais pas :D Pour le HDD, je me suis emmelé les pinceaux et pensais à la RAM (mais une fois que j'ai dis HDD je suis partis dedans :'( )

    merci, je m'en vais, tête baissée, programmer un moteur en DX :D
    cordialement

  • signaler à un administrateur
    Commentaire de Wett le 16/06/2004 11:24:22

    LOOL j'imagine trop le concept : Pour optimiser l'acces à la ram et eviter de trop en bouffer... Privilégiez la mémoire virtuelle!!! ARGGG ou mieux : ils vont nous sortir de la HDDR à debit maxi de.... 50Mo/s!!! la galere... Pardon private joke ^^

  • signaler à un administrateur
    Commentaire de Xs le 16/06/2004 11:30:57

    Spa bien de se moquer :'(
    Jtaurai toi à la première gaffe  :D

  • signaler à un administrateur
    Commentaire de Wett le 16/06/2004 11:33:42

    je me moquais pas de toi promis ^^ Juste je reprennais le concept parce qu'il se defandait ^^ Et t'inquiete si tu veux m'avoir à la 1ere gaffe tu va pas chercher longtemps ;o)

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 11:49:47

    malheureusement avec Wett on risque de chercher longtemps parce qu'il s'enferme à Lyon. Il sait qu'il dit bcp de bêtises alors il se met ds un endroit où y a que des daubes comme connexions internet, et comme ça il risque pas de se dévoiler... naaah, c bientôt les vacances, tu vas retourner chez toi, pas vrai? on t'aura plus svt :)

    le truc de l'opéro new qui est lent, j'ai pas trouvé ça tout seul, c'était dans un document sur les optimisations à prendre en compte en C++, tout spécialement en ce qui concerne les chaînes de caractères (qui sont dég. en C/C++ ;))

    http://www.joelonsoftware.com/articles/fog0000000319.html

    ça vaut vrmnt le coup de le lire en entier

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 11:54:25

    L'extrait qui nous intéresse: (url du document, commentaire précédent). ça parle de malloc et free en fait, pas de new et delete, mais je suppose que c'est le même genre de fonctionnement (?)

    That opens another whole can of worms: memory allocators. Do you know how malloc works? The nature of malloc is that it has a long linked list of available blocks of memory called the free chain. When you call malloc, it walks the linked list looking for a block of memory that is big enough for your request. Then it cuts that block into two blocks -- one the size you asked for, the other with the extra bytes, and gives you the block you asked for, and puts the leftover block (if any) back into the linked list. When you call free, it adds the block you freed onto the free chain. Eventually, the free chain gets chopped up into little pieces and you ask for a big piece and there are no big pieces available the size you want. So malloc calls a timeout and starts rummaging around the free chain, sorting things out, and merging adjacent small free blocks into larger blocks. This takes 3 1/2 days. The end result of all this mess is that the performance characteristic of malloc is that it's never very fast (it always walks the free chain), and sometimes, unpredictably, it's shockingly slow while it cleans up. (This is, incidentally, the same performance characteristic of garbage collected systems, surprise surprise, so all the claims people make about how garbage collection imposes a performance penalty are not entirely true, since typical malloc implementations had the same kind of performance penalty, albeit milder.)

    Smart programmers minimize the potential distruption of malloc by always allocating blocks of memory that are powers of 2 in size. You know, 4 bytes, 8 bytes, 16 bytes, 18446744073709551616 bytes, etc. For reasons that should be intuitive to anyone who plays with Lego, this minimizes the amount of weird fragmentation that goes on in the free chain. Although it may seem like this wastes space, it is also easy to see how it never wastes more than 50% of the space. So your program uses no more than twice as much memory as it needs to, which is not that big a deal.

  • signaler à un administrateur
    Commentaire de StanOfSky le 16/06/2004 14:12:03

    ouai la fonction la plus rapide est bien triangle_strip donc faire des carré. a noter que les objets 3d sont tres souvent exporté sont un format triangle_strip pour l'optimisation du rendu.
    bien entendu 2 triangles = un carré (ou rectangle ou paralelogramme)

    pour ce qui est de allocation en effet c assez lent c pourquoi fau faire ses allocation au tout début quitte à prevoir l'espace que tu devras allouer
    de maniere générales tous les calculs lourds qui n'ont pas besoin d'etre dynamique ou qui peuvent etre précalculé doivent etre fait au debut quitte a perdre un peu d'espace ram pour plus de rapidité dans l'exécution.

    sinon c vrai que le moteur est assez bleuffant, le rendu est vraiment tres beau.
    mais chez moi c po tres rapide donc reste à optimisez tout ca.
    parce qu'avec 6500 particules pour les 2 premiers et 2000 pour le 3e ca rame un peu
    et pourtant j'ai une GF2 1600+ qui supporte parfaitement UT2004 ou warcraft iii ;)

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 14:19:58

    hi bh la chez moii ca marche vraimment tres lent avec 6500 alors si quelqu'un peu l'optimizer :

    j'ai un p4 1.60 GHz 520 mo ram .

    Merci

  • signaler à un administrateur
    Commentaire de Xs le 16/06/2004 14:22:31

    euh chez moi aucuns problémes avec 6500*2 + 2000 particules sur une G4 Ti4200 128Mo, 512 DDR et un 1.1Ghz (AMD TBird)

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 14:43:00

    bh ca peut que ca soit ma carte graphique car j'ai une de  32 Mo

  • signaler à un administrateur
    Commentaire de Wett le 16/06/2004 14:53:02

    Là c'est sur, le seul facteur c'est la vitesse brute de la carte graphique qui joue, les effets sont simples et ne demandent pas je pense plus de 16 Mo de ram... Et c'est pas le proco qui prend donc --> CG

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 15:18:35

    hmm, l'exe du zip est compilé avec la texture à 256*256 pixels. si vous recompilez avec le code que j'ai mis plus haut (je me souviens plus si j'ai modifé le zip avec la màj...) pour passer à une texture 64*64 (32*32 c'est pas très beau), vous aurez des meilleures perf!

    ts vos ordinateurs st excellents, si mon moteur est lent sur ces ordis, c'est la faute du programmeur qui est un incapable, ça c'est du certain ;-)

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 16:03:40

    non mais please moi j'ai pas le devc++ alors la je ne peut avoir L'image. peut tu le recompiler pour Moi
    ta mon mail ta msn alors ..fill le moi please :)

  • signaler à un administrateur
    Commentaire de Funto66 le 16/06/2004 18:16:56

    J'admet mon erreur (quelques dizaines de posts plus haut lol), je savais pas que tu voulais laisser au programmeur la possibilité d'utiliser une autre texture que celle que produit GenerateTexture().

    Au sujet de malloc()/free() vs new[]/delete[] en fait la principale différence c'est que new[]/delete[] appellent le constructeur de chaque objet alloué, C++ oblige.

    Donc, quand on alloue des GLubyte comme dans ce cas, en toute logique new[] les initialisera à 0 (c'est ce que fait le constructeur par défaut non?) alors qu'on n'en a pas besoin -> garde les malloc()/free().
    Arrêtez-moi si j'ai (encore...) dit une connerie, je ne suis pas sûr du tout de ce que j'avance mais c'est ce il me semble que c'est ça...

    Ah oui aussi; y'a un glDisable(GL_TEXTURE_2D); à la fin de CParticleEngine::Dessiner() ; ça pourra conduire un gars qui veut utiliser le moteur de particules et qui n'aura pas lu le code à se demander pourquoi sa *** de texture ne veut pas s'afficher...
    Le mieux dans ce cas-là c'est d'utiliser glPushAttrib()/glPopAttrib().

  • signaler à un administrateur
    Commentaire de xarier le 16/06/2004 18:35:31

    Hoola pardon pour tout a heur car j'avait pas lue la  source.
    Mais apres que je l'ai lue  j'ai changer l'image 256/256 par 32/32
    et ca merche meiux :)

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 18:51:45

    les types embarqués du C++ n'ont pas de constructeur, donc si je n'utilise pas GLuint mais unsigned int, je peux utiliser les new[] et delete[] sans perte de performance.

    Pour les glPushAttrib tu as parfaitement raison. J'ai compris à quoi ça servait en lisant quelques codes, mais comme je n'étais pas absolument certain du fonctionnement, je ne l'ai pas implémenté. D'ailleurs je devrais généraliser l'usage de cette fonction! Est-ce que tu pourrais me donner un mot d'explication sur ces fonctions, et aussi (si tu sais) me dire si ces appels répétés à glEnable/glDisable sont couteux, où si ils ne font que modifier des flags (bool) ?

    Xarier, tu as su compiler alors?

  • signaler à un administrateur
    Commentaire de Cyberboy2054 le 16/06/2004 19:57:05

    Ben Opengl c est une machine a état. Ca veut dire qu elle fait toujours la meme chose tant que son etat ne change pas. Et comme ces états sont sur la CG, lui faire appel coute cher ... C est pour quoi vaut mieux eviter
    for  (....)
    {
    glBegin (...)
    }
    et mettre plutot
    glBegin (..);
    for (...)
    {

    }
    car a chaque fois que tu passe dans ta boucle tu demande de faire qqch qui ne sert a rien (sil te plait la CG, mets moi les blending dans son état actuel ...), ce qui est forcément couteux.

  • signaler à un administrateur
    Commentaire de Kirua le 16/06/2004 20:32:42

    ok, merci pr l'info.
    j'ai jamais mis de glEnable dans une boucle, c'est déjà ça :p quoiqu'au final, le programme étant une boucle, ça revient à ça aussi, mais en moins con ^^.

  • signaler à un administrateur
    Commentaire de StanOfSky le 17/06/2004 12:19:49

    ouai ya des petites techniques pour optimiser un peu les rendu opengl....
    ya
    * utiliser des listes d'affichage (bon la ct po possible bien que...)
    * utiliser des tableau de points (pareil encore pour faire un carré c po nécessaire bien que...)
    * penser à changer les états une fois pour toutes, ou tout du moins un minimum de fois : cad a dire eviter de les mettres dans une boucle
    * générer les textures de facon aproprié : ici gl8linear sert pas a grand chose, fau mettre gl_nearest
    * utiliser push et pop au lieu de faire des rotation ou translation supplémentaires, et surtout utiliser les opérations matricielle de opengl (gltranslate etc...) car elles seront bcp plus optimisées que toutes celle que tu pourras faire

    parce que la faut qd meme une grosse carte graphique pour des effets qui sont pourtant tres basiques ;)

    pour ce qui est des new et delete, ca n'apelle pa de constructeur pour les types de base comme les int, double etc....
    par contre apres fau savoir ce qu'on veut...si on fait du C++ on  utilise des new et delete po malloc (a part dans certain constructeur pour des utilisations bien particulieres) ou alors on fait du C

  • signaler à un administrateur
    Commentaire de Funto66 le 17/06/2004 23:50:15

    Pour glPushAttrib()/glPopAttrib() , d'après ce que je me rappelle de "OpenGL 1.2", ça permet de mettre dans une pile des "attributs", en gros une partie de l'état actuel d'OpenGL : des informations relatives à l'éclairage, à la couleur...etc, presque tout quoi.
    Mais exactement, comment l'utiliser, ben j'ai pas le bouquin sur moi et j'ai la flemme