INTRODUCTION

Original Author: Damiano Vitulli

Translation by: Click here

Lors de la leçon précédente, nous avons mis en place les premiers éléments de notre pipeline de rendu : comment acquérir les données d'un objet et sauvegarder toutes ces données dans une structure. Aujourd'hui, nous allons accomplir les poins 2 et 3 :

  1. Acquire the object's data and store all the data in a structure (Completed!)
  2. Transformations : pour placer les objets dans le monde (transformations de modélisation et de visualisation)
  3. Rendu de la scène sur un écran en 2d (projection, transformation du viewport , back face culling, tampons de couleur et de profondeur)

Ensuite nous allons introduire la bibliothèque graphique d'OpenGL et la librairie d'utilitaire de GLUT. &Agravela fin de cette leçon nous serons capacble d'afficher un objet solide en rotation sur notre écran !

TRANSFORMATIONS POUR PLACER LES OBJETS DANS LE MONDE (transformations de modélisation et de visualisation)

Après avoir défini la structure objet, il faut appliquer quelques transformations à tous les points que nous avons avant de pouvoir les voir à l'écran. Nous voulons créer un monde, ou pour être plus exact, (soyons fou pour les simulateurs spaciaux) un uniivers complet.

La première transformation est la TRANSFORMATION de MODELISATION. Comme nous avons l'intentation de créer des vaisseaux spaciaux qui, sans la preuve du contraire, ne sont pas des objets statiques ;-), nous devons transformer le système de coordonnées locales de l'objet (qui est relatif à la position centrale de chaque objet) en un système de coordonnées absolues (qui est relatif à l'unviers tout entier ;-) ). En d'autres termes, nous devons déplacer l'objet en ajoutant la position de l'objet dans l'univers (qui peut changer si l'objet continue de bouger) aux coordonnées locales des points.

Ensuite vient la TRANSFORMATION de VISUALISATION. Notre but principal, bien sûr, est d'explorer cet univers en s'y déplaçant comme bon nous semble, transformant l'écran en une caméra libre. Comment pouvons-nous faire ce genre de tranformations ? La réponse est relativement simple. En fait, il suffit simplement de considérer que la caméra est toujours positionnée en 0,0 sans aucune rotation. Et alors ? C'est simple ! Nous prenons n'importe quelle transformation que nous devrions appliquer à la caméra pour obtenir un certain mouvement et nous appliquons la transformation inverse à tous les objets au lieu de déplacer la caméra. Par exemple, supposons que nous voulions déplacer notre point de vue vers l'objet de 10 points selon l'axe des Z et de regarder l'objet d'en haut (rotation selon l'axe des x de 40 degrés). Ce qui se passe réellement le plus souvent dans les moteurs graphiques c'est que l'objet a reculé de 10 selon l'axe des Z et a ensuite effectué ensuite une rotaion de -40 degrés selon l'axe des X. Cela simplifie grandement l'utilisation du moteur car la caméra sera toujours à l'origine.

RENDU DE LE SCENE SUR UN ECRAN EN 2D (back face culling, transformation de projection et de visualisation, tampons de couleur et de profondeur)

L'opération suivante à réaliser est le BACK FACE CULLING (face cachée). Cela signifie que nous allons exclure les triangles qui ne sont pas visibles, c'est à dire les faces qui sont au dos des faces visibles de l'objet. Ainsi nous pouvons gagner énormément de temps de rendu car la fonction de dessin ne va dessiner que la moitié de la totalité des traingles. OpenGL réalise cette opération pour nous

La transformation suivante est la TRANSFORMATION de PROJECTION . Maintenant nous devons "écraser" une scène 3d sur un écran en 2d. Nous devons simuler l'axe Z car notre pauvre moniteur ne possè que les axes X et Y. La faç la plus simple de réaliser cette translation est de diviser tous les coordonnées (x,y) des points apar leur profondeur Z. L'effet de cette procé est de rapprocher les points distants ainsi ils donnent l'impression de se rapprocher du point central x = 0 et y = 0. C'est exactement ce qu'il se produit en OpenGL. Nombreux d'entre vous doivent connaître ceci comme étant la "projection en perspective ".

La dernière transformation est la VIEWPORT TRANSFORMATION (transformation d'affichage). Cela convertit juste tous les points qui vont être utilisés dans la résolution de l'affichage courant.

Un tampon est une zone mémoire dans laquelle il est possible de sauvegrader des données. Les tampns d'OpenGL sont des régions précisément aussi grande que la zone d'affichage (viewport). Par exemple, si nous avons une fenêtre d'un taille de 640 x 480, nous allouons un tampon de: 640 x 480 = 307200 pixels. Ce qui &eacutequivaut en mode couleur 16 bits: 307200*16 = 4915200 bits. Ce qui correponds à peu près à 614 Koctets de mémoire vidéo!

OpenGL possède deux tampons principaux: le TAMPON de COULEURS (qui peut être simple ou double) et le TAMPON de PROFONDEUR (DEPTH BUFFER).

Le TAMPON de COULEUR est ce que l'on voit à l'écran et où aboutissent toutes les opérations de dessin. Après avoir réalisé tous les calculs géométriques, OpenGL commence à remplir ce tampon pixel par pixel, remplissant nos triangles. Si la sc&egave;ne est animée, le TAMPON de COULEURS est dessiné et effacé &agave; chaque frame. Le TAMPON de COULEURS fonctionne souvent par paire, il s'agit du TAMPON DOUBLE (DOUBLE BUFFER), qui est ce dont nous allons nous servir. Le TAMPON DOUBLE à afficher un tampon pendant que l'autre est effacé et rempli avec l'image suivante. Une fois cette opération r&eacutealisée, les tampons sont échangés. En utilisant cette technique on élimine quasiment l'effet scintillement.

Maintenant, supposons qu'il y ait deux triangles dans notre scène, l'un devant l'autre, les deux étant visibles. Dans ce cas, l'ordre dans lequel les triangles sont dessinés est très important. Si le triangle le plus proche de nous est dessiné en premier et ensuite on dessine le plus loin, les pixels du triangle le plus proche seront recouverts par ceux du triangle le plus éloigné, créant un effet indésirable. Une technique pour éviter ce désagrément consiste à trier tous les triangles visibles selon leur profondeur Z. Et ensuite les dessiner dans cet ordre, du plus distant au plus proche. Cette technique est appelée "l'ALGORITHME du PEINTRE". Nous n'allons pas utiliser cette méthode car OpenGL nous offre un outils plus puissant: le TAMPON de PROFONDEUR (DEPTH BUFFER). Ce tampon a les mêmes dimensions que le TAMPON de COULEUR mais au lieu de contenir la couleur des pixels, il contient des informations à propos de la profondeur de chaque pixel selon l'axe des Z. Sauvegarder cette information est très important et ce pour une raison très simple. Quand nous allons dessiner nos triangles pixel par pixel à l'écran, nous allons d'abord faire un test pour savoir si le pixel que nous allons dessiner est plus proche que celui actuellement sauvegardé dans le Z BUFFER (tampon de profondeur). S'il est plus proche, il faut alors mettre à jour le Z BUFFER avec la nouvelle valeur et écrire dans le tampon de couleurs. Si ce n'est pas le cas alors le pixel n'est pas pris en compte pour le dessin. Cette procédure donne d'excellents r&eacutesultats!

Nous n'avons pas besoin de nous soucier de comment coder ces opérations à la main car notre superbe librairie OpenGL va réaliser tous les calculs pour nous. OpenGL va aussi s'occuper de toutes les opérations bas niveau de dessins, y compris le remplissage des triangles ainsi que l'application des couleurs aussi bien que l'éclairage et les effets de mapping.

Nous n'avons rien à faire? Donc, qu'est ce que nous faisons là? Nous perdons notre temps? Non! Nous devons fournir à OpenGL toutes les informations il a besoin pour qu'il puisse faire tous ces calculs, faire le lien avec la carte graphique et réaliser toutes les opérations de bas niveau en utilisant (si elle est présente) l'accélération 3d matérielle.

OPENGL, ENFIN!

OpenGL est une librairie qui nous permet d'interagir avec le matériel graphique. Il possèssde de nombreuses fonctions permettant de dessiner des points, des lignes et des polygones et effectue tous les calculs nécessaire pour l'éclairage, le shading et les transformations de points. GLUT, quant à elle, est une boîte à outils utilisée pour faire le lien entre OpenGL et le système de fenêtrage. Il nous permet de créer une fenêtre indépendamment de la plateforme utilisée (Windows ou Linux). Elle gère aussi les entrées au clavier.

La structure de notre programme OpenGL est divisé en plusieurs sections:

  1. La fonction init: utilisé pour démarrer OpenGL et initialiser les matrices de modélisation, de visualisation et de projection. Il est aussi possible de mettre toutes les autres initialisations dans cette fonction.
  2. La function resize: appelée à chaque fois que l'utlisateur démarre le programme ou change la résolution de la fenêtre de sortie. Elle est nécessaire pour communiquer la nouvelle taille de la fenêtre de sortie à OpenGL
  3. La fonction keyboard: appelée à chaque fois qu l'utilisateur appuie sur une touche.
  4. La fonction de dessin: nettoyage de tous les tampons (couleurs et profondeur). Toutes les transformations de modélisation, de visualisation et de projection sont effectuées et la scène est dessiné. Enfin les 2 tampons de couleurs sont échangés.
  5. Boucle principale: une boucle infinie, qui appelle toutes les fonctions à chaqe image.

Une fonction OpenGL typique ressemble à: glFunctionName(GL_TYPE arguments).

Pour les fonctions GLUT, cela ressemble à: glutFunctionName(arguments).

OpenGL possède aussi des types propres pour faciliter la portablilité. Ces types commencent avec le préfixe "GL" et sont suivis de "u" (pour les valeur non signées) et apr le type(float, int etc.). Par exemple, on peut utiliser GLfloat ou GLuint pour déclarer des variables de types similaires au type "float" et "unsigned int" en C.

ENTETES

La première chose à faire est d'inclure les fichiers d'entête nécessaire: windows.h (pour les utlisateurs de Windows) et glut.h

#include <windows.h>
#include <GL/glut.h>

En incluant glut.h, nous aussi indirectement inclus gl.h et glu.h (les fichiers d'entête d'OpenGL). Il est aussi très important de mettre en place les options du linker dans le compilateurPour cela il faut inclure les librairies opengl32.lib, glu32.lib et glut32.lib

Maintenant, nous devons déclarer une fonction qui intialise OpenGL.

LA FONCTION INIT

void init(void)
{
   glClearColor(0.0, 0.0, 0.2, 0.0);
   glShadeModel(GL_SMOOTH);
   glViewport(0,0,screen_width,screen_height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,1.0f,1000.0f);
   glEnable(GL_DEPTH_TEST);
   glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
}

Analysons le code:

  • void glClearColor( GLfloat rouge, GLfloat vert, GLfloat bleu, GLfloat alpha); définit les veleurs rouge, vert, bleu et alpha utilisées par glClear pour nettoyer les tampons de couleurs. Nous utilisons un bleu profond comme couleur de fond donc nous assignons 0.2 à la composante bleue. Les autres composantes sont mise à 0.0 aisni que la composante alpha (la signification de cette composante sera expliquée dans un prochain tutorial). J'ai oublié de vous dire que la gamme des valeurs admises pour les paramètres des fonctions OpenGL est 0-1. Nous pouvons donc mélanger toutes les composantes pour créer n'importe quelle couleur. Par exemple, pour créer un fond jaune, nous devons mettre la composante bleue à 0 et les composantes verte et rouge à 1.
  • void glShadeModel( GLenum mode ); spécifie une valeur pour indiquer le type de lissage utilisé (la façon dont OpenGL va remplir les triangles). Si nous utilisons GL_FLAT comme "mode" alors tous les triaangles seront dessinés en modeFLAT SHADING et la couleur sera uniforme (la même couleur pour tous les pixels du triangle). Si nous utilisons GL_SMOOTH à la plcae, OpenGL utilisera une interpolation linéaire entre les couleurs des sommets du triangle. Cette technique est aussi appelée LISSAGE de GOURAUD (GOURAUD SHADING).
  • void glViewport( GLint x, GLint y, GLsizei largeur, GLsizei hauteur); définit les dimensions de la fenêtre d'affichage pour les transormations d'affichage.
  • void glMatrixMode( GLenum mode); indique à OpenGL wuelle matrice est la matrice active pour les opérations sur les matrices. Qu'est ce qu'une matrice? Nous n'avons pas encore parlé des matrices. C'est un sujet trop compliqué pour l'instant et nous allons dédier un tutorial complet aux matrices plus tard. Pour l'instant, vous devez juste savoir qu'une matrice est un objet utilisé par OpenGL pour réaliser. Pour "mode", on peut avoir les valeurs GL_PROJECTION pour les transformations de projections ou GL_MODELVIEW pour les transformations de visualisation et de modélisation. Une fois la matrice courante spécifiée, on peut la modifier comme on veut.
  • void glLoadIdentity( void ); réinitialisé la matrice courante (GL_PROJECTION dans notre cas) en chargeant la matrice identité.
  • void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near,GLdouble far); vous rappelez vous la transformation de projection? C'est ici que nous la mettons en pratique. OpenGL remplit la matrice courant active (GL_PROJECTION) en utilisant les valeurs spécifiée dans gluPerspective. Avec "fovy",nous devons indiquer l'angle du champs de vue (field of view), dans "aspect", le rapport de l'aspect (largeur/hauteur), dans "near" et "far", la distance minimale et maximale des plans de clipping.
  • void glEnable( GLenum cap ); active différentes capacités. Ici, nous avons activé le Z Buffer (TAMPON de PROFONDEUR).
  • void glPolygonMode( GLenum face, GLenum mode ); dessine nos polygones comme des points, des lignes ou des polygones remplis (en utilisant GL_POINT,GL_LINES ou GL_FILL comme paramètre).

LA FONCTION RESIZE

Cette fonction est très similaire à "init". Elle nettoie les tampons, redéfinit notre fenêtre d'affichage et reaffiche notre scène.

void resize (int width, int height)
{
   screen_width=width; 
   screen_height=height; 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glViewport(0,0,screen_width,screen_height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,1.0f,1000.0f);
   glutPostRedisplay ();
}

Voici les fonctions que nous n'avons pas encore vu:

  • void glClear( GLbitfield mask ); nettoie les tampons spécifiés par "mask". Nous pouvons indiquer plus de 1 tampon en les séparant par l'opérateur logique "|". Dans notre cas, nous nettoyons les tampons de couleurs et de profondeur.
  • L'appel à glViewport est nécessaire ici pour redéfinir la nouvelle fenêtre d'affichage avec les nouvelles valeurs contenues dans screen_width et screen_height.
  • void glutPostRedisplay(void); Cette une fonction GLUT. Elle appèle n'importe quelle fonction que nous avons indiqué dans la fonction glutDisplayFunc (appelée dans notre fonction Main), pour redessiner la scène.

LES FONCTIONS KEYBOARD

Nous allons définir deux fonctions pour le clavier: une pour gérer les entrées de caractères ASCII ("r" et "R" et un caractère vide ' ') et une autre pour gérer les touches de direction:

void keyboard (unsigned char key, int x, int y)
{
   switch (key)
   {
      case ' ':
         rotation_x_increment=0;
         rotation_y_increment=0;
         rotation_z_increment=0;
      break;
      case 'r': case 'R':
         if (filling==0)
         {
            glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
            filling=1;
         } 
         else 
         {
            glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
            filling=0;
         }
      break;
   }
}

Nous utilisons trois variables pour autoriser note objet à tourner autour des axes désirés: rotation_x_increment, rotation_y_increment and rotation_z_increment. On peut réinitialiser chacune de ces variables en utilisant la touche espace et arrêter le mouvement de notre objet dans sa position actuelle. Nous pouvons aussi changer le mode de dessin pour nos polygones de rempli à filaire avec les touche "r" ou "R".

void keyboard_s (int key, int x, int y)
{
   switch (key)
   {
      case GLUT_KEY_UP:
         rotation_x_increment = rotation_x_increment +0.005;
      break;
      case GLUT_KEY_DOWN:
         rotation_x_increment = rotation_x_increment -0.005;
      break;
      case GLUT_KEY_LEFT:
         rotation_y_increment = rotation_y_increment +0.005;
      break;
      case GLUT_KEY_RIGHT:
         rotation_y_increment = rotation_y_increment -0.005;
      break;
   }
}

Cette fonction est vraiment semblable à la précédente mais elle gère les touches de direction. Remarquez les constantes GLUT: GLUT_KEY_UP, GLUT_KEY_DOWN, GLUT_KEY_LEFT et GLUT_KEY_RIGHT qui identifient leur directions respectives et incrémente ou décrémente les valeurs de rotations.

LA FONCTION DE DESSIN

Ladies and gentlemen, la fonction que vous attendez tous: la fonction de dessin!

void display(void)
{
   int l_index;
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0,0.0,-50);
   rotation_x = rotation_x + rotation_x_increment;
   rotation_y = rotation_y + rotation_y_increment;
   rotation_z = rotation_z + rotation_z_increment;
   if (rotation_x > 359) rotation_x = 0;
   if (rotation_y > 359) rotation_y = 0;
   if (rotation_z > 359) rotation_z = 0;
   glRotatef(rotation_x,1.0,0.0,0.0);
   glRotatef(rotation_y,0.0,1.0,0.0);
   glRotatef(rotation_z,0.0,0.0,1.0);

la première partie de cette fonction nettoie les tampons de couleur et de profondeur et applique les transformations de visualisation et de modélisation. Nous indiquons que la matrice courante est la matrice "modelview" en utilisant GL_MODELVIEW dans glMatrixMode. Ensuite nous initialisons la matrice à chaque imageen appelant glLoadIdentity.

  • void glTranslatef( GLfloat x, GLfloat y, GLfloat z ); déplace notre objet dans le monde 3D. Cette fonction multiplie la matrice du modèle par une matrice de translation définie en utilisant les paramètres x,y,z. La lettre "f" à la fin du nom indique que nous allons utiliser des valeurs de type flottant, alors que la lettre "d" indique des paramètres de type double. Nous utilisons glTranslate pour bouger l'objet de 50 points vers l'avant dans ce cas. Vous rappelez-vous la caméra et les transformations de visualisation? Bien, nous pouvons considérer cette opération comme une translation de notre caméra de -50. Ce mouvement est nécessaire car nous devons déplacer l'objet d'une petite distance au loin pour pouvoir le voir. Une fois le projet compilé vous pouvez essayer de modifier la valeur du Z, juste pour voir comment cela affecte la distance.
  • void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); Cette fonction multiplie la matrice courante par une matrice de rotation. C'est utilisé pour appliquer des rotations de angle degrés autour du vector (x,y,z). Les variables variables rotation_x, rotation_y et rotation_z sauvegardent les valeurs de rotation de l'objet. Nous considérons cette transformation comme une transformation de modélisation car nous faisons tourner l'objet et non pas le point de vue. Comme vous pouvez le voir, la différence entre les transformations de modélisation et de visualisation ne sont pas si évidentes. Cependant, nous ne devons pas nous occuper de cela pour l'instant. Nous nous occuperons de ce sujet dans le tutorial sur la caméra.
   glBegin(GL_TRIANGLES);
   for (l_index=0;l_index<12;l_index++)
   {
      glColor3f(1.0,0.0,0.0);
      glVertex3f( cube.vertex[ cube.polygon[l_index].a ].x, cube.vertex[ cube.polygon[l_index].a ].y, cube.vertex[ cube.polygon[l_index].a ].z);
      glColor3f(0.0,1.0,0.0);
      glVertex3f( cube.vertex[ cube.polygon[l_index].b ].x, cube.vertex[ cube.polygon[l_index].b ].y, cube.vertex[ cube.polygon[l_index].b ].z);
      glColor3f(0.0,0.0,1.0);
      glVertex3f( cube.vertex[ cube.polygon[l_index].c ].x, cube.vertex[ cube.polygon[l_index].c ].y, cube.vertex[ cube.polygon[l_index].c ].z);
   }
   glEnd();
   glFlush();
   glutSwapBuffers();
}

La seconde partie de la fonction de dessin utilise les fonctions glBegin et glEnd. Ces deux commandes indiquent les points qui définissent une primitive graphique.

  • void glBegin( GLenum mode ); indique le début d'une liste de données pour les points qui définissent une primitve géométrique. Le paramètre "mode" permet d'indiquer le type de primitives qu'on va dessiner. Il y a dix types de primitives disponibles (GL_TRIANGLES, GL_POYLGON, GL_LINES etc.). Nous utilisons GL_TRIANGLES car nous voulons dessiner notre cube en utilisant 12 triangles. Nous faisons ceci en démarrant une boulce "for" dans laquelle sont effectués 3 appels à glVertex3f et glColor3f.
  • void glVertex3f( GLfloat x, GLfloat y, GLfloat z ); indique les coordonnées x,y,z d'un point. Le suffixe "3f" indique qu'il s'agit de trois paramètres de type flottant. Si vous devez juste travailler avec les valeurs x et y de type double, la commande correcte est: void glVertex2d( GLdouble x, GLdouble y ). Nous inséons les données de la géométrie de l'objet pour chaque paramètre.
  • void glColor3f( GLfloat red, GLfloat green, GLfloat blue ); spécifie la couleur active. Nous définissons une couleur différente (rouge 1,0,0 - vert 0,1,0 - bleu 0,0,1) pour chaque point. Remarquez comment le mode de lissage GL_SMOOTH d'OpenGL affècte les couleurs finales du triangle. Nous voyons que les couleurs sont interpolées entre chaque point ainsi elles changent graduellement. C'est très joli à voir!!
  • void glEnd( void ); finit la définition de notre objet.
  • void glFlush( void ); est utilisé pour obliger OpenGL à dessiner la scène. Les tampon de couleur et de profondeur sont remplis et la scène est maintenant visible. Enfin!
  • void glutSwapBuffers(void); échange le tampon secondaire (back buffer) (où travaillent toutes les fonctions de dessin) avec le tampon primaire (front buffer) (ce que nous voyons dans notre fenêtre) quand nous sommes en mode double tampon. Si nous ne sommes pas en mode double tampon cette fonction n'a aucun effet.

LA FONCTION MAIN

int main(int argc, char **argv)
{

Les quatre fonctions suivantes de la librairie GLUT nous permettent de créer notre fenêtre pour la sortie graphique.

   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize(screen_width,screen_height);
   glutInitWindowPosition(0,0);
   glutCreateWindow("www.spacesimulator.net - tutoriaux de moteur 3D: Tutorial 2");
  • void glutInit(&argc, argv); initialise la bibliothèque GLUT. Nous devons appeler cette fonction avant d'appeler n'importe quelles autres fonctions GLUT.
  • void glutInitDisplayMode(unsigned int mode); mets en place le mode d'affichage. Les constantes GLUT : GLUT_DOUBLE, GLUT RGB, GLUT DEPTH définissent respectivement le mode double tampon, le mode couleur RVB et le tampon de profondeur.
  • void glutInitWindowSize(int width, int height); and void glutInitWindowPosition(int x, int y); est utilisée pour définir les dimensions et la position initiale de la fenêtre de sorite.
  • int glutCreateWindow(char *name); crée notre fenêtre de sorite.

Pour définir les callbacks, nous utilisons:

   glutDisplayFunc(display);
   glutIdleFunc(display);
   glutReshapeFunc (resize);
   glutKeyboardFunc (keyboard);
   glutSpecialFunc (keyboard_s);
   init();
   glutMainLoop();
}
  • void glutDisplayFunc(void (*func) (void)); spécifie la fonction à appeler quand la fenêtre doit être redessiner, c'est-à-dire quand il y a un appel à glutPostRedisplay ou quand il y a une erreur signalée par le système de fenêtre.
  • void glutIdleFunc(void (*func) (void)); mets en place le callback de la fonction idle: cette fonction est appelée à chaque fois qu'il n'y a aucun événement signalé par le système de fenêtre. Ce qui signifie que notre fonction de dessin "idle" est continuement appelée, tant qu'aucun événement n'est reçu. Ce qui maintient notre animation en marche.
  • void glutReshapeFunc(void (*func) (void)); mets en place la fonction callback de redimensionnement.
  • void glutKeyboardFunc(void (*func) (void)); la fonction callback du clavier pour les caractères ASCII.
  • void glutSpecialFunc(void (*func) (void)); la fonction callback du clavier pour les caractères non-ASCII.
  • void glutMainLoop(void); démarre la boucle infinie pour la GLUT avec la gestion des événements.

CONCLUSIONS

Alors? Ca y est tout est là! Je sais, c'est un travil de longue haleine mais regardez! Vous êtes maintenant de créer un objet 3D réel en rotation! Ce qui signifie que vous avez créé votre premier moteur 3D!

Dans la leçon suivante, nous allons étudier comment réliser le texture mapping (le plaçage de texture en français?)

SOURCE CODE

The Source Code of this lesson can be downloaded from the Tutorials Main Page