OpenGL Listes d`affichage.

Download Report

Transcript OpenGL Listes d`affichage.

Listes d’affichage
À quoi servent-elles ?
Définition :
° Un groupe de commandes OpenGL stockées pour une exécution ultérieure.
° Les commandes OpenGL sont exécutées dans l’ordre selon lequel elles avaient
été émises.
° La plupart des commandes OpenGL peuvent être soit stockées dans une liste
d’affichage, soit émises en mode exécution, ce qui provoque leur exécution
immédiate.
° On peut passer d’un mode à l’autre dans un programme comme bon nous semble.
Rôles :
° Elles contribuent à l’amélioration des performances si l’on prévoit dessiner une
même géométrie à plusieurs reprises ou si l’on dispose d’un jeu de changements
d’état à appliquer plusieurs fois.
° Elles sont créées une seule fois et exécutées autant de fois que nécessaire.
° Dans le cas où elles résident sur un serveur, cela permet de réduire le temps de
transmission des données via le réseau lorsque l’exécution s’effectue en local.2
Nommer une liste d’affichage
Chaque liste d’affichage est identifiée par un entier.
Pour éviter de choisir un entier déjà utilisé et donc de supprimer une liste déjà créée,
faites appel aux commandes glGenLists() ou glIsList() :
GLuint glGenLists(GLsizei n);
alloue n listes d’affichage jamais attribuées dont les entiers correspondants sont contigües et retourne l’entier qui marque le début de ce bloc
contigu d’entiers. Retourne 0 si le bloc d’entiers n’est pas disponible.
GLboolean glIsList(GLuint i);
retourne GL_TRUE si i est déjà utilisé pour une liste d’affichage;
GL_FALSE autrement.
Supprimer une liste d’affichage
Vous pouvez supprimer volontairement des listes d’affichage et rendre les indices
disponibles :
void glDeleteLists(GLuint i, GLsizei n);
supprime n listes d’affichage en commençant par celle d’indice i.
Si l’une d’elle n’a pas été créée, OpenGL l’ignore.
3
Créer une liste d’affichage
OpenGL fournit des délimiteurs lors de la création d’une liste d’affichage :
void glNewList(GLuint i, GLenum mode);
Spécifie le début d’une liste d’affichage désignée par i  0
selon un des modes suivants :
- GL_COMPILE : les commandes ne sont pas exécutées,
- GL_COMPILE_AND_EXECUTE :
permet une exécution immédiate et une réutilisation
ultérieure.
Les primitives d’OpenGL appelées par la suite font partie de la liste.
void glEndList();
Marque la fin de la liste d’affichage.
Exécuter une liste d’affichage
Une fois la liste d’affichage créée, il est possible de l’exécuter à l’aide de glCallList():
void glCallList(GLuint i);
4
exécute dans l’ordre les commandes de la liste d’affichage d’indice i.
Exemples
1.
Conception d’un tricycle.
Les 2 roues arrière ont les mêmes dimensions mais, à des positions différentes.
La roue avant est plus grosse et, à une position différente.
La géométrie d’une roue est stockée dans une liste d’affichage et exécutée à trois
reprises après avoir ajusté au préalable la matrice de transformation pour tenir
compte de la taille et de la position de chaque roue.
2.
Affichage d’un tore (« beigne »).
GLuint No_tore;
void Initialisation(void)
{
No_tore = glGenLists(1);
// Fournit un entier identifiant de manière unique
// la liste d’affichage.
glNewList(No_tore, GL_COMPILE);
glutSolidTorus(0.3, 1.0, 15, 30);
délimiteurs de la liste
glEndList();
glClearColor(0.0, 0.0, 0.0, 0.0);
}
5
Exemples (suite)
void affichage( void )
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
/* La commande de la liste d’affichage est exécutée.
*/
glCallList(No_tore);
/* Cela force le système à afficher les points aussitôt que possible.
*/
glFlush();
}
6
Exemples (suite et fin)
void clavier(unsigned char cle, int x, int y)
{
switch (cle)
{
case 'x': case 'X':
glRotatef(30., 1.0, 0.0, 0.0); // Rotation de 30° autour de x.
/*
La fenêtre active devra être réaffichée; la fonction
"affichage" sera appelée.
*/
glutPostRedisplay();
break;
case 'y': case 'Y':
glRotatef(30., 0.0, 1.0, 0.0); // Rotation de 30° autour de y.
glutPostRedisplay();
break;
case 'i': case 'I':
// Ramener le tore à son angle original.
glLoadIdentity();
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
glutPostRedisplay();
break;
case 27: exit(0);
break;
}
}
7
Choix de conception des listes d’affichage
Une fois la liste créée, il n’est plus possible de la lire et de la modifier
pour des raisons de performance et de gestion mémoire.
Il est impossible d’ajouter des commandes à la liste après que celle-ci a été définie.
Les paramètres des commandes OpenGL de la liste sont évalués et leurs valeurs
sont copiées dans la liste une seule fois lors de sa création. On ne peut les modifier.
Lorsque vous modifiez ultérieurement les valeurs d’un tableau par exemple,
cela ne modifie en rien les valeurs de la liste d’affichage.
Exemple :
GLfloat couleur[3] = {0.0, 0.0, 0.0};
glNewList(1, GL_COMPILE);
glColor3fv(couleur);
couleur[0] = 1.0;
glEndList();
Les meilleures implémentations d’OpenGL sont capables de concaténer des
commandes de transformation affine adjacentes pour obtenir une matrice unique.
Note :
En voulant appliquer une transformation à un objet et dessiner le résultat
obtenu, 2 options s’offrent à nous :
° la transformation ne change pas : l’inclure dans la liste d’affichage,
° la transformation change à chaque fois : ne pas l’inclure.
Vous ne pouvez exploiter qu’une seule liste d’affichage à la fois. Vous devez toujours
placer un glEndList() après un glNewList() pour mettre fin à la liste d’affichage8
avant d’en créer une autre.
Gestion des variables d’état dans les listes
Lorsque vous exécutez une liste d’affichage, n’oubliez pas de tenir compte de l’effet
de ces commandes sur la suite du programme.
Si les paramètres de visualisation sont changés entre 2 exécutions d’une liste
d’affichage, l’affichage donnera des résultats différents.
Exemple :
GLuint Numero;
void Initialisation(void)
{
Numero = glGenLists(1);
glNewList(Numero, GL_COMPILE);
glColor3f(1.0, 0.0, 0.0);
// Couleur rouge.
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f(10.0, 0.0);
glVertex2f(0.0, 10.0);
glEnd();
glTranslatef(15, 5.0, 0.0);
Nécessaire sans quoi les
glEndList();
triangles seraient superposés.
9
}
Gestion des variables d’état dans les listes
void Dessin_Segment()
{
glBegin(GL_LINES);
glVertex2f(0.0, 0.5);
glVertex2f(15.0, 0.5);
glEnd();
}
void affichage( void )
{
GLint i;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 200.0, 0.0, 200.0);
}
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
// Couleur verte.
for (i = 0; i < 10; i++) glCallList(Numero);
Dessin_Segment();
Appel en mode exécution affecté par les 10
glFlush();
appels précédents à la liste d’affichage.
10
Usage d’une pile
Puisqu’une liste d’affichage peut renfermer des modifications aux valeurs des
variables d’état, avant d’exécuter une liste d’affichage, il peut être souhaitable de
ranger l’état courant du système dans une pile et de revenir à cet état à la fin de
l’exécution de la liste.
toutes les variables
d’état
Il s’agit de placer
glPushAttributes(GL_ALL_ATTRIB_BITS);
glPushMatrix();
Ranger les variables d’état
et les matrices d’état.
au début de la liste d’affichage et
glPopAttributes();
glPopMatrix();
Restaurer le tout.
à la fin.
11
Usage d’une pile - Exemple
void Initialisation(void)
{
Numero = glGenLists(1);
glNewList(Numero, GL_COMPILE);
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0, 0.0, 0.0);
// Couleur rouge.
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f(10.0, 0.0);
glVertex2f(0.0, 10.0);
glEnd();
glTranslatef(15, 5.0, 0.0);
glPopAttrib();
glEndList();
}
Groupe d’attributs
actif
12
Listes d’affichage hiérarchisées
Ce sont des listes d’affichage qui en intègrent d’autres par un appel à glCallList()
à l’intérieur d’une paire glNewList() / glEndList().
Permet de définir des objets à l’aide de plusieurs composantes et, en particulier,
si certaines sont utilisées plusieurs fois.
Exemple :
glNewList(Indice_bicyclette, GL_COMPILE);
glCallList(Indice_guidon);
glCallList(Indice_cadre);
glTranslatef(1.0, 0.0, 0.0);
glCallList(Indice_roue);
glTranslatef(3.0, 0.0, 0.0);
glCallList(Indice_roue);
glEndList();
Le niveau d’imbrication est limité (64 par exemple).
13
Listes d’affichage hiérarchisées
Permet d’éditer une liste d’affichage en insérant plusieurs listes de bas niveau
au sein d’une liste conteneur.
Exemple : On peut modifier un sommet d’un polygone en recréant la liste d’affichage
correspondant à ce sommet.
glNewList(1, GL_COMPILE);
glVertex3fv(v1);
glEndList();
glNewList(2, GL_COMPILE);
glVertex3fv(v2);
glEndList();
glNewList(3, GL_COMPILE);
glVertex3fv(v3);
glEndList();
glNewList(4, GL_COMPILE);
glBegin(GL_POLYGON);
glCallList(1);
glCallList(2);
glCallList(3);
glEnd();
glEndList();
Le fait de créer une liste d’affichage
avec le même indice (1, 2 ou 3)
supprime la précédente.
14
Exécution de plusieurs listes d’affichage
En plaçant les index des listes d’affichage dans un tableau, vous pouvez exécuter
l’une après l’autre plusieurs listes d’affichage :
void glCallLists(GLsizei n, GLenum t, GLvoid * tab);
exécute n listes d’affichage où les index sont obtenus en ajoutant aux
composantes de tab une valeur de décalage indiquée par la base active.
Le paramètre t indique le type de données des valeurs de tab :
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, etc.
Spécifiez cette valeur de décalage en utilisant glListBase() avant d’appeler
glCallLists() :
void glListBase(GLuint base);
spécifie le décalage ajouté aux index de listes d’affichage de glCallLists()
pour obtenir les index finaux des listes d’affichage.
La base par défaut est 0.
Cette valeur de décalage n’intervient pas avec glCallList() et glNewList().
15
Exemple : affichage d’un texte
Une utilisation évidente de glListBase() et glCallLists() intervient lorsque les index
des listes d’affichage correspondent à des valeurs significatives comme par exemple
la valeur ASCII d’une lettre.
Chaque caractère d’une fonte est représenté à partir d’un ensemble de segments
de droite ou d’un polygone.
Une liste d’affichage est alors créée pour chaque caractère.
L’affichage d’un texte est réalisé en exécutant la liste d’affichage de chaque
caractère du texte.
16
Exemple : affichage d’un texte
1ière étape :
Afficher n’importe quel caractère ASCII c passé en paramètre.
void Notre_fonte(char c)
{
switch(c)
{
case ‘a’ :
.
.
.
break;
case ‘A’ :
.
.
.
break;
.
.
.
}
}
17
Exemple : affichage d’un texte

À l’intérieur de chaque « case », une attention particulière doit être portée au
positionnement de chaque caractère (chaque caractère doit être placé
exactement à la droite du caractère précédent).
Ex. :
case ‘O’ :
glTranslatef(0.5, 0.5, 0.0); /* Positionnement au centre */
glBegin(GL_QUAD_STRIP);
for (i=0; i<=12; i++)
/* 12 sommets */
{
angle=3.14159 / 6.0 * i; /* 30 degrés en radians */
glVertex2f(0.5*cos(angle), 0.5*sin(angle));
glVertex2f(0.7*cos(angle), 0.7*sin(angle));
}
glEnd();
/*Positionnement au coin inférieur droit lequel correspond au coin inférieur
gauche du caractère suivant */
glTranslatef(0.5, -0.5, 0.0);
break;
18
Exemple : affichage d’un texte
2ième étape :
/*
Création d’une liste d’affichage pour chaque caractère.
retourne le premier entier parmi un ensemble de 256 index
consécutifs disponibles.
*/
base = glGenLists(256);
/*
Spécifie le décalage à ajouter aux index des listes d’affichage. */
glListBase(base);
/*
Création des listes d’affichage.
for (i=0; i<256; i++)
{
glNewList(base + i, GL_COMPILE);
Notre_fonte(i);
glEndList();
}
*/
19
Exemple : affichage d’un texte
3ième étape :
Affichage d’un texte.
char * test = "Locomotive";
...
GLsizei longueur = strlen(test);
glCallLists(longueur, GL_BYTE, (GLbyte *) test);
...
FIN
20