IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[Debutant] Repeter deux evenements sans interruption


Sujet :

OpenGL

  1. #1
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut [Debutant] Repeter deux evenements sans interruption
    Bonjour

    Je préviens tout de suite, je commencé à apprendre l'OpenGL depuis seulement quelques minutes (30 minutes).

    J'ai lu quelques cours qui se ressemblent tous, avec des exemples de création de fenêtre, traçage de forme géométrique, etc.

    Dans mon premier programme, j'ai fait un traçage "au hasard" comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     void Affichage()
     {
     
     float i ;
     glClearColor(0,0,0,1.0) ;
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_POLYGON);
     glColor4f(1.0,1.0,1.0,1.0);
     for(i=0.0; i<1.0 ; i=i+0.5)
      {
     glPointSize(20.0);
     glColor4f(1.0,1.0,1.0,1.0);
     glVertex2f(i,i+0.5);
     glColor4f(0.0,1.0,1.0,1.0);
     glVertex2f(i,i+0.3);
     glColor4f(0.0,0.0,1.0,1.0);
     glVertex2f(i,i+0.2);
     glColor4f(0.0,0.0,0.7,1.0);
     glVertex2f(i,i+0.1);
      }
     glEnd();
     glFlush();
     }
    Voila, j'ai mis au hasard des valeurs pour le positionnement de chaque point. Ca me donne une figure sans signification apparente.
    Maintenant, pour mieux comprendre comment s'est effectué le traçage, j'ai utilisé des fonctions qui permettent d'afficher uniquement les sommets de la figure ou bien les lignes (sans que les faces soit remplies avec de la couleur).

    Ce que je souhaite, c'est ceci :
    tant que je n'ai pas appuyé sur Y (par exemple)
    afficher la figure avec les faces remplies (figure tracée par défaut)
    afficher la figure avec uniquement les contours (lignes)

    Donc la figure doit faire un truc du genre clignotement, remplie, vide, remplie, vide , remplie vide.... et ceci tant que je n'ai pas appuyé sur Y.
    Ca fait en faite comme de la lumière qu'on allume et qu'on éteind (enfin c'est comme ca que j'imagine la figure si ça marche).
    Le truc, c'est que ma fonction ne semble pas fonctionner car j'ai toujours la figure pleine, avec les faces remplies.

    Voila ma fonction qui permet la gestion du clavier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     void Clavier(unsigned char touche, int x, int y)
    {
      do
       {
         Lumiere();
       }
      while(touche !='p');
     
    }
    et la fonction Lumiere (je l'ai appelée comme ceci car comme je l'ai dit, c'est supposé clignoter et faire comme de la lumière)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     void Lumiere()
     {
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glutPostRedisplay();
       /* sleep(1); */
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glutPostRedisplay();
     
     }
    J'ai rajouté un sleep (en commentaire) pour voir si ce n'était pas la vitesse qui faisait que je ne vois pas le changement, mais ca ne donne rien.

    Je dois mal m'y prendre, comme je l'ai dit, je débute depuis très très peu (trop peu).

    Merci d'avance , en espérant que vous aillez compris ce que je souhaite faire.

    Nas'

  2. #2
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Hey !

    En fait, j'ai réussi à faire ce que je voulais mais d'une autre façon, et je ne comprend pas tout à fait pourquoi ça marche.
    J'ai tout simplement fait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void afficher()
    {
            glClearColor(0.0,0.0,0.0,0.0);
            glClear(GL_COLOR_BUFFER_BIT);
            glBegin(GL_POLYGON);
            glColor3f(1.0,1.0,1.0);
            glVertex2f(-0.5,0.5);
            glPointSize(10.0);
            glVertex2f(0.5,0.5);
            glPointSize(10.0);
            glVertex2f(0.5,-0.5);
            glVertex2f(-0.5,-0.5);
            glEnd();
            glFlush();
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glutPostRedisplay();
            sleep(1);
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            glutPostRedisplay();
     
     
    }
    Et là, ca marche parfaitement. J'ai bien le carré qui se rempli puis une fraction de seconde se "vide" (juste les contours sont visibles) puis se rempli de nouveau, etc...

    Mais pourquoi ca marche ? En fait, est-ce que le programme appelle indiffiniment la fonction d'affichage quand on dessine un carré plein normal ?

    Car la, je n'ai fait aucune boucle et pourtant ca s'arrete jamais, ca continue jusqu'à ce que j'arrête moi-même le programme !
    Donc quand on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    glutDisplayFunc(afficher);
    glutMainLoop();
    c'est comme si on était dans une boucle ?
    Et quand on definie les 4 sommets du carré, ca les dessine indiffiniment et on a donc l'impression que ca reste figé mais en fait ca dessine en continue ? Parce que le carré je le vois figé moi quand j'en dessine un simple (tout blanc par exemple).
    Enfin bon, le "MainLoop" ... ca pourrait signifier "boucler dans le main" ... c'est bien ça, je ne me trompe pas ?
    Merci

    Nas'

  3. #3
    Futur Membre du Club
    Inscrit en
    Mars 2004
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 9
    Points : 9
    Points
    9
    Par défaut
    Oui, une fois que tu lance glutMainLoop() OpenGl va boucler infiniment sur l'affichage.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2003
    Messages : 835
    Points : 1 046
    Points
    1 046
    Par défaut
    MainLoop veut dire boucle principale. Qd tu fais un peu de programmation windows , tu mets les mains dedans, il s'agit en fait d'une pompe à message (c'est comme ça que windows marche, avec des messages. J'y connais rien mais je suppose que linux c'est a peu prés la même chose).

    En gros ce que tu fais dans ton main, c'est :

    1) enregistrer des callback qui seront appelées automatiquement par glut sur certains evenements ou messages (appuie sur une touche, clic souris, réaffichage, etc...)
    2) tu appelles glutMainLoop qui va boucler indéfiniment, et celon les messages destinés à ta fenêtre va appeler tes callbacks.

    La fonction glutPostRedisplay va poster un message de type "DRAW" dans la file de message de ta fenêtre. Qd la glutMainLoop tombe dessus, elle appelle la callback d'affichage.

    Donc qd tu enregistres ta fonction "Afficher" comme callback de réaffichage, et que dans le code de celle-ci tu appelles glutPostRedisplay, je te laisse imaginer ce que ça fait... Tu réinventes le vieux truc de la boucle infinie, ce qui a apparemment l'effet que tu attends, mais de manière pas trés élégante.

    A ta place ce que je ferais :

    Dans ta callback d'affichage, tu effectues l'affichage, un point c'est tout. Autrement dit, tu dessines ta scene, une seule fois, et sans appeler glutPostRedisplay surtout !

    Ensuite, dans ton main, tu enregistres une nouvelle callback : idle (avec glutIdleFunc je crois, mais je te laisse chercher). Cette fonction sera appelée par la boucle principale à chaque fois qu'elle n'a rien d'autre à faire (aucun message dans la file). C'est une callback trés utile, indispensable même, en particulier si tu veux faire des choses un peu plus avancées, comme un jeu par exemple, c'est qd cette fonction sera appelée que tu mettras à jour tte la logique de ton jeu.

    Ta fonction idle je la verrais comme ça (je te laisse comprendre le code ):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    void Idle()
    {
      static long lastCall = GetTickCount();
      static bool ModeLine = true;
     
      //ici tu demandes le réaffichage tte les secondes
      if( (GetTickCount() - LastCall) > 1000)
      {
         //tu changes de mode d'affichage
         if(ModeLine)
         {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
         }
         else
         {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
         }
     
         //tu dis que la prochaine fois tu veux changer de mode
         ModeLine = ! ModeLine;
     
         //ici tu demandes le réaffichage
         glutPostRedisplay();
     
         //tu mets à jour l'heure de dernier appel
         LastCall = GetTickCount();
      }
    }
    J'espere que je suis assez clair. Enfin si j'ai un conseil à te donner :

    1) procure toi un bon livre sur OpenGL (je te conseil le "Red book" , ya eu un post à ce sujet recemment, fais une recherche).
    2) imprime toi la doc de glut, elle est assez petite, et en la lisant tu decouvriras surment plein de nouvelles callback à enregistrer, comme idle par exemple qui te seront bien utiles.

    PS : juste au cas où tu ne saurais pas ce que ça veut dire : Une callback c'est simplement une fonction qui sera appelée lorsque un evenement particulier survient. glut consiste en une couche d'abstraction entre toi et le systeme, en particulier il te cache la pompe à message et la gestion des evenements windows. Qd tu appelles glutKeyboardFunc(LeNomDeMaFonction) par exemple, tu enregistres une fonction qui sera appelée sur un evenement clavier.

  5. #5
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    J'en apprend des choses
    Callback... un mot que j'avais déjà vu quand j'apprenais le VB. C'était lié à "procédure" il me semble...
    J'ai bien compris la première partie de ton message, merci
    Par contre dans la seconde, là où tu me proposes une autre version du code, quelques trucs m'échappent !
    Dans le code, tu définis une variable ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static long lastCall = GetTickCount();
    Donc lastCall prend la valeur renvoyée par GetTickCount().
    Puis à la fin de la fonction (callback) tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //tu mets à jour l'heure de dernier appel
         LastCall = GetTickCount();
    Donc, à la fin de la fonction, on change la valeur de LastCall (qui était lastcall avant, sans majuscule sur le "l" mais ca doit etre une erreur de frappe).
    Puis on repasse dans le main() et ça repart de nouveau car il y'a glutMainLoop (merci d'avoir confirmé ce que je pensais, BibiGmi et Sphax)... On rappelle donc la callback idle() et là, lastCall ne prend pas la valeur définie au début du programme par la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static long lastCall = GetTickCount();
    ? Donc, si c'est le cas, à quoi a servi la dernière ligne de la fonction ?
    Désolé si c'est stupide... mais je vois vraiment pas !
    De plus, est-ce que true est défini dans gl.h ou glut.h ou bien je dois mettre 1 (équivaut à true) ?
    Et pour l'écriture suivante( que j'ai vu dans un cours mais que je ne comprenais pas) :
    , elle fait passer automatiquement ModeLine à 0 (false), mais là encore, au début du programme, ModeLine prend la valeur "true" donc on va mettre à la fin ModeLine à false mais ca revient à true, non ?

    Merci pour ton explication déjà faite ... elle m'a apporté pas mal de choses ! Si tu pouvais m'expliquer ce que je demande maintenant, ca serait encore mieux
    Merci encore

    Nas'

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2003
    Messages : 835
    Points : 1 046
    Points
    1 046
    Par défaut
    Salut,

    Alors, prenons les choses dans l'ordre, d'abord :

    • - GetTickCount est une fonction windows (si tu programmes sous un autre OS je te laisse chercher l'equivalent) qui renvoie le temps écoulé en milisecondes depuis je sais plus qd (peu importe). La seule manière d'utiliser cette fonction est en faisant une soustraction pour connaitre le temps écoulé entre 2 appels.

    • - true et false sont des mots cléfs du C++ et ne sont donc pas définis par glut. Si tu programme en C pur, utilise des 0 et des 1 à la place ça fera trés bien l'affaire.

    • - le mot cléf "static" sert à créer une variable qui ne sera pas détruite qd tu sors de la fonction, c'est en gros dans le cas qui nous interesse une espece de variable globale accessible uniquement dans la fonction "idle". De plus elle ne sera initialisée qu'une seule fois (la premiere fois qu'on entre dans idle) et JAMAIS ensuite. Pour plus d'infos la dessus trouve un bon tutorial ou livre C/C++.

    • - la syntaxe "ModeLine = ! ModeLine" est une négation, ça revient à faire :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
       
      if(ModeLine == true)
      {
        ModeLine = false;
      }
      else
      {
        ModeLine = true;
      }
      Et ici encore comme ModeLine est déclarée "static", l'initialisation n'aura lieu qu'une seule fois, et non pas à chaque fois qu'on entre dans la fonction "idle". Donc qd ce bout de code sera executé, ModeLine va passer de "vrai" à faux" la premiere fois, puis inversement, puis inversement, etc...




    Voila qques points d'eclaircissement . En ce qui concerne le fonctionnement global, ce que je fais c'est simplement changer le mode de dessin (de FILL à LINE et inversement) toutes les secondes, pour pas que ça aille trop vite. Si tu n'arrives pas trop à comprendre encore, essaye de coder la chose et de voir ce que ça fait (là je croise les doigts pour n'avoir écrit aucun bug).

    PS : oui c'etait bien une faute de frappe pour le "l" de LastCall

  7. #7
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Merci pour tes explications.
    Je n'avais pas fait attention au mot-clé "static" ... et vu que je ne l'utilise presque jamais dans mes programmes C, j'ai oublié ce qu'il faisait exactement. Maintenant, ça me revient
    Merci encore, je vais me renseigner sur l'équivalent de GetTickCount, même si je pense que la fonction time permet de faire la même chose. (elle est portable en plus, il me semble)

    Nas'

Discussions similaires

  1. Permuter deux variables sans variable temporaire
    Par khayyam90 dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 09/01/2015, 08h02
  2. Regrouper les infos de deux table sans jointure
    Par ricobye dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/07/2005, 09h30
  3. [sql] afficher deux champs de deux tables sans jointure
    Par Hell dans le forum Langage SQL
    Réponses: 6
    Dernier message: 30/06/2005, 12h38
  4. [debutant][formulaire] deux boutons
    Par F.F. dans le forum Balisage (X)HTML et validation W3C
    Réponses: 8
    Dernier message: 08/03/2005, 15h44
  5. Réponses: 6
    Dernier message: 27/05/2004, 10h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo