INTRODUCTION OPENGL Open GL est une interface logicielle

  • Slides: 58
Download presentation
INTRODUCTION À OPENGL Open. GL est une interface logicielle capable de communiquer avec le

INTRODUCTION À OPENGL Open. GL est une interface logicielle capable de communiquer avec le matériel graphique. Il s’agit d’une bibliothèque d’outils de traitement graphique indépendante du matériel où l’on peut créer des programmes interactifs produisant des images réalistes ou abstraites en couleurs d’objets 3 D. Les lettres GL signifient Graphics Library.

Qu’est-ce qu’Open. GL ? Open. GL est une interface logicielle destinée aux applications graphiques

Qu’est-ce qu’Open. GL ? Open. GL est une interface logicielle destinée aux applications graphiques composée d’environ 250 commandes distinctes. C’est une interface indépendante du matériel qu’il est possible d’implémenter sur de nombreuses plates-formes matérielles différentes. Open. GL ne renferme pas à proprement parler de commandes permettant d’effectuer des tâches de fenêtrage ou de récupérer des entrées utilisateur. Il faudra faire appel notamment à un gestionnaire de fenêtres. Open. GL ne renferme pas de commandes de haut niveau permettant de définir des objets tridimensionnels complexes. Vous devez construire vos modèles à partir d’un jeu restreint de formes géométriques primitives : des points, des segments et des polygones. On peut superposer à Open. GL une bibliothèque GLU (Open. GL Utility Library) sophistiquée intégrant ces fonctionnalités : les surfaces quadriques et les techniques de points de contrôle. Les primitives de GLU commencent par le préfixe glu.

Pour chaque gestionnaire de fenêtres, une bibliothèque étend les fonctionnalités du système afin de

Pour chaque gestionnaire de fenêtres, une bibliothèque étend les fonctionnalités du système afin de supporter Open. GL. Pour les ordinateurs X Window, l’extension Open. GL correspondante est GLX où les routines emploient le préfixe gl. X. Une autre librairie GLUT (Open. GL Utility Toolkit) est un ensemble d’outils indépendant du gestionnaire de fenêtres, conçu afin de masquer les complexités des différents appels au gestionnaire de fenêtres. PROGRAMME D’APPLICATION GL GLUT GLX Librairie de base Microsoft Windows requiert l’insertion de windows. h comme suit : #include <windows. h> #include <GL/glu. h> ----fichiers personnels ----Si vous faites appel à GLUT, éviter les redondances et omettre GL et GLU.

Fonctionnalités d’Open. GL ? Voici les principales opérations graphiques réalisées par Open. GL pour

Fonctionnalités d’Open. GL ? Voici les principales opérations graphiques réalisées par Open. GL pour restituer une image à l’écran : Construire des formes géométriques à l’aide de primitives (points, segments, polygones, images). Positionner et orienter les objets dans un espace tridimensionnel et sélectionner le point de vue le plus avantageux pour visualiser la scène composée. Déterminer les couleurs des objets en prenant en compte les conditions d’éclairage et leur texture. Convertir les données géométriques et les caractéristiques physiques en valeurs pour les pixels à l’écran.

Gestion des fenêtres Surface rectangulaire d’affichage sur l’écran (par défaut, il s’agit de l’écran

Gestion des fenêtres Surface rectangulaire d’affichage sur l’écran (par défaut, il s’agit de l’écran au complet). La fenêtre est définie par sa hauteur et sa largeur de même que sa position en coordonnées écran (unités : « pixels » ) Dans des environnements riches, il peut exister plusieurs fenêtres. En Open. GL, l’origine de la fenêtre est en bas à gauche tandis que les données fournies par le système de gestion de fenêtres optent pour une origine en haut à gauche. glut. Init (int *argcp, char **argv) Permet une interaction entre le système de gestion de fenêtres et Open. GL. Doit être appelée avant toute autre routine GLUT. int glut. Create. Window(char * titre_de_la_fenêtre) Création d’une fenêtre avec un titre au haut fourni en paramètre. La fenêtre créée a une dimension et une position par défaut. La primitive retourne un entier unique pour la nouvelle fenêtre.

Gestion des fenêtres Avant la création de la fenêtre, on peut fixer les paramètres

Gestion des fenêtres Avant la création de la fenêtre, on peut fixer les paramètres de celle-ci au-lieu de se contenter de ceux par défaut : void glut. Init. Window. Size(int largeur, int hauteur); Fixe la largeur et la hauteur initiales, en pixels, de la fenêtre. glut. Init. Window. Position(int x, int y); Fixe la position du coin supérieur gauche, en pixels, de la fenêtre. Une fois la fenêtre créée, pour faire en sorte que la fenêtre s’affiche et afin de conserver l’image produite à l’écran, il faudra appeler la primitive suivante : void glut. Main. Loop(void); Entre dans la boucle de traitement sans fin GLUT à moins que des événements soient générés. Puisqu’aucun événement n’est prévu, le programme exécuté sera mis en attente, l’image affichée à l’écran. On peut détruire une fenêtre déjà créée dont le numéro est i : void glut. Destroy. Window(int i);

Gestion des fenêtres Une fenêtre nouvellement créée devient la fenêtre courante. Pour rendre active

Gestion des fenêtres Une fenêtre nouvellement créée devient la fenêtre courante. Pour rendre active une autre fenêtre déjà créée, on a : void glut. Set. Window(int id); Ainsi, nous pouvons avoir plusieurs fenêtres et chacune possède ses propres caractéristiques. On peut aussi créer des sous-fenêtres à l’intérieur d’une fenêtre déjà créée. int glut. Create. Sub. Window(int parent, int x, int y, int largeur, int hauteur); La sous-fenêtre devient la fenêtre courante; son origine est à (x, y) tandis que largeur et hauteur désignent resp. la largeur et la hauteur de la sous-fenêtre en pixels. (x, y) désigne le coin supérieur gauche de la sous-fenêtre par rapport à l’origine de la fenêtre.

Fonction d’affichage La primitive void glut. Display. Func(void (*f)(void)) permet de spécifier le nom

Fonction d’affichage La primitive void glut. Display. Func(void (*f)(void)) permet de spécifier le nom de la fonction qui renfermera les primitives d’affichage. f sera appelée si le système de gestion des fenêtres détermine que la fenêtre courante a besoin d’être réaffichée.

Ébauche de programme en Open. GL Voici la forme la plus simple d’un programme

Ébauche de programme en Open. GL Voici la forme la plus simple d’un programme Open. GL où une fenêtre vide est affichée : #include <windows. h> #include <GL/glut. h> void Affichage() { // Permet d’effacer la fenêtre active et de l’afficher avec la couleur de fond // par défaut. gl. Clear(GL_COLOR_BUFFER_BIT); // Force les commandes Open. GL émises précédemment à s’exécuter. gl. Flush(); }

void main(int argc, char** argv) { // Permet d'initialiser des paramètres de certains utilitaires

void main(int argc, char** argv) { // Permet d'initialiser des paramètres de certains utilitaires d’Open. GL. glut. Init(&argc, argv); /* Permet de fixer la dimension de la fenêtre à l'écran soit, 800 pixels de largeur par 500 de hauteur. */ glut. Init. Window. Size(800, 500); // Permet de fixer la position du coin supérieur gauche de la fenêtre. glut. Init. Window. Position(500, 100); /* Créer une fenêtre avec comme titre celui passé en paramètre. Les paramètres de la fenêtre doivent avoir été fixés au préalable. */ glut. Create. Window("Fenetre principale"); /* Spécifie la fonction "Affichage" qui sera appelée chaque fois que la fenêtre doit être affiché. */ glut. Display. Func(Affichage); /* Permet de conserver l'image produite à l'écran. Le programme exécuté est mis en attente jusqu'à ce qu'un événement se produise, l'image demeurant affichée à l'écran. */ glut. Main. Loop(); }

TYPES DE DONNÉES OPENGL Open. GL manipule des types de données propres à Open.

TYPES DE DONNÉES OPENGL Open. GL manipule des types de données propres à Open. GL. Puisqu’il n’y a pas de standard pour le type int (16 ou 32 bits), le type float ou le type double, nous devons utiliser des types de données propres à Open. GL. Suffixe b s i f d ub us ui Type de donnée entier 8 bits entier 16 bits entier 32 bits réel 64 bits nb. sans signe 8 bits nb. sans signe 16 bits nb. sans signe 32 bits C++ signed char short int ou long float double unsigned char unsigned short unsigned int ou unsigned long Open. GL GLbyte GLshort GLint, GLsizei GLfloat, GLclampf GLdouble, GLclampd GLubyte, GLboolean GLushort GLuint, GLenum, GLbitfield

Tracé de formes géométriques de base Pour afficher différentes formes géométriques, nous devrons procéder

Tracé de formes géométriques de base Pour afficher différentes formes géométriques, nous devrons procéder à l’intérieur d’une fonction « Affichage » : glut. Display. Func(Affichage); Open. GL définit des objets géométriques de base à partir d’une liste de sommets. En Open. GL, on réfère plutôt au concept de sommet de préférence à celui de point : forme générale : gl. Vertex*() où * représente 2 ou 3 caractères de la forme nt ou ntv où n : dimension (2, 3 ou 4), t : type de donnée : : i pour entier f pour réel en point flottant d pour réel double précision. v : indique la présence d’un pointeur à un vecteur plutôt qu’une liste d’éléments.

Exemples de définition de sommets : (i) entiers dans l’espace à 2 dimensions gl.

Exemples de définition de sommets : (i) entiers dans l’espace à 2 dimensions gl. Vertex 2 i(GLint xi, GLint yi); (ii) nombres réels dans l’espace à 3 dimensions gl. Vertex 3 f(GLfloat x, GLfloat y, Glfloat z); (iii) vecteur de 3 nombres réels typedef GLfloat vertex[3]; nous avons ainsi : gl. Vertex 3 fv(vertex); (iv) vecteur de 3 points dans l’espace à 2 dimensions typedef GLfloat point 2[2]; point 2 triangle[3];

 FORME GÉNÉRALE POUR DÉFINIR UN OBJET Pour regrouper les sommets définissant un objet,

FORME GÉNÉRALE POUR DÉFINIR UN OBJET Pour regrouper les sommets définissant un objet, on utilise les fonctions : gl. Begin et gl. End. Le paramètre de gl. Begin définit le type d’objet géométrique l’on veut représenter. La forme générale pour définir des objets géométriques : gl. Begin(type); gl. Vertex*(…); . . . gl. Vertex*(…); gl. End(); La valeur de « type » permet de définir le type d’objet géométrique représenté par ces sommets.

EXEMPLES DE DÉFINITION (i) un segment de droite gl. Begin(GL_LINES); gl. Vertex 2 f(x

EXEMPLES DE DÉFINITION (i) un segment de droite gl. Begin(GL_LINES); gl. Vertex 2 f(x 1, y 1); gl. Vertex 2 f(x 2, y 2); gl. End(); (ii) une paire de points gl. Begin(GL_POINTS); gl. Vertex 2 f(x 1, y 1); gl. Vertex 2 f(x 2, y 2); gl. End(); (iii) un polygone gl. Begin(GL_POLYGON); gl. Vertex 3 f(0. 0, 0. 0); gl. Vertex 3 f(0. 0, 1. 0); gl. End(); D’autres fonctions peuvent être appelées entre gl. Begin et gl. End : - modification des attributs - calcul de nouveaux sommets - etc.

Types d’objets géométriques Plusieurs types d’objets géométriques sont disponibles : P 2 P 0

Types d’objets géométriques Plusieurs types d’objets géométriques sont disponibles : P 2 P 0 P 5 GL_POINTS P 5 GL_LINES P 2 P 0 P 5 GL_LINE_STRIP P 5 GL_LINE_LOOP

P 2 P 0 P 5 P 6 P 7 P 2 P 0

P 2 P 0 P 5 P 6 P 7 P 2 P 0 P 7 GL_POLYGON P 5 P 6 P 7 GL_QUADS GL_TRIANGLES P 1 P 3 P 5 P 7 P 1 P 3 P 5 P 6 P 7 P 2 P 3 P 0 P 2 P 4 P 6 GL_TRIANGLE_STRIP P 0 P 2 P 4 P 6 GL_QUAD_STRIP P 4 GL_TRIANGLE_FAN

PRÉSENCE DE VARIABLES D’ÉTAT Open. GL possède plusieurs variables d’état : taille courante d’un

PRÉSENCE DE VARIABLES D’ÉTAT Open. GL possède plusieurs variables d’état : taille courante d’un point, la couleur d’affichage courante, la couleur d’arrière-plan courante, etc. La valeur d’une variable d’état demeure la valeur courante ou la valeur par défaut jusqu’à ce qu’une nouvelle valeur soit spécifiée. Exemples : gl. Point. Size(3. 0); Spécifie la taille d’un point (réel) à l’affichage. gl. Color 3 f(rouge, vert, bleu); Spécifie la couleur d’affichage courante où rouge, vert et bleu sont des réels entre 0. 0 et 1. 0. gl. Clear. Color(rouge, vert, bleu, alpha); Spécifie la couleur d’arrière-plan courante où alpha désigne un niveau de transparence. (0, 0, 0, 0) est la valeur par défaut (noir). gl. Clear(GL_COLOR_BUFFER_BIT); Efface la fenêtre au complet avec la couleur d’arrière-plan.

Choix d’un système de coordonnées Nous devons aussi établir le système de coordonnées à

Choix d’un système de coordonnées Nous devons aussi établir le système de coordonnées à partir duquel nous définirons des objets géométriques et à quel endroit ces objets apparaîtront dans la fenêtre. À éviter : Se contraindre à définir les données dans le système de coordonnées de l’unité d’affichage. Le concepteur doit travailler dans son propre système de référence indépendant de l’unité d’affichage (système de coordonnées du monde). Chaque unité d’affichage possède son propre système de référence (système de coordonnées écran). Le logiciel d’infographie doit renfermer les outils pour passer d’un système à l’autre. Pour le moment, nous débuterons avec un système de coordonnées 2 D très proche de celui de la fenêtre et des distances mesurées en « pixels » .

Choix d’un système de coordonnées Pour définir dans quelle plage se retrouve les coordonnées

Choix d’un système de coordonnées Pour définir dans quelle plage se retrouve les coordonnées des sommets qui définissent les objets de la scène, on peut utiliser : void glu. Ortho 2 D(GLdouble gauche, GLdouble droite, GLdouble bas, GLdouble haut) Exemple : À préciser ultérieurement. Défn d’un rectangle à l’intérieur duquel les objets sont définis. gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0. 0, 500. 0); Après avoir défini la fenêtre courante, Open. GL fait le passage automatiquement entre le système de coordonnées du monde et celui de l’unité d’affichage.

Exemple : Affichage de 2 objets resp. dans une fenêtre et une sous-fenêtre. #include

Exemple : Affichage de 2 objets resp. dans une fenêtre et une sous-fenêtre. #include <windows. h> #include <GL/glut. h> void Affichage_principal() { gl. Clear(GL_COLOR_BUFFER_BIT); void Affichage_secondaire() { gl. Clear(GL_COLOR_BUFFER_BIT); gl. Color 3 f(1. 0, 0. 0); gl. Color 3 f(0. 0, 1. 0, 0. 0); gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0, 500, 0, 500); gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0, 500, 0, 500); gl. Begin(GL_POLYGON); gl. Vertex 2 i(10, 20); gl. Vertex 2 i(100, 10); gl. Vertex 2 i(20, 200); gl. End(); gl. Begin(GL_LINE_LOOP); gl. Vertex 2 i(10, 20); gl. Vertex 2 i(100, 10); gl. Vertex 2 i(20, 200); gl. End(); gl. Flush(); }

void main(int argc, char** argv) { int id; glut. Init(&argc, argv); /* Permet de

void main(int argc, char** argv) { int id; glut. Init(&argc, argv); /* Permet de fixer la dimension de la fenêtre à l'écran soit, 800 pixels de largeur par 500 de hauteur. */ glut. Init. Window. Size(800, 500); // Permet de fixer la position du coin supérieur gauche de la fenêtre. glut. Init. Window. Position(500, 100); /* Créer une fenêtre avec comme titre celui passé en paramètre. Les paramètres de cette fenêtre doivent avoir été fixés au préalable. */ id = glut. Create. Window("Fenetre principale"); /* Spécifie la fonction "Affichage_principal" qui sera appelée chaque fois que la fenêtre doit être affichée. */ glut. Display. Func(Affichage_principal); /* Permet de créer une sous-fenêtre 300 x 200 où (400, 250) désigne le coin supérieur gauche par rapport à la fenêtre principale. */ glut. Create. Sub. Window(id, 400, 250, 300, 200); /* Spécifie la fonction "Affichage_secondaire" qui sera appelée chaque fois que la sous-fenêtre doit être affichée. */ glut. Display. Func(Affichage_secondaire); /* Permet de conserver l'image produite à l'écran. Le programme exécuté est mis en attente jusqu'à ce qu'un événement se produise, l’image demeurant affichée à l'écran. */ glut. Main. Loop(); }

Primitives de sortie Pour débuter, nous allons opter pour les constructions les plus simples

Primitives de sortie Pour débuter, nous allons opter pour les constructions les plus simples d’Open. GL en choisissant implicitement plusieurs options par défaut. Toutes ces options seront approfondies au fur et à mesure que nous assimilerons la matière du cours. Nous pouvons distinguer 4 types de primitives de sortie : a) « polyline » b) texte c) région de remplissage d) images point à point À chaque primitive de sortie est associée différents attributs (couleur, épaisseur de trait, etc. ). Ces attributs possèdent des valeurs par défaut et des valeurs courantes.

Polyline « polyline » : suite de segments de droite reliés deux à deux.

Polyline « polyline » : suite de segments de droite reliés deux à deux. Des images obtenues à partir de « polylines » sont appelées quelquefois dessins au trait. Chaque segment d’un « polyline » est appelé arête et 2 segments adjacents ont un sommet commun. Les arêtes d’un « polyline » peuvent se croiser. Un « polyline » est défini à partir d’une liste de sommets : (x 0, y 0), (x 1, y 1), …, (xn, yn). Attributs : - couleur des arêtes - épaisseur des arêtes - trait continu ou discontinu - la manière avec laquelle les extrémités des arêtes adjacentes sont représentées.

Polygone polygone : un « polyline » fermé (l’extrémité initiale du 1 e segment

Polygone polygone : un « polyline » fermé (l’extrémité initiale du 1 e segment coïncide avec l’extrémité terminale du dernier segment) polygone simple : un polygone où aucune paire d’arêtes ne se croise. polygone simple polygone Note : GL_POLYGON désigne dans la structure gl. Begin() et gl. End() un polygone convexe simple.

Polygone Pour déterminer de quelle façon le contour polygonal et l’intérieur du polygone seront

Polygone Pour déterminer de quelle façon le contour polygonal et l’intérieur du polygone seront affichés, cela dépend de la valeur des attributs courants : gl. Polygon. Mode( , ); Premier paramètre: GL_FRONT face du polygone du côté de l’observateur GL_BACK autre face ou GL_FRONT_AND_BACK les deux. Deuxième paramètre : Exemple : GL_POINT GL_LINE GL_FILL affichage des sommets affichage du contour remplissage. gl. Polygon. Mode(GL_FRONT, GL_FILL); gl. Polygon. Mode(GL_BACK, GL_LINE);

Texte Il existe habituellement 2 modes d’affichage distincts : (a) le mode texte :

Texte Il existe habituellement 2 modes d’affichage distincts : (a) le mode texte : dans des applications non graphiques, le texte est la norme; le jeu de caractères est toujours affiché de la même façon. (b) le mode graphique : dans des applications graphiques, le texte peut être affiché de multiples façons : style, taille, fontes, couleurs, orientation, transformations, etc.

2 modes de représentation des caractères dans une application graphique (i) Les caractères sont

2 modes de représentation des caractères dans une application graphique (i) Les caractères sont définis comme d’autres objets graphiques : Le contour du caractère est approximé par des segments de droite ou courbes. Si le contour est fermé, l’intérieur du caractère est accessible. Le caractère peut alors être manipulé comme n’importe quel autre objet graphique avec tous les avantages qui s’y rattachent. Une fonte de 256 caractères peut être complexe à réaliser et exiger beaucoup de mémoires et de temps de calcul.

(ii) Matrice rectangulaire de points (masque) Chaque caractère est défini à partir d’un bloc

(ii) Matrice rectangulaire de points (masque) Chaque caractère est défini à partir d’un bloc rectangulaire de bits 0 ou 1. L’opération bit-block – transfert « bitblt » permet de transférer le bloc (le masque) d’un caractère dans la mémoire d’entretien. - Les transformations sont difficiles à effectuer. - gl. Raster. Pos*() et gl. Bitmap() fixe la position et affiche un masque sur l’écran. Masques de caractères - gl. Read. Pixels() lit un bloc rectangulaire de « pixels » de la mémoire d’entretien à la mémoire du processeur. - gl. Draw. Pixels() lit un bloc rectangulaire de pixels de la mémoire du processeur à la mémoire d'entretien à la position courante gl. Raster. Pos*(). - gl. Copy. Pixels() copie un bloc rectangulaire de « pixels » d’une position à l’autre de la mémoire d’entretien.

 Images point à point Chaque image est constituée d’un ensemble de petites cellules

Images point à point Chaque image est constituée d’un ensemble de petites cellules appelées « pixels » . Une image est rangée dans un tableau rect. renfermant des valeurs numériques. Chaque valeur numérique désigne une teinte de gris ou une couleur quelconque. Comment ces images sont-elles créées ? 1) des images conçues manuellement à l’aide de programmes de dessins interactifs 2) des images générées par un système graphique, 3) des images numérisées avec un scanner, 4) des modèles de génération de textures.

NOTION DE « VIEWPORT » EN OPENGL Surface rectangulaire à l’intérieur de la fenêtre

NOTION DE « VIEWPORT » EN OPENGL Surface rectangulaire à l’intérieur de la fenêtre de l’écran. void gl. Viewport(GLint x, GLint y, GLsizei w, GLsizei h); où x, y est le coin inférieur gauche du « viewport » déterminé à partir du coin inférieur gauche de la fenêtre w, h : hauteur et largeur du rectangle. Les positions sont spécifiées en entier et les distances en « pixels » . Par défaut, il s’agit de la fenêtre entière. L’usage des « viewports » permet : - d’éliminer les distorsions à l’écran (ratios différents pour la fenêtre et le volume de visionnement) permet d’avoir plusieurs « viewports » (pour afficher des images différentes à des parties différentes de la fenêtre).

Systèmes de coordonnées : fenêtre et « viewport » 2 D Les objets qui

Systèmes de coordonnées : fenêtre et « viewport » 2 D Les objets qui nous intéressent sont définis plus naturellement dans un système de coordonnées « du monde » , propre à votre application. À l’intérieur de ce système de coordonnées « du monde » , une fenêtre rectangulaire est définie en coordonnées « du monde » . Les objets ou les parties d’objets à l’intérieur de la fenêtre sont conservés et tout ce qui est à l’extérieur de la fenêtre est exclu. On définit aussi un « viewport » (une surface rectangulaire à l’intérieur de la fenêtre à l’écran) en coordonnées « écran » . C’est à l’intérieur de ce « viewport » que l’image est affichée. 32

Passage d’un système de coordonnées à un autre y yhaut syhaut x xgauche ybas

Passage d’un système de coordonnées à un autre y yhaut syhaut x xgauche ybas sybas xdroite sxgauche sxdroite Une fenêtre dans le système de Un « viewport » en coordonnées « écran » . coordonnées du « monde » . Note : Lorsque le rapport « hauteur / largeur » n’est pas le même pour une fenêtre que pour un « viewport » , des distortions peuvent survenir.

Transformation linéaire : un point (x, y) en coordonnées du monde à un point

Transformation linéaire : un point (x, y) en coordonnées du monde à un point (sx, sy) en coordonnées écran Soit sx = A x + C et sy = B y + D. En respectant les règles de proportionnalité, on obtient : sx – sxgauche = x – xgauche sxdroite – sxgauche xdroite - xgauche ce qui donne sx = sxdroite – sxgauche x + sxgauche - sxdroite – sxgauche xdroite – xgauche xdroite - xgauche d’où, A = sxdroite – sxgauche xdroite – xgauche B = syhaut – sybas yhaut – ybas C = sxgauche – A xgauche D = sybas – B ybas Note : N’importe quel point (x, y) à l’intérieur de la fenêtre nous donne après transformation un point (sx, sy) à l’intérieur du « viewport » .

Procédé en Open. GL En Open. GL, ce processus est effectué automatiquement comme suit

Procédé en Open. GL En Open. GL, ce processus est effectué automatiquement comme suit : la transformation précédente est appliquée automatiquement à tous les sommets définis via gl. Vertex 2*(); le découpage des objets se fait automatiquement. Nous avons besoin seulement de spécifier les paramètres de transformation : void glu. Ortho 2 D(GLdouble gauche, GLdouble droite, GLdouble bas, GLdouble haut); Permet de définir la fenêtre dont le coin inférieur gauche est (gauche, bas) et le coin supérieur droit est (droite, haut). void gl. Viewport( GLint x, GLint y, GLint Largeur, GLint Hauteur); Permet de définir un «viewport» dont le coin inférieur gauche est (x, y) et le coin supérieur droit est (x + Largeur, y + Hauteur). Note : Le « viewport » par défaut est l’écran au complet.

Exemple : Tracé de f(x) = sin( x) / ( x), 1 x 8

Exemple : Tracé de f(x) = sin( x) / ( x), 1 x 8 #include <windows. h> #include <GL/glut. h> #include <cmath> void Affichage() { gl. Clear(GL_COLOR_BUFFER_BIT); gl. Color 3 f(1. 0, 0. 0); gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0. 0, 10. 0, -1. 0, 1. 0); gl. Viewport(0, 0, 640, 480); gl. Begin(GL_LINE_STRIP); for (GLfloat x = 1. 0; x < 8. 0; x += 0. 1) gl. Vertex 2 f(x, sin(3. 14159 * x) / (3. 14159 * x)); gl. End(); gl. Flush(); }

void main(int argc, char** argv) {. . . /* Permet de fixer la dimension

void main(int argc, char** argv) {. . . /* Permet de fixer la dimension de la fenêtre à l'écran soit, 800 pixels de largeur par 500 de hauteur. */ glut. Init. Window. Size(800, 500); /* Permet de fixer la position du coin supérieur gauche de la fenêtre. */ glut. Init. Window. Position(500, 100); . . . } En Open. GL, le découpage est fait automatiquement p/r à la fenêtre du monde. Ex. : En optant pour glu. Ortho 2 D(4. 0, 6. 0, -0. 5, 0. 5) dans l’exemple précédent, Une portion du tracé ne sera pas affichée.

Effets de zoom En modifiant les dimensions de la fenêtre du monde, on peut

Effets de zoom En modifiant les dimensions de la fenêtre du monde, on peut créer des effets de zoom. Par ex. , une fenêtre plus petite permet de mettre l’emphase sur une partie d’un objet; de plus, si le « viewport » ne change pas, cette partie de l’objet se trouve agrandie. On peut ainsi créer des animations. Comment fixer la dimension d’une fenêtre pour inclure un objet au complet ? Une façon de faire est de déterminer une surface rectangulaire d’aire minimale renfermant l’objet. 1558 polygones

Exemple en Open. GL Affichage de plusieurs motifs de dinosaures void Affichage() {. .

Exemple en Open. GL Affichage de plusieurs motifs de dinosaures void Affichage() {. . . for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { gl. Viewport(i * 64, j *44, 64, 44); --Affichage d’un motif de dinosaure – F. S. Hill, 2001 } gl. Flush(); }

Distorsion d’une figure Pour éviter les distorsions d’une figure en passant d’un système de

Distorsion d’une figure Pour éviter les distorsions d’une figure en passant d’un système de coordonnées du monde à celui de l’écran tout en occupant la plus grande surface de l’écran, considérons les 2 cas suivants : soient R = largeur de la fenêtre du monde / hauteur de la fenêtre du monde, L = largeur de la fenêtre de l’écran H = hauteur de la fenêtre de l’écran, 1 er cas : R > L / H Fenêtre du monde (R) viewport H L / R L gl. Viewport(0, 0, L, L / R); 2 ième cas : R < L / H Fenêtre du monde (R) H HR gl. Viewport(0, 0, H * R, H); viewport L

Il peut arriver aussi que l’usager modifie les dimensions de la fenêtre à l’écran

Il peut arriver aussi que l’usager modifie les dimensions de la fenêtre à l’écran en faisant glisser un de ses sommets à l’aide de la souris. L’événement généré est pris en compte grâce à la commande : glut. Reshape. Func(Reconfiguration); que l’on retrouve dans la fonction main(). La fonction « Reconfiguration » doit permettre d’identifier un nouveau « viewport » à l’intérieur de la nouvelle fenêtre à l’écran tout en conservant le ratio R de la fenêtre du monde. void Reconfiguration (GLsizei L, GLsizei H) { if (R > L / H) gl. Viewport(0, 0, L, L / R); else gl. Viewport(0, 0, H * R, H); } Lorsque la fonction « Reconfiguration » est exécutée, le système lui transmet automatiquement la nouvelle largeur (L) et hauteur (H) de la fenêtre à l’écran. ------------------------------------------

Exemple : Reprise de l’exemple précédent. GLfloat R = (10. 0 - 0. 0)

Exemple : Reprise de l’exemple précédent. GLfloat R = (10. 0 - 0. 0) / (1. 0 - -1. 0); void Affichage() { gl. Clear(GL_COLOR_BUFFER_BIT); gl. Color 3 f(1. 0, 0. 0); gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0. 0, 10. 0, -1. 0, 1. 0); gl. Begin(GL_LINE_STRIP); for (GLfloat x = 1. 0; x < 8. 0; x += 0. 1) gl. Vertex 2 f(x, sin(3. 14159 * x) / (3. 14159 * x)); gl. End(); gl. Flush(); } void Reconfiguration (GLsizei L, GLsizei H) { if (R > L / (GLfloat) H) gl. Viewport(0, 0, L, L / R); else gl. Viewport(0, 0, H * R, H); }

Définition d’une fonction « Initialisation » Dans un programme d’application, on retrouve habituellement une

Définition d’une fonction « Initialisation » Dans un programme d’application, on retrouve habituellement une fonction « Initialisation » permettant d’initialiser les variables d’état d’Open. GL si les valeurs par défaut ne nous satisfont pas. Celles-ci peuvent aussi être modifiées dans la fonction « Affichage » à chaque fois que la fenêtre est redessinée. Lorsque ces valeurs des variables d’état ne sont pas modifiées au cours de l’application, il est souhaitable de procéder à l’intérieur d’une telle fonction d’initialisation pour des raisons de modularité et d’efficacité.

Exemple : #include <windows. h> #include <GL/glut. h> #include <math. h> /* Tracé de

Exemple : #include <windows. h> #include <GL/glut. h> #include <math. h> /* Tracé de la courbe de Sierpinski. 3 points (x 1, y 1), (x 2, y 2) et (x 3, y 3) dans le plan sont spécifiés. Procédé : (1) générer aléatoirement un point à l'intérieur du triangle. (2) choisir l'un des 3 sommets du triangle aléatoirement. (3) Trouver le point-milieu entre le point initial et le sommet choisi aléatoirement. (4) Afficher ce nouveau point à la position obtenue (un petit cercle par exemple). (5) Remplacer le point initial généré par ce nouveau point. (6) Retourner à l'étape 2. */

void Initialisation(void) { // Permet d'initialiser la couleur de fond RVB noire. gl. Clear.

void Initialisation(void) { // Permet d'initialiser la couleur de fond RVB noire. gl. Clear. Color(0. 0, 0. 0); /* Permet de fixer la couleur d'affichage rouge. gl. Color 3 f(1. 0, 0. 0); /* Open. GL possèdent 2 matrices, MODELVIEW et PROJECTION pour représenter respectivement les transformations ponctuelles et les transformations visuelles courantes. On opte ici pour la matrice de projection. */ gl. Matrix. Mode(GL_PROJECTION); /* Permet d'initialiser la matrice de transformation courante soit, la matrice de projection dans ce cas-ci à la matrice identité. */ gl. Load. Identity(); /* Permet de spécifier la surface de visualisation. La signification des paramètres est : gauche, droite, bas, haut. */ glu. Ortho 2 D(0. 0, 800. 0, 500. 0); }

void Affichage( void ) { typedef GLfloat point 2[2]; point 2 vertices[3] = {{10.

void Affichage( void ) { typedef GLfloat point 2[2]; point 2 vertices[3] = {{10. 0, 10. 0}, {300. 0, 30. 0}, {200. 0, 300. 0}}; int j, k; long random(); point 2 p = {10. 0, 10. 0}; gl. Clear(GL_COLOR_BUFFER_BIT); for ( k=0; k<5000; k++) { j=rand()%3; p[0] = (p[0]+vertices[j][0])/2. 0; gl. Begin(GL_POINTS); } gl. Flush(); } p[1] = (p[1]+vertices[j][1])/2. 0; gl. Vertex 2 fv(p); gl. End();

void main(int argc, char** argv) { glut. Init(&argc, argv); glut. Init. Window. Size(800, 500);

void main(int argc, char** argv) { glut. Init(&argc, argv); glut. Init. Window. Size(800, 500); glut. Init. Window. Position(500, 100); glut. Create. Window("Courbe de Sierpinski"); glut. Display. Func(Affichage); Initialisation(); glut. Main. Loop(); }

Modélisation 3 D et visualisation Le passage du 2 D au 3 D nécessite

Modélisation 3 D et visualisation Le passage du 2 D au 3 D nécessite 2 matrices en Open. GL représentant les transformations courantes suivantes à appliquer aux objets : GL_MODELVIEW : (par défaut) elle est unique même si on peut la voir comme le produit de 2 matrices : ° les transformations à appliquer aux objets dans l’espace du « monde » , ° celles permettant de passer du repère des objets à celui de la caméra. GL_PROJECTION : ° les transformations permettant de définir la forme et l’orientation du volume de visualisation et de projeter les objets dans le plan de vue. Chaque changement à l’une de ces matrices demeure actif tant et aussi longtemps qu’un autre changement n’a pas eu lieu. Initialement, ce sont des matrices identité. Celles-ci sont mises à jour à partir d’une suite de transformations (fonctions d’Open. GL). Lorsque nous voulons appliquer une transformation, nous devons choisir le mode « GL_MODELVIEW » ou « GL_PROJECTION » .

Projections parallèles orthographiques La projection parallèle orthographique d’un point (x, y, z) nous donne

Projections parallèles orthographiques La projection parallèle orthographique d’un point (x, y, z) nous donne (x, y, 0). Le volume de visualisation est un parallélépipède. y x z = 0 z

Projections parallèles orthographiques En Open. GL, cette projection est spécifiée comme suit : void

Projections parallèles orthographiques En Open. GL, cette projection est spécifiée comme suit : void gl. Ortho( GLdouble gauche, GLdouble droite, GLdouble bas, GLdouble haut, GLdouble proche, GLdouble loin) Le plan z = 0 doit se situer entre proche et loin. Ce volume de visualisation (parallélépipède) sert aussi de volume de découpage. La procédure de découpage est alors effectuée automatiquement par Open. GL. On peut aussi utiliser void glu. Ortho 2 D(GLdouble gauche, GLdouble droite, GLdouble bas, GLdouble haut) laquelle est équivalente à la fonction 3 D avec proche = -1 et loin = 1.

Exemple : #include <windows. h> #include <GL/glut. h> #include <math. h> const int L

Exemple : #include <windows. h> #include <GL/glut. h> #include <math. h> const int L = 800; const int H = 500; const GLfloat xmin = 1. 0 f; const GLfloat xmax = 5. 0 f; const GLfloat ymin = 1. 0 f; const GLfloat ymax = 5. 0 f; const GLfloat zmin = -1. 0 f; const GLfloat zmax = 1. 0 f; const GLfloat precision = 0. 03 f; // Largeur de la fenêtre en pixels. // Hauteur de la fenêtre en pixels. // Intervalle de variation de x. // Intervalle de variation de y. // Intervalle de variation de F(x, y). GLfloat F(GLfloat x, GLfloat y) { return sin(2 * 3. 14159265 * x) * cos(2 * 3. 14159265 * y); }

void Initialisation(void) { gl. Clear. Color(0. 0, 0. 0); gl. Color 3 f(1. 0,

void Initialisation(void) { gl. Clear. Color(0. 0, 0. 0); gl. Color 3 f(1. 0, 0. 0); // Une rotation de 45° autour de l'axe (1, 1, 0) est appliquée à la surface. gl. Matrix. Mode(GL_MODELVIEW); gl. Load. Identity(); gl. Rotatef(45. 0, 1. 0, 0. 0); /* Permet de spécifier une projection orthographique où le volume de visualisation est un parallélépipède. La signification des paramètres est : gauche, droite, bas, haut, proche et loin. */ gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); gl. Ortho(xmin-1, xmax+1, ymin-1, ymax+1, zmin-1, zmax+1); }

void Affichage( void ) { gl. Clear(GL_COLOR_BUFFER_BIT); for (GLint i = 0; i <=

void Affichage( void ) { gl. Clear(GL_COLOR_BUFFER_BIT); for (GLint i = 0; i <= (int)((xmax - xmin) / precision); i++) for (GLint j = 0; j <= (int)((ymax - ymin) / precision); j++) { GLfloat x, y; x = xmin + i * precision; y = ymin + j * precision; gl. Begin(GL_LINE_LOOP); gl. Vertex 3 f(x, y, F(x, y)); gl. Vertex 3 f(x, y + precision, F(x, y + precision)); gl. Vertex 3 f(x + precision, y + precision, F(x + precision, y + precision)); gl. End(); gl. Begin(GL_LINE_LOOP); gl. Vertex 3 f(x, y, F(x, y)); gl. Vertex 3 f(x + precision, y + precision, F(x + precision, y + precision)); gl. Vertex 3 f(x + precision, y, F(x + precision, y)); gl. End(); }; gl. Flush(); }

Élimination des parties cachées Dans l’exemple précédent, l’affichage de la fonction z = F(x,

Élimination des parties cachées Dans l’exemple précédent, l’affichage de la fonction z = F(x, y) a été réalisé en mode « fil de fer » . En optant plutôt pour un mode par remplissage « GL_FILL » , il faut procéder à l’élimination des parties cachées de la scène. Au départ, un tableau doit être initialisé à la distance maximale possible en se référant au plan de découpage le plus éloigné de l’observateur. Cette initialisation est faite grâce à la commande gl. Clear() avec le paramètre GL_DEPTH_BUFFER_BIT. Pour pouvoir utiliser ce tableau de distances, les déclarations initiales suivantes sont aussi nécessaires : glut. Init. Display. Mode(GLUT_DEPTH); choix d’une matrice de profondeurs pour l’élimination des parties cachées gl. Enable(GL_DEPTH_TEST); l’élimination des parties cachées est réalisée. 54

Exemple précédent en mode remplissage : La fonction « Initialisation » demeure la même.

Exemple précédent en mode remplissage : La fonction « Initialisation » demeure la même. void Affichage( void ) { gl. Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (GLint i = 0; i < (int)((xmax - xmin) / precision); i++) for (GLint j = 0; j < (int)((ymax - ymin) / precision); j++) { GLfloat x, y; x = xmin + i * precision; y = ymin + j * precision; gl. Begin(GL_POLYGON); gl. Vertex 3 f(x, y, F(x, y)); gl. Vertex 3 f(x, y + precision, F(x, y + precision)); gl. Vertex 3 f(x + precision, y + precision, F(x + precision, y + precision)); gl. End(); gl. Begin(GL_POLYGON); gl. Vertex 3 f(x, y, F(x, y)); gl. Vertex 3 f(x + precision, y + precision, F(x + precision, y + precision)); gl. Vertex 3 f(x + precision, y, F(x + precision, y)); gl. End(); }; 55 gl. Flush(); }

void main(int argc, char** argv) { glut. Init(&argc, argv); /* On réserve un bloc

void main(int argc, char** argv) { glut. Init(&argc, argv); /* On réserve un bloc de mémoire nécessaire pour résoudre le problème d'élimination des parties cachées. */ glut. Init. Display. Mode (GLUT_DEPTH); /* Cette fonction permet de rendre active une option d'Open. GL spécifiée en paramètre. Dans le cas présent, l'élimination des parties cachées sera effectuée. */ gl. Enable(GL_DEPTH_TEST); glut. Init. Window. Size(L, H); glut. Init. Window. Position(500, 100); glut. Create. Window("Trace de la fonction F(x, y)"); glut. Display. Func(Affichage); Initialisation(); glut. Main. Loop(); } 56

Effets d’animation Pour créer une animation, on peut procéder en répétant les étapes suivantes

Effets d’animation Pour créer une animation, on peut procéder en répétant les étapes suivantes : (a) on efface l’écran (b) on affiche de nouveau la figure modifiée. Or, l’étape (b) peut être lente et l’usager peut voir l’affichage se faire graduellement. Il serait préférable de procéder comme suit : (a) Tracer ailleurs une nouvelle figure tandis que l’usager observe la figure courante. (b) Remplacer instantanément la figure courante par la nouvelle figure complétée. Pour y arriver, Open. GL utilise une mémoire tampon supplémentaire lors des communications ( « double buffering » ). Cela est rendu possible grâce au paramètre GLUT_DOUBLE qui remplace le paramètre GLUT_SINGLE lors de l’initialisation du mode d’affichage : glut. Init. Display. Mode(GLUT_DOUBLE); 57

Effets d’animation Tous les tracés se font sur cette mémoire tampon supplémentaire lesquels sont

Effets d’animation Tous les tracés se font sur cette mémoire tampon supplémentaire lesquels sont invisibles à l’écran. La commande glut. Swap. Buffers(); transfert l’image à l’écran et l’image devient alors visible à l’usager. Exemple : for(int i = 0; i < Longueur_sequence; i ++) { Effacer l’écran; Définir la fenêtre et le viewport; Tracé de la figure; glut. Swap. Buffers(); } 58