Programmation Graphique : TP séance 02
- Rendu du TP sur Ametice :
- Suivez les instructions pour le rendu du TP en mettant le bon numéro de séance dans le nom du répertoire.
- N'oubliez pas de rendre votre travail à la fin de la séance comme indiqué, même si vous n'avez pas fini la planche de TP, puis de rendre la version finale (sans changer le nom du fichier) avant le début de la séance suivante.
Exercice 1. Dessin de piston et de bielle avec un VAA
Le but est de dessiner un piston fixe et une bielle actionnant une roue et de les mettre en mouvement.
Cet exercice est l'occasion d'expérimenter OpenGL "moderne" avec des shaders, en faisant des dessins avec un VAA (profile compatibility).
Dans votre nouveau répertoire pgra-TP02-NOM1-NOM2
, commencez par récupérer
tous les fichiers suivants :
ce nouveau Makefile
,
les fichiers de GLAD glad.c
, glad.h
,
khrplatform.h
,
le module de calcul matriciel vmath.h
et l'exemple de départ fw24-proj.cpp
.
Vérifiez que vous pouvez compiler et exécuter l'exemple (au besoin, voir 3.1. Installation et compilation dans le CM 01).
La touche a
déclenche une animation, la touche p
change le type de
projection, c
change le cube repère, h
affiche l'aide pour les réglages
de la projection.
Tout ce dont vous avez besoin de savoir en OpenGL pour réaliser ce TP est expliqué dans le CM 02, section 5. OpenGL moderne.
1.1. Paramètres d'un cylindre
Tous les éléments vont être représentés à l'aide de cylindres.
En vous inspirant des classes Triangles
et WireCube
présentes dans
l'exemple, déclarer une classe Cylindre
avec les données membre suivantes, en
rajoutant le préfixe m_
:
- l'épaisseur (en \(z\))
ep_cyl
= \(AB\) ; - le rayon
r_cyl
= \(AC\) dans le plan \(xy\) ; - le nombre de facettes
nb_fac
; - la couleur
(coul_r, coul_v, coul_b)
d'un côté.
Le cylindre est centré à l'origine.
Les centres \(A\) et \(B\) des côtés sont situés de part et d'autre de l'origine
\(O\) sur l'axe des \(z\), leurs coordonnées sont donc \((0,\,0,\,\)ep_cyl
\(/2\))
et \((0,\,0,\,-\)ep_cyl
\(/2\)).
Dans l'exemple ci-contre il y a 20 facettes, dont la facette \(CDEF\).
1.2. Dessin d'un cylindre
Dans la classe Cylindre
, rajouter une méthode draw
, qui dessine les deux
côtés d'un cylindre dans la couleur (coul_r, coul_v,
coul_b)
, et les facettes du pourtour du cylindre avec dans une couleur
légèrement plus sombre, par exemple (coul_r*0.8, coul_v*0.8, coul_b*0.8)
.
Attention : on demande d'utiliser une stratégie différente de celle utilisée au TP1 (où l'on dessinait une dent puis on la dupliquait avec des rotations).
On demande ici de remplir un tableau avec toutes les coordonnées des sommets
d'un côté (en commençant par le centre, en vue de dessiner un GL_TRIANGLE_FAN
),
puis toutes celles de l'autre côté (idem),
puis toutes celles des facettes
(en vue de dessiner le pourtour du cylindre avec un GL_TRIANGLE_STRIP
).
Faire de même pour les couleurs dans un autre tableau. Les deux tableaux seront déclarés chacun dans un VAA.
Pour calculer les coordonnées \(x,y\) des sommets des facettes, utilisez l'angle
\(\gamma =\widehat{CAF} = 360.0 /\) nb_fac
.
Rajouter un paramètre flag_fill
à la méthode draw
de manière à pouvoir
choisir entre des faces remplies et un dessin "fil de fer" ; dans le programme,
gérer le flag avec une touche du clavier, par exemple la touche L
.
Il suffit ensuite de changer le mode de rendu des triangles,
en appelant glPolygonMode
avant d'effectuer les glDrawArrays
:
glPolygonMode (GL_FRONT_AND_BACK, flag_fill ? GL_FILL : GL_LINE);
1.3. Animation
On rappelle que la touche a
permet déjà de faire tourner la scène
sur elle-même.
Introduire un angle m_alpha
en donnée membre, qui
sera utilisée dans les calculs ci-dessous en lieu et place de
\(\alpha\), permettant d'animer la roue et la bielle dans le piston.
Incrémenter m_alpha
lorsque la touche [espace] est enfoncée, de manière
à animer la scène.
1.4. Placement des 10 cylindres
Étant donné que tout cylindre est initiallement centré à l'origine, il faudra le placer ensuite à l'endroit désiré avec la bonne composition de rotations et translations (remarque : la roue est déjà au bon endroit, mais il faudra quand même lui faire subir une rotation pour voir l'animation).
Dans le dessin ci-contre, les points \(G\) et \(K\) sont fixes, tandis que les points \(H\) et \(J\) seront en mouvement. D'autre part, la distance \(GH\) est fixe, ainsi que la distance \(HJ\). Les points \(G\), \(J\) et \(K\) sont alignés. Enfin, les coordonnées en \(z\) sont toutes fixes. C'est à vous de choisir les distances fixes, les coordonnées des points fixes et les paramètres de chacun des 10 cylindres dans votre programme.
Étant donné l'angle d'animation \(\alpha\) par rapport à \(Gx\), on obtient directement le point \(H\) par \(x_H = x_G + GH.\cos\alpha\) et \(y_H = y_G + GH.\sin\alpha\).
On recherche maintenant les coordonnées de \(J\) et l'angle \(\beta = \widehat{IJH}\).
Soit \(I\) le point à l'intersection de la hauteur issue de \(H\) sur la droite \((J,G)\) ; on a \(x_I = x_H\) et \(y_I = y_G = 0\).
Or \(HJ\) est fixe et \(HJ^2 = IJ^2+HI^2\), donc \(J = I - IJ.\vec{i} = I - \sqrt{HJ^2-HI^2}.\vec{i}\), où \(\vec{i}\) est le vecteur \((1,0,0)\) ; d'où \(x_J = x_I - \sqrt{HJ^2-HI^2}\) \(= x_I - \sqrt{HJ^2-(GH.\sin\alpha)^2}\) et \(y_J = y_I = 0\). De là, \(\beta = \arctan(HI/JI) = \arctan(y_H/|x_J-x_H|)\), mais attention aux divisions par 0 et au signe de \(\beta\) pour certaines configurations.
Pour finir, recentrez la scène dans le viewport (avec le piston à gauche et la roue à droite).