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
où 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" :

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 :
- initialiser toutes les normales au vecteur nul,
- calculer les normales des faces et les ajouter à leurs trois sommets incidents au fur à mesure,
- 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 :

Dans le fichier de scène "tw.scn", remplacez le maillage "tw503.off" par "tw.off" :
<string name="filename" value="tw.off"/>