OpenGL avec Delphi


précédentsommairesuivant

VII. Listes d'affichage

VII-A. Qu'est-ce qu'une liste d'affichage

Une liste d'affichage permet d'améliorer les performances de votre application dans la mesure où il est possible d'y stocker une ou plusieurs commandes d'OpenGL et de les rappeler par UNE simple commande. Le principe est assez simple, on demande à OpenGL de nous donner un numéro d'autorisation pour la nouvelle liste et une fois ce numéro récupéré, nous stockons les commandes à l'intérieur de ces deux clauses que voici : glNewList(…); / glEndList();

Les commandes pouvant être stockées peuvent être par exemple :

  • des formes géométriques (Primitives) ;
  • rotations, translations et redimensionnements… ;
  • ou encore une partie d'une scène ou une scène entière.

VII-B. À quoi servent plus précisément les listes d'affichage

Quand on construit un cube sommet par sommet avec les deux commandes glBegin( GL_QUADS); / glEnd();, ce code prend considérablement de la place et par ailleurs il doit être recalculé à chaque rendu dans notre scène. Pour contrer ce problème, la liste d'affichage permet de créer en permanence l'objet ou l'action de votre choix et de simplement le ou la rappeler avec la commande suivante : glCallList( Numéro_de_la_liste );.

Voici un problème donné

Vous voulez dessiner un bonhomme de neige, mais vous constatez que vous devez créer trois sphères de différentes grosseurs (à supposer aussi que GLUT n'existe pas). Évidemment les trois sphères ont toutes la même forme, mais elles sont de dimensions différentes et par la même occasion vous vous dites :
mais je n'ai pas besoin de créer trois sphères, car je n'ai qu'à en fabriquer une et la redimensionner avant de l'afficher !
Et comme dit précédemment, à supposer que GLUT n'existe pas, alors il vous faudra créer la sphère avec les mathématiques et cela implique le besoin de se servir des fonctions Cos et Sin qui sont très gourmandes en temps machine. Cela n'aurait pas de sens de fabriquer trois sphères à chaque fois que votre scène se redessine, ce serait trop long. La solution…

Donc, il faut fabriquer une fonction capable de créer une sphère avec un rayon et le nombre de méridiens et parallèles donnés. Une fois celle-ci fabriquée alors nous pourrons nous en servir pour construire le bonhomme de neige en redimensionnant la sphère en fonction de la partie du corps à dessiner.

En conclusion, il suffit de stocker la ou les bases géométriques dans une liste d'affichage et y faire appel autant de fois que nécessaire. Quand vous n'aurez plus besoin de cette liste, il sera aussi possible de la supprimer, ce qui libère de la mémoire, bref… tout pour donner une chance aux performances de votre application. Mais notez qu'une fois supprimés, elle et son contenu ne seront plus en mémoire, mais par contre l'index pris par celle-ci sera maintenant réutilisable pour la création d'une nouvelle liste au besoin.

Voyons comment créer une liste d'affichage :

  1. Demandez à OpenGL d'attribuer (Générer) un index à notre liste d'affichage avec la commande suivante : glGenList(…); ;
  2. Créez la liste en vous servant de ces deux commandes : glNewList( GLuint list, GLenum mode ); / glEndList(); ;
  3. Une fois l'utilisation terminée (souvent à la fermeture du programme) alors supprimez la liste avec la commande : glDeleteList(…);.

Voici un exemple simple :

 
Sélectionnez
procedure TFrmOpenGL.FormCreate(Sender: TObject);
Begin
    ...
    glClearColor( 0, 0, 0, 1 );
    glEnable( GL_DEPTH_TEST );

    Sphere := glGenLists( 1 );
    glNewList( Sphere, GL_COMPILE );
        CreerSphere( 30, 30, 5.0 );
    glEndList();
    ...
End;

Procedure TFrmOpenGL.CreerSphere( Const NbParalleles :GLint;
                                  Const NbMeridiens :GLint;
                                  Const Rayon :GLdouble );
Const
     DOUBLE_PI = 2 * PI;
Var
   I, J          :Integer;
   Theta,Theta2  :GLfloat;
   Phi           :GLfloat;
   Vx, Vy, Vz    :GLdouble;
begin
     glPushMatrix();
     For I := 0 To NbParalleles  Do
     Begin
          glBegin( GL_TRIANGLE_STRIP );

          Theta  := I       * DOUBLE_PI / NbParalleles;
          Theta2 := (I + 1) * DOUBLE_PI / NbParalleles;
          For J := 0 To NbMeridiens Do
          Begin
               Phi  := J * DOUBLE_PI / NbMeridiens;

               Vx := Cos(Theta) * Cos(Phi);
               Vy := Cos(Theta) * Sin(Phi);
               Vz := Sin(Theta);
               glNormal3f( Vx, Vy, Vz );
               glVertex3d( Rayon * Vx, Rayon * Vy, Rayon * Vz );

               Vx := Cos(Theta2) * Cos(Phi);
               Vy := Cos(Theta2) * Sin(Phi);
               Vz := Sin(Theta2);
               glNormal3f( Vx, Vy, Vz );
               glVertex3d( Rayon * Vx, Rayon * Vy, Rayon * Vz );

          End;
          glEnd();
     End;
     glPopMatrix;
End;


Procedure TFrmOpenGL.DessinerScene;
Begin
     glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT);
     glClearColor( 0.0, 0.0, 0.0, 1.0 );

     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity;

     glTranslated( 0.0, 0.0, -20.0 );
     glCallList( Sphere );

     SwapBuffers( Canvas.Handle );
End;

VII-C. Explication de l'exemple

C'est loin d'être un exemple complet, mais j'ai juste inclus les principaux points importants pour me servir d'une liste d'affichage, vous y verrez plus clair dans l'exemple livré avec ce tutoriel dans le bas de la page.

glGenLists(1);
On demande à OpenGL de générer un nombre de listes en mémoire, ici on lui à passé 1 en paramètre donc une liste sera générée. Cette commande retourne un indice qui sera attribué à notre liste. Si glGenLists retourne 0 alors c'est qu'OpenGL n'a pu créer la liste, soit par manque de mémoire ou parce que tous les indices sont déjà pris.

glNewList( Boule, GL_COMPILE ); / glEndList();
Le premier paramètre spécifie l'index de la liste. Donc une variable de type entier non signé qui contient l'indice de la liste précédemment récupéré avec la commande glGenList(…). Le deuxième paramètre spécifie le mode de compilation. GL_COMPILE ou GL_COMPILE_AND_EXECUTE. La différence entre ces deux paramètres est la suivante : si vous utilisez GL_COMPILE alors la liste d'affichage est compilée et prête à être utilisée, en revanche si vous utilisez le mode GL_COMPILE_AND_EXECUTE alors la liste peut être utilisée lors de sa compilation. Tous les commandes, appels de fonctions ou procédures… se trouvant à l'intérieur de ces deux commandes feront partie de la conception de la liste. Donc quand vous ferez appel à cette liste, tout ce qui était à l'intérieur aura été compilé et prêt à être utilisé.

glCallList( Sphere );
Le résultat de cette commande est de faire appel à tout ce qui a été compilé à l'intérieur de la liste d'affichage, par conséquent dans ce cas-ci, se sera notre sphère qui sera dessinée.
Son seul paramètre est l'index de la liste d'affichage, alors nous lui passons la variable Sphere. Cette variable contient l'index, car elle lui a été attribuée à l'aide de la commande glGenList(…).

Je ne l'ai pas mentionné, mais il est aussi possible pendant la conception d'une liste d'affichage de faire appel à d'autres listes d'affichage selon le besoin.

Et maintenant voici l'exemple concernant les listes d'affichage :

Image non disponible

VII-D. Programme relié

Hmmm ! Pas facile, mais cette horloge est entièrement faite avec la même sphère. Tout un défi ! L'exemple n'est pas des plus faciles, mais je vous conseille fortement de l'étudier et ensuite vous devriez très bien maîtriser les listes d'affichage.

Source

Pour ceux que cela intéresse, voici l'autre manière. Source (à la C++)


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2002 Martin Beaudet. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.