Rebond de balle sur pente 60 degrées

Résolu/Fermé
koko - 26 avril 2008 à 10:29
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 - 30 avril 2008 à 21:09
Bonjour je vous écrit car j'ai un problème concernant un projet que je dois faire en caml.
Le but est de faire rebondir une balle sur des polygones crées par l'utilisateur.
J'ai une fonction pour détecter le moment de l'intersection de la balle avec un segment qui marche parfaitement.
Lorsqu'il y a possibilité de rebond j'applique une autre fonction qui donne un nouveau vecteur vitesse à la balle, et ce en utilisant le produit scalaire du vecteur initial de la balle avec le vecteur normal. La formule utilisée est:
v=v0- v*v0.n*n/sqrt(n.x*n.x+n.y*n.y) où v0 est le vecteur initial de la balle, n le vecteur normal du segment rencontré, et v le nouveau vecteur vitesse de la balle. n.x et n.y sont les composantes du vecteur normal. n doit être de norme 1.
Ma fonction marche très bien en général, sauf lorsqu'elle rencontre un sommet (je pense parce qu'elle voit deux segments donc deux vecteurs normals, mais ça c'est pas grave) mais mon problème est que lorsque la balle arrive sur un segment de pente aux alentours de 60 degrés ou -60 degrés elle ne rebondit plus sur le segment mais roule dessus, systématiquement. Je ne comprend pas pourquoi car la fonction marche très bien pour tous les autres segments.

Voila j'espere que vous pourrez m'aider.

Merci

12 réponses

Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
26 avril 2008 à 16:50
Salut
Pour les coins c'est normal que ça pose problème. Une sorte de singularité, pas de normale proprement définie dans un coin, tu l'as deviné. Je doute que tu puisse y faire grand chose. Personnellement je vois pas quelle équation on peut prendre quand la balle rebondit sur un coin...

Par contre pour le reste:
1) sqrt(n.x*n.x+n.y*n.y) ne sert à rien si ton vecteur n est unitaire
2) La formule pour le rebond (choc élastique) est plutôt celle-ci: v=v0-2*v0.n*n
Pense aussi à vérifier que ta normale est bien orientée.

Bonne fin d'après-midi
0
Tout d'abord merci d'avoir répondu.

Mais je me suis peut être mal exprimé dans ma question.

J'ai remarque pas mal de détails que je n'arrive pas à expliquer:
avant ma formule pour le rebond était:
v=v0- 2*v0.n*n *sqrt(n.x*n.x+n.y*n.y) donc je multipliais n par sa norme au lieu de diviser comme maintenant.
A ce moment là quand la balle frappait un segment (de pente 60 degrés ou -60 degrés) sa vitesse augmentait très anormalement jusque' a disparaitre de l'écran. Il se passait (et se passe toujours) la même chose quand la balle touchait un sommet.

Maintenant j'ai écrit la formule suivante:
v=v0- 2*v0.n*n /sqrt(n.x*n.x+n.y*n.y).

Le fait de diviser n par sqrt(n.x*n.x+n.y*n.y) (donc sa norme) le rend unitaire. Il ne l'est pas des le départ.
Mais mon problème est que lorsque la balle arrive (quelque soit le type de trajectoire) sur un segment de pente de environ 60 degrés ou - 60 degrés la boule roule constamment au lieu de rebondir dessus.(rouler peut etre considéré comme des mini rebonds mais quand la balle tombe de très haut sur le segment, c'est étonant de voir la balle scotché au segment. Mais une fois arrivé au bout du segment, elle reste parfois collé à l'extrémité qui est un sommet, ou elle s'en détache normalement)

Il y a t-il peut être des cas particuliers à prendre compte?

Tu as parlé de faire attention au sens du vecteur normal, mais je ne sais pas comment le prendre en compte dans ma formule. Voici pour l'instant ma méthode pour calculer le vecteur normal:
Je possède une liste qui contient des couples de points donc des segments.
si la balle doit rebondir sur ce segment je prend les coordonnées des extrémités du segment. Par exemple pour un segment [AB] avec A(ax,ay) et B(bx,by). Je calcule le vecteur normal n de ce segment. Les composantes n de ce segment sont: n.x et n.y.
On a alors:
n.x recoit (ay-by)/(bx-ax) et n.y recoit 1. (Là je ne sait pas comment donner un sens au vecteur n)

J'applique alors la formule v=v0- 2*v0.n*n /sqrt(n.x*n.x+n.y*n.y). Le vecteur v a pour composantes v(x,y)
puis les coordonnes de la balle b( b.x,b.y) sont changés tels que:
b.x soit incrementé de vx
et b.y est incrementé de vy.

Voilà j'espere avoir été le plus clair possible.

Merci
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
26 avril 2008 à 18:41
Alors si ton vecteur n'est pas unitaire, la formule correcte est:
v=v0- 2*v0.n*n /(n.x*n.x+n.y*n.y)
Car:
v=v0- 2*(v0.n/||n||)*n /||n||

La formule que tu me donnes pour le vecteur n, n'est pas celle du vecteur normal.
Pour un segment [AB] avec A(ax,ay) et B(bx,by):
nx=-(ay-by)/(bx-ax) (il y a un moins)
ny=1
Mais tu peux prendre:
nx=-(ay-by)/||AB||
ny=(bx-ax)/||AB||
T'auras directement un vecteur normal.

L'orientation de la normale avec ce calcul dépend de l'ordre de tes points. Par exemple le calcul de la normale à [BA] donnera l'opposé de celui de la normale à [AB].
Mais vu que j'ai raconté des conneries, on s'en fout! Ici le calcul est indépendant du sens de la normale. Ca se voit tout de suite, si tu changes n en -n, v ne change pas.

Pour finir, les coordonnes de la balle b( b.x,b.y) sont changées tels que:
b.x est incrémentée de vx.t
b.y est incrémentée de vy.t
Où t est le temps après le rebond.
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
26 avril 2008 à 18:51
Et pour l'explication de ton bug pour le coup...
Avec la formule de la normale que tu avais prise, quand la balle arrivait sur une pente à 60°, la normale calculée était celle d'une pente à 30°. Sans vouloir entrer dans les détails, en gros tu te retrouvais avec un angle de 60°+30°=90° ce qui fait que tu calculais le rebond pour une balle arrivant perpendiculairement à la normale, c'est à dire tangentiellement au segment. Donc elle roulait...
0
Merci d'avoir répondu si vite.

J'ai fais comme tu as dit en mettant -(ay-by) au lieu de (ay-by). Mais dans ce cas. Si la balle touche sur le haut du segment (de pente 60 degrés ou -60 degrés) la balle rebondit bien mais sa vitesse énormément d'un coup et finit par sortir de l'écran. Sinon la balle traverse le segment.
J'ai donc remis ma formule comme avant.

Mais je n'ai pas tout compris de ton analyse sur les angles.
Pour un segment de pente à 60 degrés, la normale fait un angle de 30 degrés avec l'axe des abscisses.
Mais je n'ai pas compris pourquoi cela implique forcement quelque soit la manière dont la balle est arrivé sur le segment pourquoi elle repart forcement avec un angle qui est la somme de l'angle du segment avec l'axe des abscisses et celui de la normale avec l'axe des abscisses (ici 60+30) . Est-ce à cause de ma formule?
Si oui faut-il faire un cas spécifique, et comment doit rebondir une balle dans ce cas là?

En n'espérant ne pas trop te déranger vu l'heure tardive.
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
27 avril 2008 à 00:51
Tu me déranges pas!
Désolé, mon explication pour le bug est complètement fausse, je m'en suis rendu compte après... c'est même du n'importe quoi, j'ai essayé de voir de tête ce qui se passait et en fait j'ai mal vu :-D

Par contre ta formule pour la normale est clairement fausse.
Démonstration:
1) Le vecteur AB a pour coordonnées (xb-xa,yb-ya)
2) Le vecteur tangent t a donc pour coordonnées ((xb-xa)/||AB||,(yb-ya)/||AB||)
2) Le vecteur normal n tel que la base (t,n) soit directe a donc pour coordonnées (-(yb-ya)/||AB||,(xb-xa)/||AB||) car:
||n||=1
t.n=0
det(t,n)=1
Ou l'opposé, peu importe: ((yb-ya)/||AB||,-(xb-xa)/||AB||)

Et donc... j'ai raconté des conneries encore une fois... ta première formule était juste, j'avais pas fait gaffe que dans (ay-by)/(bx-ax) l'ordre des points était pas le même au numérateur et au dénominateur... mais quel boulet je suis moi des fois!!! Et en plus j'écris fièrement ma formule fausse dans le post 3 en faisant un copier/coller de ta formule et en y ajoutant un signe moins.

Donc je réquipépète:

1) Tu prends n=(-(yb-ya)/||AB||,(xb-xa)/||AB||)
2) v=v0- 2*v0.n*n (avec le n calculé précédemment)

Désolé pour toutes mes conneries. Ça marche avec les formules 1) et 2) ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Merci encore de répondre.

J'ai fait comme tu as dit. Mais malheureusement ça na pas marché.

Cette fois quand la balle arrive sur le haut d'un segment (de pente 60 degrés) elle disparait, sinon elle continue de rouler
sur le segment.J'avoue que je ne comprends pas trop pourquoi la balle réagit differement puisque la formule est dans le fond la même que celle que j'avais écrite précédemment.

Enfin merci quand meme
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
27 avril 2008 à 09:52
Aaahhh!!!
Désespère-pas, on va continuer à y réfléchir!
Normalement la formule est pas tout à fait la même que celle que t'avais prise au départ.
La différence entre celle que tu avais écrite et celle que j'ai écrite en tout dernier (après avoir raconté moult conneries :-D), c'est que toi tu avais un facteur ||n|| en trop puisque tu aurais dû diviser par ||n||².
Reprends éventuellement ta première formule mais en divisant par ||n||² au lieu de ||n|| juste au cas où il resterait une erreur dans ce que j'ai écrit.
J'essaie de comprendre d'où vient ton bug....
0
J'ai fait comme tu as dit en faisant:

v=v0 -2*v0.n*n/||n||².

Cela a pour effet que quand la balle frappe le segment de pente 60 degrés, la boule roule moins vite. Surement parce que le vecteur vitesse est moins grand. Cependant la balle continue à rouler.

Je vais chercher avec quel angle la balle devrait repartir.

Merci
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
27 avril 2008 à 10:27
Là je commence à croire qu'il y a un problème ailleurs.

Cette formule:
n.x=(ay-by)/(bx-ax)
n.y=1
v=v0-2*v0.n*n/(n.x*n.x+n.y*n.y)

que tu viens de tester,
et celle-ci:
n=(-(yb-ya)/||AB||,(xb-xa)/||AB||)
v=v0-2*v0.n*n

que tu as testée un peu avant,
devraient donner exactement les mêmes résultats.

C'est pas le cas apparemment...
0
Effectivement quand j'utilise la méthode suivante:

n=(-(yb-ya)/||AB||,(xb-xa)/||AB||)
v=v0- 2*v0.n*n

la balle disparait quand elle touche le segment à pente 60 degrés.

avec l'autre formule:

n.x=(ay-by)/(bx-ax)
n.y=1
v=v0- 2*v0.n*n/(n.x*n.x+n.y*n.y) la balle roule dessus.

Il y aurait du avoir le meme comportement pourtant ce n'est pas le cas. Pourtant ma fonction marche tres bien pour tous les autres types de segments. Je sais que le moment du rebond est toujours bien détecté.

Il faut peut etre ne pas prendre simplement en compte le probleme methematique mais aussi des specificites du langages. Par exemple je sais que pour l'operateur || (ou), dans la condition :

a || b. a sera évalué en premier, si a est vrai alors l'opérateur || n'évaluera meme pas b.

C'est peut-être la manière dont on code qui fait la différence.

Ma fonction prend une liste de couples de couples de réels.
( (ax,ay),(bx,by)) est un élément de cette liste. Je recupère ax ay bx by.
Puis si bx=ax vx recoit -vx puis balle.x recoit balle.x+vx (pas besoin d'utiliser t car on repète ça dans une boucle, c'est le prof qui l'avait dit) et balle.y recoit balle.y+vy où v est le vecteur vitesse de la balle avec vx et vy ses composantes.
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
27 avril 2008 à 15:19
Je pense pas que ce soit un problème de spécificité du langage.

Je pense vraiment à une petite coquille de rien du tout dans ton programme. Les deux calculs devraient donner le même résultat quel que soit le langage.

J'essaie de deviner ce que tu as pu laisser trainer dans ton code pour que ça donne ce genre d'erreur...
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
27 avril 2008 à 23:03
Je vois pas où peut être l'erreur.
Il est long ton programme?
S'il est pas trop long, tu voudrais pas plutôt le poster qu'on jette un œil?
Je connais pas le Caml mais bon... je peux essayer de voir quand même...
0
Mon code de la fonction en question n'est pas très long. A noter qu'elle prend en parametre 4 nombres ax ay bx by, correspondant à A(ax,ay) et B(bx,by), et une force de rebond f. Selon si f vaut 1 ou 2 le vecteur vitesse de la balle sera changé différemment. Cependant le probleme de rebond sur segment à pente d'environ 60 degrés ou -60 degrés. c est une variable globale, de composants c.x , c.y.

Voici le code la fonction:

(* fonction qui calcule le nouveau vecteur de la balle apres un rebond*)
let vector f ax ay bx by=

if(bx=ax) then (v0.vx<- (-.v0.vx);
c.x <- c.x+.(v0.vx);
c.y <- c.y+.(v0.vy))
else(
n.vx<-(ay-.by)/.(bx-.ax);
n.vy<-1.0;
if(f=1) then(
v0.vx <- v0.vx-.2.0*.(v0.vx*.n.vx+.v0.vy*.n.vy)*.n.vx/.sqrt(n.vx*.n.vx+.n.vy*.n.vy);
v0.vy <- v0.vy-.2.0*.(v0.vx*.n.vx+.v0.vy*.n.vy)*.n.vy/.sqrt(n.vx*.n.vx+.n.vy*.n.vy))
else(
v0.vx <- v0.vx-.2.0*.(v0.vx*.n.vx+.v0.vy*.n.vy)*.n.vx/.((n.vx*.n.vx+.n.vy*.n.vy)*.1.0);
v0.vy <- v0.vy-.2.0*.(v0.vx*.n.vx+.v0.vy*.n.vy)*.n.vy/.((n.vx*.n.vx+.n.vy*.n.vy)*.1.0));
c.x <- c.x+.(v0.vx);
c.y <- c.y+.(v0.vy)
)

Merci d'avance
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
28 avril 2008 à 13:53
Salut
J'essaie de regarder ça aujourd'hui
A plus tard
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
29 avril 2008 à 13:05
Salut
J'ai regardé et j'ai plusieurs interrogations ou remarques.
1) Si l'abscisse de a et b sont les mêmes, c'est la composante vy qui change de signe, non?
2) Je pense que ton if(f=1) est mal placé parce que si ax=bx il s'applique pas.
3) Tu as laissé sqrt(n.vx*.n.vx+.n.vy*.n.vy) pour if(f=1).
4) Je ne vois aucune différence entre le cas f=1 et le cas f≠1 (après correction de 3) puisque tu multiplies par 1.
5) La boucle conditionnelle if(bx=ax) n'est pas utile si tu prends la formule n=(-(yb-ya)/||AB||,(xb-xa)/||AB||)
Voili, voilou...
Dis-moi ce que tu penses de tout ça.
0
Salut,

Cette fois j'ai un peu changé la formule.
Cette fois ça marche mieux. Je m'explique.
Jusque là lorsque une balle frappait un segment de pente de 50 à 70 degrés (respectivement de -50 à -70 degrés) la balle roulait systématiquement dessus.
J'ai alors écrit la formule suivante:

n.x=(ay-by)/(bx-ax)
n.y=1
v=v0-2*v0.n*n/(n.x*n.x+n.y*n.y),

au lieu de:
n.x=(ay-by)/(bx-ax)
n.y=1
v=v0-2*v0.n*n/sqrt(n.x*n.x+n.y*n.y)

Resultat: maintenant les marges d'erreurs sur les angles ont diminuées. Désormais je dirais que pour un segment de pente de 55 à 65 degrés (respectivement de -55 à -65 degrés) la balle continue à rouler dessus.
On dirait que plus la pente du segment est proche de 60 degrés (resp. -60 degrés), plus elle a de chances de rouler dessus.Il faut donc peut-être trouver la bonne valeur qui permettrait un bon rebond quelque soit l'angle.

Autre chose:
si bx=ax, cela signifie que l'on a un segment vertical.Donc si une balle arrive de la gauche vers la droite dessus (donc avec vx positif) elle repartira dans l'autre sens (donc vx négatif)
vy lui ne change que si la balle frappe un segment horizontal.

Voilà merci
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
29 avril 2008 à 14:54
Euh... oui pardon, sur ce coup-là j'ai été un boulet. Je voyais le segment horizontal et non vertical, va savoir pourquoi...
Cela dit ça change rien au fait que tu peux utiliser la formule n=(-(yb-ya)/||AB||,(xb-xa)/||AB||) qui évitera de faire ta boucle et d'avoir de mauvaises surprises quand ton segment sera très proche d'un segment vertical mais qu'il ne le sera pas.
J'essaie de comprendre la persistance de ton bug un peu plus tard.
0
Sacabouffe Messages postés 9427 Date d'inscription dimanche 19 août 2007 Statut Membre Dernière intervention 29 mai 2009 1 832
30 avril 2008 à 21:09
Salut
Bon vraiment, ce problème d'angle de 60° je comprends pas... t'as des news de ton côté? C'est toujours pareil?
Ton code en entier il est long?
S'il l'est pas trop ben... tant qu'à faire autant tout le vérifier parce que là je vois pas :-(
0