Introduction

Les mécanismes de sélection et de picking permettent l'interaction de l'utilisateur avec la scène 3-D :

Le mécanisme de feedback permet de récupérer des informations sur ce qui doit être dessiné sur l'écran

Sélection

  1. On dessine d'abord la scène dans le framebuffer.
  2. On entre en mode sélection et on redessine la scène.
  3. Quand on sort du mode sélection, on reçoit la liste les primitives qui intersectent le volume de visualisation (défini par la modelview, la projection, et les plans de clipping)
  4. Chaque primitive génère un hit, chaque hit contient un tableau de noms (qui sont en fait des entiers).

Sélection : les étapes

  1. Spécifier la zone mémoire pour le retour des informations de sélection par glSelectBuffer().
  2. Entrer en mode sélection en passant GL_SELCT à glRenderMode().
  3. Initialiser la pile de noms avec glInitNames() et glPushName().
  4. Définir le volume à utiliser pour la sélection. Penser à sauvegarder l'ancien volume par les glPushMatrix() et glPopMatrix() appropriés.
  5. Redessiner la scène, et faire des appels aux fonctions de manipulation de la pile de noms
  6. Sortir du mode sélection, et examiner les données retournées (une liste de hits).

Sélection : gestion de la pile de noms

glInitNames();
glPushName(-1);

glPushMatrix();   /* save the current transformation state */

    /* create your desired viewing volume here */

    glLoadName(1);
    drawSomeObject();
    glLoadName(2);
    drawAnotherObject();
    glLoadName(3);
    drawYetAnotherObject();
    drawJustOneMoreObject();

glPopMatrix ();   /* restore the previous transformation state*/

Sélection : exemple

select select.c

> ./select 
hits = 2
 number of names for hit = 1
  z1 is 3.05176e-05; z2 is 3.05176e-05
   the name is 1 
 number of names for hit = 1
  z1 is 3.05176e-05; z2 is 3.05176e-05
   the name is 3 

Le picking : un cas particulier de la sélection

On utilise gluPickMatrix() pour effectuer la sélection sur une petite zone de l'affichage

pickmatrix

On multiplie la matrice de projection par la matrice suivante :

formula

Utilisation

      glMatrixMode (GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity ();
      gluPickMatrix (...);
      gluPerspective, glOrtho, gluOrtho2D, or glFrustum
         /* ... draw scene for picking ; perform picking ... */
      glPopMatrix();

Picking : exemple

picksquare picksquare.c

> ./picksquare 
hits = 1
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 1 1 
hits = 1
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 2 1 
hits = 4
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 1 0 
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 1 1 
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 2 0 
 number of names for this hit = 2
  z1 is 3.05176e-05; z2 is 3.05176e-05
   names are 2 1 

Picking : gestion d'une hiérarchie d'objets

On utilise des noms multiples, qui reflètent la hiérarchie d'objets :

Création de noms multiples

draw_wheel_and_bolts()
{
    long i;

    draw_wheel_body();
    for (i = 0; i < 5; i++) {
        glPushMatrix();
            glRotate(72.0*i, 0.0, 0.0, 1.0);
            glTranslatef(3.0, 0.0, 0.0);
            glPushName(i);
                draw_bolt_body();
            glPopName();
        glPopMatrix();
    }
 }

draw_body_and_wheel_and_bolts()
{
    draw_car_body();
    glPushMatrix();
        glTranslate(40, 0, 20);  /* first wheel position*/
        glPushName(1);           /* name of wheel number 1 */
            draw_wheel_and_bolts();
        glPopName();
    glPopMatrix();
    glPushMatrix();
        glTranslate(40, 0, -20); /* second wheel position */
        glPushName(2);           /* name of wheel number 2 */
            draw_wheel_and_bolts();
        glPopName();
    glPopMatrix();

    /* draw last two wheels similarly */
 }

Utilisation des noms multiples

draw_three_cars()
{
    glInitNames();
    glPushMatrix();
        translate_to_first_car_position();
        glPushName(1);
            draw_body_and_wheel_and_bolts();
        glPopName();
    glPopMatrix();

    glPushMatrix();
        translate_to_second_car_position();
        glPushName(2);
            draw_body_and_wheel_and_bolts();
        glPopName();
    glPopMatrix();

    glPushMatrix();
        translate_to_third_car_position();
        glPushName(3);
            draw_body_and_wheel_and_bolts();
        glPopName();
    glPopMatrix();
}

Exemples de résultats

d1 et d2 sont les valeurs de profondeur min et max du pick

Picking et profondeur

Les valeurs de profondeur retournées permettent éventuellement de distinguer les objets par leur profondeur, si deux objets ont le même nom.

Exemple

pickdepth pickdepth.c

> ./pickdepth 
hits = 1
 number of names for hit = 1
  z1 is 0.833333; z2 is 0.833333
   the name is 3 
hits = 2
 number of names for hit = 1
  z1 is 0.166667; z2 is 0.166667
   the name is 1 
 number of names for hit = 1
  z1 is 0.5; z2 is 0.5
   the name is 2 
hits = 3
 number of names for hit = 1
  z1 is 0.166667; z2 is 0.166667
   the name is 1 
 number of names for hit = 1
  z1 is 0.5; z2 is 0.5
   the name is 2 
 number of names for hit = 1
  z1 is 0.833333; z2 is 0.833333
   the name is 3 

Avantages de la sélection OpenGL

Limitations de la sélection OpenGL

Solutions

Picking par marquage coloré

Avantages

Surbrillance

Surbrillance : mode d'emploi

Picking rapide

Surbrillance

Feedback

Retourne des informations sur ce qui doit être dessiné.

Exemple d'utilisation : Export vers un format de fichier 3D, impression

Les étapes du mode feedback :

  1. Appeler glFeedbackBuffer() pour spécifier le tableau devant recevoir les données sur les objets dessinés.
  2. Appeler glRenderMode(GL_FEEDBACK). Apres cet appel, les primitives ne sont plus rasterisées, à la place le feedback buffer est rempli.
  3. Dessiner. Éventuellement, faire des appels à glPassThrough() pour insérer des marqueurs dans le feedback buffer
  4. Appeler glRenderMode(GL_RENDER), qui renvoie le nombre de valeurs stockées dans le feedback buffer.
  5. Parser le feedback buffer

Exemple

feedback.c feedback.c

> ./feedback 
GL_LINE_RESET_TOKEN
  30.00 30.00 0.00 0.84 0.84 0.84 1.00 
  50.00 60.00 0.00 0.84 0.84 0.84 1.00 
GL_LINE_TOKEN
  50.00 60.00 0.00 0.84 0.84 0.84 1.00 
  70.00 40.00 0.00 0.84 0.84 0.84 1.00 
GL_PASS_THROUGH_TOKEN
  1.00
GL_PASS_THROUGH_TOKEN
  2.00
GL_POINT_TOKEN
  50.00 50.00 0.00 0.84 0.84 0.84 1.00 

Références