TD3 - Maillage triangulaire

Afin de commencer dans de bonnes conditions, téléchargez l'archive pghp_td3.zip qui contient une correction partielle du TD précédent. La fonction render du fichier "main.cpp" a été modifiée pour permettre la génération en parallèle des rayons primaires par blocs de 32x32 pixels. L’intégrateur de Whitted inclut la gestion des rayons d'ombres et des réflexions.

La classe Mesh permet de charger depuis un fichier et de manipuler un maillage triangulaire. Elle consiste en une liste de sommets m_vertices et une liste de faces m_faces. Chaque sommet est un structure contenant une position ainsi que, optionnellement, une normale et des coordonnées de texture. Une face est simplement un triplet d'indices vers trois éléments dans la liste des sommets.

1. Calcul d'intersection

Pour calculer l'intersection d'un rayon avec un triangle, vous utiliserez la technique de Möller-Trumbore (référez-vous au cours). Implémentez celle-ci dans la méthode :

bool Mesh::intersectFace(const Ray& ray, Hit& hit, int faceId) const

faceId est l'index de la face à tester dans la liste m_faces.

Dans un premier temps, vous utiliserez la normale de la face comme normale au point d'intersection.

Pour raytracer un maillage complet, il vous suffit ensuite d'appeler la méthode d'intersection du triangle sur chacune des faces du maillage. Vous devriez obtenir l'image suivante avec le fichier de scène "tw.scn" :

Maillage
Normales par face

2. Normales par sommet

Les modèles 3D ne sont pas toujours fournis avec des normales par sommet. Celle-ci peut alors être obtenue en calculant la moyenne pondérée des normales des faces adjacentes à ce sommet, sachant que la normale $\vx{n}_f$ d'une face de sommets $(\vx{v_1}, \vx{v_2}, \vx{v_3})$ est : \[ \vx{n}_f = (\vx{v_2} - \vx{v_1}) \times (\vx{v_3} - \vx{v_1}) \] où $\times$ représente le produit vectoriel. Il s'avère que $\|\vx{n}_f\| = 2 \Delta$, où $\Delta$ est l'aire du triangle $(\vx{v_1}, \vx{v_2}, \vx{v_3})$. Par conséquent, en calculant directement la moyenne des normales $\vx{n}_f$ des faces adjacentes à un sommet, nous obtenons une moyenne pondérée par les aires des triangles adjacents. Cette pondération est fréquemment utilisée car elle produit de bons résultats tout en étant rapide à calculer.

Implémentez ce calcul dans la méthode :

void Mesh::computeNormals()

Indices : Si votre implémentation utilise des boucles imbriquées ou une structure de donnée temporaire, vous faites fausse route. L'algorithme consiste à calculer les normales en trois passes :

  1. initialiser toutes les normales au vecteur nul,
  2. calculer les normales des faces et les ajouter à leurs trois sommets incidents au fur à mesure,
  3. normaliser la normale de chaque sommet.

Modifiez intersectFace pour calculer la normale au point d'intersection comme l'interpolation barycentrique des normales aux trois sommets, à l'aide des coordonnées de texture calculée par la technique de Möller-Trumbore. Vous devriez obtenir ce résultat :

Maillage
Normales par sommet

Dans le fichier de scène "tw.scn", remplacez le maillage "tw503.off" par "tw.off" :

<string name="filename" value="tw.off"/>
comptant 12576 faces. Faites le rendu de l'image ; le coût de calcul devient clairement perceptible.