Master Informatique 2017-2018
M3DS



TP 08 : Particules/Collisions


Exercice 1. Introduction


Exercice 2. Particules
Les particules sont simplement des points 3D générés au cours du temps selon un taux de naissance (nombre de particules qui naissent par seconde). Pour avoir un flot continu de particules, sans dépasser un nombre de particules maximum, chaque particule a une durée de vie finie (elle disparait après un certain temps donné).

La naissance et l’extinction des particules sont déjà gérées par le squelette (principalement par la méthode ParticleList::updateLife : nous ne nous préoccuperons pas de cela dans le TP).

Le taux de naissance est initialisé dans la méthode GLApplication::initParticle par, par exemple, _particleList.birthRate(10) (naissance de 10 particules par seconde; vous pourrez changer cette valeur bien sûr).

Lorsqu’une particule nait, ses données initiales (position, vitesse, durée de vie, ...) sont fixées dans la méthode ParticleList::initState qui est appelée à chaque naissance. Vous pourrez modifier les valeurs qui s’y trouve selon la "scène" souhaitée.

Pour mettre en mouvement les particules, à chaque image est appelée la méthode Engine::update() de Engine.cpp. On y trouve le calcul des forces (méthode computeForce), les collisions (méthodes collisionPlane et interCollision), et l’intégration du mouvement (méthode euler). Pour le moment, chacune de ces méthodes ne fait rien et seront à compléter au fur et à mesure des questions du TP (seules l’apparition aléatoire et la disparition des particules est pour l’instant visualisable à l’exécution du squelette : constatez le en exécutant le squelette).

Question 1. Complétez la méthode Engine::euler(double dt) qui met à jour la vitesse et la position de chaque particule dans l’intervalle de temps dt donné, selon la méthode d’Euler (cf cours et les commentaires de la méthode).

Testez : vous devez voir les particules aller en ligne droite (il n’y a encore aucune force : l’accélération est donc nulle, et la vitesse est par conséquent constante).

La vitesse et la position initiales sont données aléatoirement dans ParticleList::initState : vous pouvez bien sûr modifier à loisir ces données (donnez par exemple une vitesse initiale vers le haut).

Vous pouvez également réduire ou augmenter le taux de natalité des particules en modifiant le 10 de _particleList.birthRate(10) dans GLApplication::initParticle().

Question 2. Nous souhaitons faire subir la force de gravité aux particules : complétez Engine::computeForce (qui est appelée depuis Engine::update à chaque image).

Testez : à présent les particules doivent subir la gravité (elles traversent le sol car il n’y a pas encore de gestion des collisions).

Question 3. Nous souhaitons maintenant que les particules subissent la collision avec le sol : on commence par la détection. Dans la méthode Engine::collisionPlane(), chaque plan est donné par sa normale plane->normal() et un point plane->point() : nous considérons ici qu’une particule est en collision avec le plan si elle le "traverse" : on suppose qu’initialement toutes les particules sont du coté positif du plan, et doivent le rester. Donc si on trouve à un instant une particule du coté négatif du plan, il y a collision.

Effectuez ce test de signe dans Engine::collisionPlane et imposez une vitesse nulle en cas de collision (en faisant simplement p->velocity(Vector3(0,0,0))), et imposez une position de la particule pour qu’elle soit sur le plan (on calcule le point H projeté orthogonal de p->position() sur le plan plane, puis on affecte p->position(H)) (ne tenez pas compte, pour l’instant, des posCorrection, velCorrection, addPositionCorrec et addVelocityCorrec qui apparaissent dans le squelette).

Testez : les particules doivent "coller" au sol lorsqu’elles l’atteignent (elles paraissent "enfoncées" dans le plan, car la position testée correspond au centre de la particule; nous accepterons cela et nous reviendrons sur ce problème dans l’exercice sur les sphères).

Question 4. Pendant toute la résolution des collisions, il ne faut pas modifier immédiatement la position et la vitesse des objets car la résolution de chaque collision doit se faire dans l’état courant de chaque particule à l’instant t (cf cours, notamment pour les collisions multiples).

On raisonne donc par "correction" qui seront appliquées qu’à la fin de la résolution de toutes les collisions (voir l’appel à updatePositionVelocity après le traitement des collisions dans Engine::update) : pour cela on cumule pour chaque collision de particule des corrections (avec p->addVelocityCorrec(...) et p->addPositionCorrec(...)) qui seront appliquées une fois que toutes les collisions auront été effectuées.

Modifiez Engine::collisionPlane pour affecter les variables velCorrection et posCorrection (ce sont des corrections, c’est à dire qu’il s’agit de la différence entre les valeurs souhaitées et les valeurs actuelles). Vous devez obtenir le même résultat qu’à la question précédente (il faut bien sûr maintenant enlever les affectations directes p->position(...) et p->velocity(...)). Testez

Remarque : cette approche par correction n’a pas d’impact tant qu’il n’y a pas de multi-collisions sur une particule (ce qui sera le cas lors de l’exercice sur les sphères).

Question 5. On souhaite que les particules rebondissent sur le plan lors d’une collision. Il faut donc modifier la méthode Engine::collisionPlane() précédente pour intégrer la réponse à la collision. On applique le principe d’impulsion (cf cours) :

Testez. Vous devez constatez un rebond naturel des particules sur le sol (testez plusieurs restitutions : avec 0 les particules s’"écrasent" sur le sol sans rebond, avec 1 les particules rebondissent infiniment à la même hauteur à chaque rebond).


Exercice 3. Sphères
Dans l’exercice précédent, les particules ne rentrent pas en collision les unes avec les autres (particules considérées comme des points sans volume). Dans cet exercice, nous modifions ce comportement en considérant les particules comme des sphères : elles peuvent rentrer en collision les unes avec les autres (nous conservons cependant la mécanique du point et non la mécanique du solide : les sphères ne peuvent pas "rouler" par exemple).

Question 1. Il faut cliquer sur "Sphere" pour afficher des sphères au lieu des particules et cela activera également l’appel à la gestion des collisions entre sphères (cf appel à Engine::interCollision depuis Engine::update).

Modifiez ParticleList::initState, dans la partie if... ==PARTICLE_SPHERE) pour que les sphères partent toutes de la position y=5 (faire un random en x), et avec une vitesse nulle (les sphères vont donc normalement tomber une à une). Donnez également le birthrate dans GLApplication::initParticle (à 5 par exemple) pour avoir peu de sphères.

Testez : notez que les sphères se superposent les unes aux autres (il n’y a pas encore de collisions entre elles), et qu’elles s’enfoncent également dans le plan, puisque la détection (faite à l’exercice précédent) se fait par rapport au centre de la sphère.

Question 2. Corrigez la détection de collision avec les plans dans Engine::collisionPlane() pour que la collision soit détectée correctement en tenant compte du rayon de la sphère. Le rayon de chaque particule est donné par p->radius(). Le point à tester n’est donc plus le centre mais le point de la sphère le plus proche du plan : quel est ce point ?). Testez : les sphères ne doivent plus s’enfoncer dans le sol. Testez notamment avec une restitution de 0 : constatez que les sphères doivent être correctement sur le plan.

Question 3. On gère à présent la collision entre toutes les paires de sphères (p1,p2). Ceci est fait dans la méthode Engine::interCollision() que vous devez compléter :

  1. Il faut détecter la collision entre p1 et p2 (test d’intersection entre les 2 sphères)
  2. S’il y a collision, il faut corriger les vitesses/positions de p1 et p2 par impulsion :

Testez : les sphères doivent avoir un comportement "naturel" lorsqu’elles entrent en collision (rebond les unes sur les autres).

Question 4. Testez l’ajout de plans (infinis) qui restreignent les sphères dans un volume (il suffit de décommenter les _engine.addPlane qui se trouvent dans la méthode GLApplication::GLApplication(); les plans ne seront pas visualisés). Réglez alors au mieux les différents paramètres (coefficient de restitution et/ou masses des particules) pour avoir une animation relativement naturelle .

Testez en augmentant le taux de naissance : vous devez constater une instabilité du mouvement. Quelle est la raison principale de cette instabilité selon vous ? (répondre dans le Readme.txt)


Ce document a été traduit de LATEX par HEVEA