Série 17 : Début de l'exercice "Cinematique inverse". Dessin 2D avec la librairie Open GL Buts



Documents pareils
Chapitre II : Infographie et bibliothèques graphiques

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Fête de la science Initiation au traitement des images

I. Introduction aux fonctions : les fonctions standards

Les algorithmes de base du graphisme

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Interface PC Vivago Ultra. Pro. Guide d'utilisation

Dessiner dans Galaad FRANÇOIS PALLUT

VOS PREMIERS PAS AVEC TRACENPOCHE

Rapidolect Les Productions de la Columelle ( ) Page 1

Gestion de projet. GanttProject Didacticiel V novembre Gérard Gervois Frédéric Giamarchi

Utilisation du logiciel GALAAD

Algorithmique avec Algobox

Tp_chemins..doc. Dans la barre "arche 2" couleur claire 1/5 21/01/13

DOSSIER D'ACTIVITES SUR TUXPAINT Dessiner avec Tuxpaint. Objectifs :

Généralités sur le Langage Java et éléments syntaxiques.

TD de supervision. J.P. Chemla. Polytech Tours Département productique 2ème année

TP : Gestion d une image au format PGM

TUTORIEL IMPRESS. Ouvrir Impress cocher «présentation vierge», «suivant» cocher «écran», «suivant» cocher «standard», «créer»

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Cours Excel : les bases (bases, texte)

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Navigation dans Windows

Sommaire. Aide Page 1

Introduction au langage C

Didacticiel de mise à jour Web

1. Introduction Création d'une requête...2

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Parcours FOAD Formation EXCEL 2010

SOMMAIRE... 1 ESPACE DU CLUB...

Once the installation is complete, you can delete the temporary Zip files..

LES NOUVEAUTÉS DE ARCON 15 PRO

Le langage C. Séance n 4

Choisir entre le détourage plume et le détourage par les couches.

Chapitre 4 Pierre, papier, ciseaux

Traitement numérique de l'image. Raphaël Isdant

Programmation système I Les entrées/sorties

Installation et prise en main

Initiation à la librairie graphique VTK

Algorithmique et Programmation, IMA

Programmation Objet - Cours II

TABLEAU CROISE DYNAMIQUE

TP1 : Initiation à Java et Eclipse

LES TOUT PREMIERS PAS

TRUCS & ASTUCES SYSTEME. 1-Raccourcis Programme sur le Bureau (7)

TBI-DIRECT. Bridgit. Pour le partage de votre bureau. Écrit par : TBI Direct.

Utilisation du visualiseur Avermedia

Adobe Illustrator Logiciel de dessin vectoriel et de Cartographie Assistée par Ordinateur

Guide pour la réalisation d'un document avec Open Office Writer 2.2

Le service d'agenda en ligne SOGo

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

Access 2007 FF Access FR FR Base

Les tablettes et l'extranet Intermixt Mode d'emploi

My Custom Design ver.1.0

Leçon 18 Coupes et sections

2013 Pearson France Adobe Illustrator CC Adobe Press

@telier d'initiation

Le générateur d'activités

La C.A.O (Conception Assistée par Ordinateur). Le logiciel de C.A.O.

Compression de Données - Algorithme de Huffman Document de Conception

pcon.planner 6 Préparer et présenter une implantation en toute simplicité

Initiation à linfographie

Publication Assistée par Ordinateur

Pop-Art façon Roy Liechtenstein

Solutions du chapitre 4

L import massif introduit plusieurs nouvelles fonctionnalités, selon que l on importe un thésaurus, un ensemble de valeurs contrôlées ou un corpus.

ACTIVITÉ DE PROGRAMMATION

GL BE FLYER. Chef de projet de l équipe : SCIONICO Pierre

Vision industrielle et télédétection - Détection d ellipses. Guillaume Martinez 17 décembre 2007

HMI target Visu / PLC HMI. Pour réaliser une interface homme machine avec PLC control

Débuter avec OOo Base

Synthèse d'images I. Venceslas BIRI IGM Université de Marne La

FOXIT READER 6.0 Guide rapide. Table des matières... II Utilisation de Foxit Reader Lecture Travailler dans des documents PDF...

Cours Programmation Système

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

UTILISATION DE L'APPLICATION «PARTAGE DE FICHIERS EN LIGNE»

MERLIN. Guide de démarrage rapide Gestion de projet professionnelle ProjectWizards GmbH, Melle, Allemagne. Tous droits réservés.

Stockage du fichier dans une table mysql:

BAMOSONIC IT. - Mesure de niveau -

Tutorial Ophcrack. I) Ophcrack en API. (ou comment utiliser Ophcrack pour recouvrir un mot de passe sous Windows XP et Windows Vista)

Transférer et enregistrer les photos sur l'ordinateur

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Organiser vos documents Windows XP

Guide d utilisation de fonctionnalités avancées de Beyond 20/20 (application à des données départementales issues de Sit@del2)

DETERMINER LA LARGEUR DE PAGE D'UN SITE et LES RESOLUTIONS d'ecran

Le prototype de la fonction main()

GESTION DU LOGO. 1. Comment gérer votre logo? Format de l image Dimensions de l image Taille de l image 9

Traitement de texte : Quelques rappels de quelques notions de base

Freeway 7. Nouvelles fonctionnalités

Opérations de base sur ImageJ

Gérer ses impressions en ligne

Les chaînes de caractères

TPs Architecture des ordinateurs DUT Informatique - M4104c SUJETS. R. Raffin Aix-Marseille Université romain.raffin-at-univ-amu.fr

PRODIGE V3. Manuel utilisateurs. Consultation des métadonnées

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Infolettre #18 : Les graphiques avec Excel 2010

Programmation C. Apprendre à développer des programmes simples dans le langage C

Transcription:

Série 17 : Début de l'exercice "Cinematique inverse". Dessin 2D avec la librairie Open GL Buts Le but des trois séries 17-18-19 est d'écrire une petite application graphique interactive. Il s'agit d'un exemple très simple de cinématique inverse, une technique utilisée en robotique. Dans cette série, vous étudierez la partie mathématique du problème, ainsi que l'utilisation de la librairie Open GL pour l'affichage graphique en deux dimensions. Dans les séries 18 et 19, vous verrez comment utiliser GLUT/GLUI dans l'application, pour la partie interface utilisateur. Exercice 0 en anglais: Running OpenGL applications on VirtualBox image of CO configurations (document pdf séparé) Exercice 1 théorique (à faire avant la séance de TP): cinématique inverse (étude du problème) Soit une chaîne articulée en 2D, composée de deux parties rigides et de deux articulations: Les paramètres fixes de cette chaîne sont les longueurs l 1 et l 2 des deux parties rigides. Par contre, les angles alpha et beta des deux articulations peuvent varier (sans limites), donnant ainsi lieu à une infinité de configurations différentes. La position (x E, y E ) de l'extrémité de la chaîne, représentée par un carré blanc et appelée effecteur, dépend de ces quatre paramètres (l 1, l 2, alpha et beta), et peut

être calculée comme suit: Un problème fondamental en robotique (appelé cinématique inverse) consiste à calculer les angles alpha et beta pour que l'effecteur atteigne une position désirée (x B, y B ). Ce problème est compliqué car il n'y a pas forcément une et une seule solution. Par exemple, la position désirée peut ne pas être atteignable: dans ce cas il n'y a pas de solution. D'un autre coté, si la position est atteignable, il peut exister deux configurations pour l'atteindre, et il faut bien en choisir une. Question: Déterminez la condition d'atteignabilité d'une position (x B, y B ) par l'effecteur, en fonction des longueurs l 1 et l 2. La condition est facilement exprimée à partir du "rayon": Ensuite représentez graphiquement l'espace atteignable par l'effecteur. En faisant quelques calculs, il est possible de déterminer l'une des deux solutions au problème de cinématique inverse, qui donne alpha et beta en fonction des longueurs l 1 et l 2 et de la position désirée (x B, y B ), quand celle-ci est atteignable: il faut encore gérer correctement le cas où r=0 (car il existe une infinité de solutions si l 1 = l 2 ), et le cas où le but n'est pas atteignable (car il faut déterminer une configuration telle que l'effecteur soit aussi proche que possible du but). Remarque: Dans la librairie math.h, la fonction acos() permet de calculer l'inverse de la fonction cosinus. La fonction atan2(y,x) retourne la valeur de arctan(y/x) entre +/-. Enfin, la constante est aussi déjà définie dans math.h (macro M_PI). Exercice 2 (niveau 0): Démonstration de l'objectif à atteindre

Copiez chez vous le répertoire boulic/serie17. Il contient une démo très partielle de l'application de cinématique inverse, ainsi que les fichiers source (incomplets) de l'application, que vous devrez compléter aujourdhui. Pour commencer, placez-vous dans votre répertoire serie17 et lancez la démo en tapant./demo_cine.x. Cet exécutable montre seulement ce que vous devez obtenir aujourdhui comme affichage pour les valeurs initiales des paramètres (longueurs des segments et position du but). Les deux cercles concentriques représentent les limites de l'espace atteignable par l'effecteur. Remarque: une nouvelle version du code source sera fournie pour la série19. Architecture du programme L'application que nous vous fournissons pour cette série est une version simplifiée du module principal de votre prochain projet. Il est donc très important que vous compreniez l'architecture d'un tel programme. Il s'agit d'une application composée de plusieurs fichiers source. Il faut donc utiliser la commande make (voir série 15) pour pouvoir générer l'exécutable cine.x. Regardez la liste de fichiers qui composent cette application: chaque module s'occupe d'une partie bien précise. Cela illustre le principe de séparation des fonctionalités. Ici, il y a deux modules: chaine : regroupe les fonctions relatives à la chaîne articulée (calcul de cinématique inverse + appels de graphic pour faire un dessin). graphic : fournit des fonctions pour l'affichage de primitives graphiques (segment, rectangle et cercle). Analysez les modules chaine et graphic. Notez que le nom de chaque fonction exportée par un module commence par le même identificateur (chaine_ ou graphic_). Dans un grand projet, cela permet d'identifier automatiquement la provenance d'une fonction à partir de son nom. Notez aussi que tous les prototypes des fonctions exportées par un module se trouvent dans le fichier en-tête (.h), encore appelé l'interface du module. Enfin, le programme principal se trouve dans le fichier cine.cpp et fait appel aux modules ci-dessus. L'extension "cpp" montre que cine.cpp est écrit en C++. Cependant, l'essentiel de ce code source est du C que nous connaissons bien. Les deux seules différences sont les suivantes: 1) Comment inclure des fichier en-têtes écrits en C dans un fichier écrit en C++: Dans un fichier C++ il faut inclure les fichiers en-tête des modules C de la manière suivante : extern "C"

#include "graphic.h" #include "chaine.h" 2) Comment déclarer des variables globales restreintes à un fichier en C++: En C nous utilisons le mot clef static pour restreindre la portée d'une variable globale au fichier où elle est déclaré, par exemple: // syntaxe correcte en C mais deprecated en C++ static float length_segment1 ; En C++ il fautdéclarer les variables globales restreinte au module avec l'espace de noms non-nommé, ce qui donne pour l'exemple précédent: namespace float length_segment1; Recommendation de programmation robuste: on cherchera toujours à réduire le nombre de telles variables globales au strict nécessaire. Structure de la fonction main( ) première notion de programmation par évènements la fonction principale est composée de deux partie caractéristiques: un ensemble d'initialisations suivi d'une boucle infinie de traitement des évènements. On ne pourra sortir de cette boucle infinie que par un appel exit(). La boucle infinie est cachée dans l'appel de la dernière fonction de l'exemple à la ligne 21. Nous décrivons d'abord les initialisations. 1 int main(int argc, char* argv[]) 2 3 int main_window; // pour le numéro d'identification de la fenêtre 4 5 glutinit(&argc, argv); // init GLUT 6 7 glutinitdisplaymode( GLUT_RGB GLUT_DOUBLE GLUT_DEPTH ); 8 9 glutinitwindowposition( 50, 50 ); // pas toujours prise en compte... 11 glutinitwindowsize( 400, 400 ); // taille de la fenêtre 12 13 main_window = glutcreatewindow( "Serie 17" ); // creation fenêtre 14 15 glutdisplayfunc( display_cb ) // fonction callback d'affichage 16 17 glutreshapefunc( reshape_cb ) // fonction callback reshape 18 19

20 21 glutmainloop(); // boucle infinie de traitement des évènements... Pour la série de cette semaine vous trouverez seulement des commandes GLUT qui définissent la fenêtre dans laquelle on va dessiner avec OPEN-GL. Ce programme repose en particulier sur une fenètre graphique, appelée main_window, dans laquelle nous allons exécuter des commandes de dessin. C'est pourquoi la fonction main commence par définir et créer cette fenêtre de dessin. Le code ci-dessous montre la définition d'une zone de taille 400 x 400 pixels puis la création de la fenètre main_window par l'appel à glutcreatewindow() à la ligne 13: La suite des initialisations est composée de la déclaration de quelques fonctions callback qui seront exécutées pendant l'exécution de la boucle infinie, en réponse à des évènements. On appelle "évènement" une action élémentaire produite par l'utilisateur du programme telle que: "cliquer sur un bouton de la souris", "modifier la taille de la fenètre graphique", "déplacer la fenètre graphique", "frapper sur une touche du clavier" etc... Il est possible d'écrire une fonction pour chacun de ces évènements. Une telle fonction est automatiquement exécutée si l'évènement se produit pendant l'exécution du programme. Ces fonctions sont appelée des fonctions callback (nous les distinguons en adoptant la convention d ajouter _cb à la fin de leur nom). Elles doivent être déclarées à GLUT dans la phase d'initialisation avant de lancer la boucle infinie. Cela est fait dans le code fourni aujourdhui pour les fonctions callback display_cb et reshape_cb: La fonction callback display_cb est automatiquement appelée quand la fenètre est bougée ou rendue à nouveau visible ; son but est de refaire le dessin. La seconde fonction callback reshape_cb est automatiquement appelée lorsque la fenêtre change de taille ; son but est d'ajuster la projection si le rapport largeur/hauteur change. Lorsqu'on déclare une fonction callback (lignes 15 et 17) on fournit un pointeur de fonction à GLUT qui le stocke dans ses structures de données internes. Ce pointeur est ensuite utilisé pour appeler la fonction automatiquement quand l'évènement est détecté. Voici la description détaillée des fonctions utilisées pour déclarer les fonctions callback. void glutdisplayfunc(void (*displayfunc)(void)); Définit la fonction exécutée automatiquement par GLUTquand un événement intervient entraînant le rafraîchissement de l'image affichée (création initiale e la fenêtre d'affichage, déplacement, agrandissement, réduction, réactivation en avant-

plan, rdre par programme,...). La fonction displayfunc passée en paramètre ne doit assurer l'affichage que d'une seule image. void glutreshapefunc(void (*fonct)(int largeur, int hauteur)); Définit la fonction exécutée automatiquement par GLUT quand la taille d'une fenètre est modifiée. Cette fonction recalcule les paramètres de la projection (orthographique ou perspective) pour que le rapport largeur/hauteur (appelé aspect-ratio ) de la projection soit le même que celui de la fenètre. Si cela n'est pas vérifié cela introduit une distorsion dans le dessin (cf cours). Voici le pseudocode de la boucle infinie : //Pseudo-code glutmainloop() while(1) //infinite loop if (graphic has changed) function call with pointer provided by display_cb else if (window position or size has changed) function call with pointer provided by reshape_cb else if(keyboard or mouse event) // évt clavier ou souris ; série 19 function call with pointer provided by corresponding callback decl. else // aucun évènement ; sera vu à la série 19 function call with pointer provided by the idle callback declaration Mise oeuvre de GLUT et de OPEN-GL Fichiers en-tête: pour Open GL, il faut GL/glu.h Bibliothèques (en anglais: Librairies): pour utiliser les bibliothèques compilées de GLUT et Open GL, il faut fournir leur liste avec les option -l (avec l comme library) : - lglut -lgl -lglu -lm -Llib lors de l'édition des liens (cela est déjà fait dans le fichier Makefile qui vous est fourni). Exercice 3 (niveau 0): Introduction à OpenGL (voir aussi le cours) Open GL est un standard industriel pour faire du dessin 2D et 3D. Dans le cadre des TP on s'en tiendra à la 2D (dessin dans le plan). Open GL est une librairie de fonctions graphiques que l'on peut appeler depuis son code C. Pour les distinguer d'autres fonctions (d'autres librairies), elles commencent toutes par le préfixe gl. Notre module graphic rassemble des fonctions dépendantes de Open GL : l'interface de ce module (c.à.d. les fonctions qu'il exporte et dont les prototypes se trouvent dans le fichier en-tête graphic.h) vous permet d'accéder aux fonctions graphiques dont vous aurez besoin. Pour cette série vous devez compléter une fonction de ce module: donc ouvrez déjà graphic.c en édition.

Remarque: vous trouvez la liste de toutes les fonctions disponibles dans Open GL sur la page web du cours. Le site officiel de Open GL est: www.opengl.org L'affichage se fait dans la partie de l'écran du widget glut. Avant de pouvoir dessiner, il faut avoir établi un système de coordonnées. Système de coordonnées Voici la convention utilisée par Open GL: l'axe x est horizontal et pointe vers la droite de l'écran dans le sens positif. L'axe y est vertical et pointe vers le haut de l'écran dans le sens positif. Par défaut, l'intervalle en x et en y est [0,1]. Cela signifie que le domaine visualisé sur toute la fenêtre est le sous-espace [0, 1] x [0, 1] : bien sûr, il s'agit de coordonnées de type flottant. L'utilisateur peut définir ses propres valeurs min et max en x et en y avec la fonction glortho. Attention: il faut appeler la fonction glloadidentity () avant. Exemple: glloadidentity (); glortho (-10., +10., -5., +5., -1, 1); Cela définit un domaine pour x variant entre -10. et +10., et un domaine pour y entre -5. et +5. Le centre du widget glut sera donc à l'origine du domaine. (ignorez les valeurs -1 et 1) Dessin 2D de primitives graphiques On peut maintenant voir les véritables fonctions de dessin. Nous allons nous limiter au traçage des primitives géométriques suivantes: segment, rectangle et cercle. Dans tous les cas, le principe est le même, illustré par l'exemple suivant qui dessine un rectangle (vide) de centre (x c, y c ), de largeur width et de hauteur height (voir

fonction graphic_draw_rectangle () dans graphic.c): glbegin (GL_LINE_LOOP); glvertex2f (xc + width/2, yc + height/2); glvertex2f (xc - width/2, yc + height/2); glvertex2f (xc - width/2, yc - height/2); glvertex2f (xc + width/2, yc - height/2); glend (); L'instruction glvertex2f, qui spécifie un sommet de la primitive, peut être appelée un nombre quelconque de fois entre les deux fonctions glbegin et glend, suivant ce que l'on souhaite dessiner. Le mode choisi (l'argument de la fonction glbegin) influence aussi le résultat. Voyons quelques modes simples: GL_LINE_STRIP: trace des segments connexes, dont les sommets sont donnés. GL_LINE_LOOP: trace le contour d'un polygone dont les sommets sont donnés (comme GL_LINE_STRIP mais un segment reliant le premier sommet au dernier est aussi dessiné). GL_POLYGON: comme GL_LINE_LOOP, mais le polygone (qui doit être convexe), est aussi rempli (filled, en anglais). Exercice: complétez la fonction graphic_draw_circle dans le fichier graphic.c (dessinez en fait un polygone régulier ayant une cinquantaine de côtés). Epaisseur de lignes

Il est possible de changer l'épaisseur des lignes dessinées. Par défaut, celle-ci est de un pixel. En appelant la fonction gllinewidth (4.) par exemple, toutes les lignes dessinées ensuite auront une épaisseur de 4 pixels. Pour revenir à une épaisseur de un pixel, il suffit d'appeler gllinewidth (1.); Couleurs (au format RGB) Il est possible de contrôler la couleur des objets dessinés. Une couleur se spécifie d'après ses composantes RGB (Red - Green - Blue, en anglais). Chaque composante peut varier entre 0 et 1. Cela permet de synthétiser des millions de couleurs. Par exemple la couleur RGB (0,0,1) correspond à un bleu pur, alors que la couleur RGB (1,1,0) correspond au jaune. La couleur RGB (0.5, 0.5, 0.5) correspond à un gris moyen. Pour établir une couleur, on peut écrire: glcolor3f (1.0, 1.0, 0.); /* jaune */ [cette fonction semble ne pas bien fonctionner en COSUN] ou bien, en déclarant un tableau: float violet [3] = 1., 0., 1. ; // composantes R,G,B glcolor3fv (violet); Processus de visualisation Quatre transformations successives utilisées au cours du processus de création d'une image: 1. Transformation de modélisation (Model): Permet de créer la scène à afficher par création, placement et orientation des objets qui la composent. 2. Transformation de visualisation (View): Permet de fixer la position et l'orientation de la caméra de visualisation. 3. Transformation de projection (Projection): Permet de fixer les caractéristiques optiques de la caméra de visualisation (type de projection, ouverture,...). 4. Transformation d'affichage (Viewport): Permet de fixer la taille et la position de l'image sur la fenêtre d'affichage. Effacement du contenu de la fenêtre On peut effacer complètement le contenu de la fenêtre, avec une couleur RGB au choix, en appelant les deux fonctions Open GL suivantes: glclearcolor (rouge, vert, bleu, 0.); // spécifie la couleur glclear (GL_COLOR_BUFFER_BIT); Back buffer et front buffer (double buffering) Il est important de comprendre que tous les appels graphiques ne sont pas exécutés

à l'écran même. Si vous dessinez une ligne, celle-ci n'apparaîtra pas immédiatement à l'écran. En effet, Open GL dessine dans une zone mémoire cachée, appelée "back buffer" en anglais. Lorsque vous avez terminé de dessiner votre image, pour la faire apparaître vous devez demander de copier cette zone mémoire à l'écran (qui est aussi un buffer, appelé "front buffer"). La fonction pour afficher le back buffer est glutswapbuffers(). Exercice 4 (niveau 0): Architecture et introduction Open GL / GLUT (document pdf séparé) Exercice 5 (niveau 1): Travail à faire Vous allez maintenant compléter (en partie) les fichiers chaine.c et cine.cpp. Travail à faire: Compilez le programme, et lancez l'exécutable. A ce stade, rien n'est affiché dans la fenêtre GLUT, et son contenu reste dans un état indéterminé. Complétez les fonctions chaine_rayon_min et chaine_rayon_max, d'après votre réponse à la question de l'exercice 1. Elles retournent les limites de l'espace atteignable par l'effecteur (situé entre deux cercles). Complétez la fonction chaine_dessine dans le fichier chaine.c. Elle doit dessiner la chaîne, qui est composée de deux segments, de deux articulations (cercles de rayon 0.2) - exploitez la 1ère formule de l'exercice 1 pour calculer la position de l'effecteur. Toutes les parties doivent être de couleur (0.2, 0.8, 1.0), et l'épaisseur de ligne doit être de 3 pixels. Remarque: Utilisez les fonctions mises à disposition par le module graphic.c pour dessiner les segments ou les cercles. Faites make pour vérifier que vous n'avez pas d'erreurs de compilation. Le résultat ne devrait pas changer. Ensuite, complétez, dans le fichier cine.cpp, la fonction redraw_all(). Cette fonction doit utiliser les variables globales au module length_segment1 et length_segment2 (longueurs des deux segments) ainsi que but_x et but_y (coordonnées de la position du but à atteindre). Cette fonction est appelée à chaque fois qu'une remise à jour complète du contenu de la fenêtre doit être effectuée. Elle doit, dans l'ordre: effacer le contenu de la fenêtre (en noir) établir un domaine de projection dont l'origine se trouve au centre de la fenêtre, et de coté 40 appeler la fonction chaine_calcule_angles pour calculer les angles alpha et beta (la position du but est passée en argument);

dessiner les limites de l'espace atteignable (avec un appel à chaine_dessine_limites); dessiner la chaîne (appel à la fonction chaine_dessine que vous avez écrit); dessiner le but à atteindre avec un carré jaune plein de coté 0.4; enfin, faire apparaître le contenu de l'image en appelant la fonction glutswapbuffers(). Ensuite, régénérez un exécutable et corrigez d'éventuelles erreurs. A ce stade, votre application devrait afficher la chaîne ainsi que les limites de l'espace atteignable, dans sa configuration par défaut. Cependant vous n'avez aucun moyen d'interagir avec l'application. Dans la série 19, vous la complèterez pour pouvoir spécifier interactivement la longueur des segments ainsi que le but à atteindre.