IN Synthèse d'Images Rendu - IUT d'Arles
IN Synthèse d'Images Rendu - IUT d'Arles
IN Synthèse d'Images Rendu - IUT d'Arles
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>IUT</strong> de Provence – Site d’Arles 2012 - 2013<br />
Département d’Informatique<br />
LP SIL <strong>IN</strong><br />
<strong>IN</strong> – Synthèse d’images<br />
TP 4<br />
Animation de feu d'artifice par système de particules<br />
Nous allons maintenant utiliser des textures translucides au moyen d’images 32 bits. Chaque pixel<br />
de ces images est codé sur un quadruplet RGBA où A est un octet indiquant le niveau d’opacité du<br />
pixel : si A = 0 le pixel est complètement transparent ; si A = 255 le pixel est complètement<br />
opaque ; entre les deux, le pixel est plus ou moins translucide.<br />
On veut représenter un feu d'artifice par un système de particules (voir le chapitre 4 du cours) où<br />
chaque particule correspondra à une étincelle. Les étincelles seront affichées au moyen de<br />
quadrilatères sur lesquels on plaque la texture RGBA « etincelle.tga ».<br />
Récupérez sur ma page web la base de ce TP.<br />
Classe Etincelle<br />
1. Ecrire une classe Etincelle pour représenter une étincelle, qui sera affichée au moyen d’un<br />
quadrilatère texturé. Une étincelle est caractérisée par sa position (xpos, ypos, zpos : 3<br />
float), sa taille (taille : 1 float, le quadrilatère étant carré), sa couleur (rouge, vert,<br />
bleu : 3 float), sa vitesse de déplacement selon x, y et z (vitesse_x, vitesse_y,<br />
vitesse_z : 3 float) et le temps qu’il lui reste à « vivre » en secondes (vie : 1 float).<br />
Ecrire le constructeur de cette classe, permettant d’initialiser ces données.<br />
2. Ecrire une méthode anime() de la classe Etincelle qui recevra en paramètre le temps<br />
écoulé en secondes entre deux affichages :<br />
void Etincelle::anime (float temps);<br />
Elle permettra de modifier la position de l'étincelle en fonction du temps écoulé et de sa<br />
vitesse :<br />
nouvelle position = position courante + vitesse * temps<br />
On réduira aussi le temps de vie restant de l'étincelle en lui soustrayant le temps écoulé.<br />
3. Ecrire une méthode affiche() de la classe Etincelle, permettant d’afficher l'étincelle<br />
au moyen d’un quadrilatère texturé :<br />
void Etincelle::affiche();<br />
1
On verra dans la question 8 comment faire pour toujours orienter ce quadrilatère face à<br />
l’observateur, mais vous pouvez pour le moment lui donner une orientation fixe (par exemple<br />
dans un plan z).<br />
A la fin du TP, vous pourrez aussi modifier la transparence de l'étincelle en jouant sur la valeur<br />
alpha grâce à glColor4f().<br />
// Comme on ne veut pas que ce quadrilatère soit affecté<br />
// par la lumière, on désactive l’éclairage juste avant<br />
// de l’afficher, et on le réactivera juste après. Vous<br />
// n’aurez donc pas besoin de spécifier la normale du<br />
// quadrilatère<br />
glDisable(GL_LIGHT<strong>IN</strong>G);<br />
// On veut pouvoir voir les deux côtés du quadrilatère<br />
glDisable(GL_CULL_FACE);<br />
// On colore la texture<br />
glColor4f(rouge, vert, bleu, alpha);<br />
// On active le blending pour que la couleur de la texture<br />
// se mélange à la couleur du reste de la scène dans des<br />
// proportions données par la valeur alpha de chaque texel<br />
// de la texture<br />
glBlendFunc(GL_SRC_ALPHA, GL_ONE_M<strong>IN</strong>US_SRC_ALPHA);<br />
glEnable(GL_BLEND);<br />
// Affichage du quadrilatère texturé avec la texture RGBA<br />
// glBegin(GL_QUADS)<br />
// ...<br />
// glEnd() ;<br />
// On désactive le blending<br />
glDisable(GL_BLEND);<br />
// On reactive l’utilisation de la lumière<br />
glEnable(GL_LIGHT<strong>IN</strong>G);<br />
// Pour ne voir qu’un seul côté des polygones<br />
// (affichage plus rapide)<br />
glEnable(GL_CULL_FACE);<br />
2
Classe Feu<br />
4. Ecrire une classe Feu pour représenter le feu d'artifice constitué d'étincelles. Elle contiendra<br />
les données membres suivantes :<br />
- La position (x,y,z) de l’origine du feu d'artifices, là où il éclate en étincelles.<br />
- Le nombre d'étincelles à générer lors de l'explosion.<br />
- Une liste chaînée d’objets de classe Etincelle. On utilisera la classe list de la STL :<br />
list liste_etincelles;<br />
- Un pointeur sur un objet de classe Texture servant de texture pour les étincelles. Vous<br />
chargerez la texture dans un objet de classe Texture dans le programme principal et<br />
vous passerez son adresse au constructeur de l’objet de classe Feu.<br />
5. Ecrire une méthode explose(float x, float y, float z, float vie_min,<br />
float vie_max) de la classe Feu qui remplira la liste liste_etincelles avec des<br />
objets de type Etincelle dont la position correspondra à celle du feu, avec des durées de<br />
vie comprises aléatoirement entre vie_min et vie_max. On donnera initialement au vecteur<br />
vitesse (vitesse_x, vitesse_y, vitesse_z) de chaque étincelle une direction<br />
aléatoire, afin que les particules partent dans toutes les directions par rapport au centre de<br />
l'explosion.<br />
6. Ecrire une méthode anime() de la classe Feu qui recevra en paramètre le temps écoulé en<br />
secondes entre deux affichages (variable globale dt du programme principal, à passer en<br />
paramètre lors de l’appel de la méthode anime() dans la fonction affiche_scene() du<br />
programme principal) :<br />
void Feu::anime(float temps);<br />
On décomposera cette fonction en deux étapes :<br />
1. Suppression d'étincelles : on parcours la liste d'étincelles à la recherche de celles dont<br />
la durée de vie s’est complètement écoulée (≤ 0). Si c’est le cas, elles seront<br />
supprimées de la liste grâce à la méthode erase() de list :<br />
list::iterator i;<br />
i = liste_etincelles.begin();<br />
while( i != liste_etincelles.end() )<br />
{<br />
if( i->duree_de_vie
7. Ecrire une méthode affiche() de la classe Feu qui affichera l’ensemble des étincelles de<br />
la liste :<br />
void Feu::affiche();<br />
8. Les étincelles apparaissent comme plates si on regarde de côté les quadrilatères qui les<br />
forment. Une solution est d’utiliser le principe de « billboarding », qui consiste à toujours<br />
orienter le quadrilatère face à l’observateur.<br />
Pour afficher en billboarding un quadrilatère de dimensions (largeur x hauteur) et centré<br />
autour de (xpos, ypos, zpos), on peut procéder comme suit :<br />
// On récupère le positionnement de la camera<br />
float matrice [16];<br />
glGetFloatv( GL_MODELVIEW_MATRIX, matrice );<br />
Vector Haut, Droite;<br />
Droite.x = matrice[0] * (largeur / 2.0f);<br />
Droite.y = matrice[4] * (largeur / 2.0f);<br />
Droite.z = matrice[8] * (largeur / 2.0f);<br />
Haut.x = matrice[1] * (hauteur / 2.0f);<br />
Haut.y = matrice[5] * (hauteur / 2.0f);<br />
Haut.z = matrice[9] * (hauteur / 2.0f);<br />
Vector A, B, C, D;<br />
// On calcule la position des 4 sommets du quadrilatère<br />
A.x = xpos + Haut.x - Droite.x;<br />
A.y = ypos + Haut.y - Droite.y;<br />
A.z = zpos + Haut.z - Droite.z;<br />
B.x = xpos + Haut.x + Droite.x;<br />
B.y = ypos + Haut.y + Droite.y;<br />
B.z = zpos + Haut.z + Droite.z;<br />
C.x = xpos - Haut.x + Droite.x;<br />
C.y = ypos - Haut.y + Droite.y;<br />
C.z = zpos - Haut.z + Droite.z;<br />
D.x = xpos - Haut.x - Droite.x;<br />
D.y = ypos - Haut.y - Droite.y;<br />
D.z = zpos - Haut.z - Droite.z;<br />
// Affichage du billboard<br />
glBegin(GL_QUADS);<br />
glVertex3f(D.x,D.y,D.z);<br />
glVertex3f(C.x,C.y,C.z);<br />
glVertex3f(B.x,B.y,B.z);<br />
glVertex3f(A.x,A.y,A.z);<br />
glEnd();<br />
4