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

Contribuez Discussion :

[Source][OpenGL] Le Picking [Sources]


Sujet :

Contribuez

  1. #1
    Membre habitué
    Avatar de yvesall
    Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2006
    Messages
    208
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 208
    Points : 127
    Points
    127
    Par défaut [Source][OpenGL] Le Picking
    Salut tout le monde, j'ai eu dernièrement l'idée de faire du picking sur une scène 3D en OpenGL.
    De nombreux tuto existe, même en français, mais ça ne m'a pas empêcher de m'arracher les cheveux pour y arriver.
    http://www.developpez.net/forums/d66...e/#post3882413

    Donc pour répondre a la demande de Shenron666 je vais poster les sources du code que j'ai pondu, dans lequel j'ai rajouter des commentaires histoire d'aider au mieux sur ce sujet la :
    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
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    /*
    ** Par Yves Desgraupes
    ** yves.desgraupes@free.fr
    ** bddy.free.fr
    ** 2008 tous droits pas reservés :)
    ** ------------------------------
    ** Test de picking sur une scène 3D (2 carrés superposés)
    ** Système de fenetrage : SDL
    ** API graphique : OpenGL
    ** Librairies nécessaires : SDL && gl && glu
    ** Fichiers nécessaires : SDL.dll || SDL.so
    ** Langage : C++ (bien que ca soit du C+ :s)
    */
     
    #include <iostream>                                                             //Pour écrire sur la sortie standard/erreur
    #include <SDL/SDL.h>                                                            //Pour créer une fenetre et gérer les évènements
    #include <GL/gl.h>                                                              //On fait de l'OpenGL, non ?
    #include <GL/glu.h>                                                             //Parce qu'elle est bien pratique cette lib (un conseil : recodez 'gluPerspective' et 'gluLookAt' pour gagner en perf)
     
    /*
    ** Déclaration du prototype de toutes les fonctions meme si là, ca ne sert pas à grand chose
    */
    void	checkevents();
    void    draw();
    void    processHits(GLint hits, GLuint *buffer);
    void    picking();
    void    drawsquare(bool cas);
    void	taketime(bool cas);
    bool    initGL();
     
    /*
    ** Déclaration de variables globales, c'est mieux que des #define, le type des variables étant déclaré
    */
    const int WIN_X = 800;                                                          //Largeur de la fenetre
    const int WIN_Y = 600;                                                          //Hauteur de la fenetre
    const int BUFSIZE = 1024;                                                       //Taille du buffer de selection
     
    /*
    ** Déclaration de variables globales, mais cette fois c'est TRES MOCHE
    ** pour une raison de clarté, je les laisse ici plutot que de les mettre dans plusieurs struct
    ** ou une éventuelle class.
    ** mais ca reste très moche !!! donc, recodez sans global de ce genre !!!
    */
    int         sTime;
    int         cTime;
    int         eTime;
    int         mx = 0;
    int         my = 0;
    bool        go = true;
    bool        click;
    SDL_Event   event;
    SDL_Surface *screen;
     
    /*
    ** Initialisation de la fenetre qui contiendra notre scène
    */
    bool    initGL()
    {
        if (SDL_Init(SDL_INIT_VIDEO))                                               //On démarre la SDL avec le système d'affichage
        {                                                                           //et on vérifie qu'elle se soit bien chargée
            std::cerr << "SDL_Init : [FAILED]" << std::endl;                        //On écrit d'ou vient la panne
            return (false);                                                         //et on s'en va
        }
        SDL_WM_SetCaption("OpenGL Rox", NULL);                                      //On ajoute un titre à notre future fenetre
        if (!(screen = SDL_SetVideoMode(WIN_X, WIN_Y, 32, SDL_OPENGL)))             //On set le système d'affichage
        {                                                                           //et on vérifie que tout se soit bien passé
            std::cerr << "SDL_SetVideoMode : [FAILED]" << std::endl;                //On écrit d'ou vient la panne
            return (false);                                                         //et on s'en va
        }
        glEnable(GL_DEPTH_TEST);                                                    //Activation des tests de profondeur du z-buffer
        SDL_WarpMouse(screen->w / 2, screen->h / 2);                                //On centre le pointeur de la souris au milieu de notre fenetre
        return (true);
    }
     
    /*
    ** Gestion du temps pour chaque tour de boucle de notre programme
    */
    void	taketime(bool cas)                                                      //cas : différencier le moment d'appel dans la boucle
    {
      if (!cas)                                                                     //cas 0 : on est en début de boucle
        sTime = SDL_GetTicks();                                                     //alors on prend le temps au départ de la boucle
      else                                                                          //cas 1 : on est en fin de boucle
        {
          cTime = SDL_GetTicks();                                                   //alors on prend le temps en fin de boucle
          eTime = cTime - sTime;                                                    //On calcule le temps écoulé entre le début et la fin
          if (eTime < 10)                                                           //et si la boucle a duré moins de 10ms
            SDL_Delay(10 - eTime);                                                  //On met en pause le programme pour 10ms moins le temps déjà écoulé
        }
    }
     
    /*
    ** On déclare les objets de notre scène
    */
    void    drawsquare(bool cas)                                                    //cas : différencier le mode de rendu (RENDER/SELECT)
    {
        if (cas)                                                                    //Cas 1 : on est en mode SELECT, le picking est actif
            glLoadName(1);                                                          //alors on attribut un nom (1) à l'objet qui suit
        glColor3ub(255, 255, 255);                                                  //On déclare la couleur de l'objet (pour le coup : blanc)
        glBegin(GL_QUADS);                                                          //On déclare le type de l'objet
            glVertex3d(0, 0, 0);                                                    //On décrit chacun des 4 points que comprend notre carré
            glVertex3d(0, 10, 0);
            glVertex3d(10, 10, 0);
            glVertex3d(10, 0, 0);
        glEnd();                                                                    //On déclare la fin de notre objet
                                                                                    //On recommence avec un carré rouge
        if (cas)                                                                    //Cas 1 : on est en mode SELECT, le picking est actif
            glLoadName(2);                                                          //alors on attribut un nom (2) à l'objet qui suit
        glColor3ub(255, 0, 0);                                                      //On déclare la couleur de l'objet (pour le coup : rouge)
        glBegin(GL_QUADS);                                                          //On déclare le type de l'objet
            glVertex3d(3, 3, 0.2);                                                  //On décrit chacun des 4 points que comprend notre carré
            glVertex3d(3, 7, 0.2);
            glVertex3d(7, 7, 0.2);
            glVertex3d(7, 3, 0.2);
        glEnd();                                                                    //On déclare la fin de notre objet
    }
     
    /*
    ** On décortique ce que le picking nous renvoie
    */
    void    processHits(GLint hits, GLuint *buffer)                                 //hits : nombre d'objets touchés ; buffer : pointeur sur le buffer de selection
    {
        GLuint  names;                                                              //Sauvegardera le nombre de noms d'un Hit
        GLuint  *ptr;                                                               //Pointeur pour parcourir le buffer
     
        std::cout << "hits = " << hits << std::endl;                                //On affiche le nombre de Hit
        ptr = (GLuint *)buffer;                                                     //On fait pointer notre pointeur sur celui du buffer
        for (int i = 0; i < hits; i++)                                              //Et on parcourt tous nos Hits
        {
            names = *ptr;                                                           //Sauvegarde du nombre de noms du Hit
            std::cout << " number of names for this hit = " << names << std::endl;  //Affichage du nombre de noms du Hit
            ptr++;                                                                  //On déplace le pointeur dans la mémoire
            std::cout << "  z1 is " << (float)*ptr / 0x7fffffff;                    //Affichage de la valeur minimale de la coordonnée Z
            ptr++;                                                                  //On déplace le pointeur dans la mémoire
            std::cout << " z2 is " << (float)*ptr / 0x7fffffff << std::endl;        //Affichage de la valeur maximale de la coordonnée Z
            ptr++;                                                                  //On déplace le pointeur dans la mémoire
            std::cout << "   NAMES ";                                               //Affichage pour faire joli
            for (unsigned int j = 0; j < names; j++)                                //On parcourt tous les noms du Hit
            {
                std::cout << *ptr << std::endl;                                     //Affichage du nom
                ptr++;                                                              //On déplace le pointeur dans la mémoire
            }
            std::cout << std::endl;                                                 //Affichage pour faire joli
        }
        std::cout << std::endl << "--------------------" << std::endl << std::endl; //Affichage pas pour faire joli mais pour y voir plus clair
    }
     
    /*
    ** On regarde ce qu'il se cache sous le pointeur de la souris
    */
    void    picking()
    {
        GLuint  selectBuf[BUFSIZE];                                                 //Création d'un buffer de sélection de la taille de BUFSIZE
        GLint   hits;                                                               //Contiendra le nombre d'objet touchés par le pointeur de la souris
        GLint   viewport[4];                                                        //Contiendra les valeurs du viewport
     
        glGetIntegerv(GL_VIEWPORT, viewport);                                       //Récupération des valeurs du viewport
     
        glSelectBuffer(BUFSIZE, selectBuf);                                         //Etablit un buffer pour les valeurs du mode SELECT
        (void)glRenderMode(GL_SELECT);                                              //Sélection de la méthode de rastérisation
     
        glInitNames();                                                              //Initialisation de la pile de nom
        glPushName(0);                                                              //On initialise la pile de nom avec (0)
     
        glMatrixMode(GL_PROJECTION);                                                //On passe par la matrice de projection
        glPushMatrix();                                                             //On sauvegarde la matrice courante
        glLoadIdentity();                                                           //et on la réinitialise
        gluPickMatrix((GLdouble) mx, (GLdouble) (viewport[3] - my), 2.0, 2.0, viewport); //On définit la région du picking et sa précision
        gluPerspective(70, float(WIN_X / WIN_Y), 0.1, 1000);                        //On donne à notre matrice les proportions de la scène
     
        drawsquare(true);                                                           //On affiche les 2 carrés et on leur attribut un (ou plusieurs) nom(s)
     
        glPopMatrix();                                                              //On recharge la matrice précédemment sauvegardée
        glPopName();                                                                //On supprime le nom de la pile
        glFlush();                                                                  //On flush les commandes OpenGL
     
        hits = glRenderMode(GL_RENDER);                                             //On récupère le nombre d'objets touchés tout en sortant du mode SELECT
        processHits(hits, selectBuf);                                               //On traite notre sélection
    }
     
    /*
    ** On crée un rendu graphique
    */
    void    draw()
    {
        glViewport(0, 0, WIN_X, WIN_Y);                                             //Création de la taille du ViewPort pour indiquer les frontières du cadrage actif
        glMatrixMode(GL_PROJECTION);                                                //On passe par la matrice de projection
        glLoadIdentity();                                                           //et on la réinitialise pour éviter de cumuler les transformations
     
        gluPerspective(70, float(WIN_X / WIN_Y), 0.1, 1000);                        //On donne les proportions de notre scène en modifiant la matrice courante
        glMatrixMode(GL_MODELVIEW);                                                 //On passe par la matrice modelview
        glLoadIdentity();                                                           //et on la réinitialise pour éviter de cumuler les transformations
     
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                         //Effacement du tampon d'affichage
        gluLookAt(-10, -10, 10, 0, 0, 0, 0, 0, 1);                                  //Mise en place du point de vue
     
        drawsquare(false);                                                          //On affiche seulement les 2 carrés sans leur attribuer de nom
     
        glFlush();                                                                  //Flushage des commandes OpenGL
        SDL_GL_SwapBuffers();                                                       //Affichage du buffer dans la fenetre
    }
     
    /*
    ** On gère les évènements (clavier / souris)
    */
    void	checkevents()
    {
        if (event.type == SDL_QUIT)                                                 //Si on clique sur la croix pour fermer la fenetre
            go = false;                                                             //on passe go a false
        else if (event.type == SDL_KEYDOWN)                                         //Si un bouton du clavier est appuyé
            if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_DELETE) //et que c'est l'un de ceux-là (Echap ou Suppr)
                go = false;                                                         //on passe go a false
        if (event.type == SDL_MOUSEMOTION)                                          //Si on bouge la souris
        {
            mx = event.motion.x;                                                    //On sauvegarde sa position en x
            my = event.motion.y;                                                    //On sauvegarde sa position en y
        }
        else if (event.type == SDL_MOUSEBUTTONDOWN)                                 //Si on clique sur l'un des boutons de la souris (molette haut/bas compris)
        {
            if (event.button.button == SDL_BUTTON_LEFT)                             //et que c'est le click gauche
                click = true;                                                       //on passe le click a true
        }
        else if (event.type == SDL_MOUSEBUTTONUP)                                   //Si on relache le click sur l'un des boutons de la souris
        {
            if (event.button.button == SDL_BUTTON_LEFT)                             //et que c'est le click gauche
                click = false;                                                      //on passe le click a true
        }
    }
     
    /*
    ** Faut bien commencer quelque part
    */
    int main(int argc, char **argv)
    {
    #ifdef WIN32                                                                    //SDL redirige de lui-meme les sorties standard/erreur
      freopen("CON","w", stderr);                                                   //En fonction de l'OS il y aura besoin de réouvrir les sorties
      freopen("CON","w", stdout);                                                   //pour afficher sur la console et non plus dans des fichiers
    #endif
        if (!initGL())                                                              //Initialisation de la fenetre SDL/OpenGL
            return (1);                                                             //si ca loupe, on quitte en failure
        while (go)                                                                  //Notre programme tourne tant que (go == true)
        {
            taketime(false);                                                        //Prise du temps du départ de la boucle
     
            while (SDL_PollEvent(&event))                                           //SDL parcourt pour nous les évènements clavier/souris et les stocks dans 'event'
                checkevents();                                                      //On fait notre gestion des évènements
            draw();                                                                 //On affiche la scène
            if (click)                                                              //Si le click gauche est appuyé
                picking();                                                          //on tente de picker la scène
     
            taketime(true);                                                         //Prise du temps de la fin de boucle et pause du programme
        }
        SDL_Quit();                                                                 //On ferme la fenetre SDL et toute autre initialisation liée à elle
     
        return (0);                                                                 //Le programme quitte correctement
    }
    je me suis aidé des liens suivant :
    http://glinfrench.apinc.org/article.php3?id_article=83
    http://helios.univ-reims.fr/Labos/LE...enGL/td10.html
    http://www.lighthouse3d.com/opengl/picking/

    en espérant avoir servit
    cordialement
    i = i++;

  2. #2
    Rédacteur

    Avatar de loka
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2004
    Messages
    2 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 672
    Points : 5 509
    Points
    5 509
    Par défaut
    merci, je vais tester ça et voir si on peut le rajouter aux sources OpenGL

  3. #3
    Membre habitué
    Avatar de yvesall
    Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2006
    Messages
    208
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 208
    Points : 127
    Points
    127
    Par défaut
    qu'en est il ?
    i = i++;

  4. #4
    Rédacteur

    Avatar de loka
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2004
    Messages
    2 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 672
    Points : 5 509
    Points
    5 509
    Par défaut
    J'ai oublié de te faire un retour, le code est ok pour l'ajout dans la partie sources. Je fais l'ajout ce soir

  5. #5
    Rédacteur

    Avatar de loka
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2004
    Messages
    2 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 672
    Points : 5 509
    Points
    5 509

  6. #6
    Membre habitué
    Avatar de yvesall
    Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2006
    Messages
    208
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 208
    Points : 127
    Points
    127
    Par défaut
    super
    merci
    i = i++;

  7. #7
    Membre habitué
    Avatar de yvesall
    Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2006
    Messages
    208
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 208
    Points : 127
    Points
    127
    Par défaut
    je signal une bourde de ma part dans les sources

    la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gluPerspective(70, float(WIN_X / WIN_Y), 0.1, 1000);
    devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gluPerspective(70, double(WIN_X) / double(WIN_Y), 0.1, 1000);
    sinon le cast ne se fait pas sur la division mais seulement sur le résultât et par conséquent retourne la valeur entière arrondi à l'inférieur et non la décimale désirée
    i = i++;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Source] [OpenGL] Shadow Mapping
    Par drcd dans le forum Contribuez
    Réponses: 4
    Dernier message: 28/06/2009, 12h41
  2. besoin d'aide opengl et picking
    Par steebatc dans le forum OpenGL
    Réponses: 2
    Dernier message: 16/03/2009, 20h05
  3. [Source] [OpenGL] Remake en OpenGL du jeux IK+
    Par BruceBoc dans le forum Contribuez
    Réponses: 18
    Dernier message: 19/04/2007, 16h55
  4. [Source] [OpenGL] Chargeur de modèles ASE (light)
    Par MrDuChnok dans le forum Contribuez
    Réponses: 1
    Dernier message: 17/07/2006, 14h03
  5. Page "Sources OpenGL" : appel à contributions
    Par raptor70 dans le forum OpenGL
    Réponses: 1
    Dernier message: 14/07/2006, 05h09

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