10.03.2014 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!