SIMULATION D'UN BILLARD

cs_Urgo Messages postés 780 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 16 avril 2009 - 30 août 2005 à 23:00
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 - 4 sept. 2005 à 13:13
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/33545-simulation-d-un-billard

cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
4 sept. 2005 à 13:13
C'est la rentrée, je n'ai plus le temps. En plus tu peux le faire toi-même, il suffit de réécrire seulement billiards.c et .h
cs_Patrice99 Messages postés 1221 Date d'inscription jeudi 23 août 2001 Statut Membre Dernière intervention 9 septembre 2018
4 sept. 2005 à 12:59
Ça à l'air d'être parfait, il faudrait que je teste le code source avec mon simulateur de gravité qui est chaotique : la moindre erreur de calcul sera amplifiée au bout d'un moment. Tu n'aurais pas envie de faire une version en C# ? Comme ça je pourrais mélanger du VB.Net et du C#...
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
4 sept. 2005 à 12:01
bon voila la regle du .exe contournee :
prgm.ex => prgm.exe
gagah1 Messages postés 509 Date d'inscription samedi 28 juin 2003 Statut Membre Dernière intervention 3 août 2010
4 sept. 2005 à 11:28
J'arrive pas à compiler la source ( j'utilise DevC++) , tu pourrais mettre l'exe comme dit Patrice99 en renommant l'extension. Pour voir exactement comment cela donne, et peut etre pour adapter à mon vieux jeu de billard que j'ai programmé il y a si longtemps. Merci
cs_Patrice99 Messages postés 1221 Date d'inscription jeudi 23 août 2001 Statut Membre Dernière intervention 9 septembre 2018
3 sept. 2005 à 14:57
Tu pourrais mettre un exe dans le zip, en renommant l'extension en .exe_ par exemple ? ça me donne envie de tester ton billard, ça m'à l'air pas mal sophistiqué quand tu en discutes comme ça en ayant l'air de rien :-)
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
3 sept. 2005 à 14:45
Effectivement je test toutes les collisions, mais l'algorithme est lineaire car je n'ai que 2.n calculs a faire, en memoire en revanche j'en ai O(n²), mais en realite c'est beaucoup plus petit que cela. L'idee de ne s'interesse qu'au voisinage pour le calcul des chocs est jolie, mais le probleme c'est que mathematiquement, rien ne me dit qu'il n'y aura aucun rebond avec une boule lointaine, car il y a des configurations pathologiques qui existent.
Donc pour le moment je calculs les eventuelles collisions avec TOUTES les autres boules, mais en revanche j'utilise des arbres pour rechecher le minimum.
Donc c'est un logique telle que :
recalculer : O(n)
memoire : O(n²)
minimum : O(log(n))
tout cela dans le pire des cas
cs_Kirua Messages postés 3006 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 31 décembre 2008
3 sept. 2005 à 14:16
Ton célèbre jeu c'est le chai-plus-quoi de newton ou qq ch dans le style. C'est pour illustrer la conservation de l'énergie mécanique. Hmm, j'avais commencé la phrase pour dire comment ça s'appelait, mais j'ai pas donné de super info là :p

Donc, si je comprends bien, ta méthode n'est pas une simulation "libre" où tu regardes pas à pas ce qui se passe, tu prévois les rebonds et tu les exécutes à la suite? C'est assez original comme procédé. Juste une chose: tu testes toutes les billes contre toutes les autres billes, où tu divise le plan en sous parties pour réduire le nombre de tests? (les quadtrees sont généralement utilisés pour ce genre de choses: ça permet de ne tester les collisions qu'entre billes relativement proches, ça va plus vite que de calculer la distance entre chaque couple)
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
3 sept. 2005 à 13:54
Tout d'abord je n'utilise pas de pas "dt", en fait j'ai en memoire toutes les collisions possibles (on peut les afficher dans le programme). Je ne garde en memoire que les collisions qui vont se produire dans le present ou dans le futur, ensuite je veux passer par exemple de t=0s a t=10s, alors je prends la premiere collision qui arrivera dans le temps (je prends le minimum dans l'arbre des collisions d'ou l'interet d'avoir une recherche en log(n)) ensuite j'effectue la collision et je recommence jusqu'a temps que j'atteigne 10s.
Mais la difficulte provient du test des collisions : la definition d'une collision est lorsque la distance entre deux boules vaut la somme des deux rayons et que la collision se produise a t>=0, car la resolution de l'equation en t peut avoir comme solution des temps negatifs, donc je ne prends que les cas t>=0, de plus il y a un autre probleme : c'est le cas t=0, car prenons le cas ou deux boules sont initialement collees sans vitesse initiale, alors la resolution donne t=0 car a t=0 la distance vaut bien la somme des deux rayons ! Mais pourtant physiquement il n'y a pas de collision. Il faut etre plus rigoureux sur la definition d'un chocs, il y a chocs que si la distance vaut la somme des deux rayons et que cela se produise a t>=0 ET que la distance diminue, i.e. sa derivee strictement negative. Donc le point crucial est ici. Il faut que ces DEUX conditions soient verifiees pour qu'il est chocs, le cas echeant la collision est enregistree dans l'arbre.

Un cas pathologique est par exemple : plusieurs boules collees et alignees sans vitesse initiale, et on envoie une boule dans l'alignement (comme le celebre jeu des 5 boules dont on lache que celle de l'extremite et seule la boule a l'autre extremite bouge). Alors la on est en plein dans le cas du dessus, et la distinction entre "se rapprochent" et "s'eloigne" est importante.



le fonction pour resoudre une collision est :
//----------------------------------------------------------
// calcul l'eventuelle collision entre deux boules
static BOOL foreseeBetweenTypeCrash(double *pTime,P_BALL B1,P_BALL B2)
{
// somme des deux rayons
double R;
// difference des deux vitesse
VECT2D dv;
// difference des deux position
VECT2D dp0;
// pour la resolution de l'equation
double a, // coefficient
b, // coefficient
c; // coefficient

AssertPointer(pTime);
AssertPointer(B1);
AssertPointer(B2);

// on calcule l'equation
SubVect2D(&dp0,&B2->p0,&B1->p0);
SubVect2D(&dv,&B2->v,&B1->v);
R = B1->r + B2->r;
a = Norm2Vect2D(&dv);
b = 2.*DotProductVect2D(&dp0,&dv);
c = Norm2Vect2D(&dp0) - R*R;
c = max(0.,c); // pour les erreurs de calculs
// on resout l'equation
// * ceci distingue le contact entre deux boules, et le rebond
// car il peut y avoir contact sans rebond, il n'y a rebond
// que si les deux boules se rapproche, i.e. la distance diminue
// i.e. sa derivee est strictement negatif, a le signe
// de cette derivee
if(b >= 0.)
return FALSE;
else
// * il y a rebond (pas forcement dans le futur)
{
double T1,T2;
if(resolve(&T1,&T2,a,b,c))
{
// si les deux racines sont negatives
if((T1 < 0.) && (T2 < 0.))
return FALSE;
// si les deux racines sont positives
else if((T1 >= 0.) && (T2 >= 0.))
return (*pTime = min(T1,T2),TRUE);
// si les deux racines sont de signes opposes
else
return (*pTime = max(T1,T2),TRUE);
}
else
return FALSE;
}
} // foreseeBetweenTypeCrash()
cs_Kirua Messages postés 3006 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 31 décembre 2008
3 sept. 2005 à 13:29
Je ne comprends pas où tu vois un problème... Qu'entends tu pas "si la solution est dans le passé/futur"? À vrai dire, j'ai toujours un bug qui revient de temps à autre, deux boules se collent l'un à l'autre et tourbillonnent ensemble pendant un moment avant de se lacher, donc ça m'intéresserait de comprendre la subtilité que tu as décelée, parce que ça pourrait bien être mon problème! Je pensais que c'était dû aux trop grands pas (dt) entre deux calculs, mais même en en choisissant un très petit ça arrive encore ...
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
3 sept. 2005 à 13:21
Pour revenir a la detection des collisions :la distance entre deux boules est une fonction quadratique du temps (ou temps les cas degeneres un fonction lineaire). Il suffit de resoudre "distance=somme des deux rayons"
Les erreurs de la resolution interviennent evidemment.
Mais cela n'est pas suffisant, comme tu le faisais remarquer Kirua, il est aussi preferable de calculer le signe du produit scalaire entre les vitesses et les positions (qui est en fait le coefficient lineaire de l'equation) pour voir si les boules se rapprochent ou s'eloignent. Le probleme est que si la solution est dans le passe, il n'y a pas de collision, par contre dans le futur aucun probleme, mais si elle est exactement au present (i.e. t(chocs) = t(courant) alors il y a un chocs que si les deux boules se rapprochent, i.e. si la derivee est negative, i.e. voir le signe de la quantite du dessus.

Donc la resolution des collisions est en soi pas complique, mais il faut bien faire les calculs sur papier, et surtout prendre en compte le cas t(chocs) = t(courant) car sinon l'algo. se plante, les cas pathologiques sont faciles a trouves.
cs_Kirua Messages postés 3006 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 31 décembre 2008
3 sept. 2005 à 12:39
D'accord pour l'absence de force, mais malgré tout, les erreurs de Patrice sont plus probablement dues à un intégrateur trop simple qu'aux arrondis du FPU (la partie du proco qui s'occupe des opérations sur les float/double). Je n'ai fait que lire des articles sur ce que j'ai évoqué plus haut Patrice, mais si tu veux améliorer les résultats de n'importe qu'elle simulation de cinématique, tu dois passer par une méthode mathématiquement plus évoluée que x(t + dt) = x(t) + dt*v(t) ... considérer que la vitesse est constante sur ce petit intervalle de temps induit de grandes erreurs pour des trajectoires courbes. Dans le cas es simus de collisions par contre, aucun souci: pas de forces, trajectoires rectilignes. Faut juste bien gérer les détections de collision avant que deux billes ne se rentrent dedans, et vectoriellement c'est aisé (tu peux vérifier le signe du produit scalaire des deux vecteurs vitesse de boules en collision pour t'assurer qu'elles n'ont pas été gérées à la frame précédente, fais un schéma). J'ai parlé des interpolateurs parce que Patrice faisait une simulation de gravitation.

Pour les collisions donc, à mon avis pas besoin de runge-kutta, mais si tu veux un exemple, il y en a plusieurs sur cppfrance et des dizaines sur internet. C'est un peu mathématique mais si tu as eu un cours d'analyse de niveau bac ça devrait passer.
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
3 sept. 2005 à 09:55
Une seule remarque : ici il n'y a pas de forces, car les boules se deplacent grace a l'intertie : l'acceleration est nulle en dehors des chocs. Pour ce qui est des chocs, il ne faut pas les resourdre avec des equations diferentielles, car le chocs est brutal, donc un force infini sur un temps infinitesimal. Il faut mieux resonner en termes de quantite conservee, et de resourdre le probleme directement au lieu de passer pas des Equa. Diff. ou les erreurs de calculs numeriques seront enormes.
cs_Patrice99 Messages postés 1221 Date d'inscription jeudi 23 août 2001 Statut Membre Dernière intervention 9 septembre 2018
3 sept. 2005 à 09:33
Tu m'intéresses, ça serait bien que tu fasses un mini simulateur, par exemple un rectangle ou rebondissent en 2D n boules de masse quelconque, avec l'interpolateur de runge-kutta.
cs_Kirua Messages postés 3006 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 31 décembre 2008
3 sept. 2005 à 01:32
Patrice, tes erreurs proviennent probablement de l'utilisateur de ce qu'on appelle l' "intégreur (ou interpolateur) d'Euler". Tu as sans doute fait un truc du style:

F = ma
A = F/m
v dt = F/m dt

et donc on a qq ch dans le goût de:

nouvelle vitesse = ancienne vitesse + (F/m) * delta temps

avec un delta temps équivalent à l'écart entre deux frames. c'est easy à coder, suffisament précis quand il s'agit de faire du "eye candy" (des jolis effets), mais pour faire une simulation physique, c'est complètement nul :/ tu fais une erreur de l'ordre de delta temps élevé au carré. pour réduire drastiquement l'erreur (due à la discrétisation du temps), tu peux utiliser l'interpolateur de runge-kutta, qui réduit l'erreur à l'ordre de delta temps exposant 5, ce qui est sérieusement plus petit!

Sinon, c'est cool pour la simu de collisions. Perso quand j'ai codé la mienne (ça fait un moment, mais je m'en souviens encore très bien, c'était génial ^^), je n'ai utilisé que des opérations vectorielles, complètement empiriques ("observé" sur des schémas de ma conception), et ça s'est révélé correct (juste pour mentionner le fait que c'est possible, et qu'il ne fait pas forcément faire un changement de repère, ce qui peut être non trivial).
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
1 sept. 2005 à 16:13
le but de se programme est de mettre beaucoups de boules pour simuler un gaz, donc comme la distribution est aleatoire, le cas ou c'est exactement identique n'intervient "presque" pas, et de tout maniere il y a un autre phenomene qui intervient : les erreurs de calculs, la resolution des equations provoque des arrondis qui se cumulent.
Globalement la simulation est assez realiste.

J'avais fait un test avec 3 boules se deplacant qu'horizontalement, et au bout de t=58 secondes, les vitesses des boules avaient des composantes verticales du justement aux erreurs.
cs_Patrice99 Messages postés 1221 Date d'inscription jeudi 23 août 2001 Statut Membre Dernière intervention 9 septembre 2018
1 sept. 2005 à 15:58
Oui, je fais la même chose, mais le résultat est décevant dans mon cas, car je simule des orbites parfaitement symétriques : au moindre écart, la symétrie se perd.
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
1 sept. 2005 à 15:12
le probleme c'est quand il y a deux chocs exactement en meme temps sur un systeme de trois boules (celle du milieu touche les deux autres).
la je gere successivement les chocs, ce qui je l'avoue n'est pas tres physique car rien ne me dit que c'est equivalent (il n'y a pas associativité des chocs).
c'est là un defaut du programme.
cs_Patrice99 Messages postés 1221 Date d'inscription jeudi 23 août 2001 Statut Membre Dernière intervention 9 septembre 2018
1 sept. 2005 à 08:45
As-tu prévu le cas ou plusieurs boules entrent en collision au meme moment ? j'ai fait un simulateur de gravité dans l'espace, et je n'ai jamais réussit à simuler des chocs parfaits, complètement réalistes : il y a toujours eu des défauts. Je vais regarder ton code.
MoDDiB Messages postés 546 Date d'inscription mardi 26 novembre 2002 Statut Membre Dernière intervention 4 mai 2007 1
31 août 2005 à 15:08
Une réalisation impeccable et une bonne explication ca vaut bien un 10 :)
cs_JCDjcd Messages postés 1138 Date d'inscription mardi 10 juin 2003 Statut Membre Dernière intervention 25 janvier 2009 4
31 août 2005 à 13:29
pas besoin de cours de physique, il n'y a que une seul calcul :
comment calculer les rebonds (les chocs).
Il y a deux quantités qui se conservent :
* l'énergie
* la quantité de mouvement

On a ainsi deux équations.
On se place dans le repere (u,v) avec u unitaire et dirige selon les deux centres des boules, et v l'orthogonal direct et

unitaire de u.
Dans ce repere on va changer les vitesses des deux boules pour simuler le rebond. Seul les vitesses selon u change, les

composantes selon v restent inchangees.
On a :
delta(mA.vA² + mB.vB²) = 0
delta(mA.vA + mB.vB) = 0

la solution est (il suffit de verifier) :
vA(apres) = 2.vG - vA(avant)
vB(apres) = 2.vG - vB(avant)
avec vG la vitesse du centre de gravité

voila les seules equations utilisees

(pour ce qui est de la resolution, physiquement parlant : dans un repere se deplacant a la vitesse du centre de gravité, les

vitesses changent seulement de signes, d'ou le resultat car :
v(apres) [-(v(avant)-vG)] + vG 2.vG - v(avant)

Un truc amusant a faire est de mettre 500 boules dans un billards, et cela donne l'effet d'un gaz (analogie non-fortuite) ou

a des abeilles, et je trouve ca beau a voir, essayez donc.
MoDDiB Messages postés 546 Date d'inscription mardi 26 novembre 2002 Statut Membre Dernière intervention 4 mai 2007 1
31 août 2005 à 12:56
Super intéressant ! Mais pourrait- on avoir un lien vers un cours de physique expliquant tes calculs ? Merci :)
cs_Urgo Messages postés 780 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 16 avril 2009 1
30 août 2005 à 23:00
J'ai les boules que tu n'utilises pas le mot "bille".
Rejoignez-nous