Ce projet vous propose de mettre en place les notions introductives à l’image de synthèse vues en cours. Un environnement a été mis en place afin de faciliter votre tâche. Téléchargez le source du projet. Vous commencerez votre travail en intégrant votre code dans le fichier eleves.cpp. Ce fichier contient la fonction TP1() appelée lors de l’appui du bouton OK présent sur la fenêtre de l’application. Lorsque vous allez créer des nouvelles classes et des nouvelles fonctions, créez les fichiers .cpp et .h correspondant et intégrez dans votre projet. Pour ouvrir un projet, ne jamais ouvrir un fichier de code seul (en faisant ouvrir depuis visual ou en double-cliquant sur le fichier depuis l’explorateur). Il faut ouvrir le fichier Projet_ima.vcproj qui contient toutes les informations relatives à l’ensemble des fichiers à compiler.


              Lorsque vous voulez migrez votre projet d’un endroit à l’autre, procédez de la manière suivante : allez dans le répertoire de votre projet, supprimez les répertoires Debug ou Release s’ils sont présents (ils contiennent des fichiers de compilation intermédiaire et des informations de débogage sans importance) puis supprimez le fichier Projet_ima.ncb, compressez le tout et vous obtenez une archive d’environ 700ko.




Schéma de la progression




             
Nous vous proposons de mettre en place successivement la paramétrisation des surfaces, le Z-Buffer et l’affichage à l’écran. Ensuite seront ajoutées les fonctions de luminosité, puis de textures…



                                   



Conventions




Orientation de l’espace de travail,
nous utiliserons le repère suivant :



Rappel, le repère utilisé par les API graphiques
est orienté de la manière suivante :

 



Nous utilisons comme repère pour les coordonnées sphériques les angles u et v suivants :





   x(u,v) = cos(v) * cos(u)
   y(u,v) = cos(v) * sin(u)
   z(u,v) = sin(v)


Nous utilisons une simple projection orthogonale pour visualiser la scène à travers l'écran en mode Z-buffer. Ainsi, l'axe x de l'écran va correspondre à l'axe x du repère 3D et l'axe y de l'écran va correspondre à l'axe z de la scène 3D à une transformation prêt car ils ne sont pas orientés de la même manière.


Modèle d'illumination



Dans le projet est fournie une classe Couleur. Consultez  le header correspond pour savoir comment utiliser cette classe. Vous remarquez que de nombreux opérateurs ont été ajoutés, notamment l'opérateur + pour ajouter deux couleurs, l'opérateur * pour multiplier une couleur par un réel et l'opérateur % pour multiplier les composantes R,V et B  deux à deux entre deux couleurs. Nous rappelons les formules données en cours pour chaque modèle d'illumination :


Camb = Cobjet % Cambiant


Cdiff =
Cobjet % Clampe × cos(θ)

θ représente l'angle entre le vecteur lumière (orienté du point courant vers la source) et le vecteur normal (orienté du point courant vers l'extérieur).  Une coefficient multiplicatif supplémentaire peut être appliqué pour régler le niveau de l'effet diffus (entre 0 : rien et 1 : 100%)

Cspec Clampe × cosk(S,O)

S représente le vecteur idéal de réflexion de la lumière. Si L correspond au vecteur lumière (orienté du point courant vers la source) et si N correspond au vecteur normal au point courant, alors S est le symétrique de L par rapport à N. O représente le vecteur de l'observateur orienté du point courant vers l'oeil de l'observateur. Notez qu'il faut par conséquent donner une position à cet oeil dans votre scène qui doit correspondre approximativement à votre position face à l'écran, c'est à dire devant la scène et non au beau milieu des objets et encore moins en plein milieu d'une des sphères.  Une coefficient multiplicatif supplémentaire peut être appliqué pour régler l'intensité de l'effet. k est l'exposant réglant la largeur du spéculaire sur l'objet, à choisir entre 30 et 100. On rappelle que :

S = 2 N
× (L.N) - L

Cette formule ne fonctionne bien sur que si les vecteurs sont normalisés


Séance de travail




● L’environnement de travail


Un squelette du projet (sous visual 2005) est fourni. Cette application est un projet MFC – Dialog Based, c'est-à-dire une application fenêtrée et non une application qui se lance dans une console texte. Sur la fenêtre de l’application, vous trouverez un seul bouton qui va déclencher la fonction : TP1() présente dans le fichier eleves.cpp. Les autres fichiers fournis sont :

  • P3 (.h/.cpp) qui contient une classe servant à la gestion des vecteurs 3D ainsi que les opérations classiques : + - * / …
  • Couleur (.h/.cpp) qui stocke les informations sur la couleur et permet de les manipuler facilement
  • Boite_a_outils (.h/.cpp) qui inclut une fonction d’effacement de la fenêtre (CLS) et une fonction d’inversion des coordonnées sphériques
  • Texture (.h/.cpp) qui permet de créer une texture à partir d’images JPG. On peut ainsi accéder à l’information de couleur par la fonction color(u,v). Cette classe doit être indépendante de la taille de l’image chargée, ainsi les coordonnées u et v seront toujours données entre 0 et 1


  • Etape 1 : surfaces paramétriques et Z-Buffer


             
    Un Z-Buffer est un tableau 2 dimensions qui est associé à l’ensemble des pixels de la zone à afficher. Ainsi pour chaque pixel allumé à la position (a,b,c), on va stocker la composante en y (qui pour nous représente la profondeur) dans la case ZBuffer[a][c]. Si jamais la valeur précédemment stockée est invalidée, cela veut dire que le nouveau point est devant l’ancien est qu’il doit le remplacer. Cette façon de procéder permet de gérer aisément l’occultation entre objets.

                En utilisant une paramétrisation correcte basée sur les coordonnées sphériques, dessinez deux sphères de rayon 100 et de coordonnées (200,0,200) et (350,0,200). Vous devriez obtenir le résultat suivant :

                                                       

    Etape 2 : modèles d’illumination

                Appliquez à ces deux sphères les modèles de lumière ambiante, diffuse et spéculaire vus en cours. Choisissez la source de lumière que vous souhaitez ainsi que son affaiblissement. Nous présentons le résultat obtenu pour une source directionnelle (1,-1,1) sans affaiblissement :

                                              

    Etape 3 : application des textures

                Grâce à la paramétrisation bidimensionnelle (u,v) vous pouvez facilement appliquer une texture provenant d’une image extérieure. A partir des fichiers joints au projet, appliquez des textures sur vos sphères tout en laissant activer les modèles d’illumination précédents. Voici le résultat obtenu à partir des textures OR et METAL.

                                            



    Etape 4 : Bump-Mapping

                Le Bump-Mapping est une technique permettant de simuler la variation des normales de l’objet relativement à une faible déformation de la surface qui produit cependant un effet visuel notable. Il s’agit par exemple des  crénelures, des cabossages, des rainures… Nous allons supposer que le point M(u,v) à la surface de l’objet subi une variation de hauteur : h(u,v) dans la direction de la normale extérieure N(u,v). Nous posons :

                            M’(u,v) = M(u,v) + h(u,v) ´ N(u,v)

    Par définition nous rappelons que la normale d’une surface paramétrique en u et v est égale à :

    N(u,v) = ± M/u ^ M/v / ||M/u ^ M/v||

    Calculez l’expression de la nouvelle normale N’(u,v) à partir des égalités précédentes et des approximations devant être effectuées. Appliquez ces résultats à la paramétrisation sphérique de nos objets. Le résultat obtenu est dépendant de la grandeur h/u et h/v. La carte de déformation h(u,v)  (le bump-map) est stockée dans une image en niveau de gris. Pour estimer la valeur h(u,v)/u on peut par exemple prendre :

    h(u,v)/u = ( Pixel[u*Largeur+1][v*Largeur]- Pixel[u*Largeur][v*Hauteur]) ´ K

                Voici le résultat obtenu avec deux bump géométriques :

                                        



    Etape 5 : les objets

    Le but de cette étape est de construire une classe représentant l’objet sphère. Ses attributs internes vont être par exemple : son rayon, son centre, sa couleur…  Après cela, vous intégrerez un nouveau type d’objet : les rectangles. D’autres objets pourront être ajoutés. Dans tous les cas, l’ensemble de ces clases doit  hériter d’une superclasse Objet3D commune à tous les futurs objets à afficher.



    Etape 6 : les lampes

            Prévoyez une classe Lumière stockant tous les attributs propres à un modèle d’éclairage (type, position…). Vous pouvez commencer par le type : point light. Comme pour la superclasse Objet3D, vous devrez créer une superclasse lampe qui sera une classe mère pour vos différents types de lampe. Essayez de ne pas mélanger la notion de lampe (cad une entité qui éclaire les objets de la scène) avec les modèles d’illumination (modèles qui décrivent la manière dont les objets renvoie la lumière).



    Etape 7 : le ray-casting

            Implémentez cette méthode afin de dessiner les boules anciennement tracées. N’oubliez pas de désactiver le Z-Buffer qui devient alors inutile. Reconstruisez le dessin obtenu à l’étape 4.



    Etape 8 : l’occultation

            Pour chaque rayon touchant un objet, vérifiez que le trajet allant de chaque source lumineuse vers ce point ne traverse pas un objet de la scène.


    Etape 9 : le ray-tracing

                Implémentez l’appel récursif dû à la propagation des rayons par transmission et réflexion.