Master Informatique 2017-2018
M3DS



TP 03 : Révolution


Exercice 1. Introduction

Question 1. Nous travaillerons principalement dans Revolution.cpp. Tous les aspects techniques bas-niveau sont offerts par le squelette (aspects déjà abordés dans les 2 premiers tp) : shaders, vao, vbo, commandes de tracé. On se concentre ici sur la création des tableaux qui permettront d’initialiser les vao/vbo (comme ce qui était fait pour le tétraèdre du tp "OpenGL3D"). Ainsi le squelette offre la méthode :

void Revolution::initVao(index,position,normal,texCoord)

Il faudra appeler cette méthode de la façon suivante :


Exercice 2. Sphère
Rendez vous dans Revolution::initSphere() qui se charge d’initialiser les données d’une sphère. Constatez l’appel à initVAO décrite précédemment. Nous commençons par construire les positions des sommets d’une sphère.

Il existe de nombreuses façons de constuire une (approximation de) sphère avec des polygones. Ici, nous nous appuyons sur une construction par slices/stacks (cf figure). Par analogie avec une planète, les slices correspondent aux méridiens alors que les stacks correspondront aux parallèles.

Autrement dit une sphère est une grille de points dont il faut calculer la position correcte de chaque sommet (remarque : la première et la dernière ligne de stack correspondent aux pôles : les points de chacune de ces lignes sont confondus).

Pour générer/tracer cette grille de nombreuses approches peuvent être adoptées. Dans les questions qui suivent nous choisissons de donner le tableau des positions correspondant aux coordonnées p[0], p[1], p[2], ... de la figure, puis de fournir les indices de chaque triangle de cette grille (sur la figure, par exemple, le premier quadrilatère correspond aux indices de 2 triangles {6,0,1,1,7,6}). Ainsi la commande de tracé du squelette est un glDrawElements(GL_TRIANGLES,... (vous pouvez le vérifier dans Revolution::draw).

Remarque : parmi les autres approches qui auraient pu être entreprises, citons principalement :

Question 1. Commençons par initialiser le tableau p de Revolution::initSphere avec les x,y,z de chaque p[0], p[1], ... de la figure. Pour la sphère (de rayon 1 et de centre l’origine), chaque point p est donné par :

P=



x=cos(θ)sin(φ) 
y=cos(φ) 
z=sin(θ)sin(φ) 
avec  
θ ∈ [0,2π] 
φ ∈ [0,π]

La direction des stacks étant ici l’axe Y; l’angle θ varie dans le sens des slices; l’angle φ varie dans le sens des stacks. La constante π est obtenue avec M_PI.

Une fois fait, il faut initialiser le tableau d’indices : il suffit de donner les indices des triangles pour chaque quadrilatère d’un stack et faire de même pour tous les slices (boucles imbriquées). Ainsi les premiers indices qu’on peut retrouver dans le tableau avec la grille de la figure est, par exemple, {6,0,1,1,7,6,...}.

Pour tester votre construction il suffit de cliquer sur le bouton Sphere de l’application (inutile d’initialiser les normales et les coordonnées de textures pour tester les positions/indices en visualisation "fil de fer" comme proposé par le squelette; les normales et textures concernent les questions suivantes). Vous pouvez tourner autour de l’objet en maintenant bouton gauche+glisser.

Remarquez que les triangles peuvent être verts ou rouges : le vert correspond aux faces FRONT et le rouge aux faces BACK (si vous obtenez une alternance rouge/vert, ou bien une orientation inverse de l’image ci-dessus, vous pouvez attendre la question suivante pour corriger et ainsi constater la conséquence).

Question 2. Passons aux normales pour avoir une visualisation avec éclairage. Il suffit d’affecter le tableau n dans Revolution::initSphere. En chaque sommet P(x,y,z) de la sphère quel est un vecteur normal à la sphère ? Affectez le tableau puis Testez (il suffit d’appuyer sur le bouton Light pour activer le tracé avec le shader qui applique l’éclairage).

Si vous constatez des triangles noirs (ou tout noir), ou bien des triangles rouges alternés avec des triangles verts il faut vérifier l’orientation de vos triangles : tous les triangles doivent être orientés directs vers l’extérieur (cette contrainte sera justifiée lors du chapitre sur l’éclairage, mais sachez que c’est une contrainte très souvent requise pour avoir une visualisation correcte d’un objet 3D). Pour corriger l’orientation, il suffit de changer le sens des sommets des triangles, c’est à dire le sens de certains indices du tableau index que vous avez affectés à la question précédente. Effectuez cette correction éventuelle.

Question 3. Passons à présent au placage de texture. Il faut donner les coordonnées de textures (tableau t) pour plaquer l’image suivante sur la sphère.

Il suffit d’attribuer "régulièrement" (i.e. interpolation linéaire) pour chaque sommet les coordonnées (s,t) en convertissant les angles (θ, φ) dans l’intervalle [0,1] (notez que l’image est déjà déformée pour avoir un placage naturel sur la sphère, i.e. par exemple les pôles s’étendent sur toute la première et dernière ligne de l’image).

Les coordonnées de texture seront alors données pour un sommet correspondant à θ et φ par :









s=
θ
 
t=
φ
π

Testez (il suffit de cliquer sur le bouton "Texture")


Exercice 3. Revolution

Un objet de révolution est construit à partir d’une courbe 2D (appelé profil ou "cross section") qui est reproduite par rotation autour d’un axe.

.

Sur l’image de gauche, on voit le profil qui sera tourné autour de l’axe représenté par le segment rouge (à droite du segment rouge est affiché le profil en miroir pour mieux appréhender le résultat final).

Le maillage de l’objet résultant est obtenu avec exactement le même principe que pour la sphère : il s’agit d’une grille décomposée en slices/stacks. La seule différence est que les coordonnées des points de chaque slice correspondent aux points du profil qui subit une rotation.

Le squelette offre la saisie d’un profil (il suffit d’appuyer sur le bouton "input profile"). Un profil par défaut apparait (pour éviter de resaisir un profil lors de chacun de vos tests). Vous pouvez appuyer sur la touche <c> pour effacer le profil et saisir les points avec click droit. Le click gauche maintenu sur un point permet de le déplacer.

Pour la construction, on suit la même démarche que pour la sphère dans les questions qui suivent.

Question 1. Dans Revolution::initRevolution il faut affecter p et index. Pour chaque slice, les points du profil sont obtenus dans le membre _profile[i] (i correspondant à un indice de stack; notez que le nombre de stacks de l’objet de révolution correspond aux nombres de points du profil).

Dans le squelette chaque _profile[i] est un Vector3 (avec une coordonnée z=0; cela aurait pu être un simple Vector2 puisque le profil est en 2D mais le fait d’être en 3D simplifie le squelette).

Pour pouvoir tourner les points du profil autour de l’axe Y à chaque slice, il suffit d’appliquer la fonction A=unVector3.rotationY(unAngle) (unAngle étant en radian). Par exemple A=_profile[0].rotationY(0.5) (ne modifie pas _profile[0]).

Affectez également correctement le tableau index ("normalement" il s’agit d’un copier-coller de ce qui a été fait pour la sphère; comprenez bien qu’il s’agit exactement de la même structuration des triangles que pour la sphère).

Testez (il faut cliquer sur le bouton "Revolution" pour générer l’objet; vous pouvez bien sûr tester avec un autre profil saisi).

Remarque : pour éviter de devoir cliquer sur le bouton "Revolution" à chaque fois que vous lancez le programme, vous pouvez changer la ligne ERequestInit _requestInit=Init_Sphere; avec Init_Revolution dans GLApplication.h.

Vous pouvez vous préoccuper d’ores et déjà de l’orientation correcte des triangles (tous les triangles doivent être orientés identiquement; i.e. il ne doit pas y avoir d’alternance rouge/vert entre 2 triangles successifs).

Question 2. Passons aux normales pour l’éclairage. Ici contrairement à la sphère nous ne connaissons pas à priori le vecteur orthogonal en chacun des points. Nous allons la déterminer par moyenne aux sommets. Il suffit de raisonner sur le profil.

Un exemple de comment procéder :

  1. La direction de chaque segment est donnée par dir=_profile[i+1]-_profile[i].
  2. Pour obtenir un vecteur orthogonal à ce segment (qui est, rappelons le, en 2D car z=0), il suffit de prendre (-dir.y(),dir.x(),0) (faire le produit scalaire avec dir pour vérifier).
  3. Une fois calculé chaque normale aux segments, on calcule la normale en chaque sommet du profil par moyenne des normales aux 2 segments adjacents (attention aux cas particuliers du premier et dernier sommet du profil).
  4. Pour obtenir la normale d’un sommet de l’objet de révolution il suffit alors d’appliquer la même rotation que pour le sommet.

Testez

profilrevolution avec éclairage

Question 3. Passons aux coordonnées de textures. Il s’agit de la même démarche que pour la sphère. Pour les slices (coordonnée s) on procède de la même façon que pour la sphère (i.e. angle de rotation reporté sur [0,1]). Pour la coordonnée t, nous proposons d’aller au plus simple : chaque sommet de stack i aura pour coordonnée t=i/\_profile.size (i.e. on plaque régulièrement la texture le long des sommets).

Testez

Remarques :


Exercice 4. Cube
Cet exercice permet de bien comprendre le problèmes des arêtes vives et de la nécessaire duplication des sommets lors de la spécification des normales et/ou des coordonnées de textures.

On travaille dans Revolution::initCube.

Question 1. On se préoccupe uniquement des positions et des indices pour cette question. Initialisez le tableau p avec les 8 sommets d’un cube d’arête de longueur 2 et centré sur l’origine (autrement dit les coordonnées sont soit -1 soit 1 pour x, y et z).

Initialisez alors index. Testez

Question 2. Pour les normales, il faut traduire le fait que les arêtes du cube sont vives. Il faut donc prendre comme normale les normales aux faces (et non, par exemple, la moyenne des normales au sommet dont le but est de traduire une surface lisse). Ainsi, un sommet du cube possède 3 normales différentes selon la face qu’on considère. Autrement dit, 1 sommet du cube correspond en fait à 3 sommets distincts (ensemble des attributs distincts).

Pour spécifier les normales il faut donc dupliquer chaque position 3 fois (donc 24 positions en tout), et pour chacun spécifier la normale. Il faut également corriger le tableau index (plutôt que de faire des copier coller hasardeux, il est conseillé de reprendre complètement depuis le début la création des tableaux p, index et n, en raisonnant face par face en les spécifiant les unes après les autres).

N’oubliez pas également l’importance de l’ordre des sommets pour la cohérence de l’éclairage (comme déjà indiqué pour la sphère) : les faces doivent être orientées directes vers l’extérieur et leur normale dirigée vers l’extérieur. C’est à dire que lorsque vous regardez une face du cube : la normale est dirigée vers vous et les sommets "tournent" dans le sens contraire des aiguilles d’une montre.

Testez

Question 3. On souhaite plaquer la texture d’un dé à jouer sur le cube. L’image à plaquer est dice.png.

Il suffit de spécifier chacune des coordonnées de texture dans le tableau t (respectez une des contraintes d’un dé qui est que la somme de 2 faces opposées est 7).

Testez


Ce document a été traduit de LATEX par HEVEA