|
graphiboc |
Posté le 15 Avr 2010 à 16:59 |
|
Messages : 262
|
t'es sur que c'est pas la discrétisation qui pose problème ?
A la base un ressort c'est un problème continu, donc si tu le discrétises mal ça peut rapidement diverger
|
|
SEB |
Posté le 02 Avr 2010 à 09:20 |

Messages : 554
|
Oui effectivement, en fait dans ton implémentation il faut que tu prenne en compte le rapport que tu souhaite entre réalisme et temps réel, si ton appli doit etre au maximum réaliste, alors va lire carément des cours de physique sur les solides déformables et essaye de voir comment tu peux l'appliquer au mieu. si tes contraintes sont de type temps réel, fais tout de même attention a ne pas vouloir pousser la machine trop loin, et essaye de voir si ce que tu as la n'est pas déja largement sufisant.
|
|
chandragon |
Posté le 30 Mar 2010 à 17:10 |

Messages : 36
|
Ne t'en fais pas j'ai pris soin de modifier la liste des voisins pour que les mêmes forces ne soient pas appliquées deux fois ;)
Sinon j'avais essayé en ajoutant une atténuation mais sous forme de frottements (accélération -= vitesse*frottements) et ça a annulé les effets jusqu'à une certaine raideur.
Je viens d'essayer avec ton aténuation et c'est pareil, ça marche endessous d'une certaine raideur qui dépends du coefficient qu'on applique à cette aténuation.
Le problème c'est que ça freine toute la structure, ce qui n'est pas dutout réaliste si je me place dans l'espace ^^
Je pense qu'il doit y avoir des moyens plus proches du phénomène physique de règler ça ... peut-être en faisant varier les valeurs du tableau "longueurs" avec l'étirement des "ressorts" ? (comme dans le cas d'un ressort réel: lorsqu'on l'étire trop, il n'a plus la même longueur à vide)
|
|
SEB |
Posté le 30 Mar 2010 à 13:44 |

Messages : 554
|
Content que tu ai pu avancer, donc je pense que pour ton probleme deux pistes sont a verifier:
1 - tu dis que tu ne calcule qu'une seule force pour deux vertex, pourtant le code que tu poste ne donne pas cette impression puisque tu a l'air de parcourir toute la liste des voisins pour chaque vertex. donc en fait je dirais plutôt que a-priori tu applique deux fois la force a chaque vertex.
2 - pour palier aux problèmes dans lesquels le système a l'air de s'emballer on utilise souvent un principe qui n'a rien de physique mais qui peut marcher assez bien, à savoir le damping qui consiste a atténuer les différentes intégration comme si on considérait une sorte de frottement global ralentissant en permanence le système.
En général on peut appliquer le damping de la facon suivante :
Code : Java
public void update_pos(double elapsedtime)
{
vitesse += acceleration * elapsedtime;
vitesse = vitesse * pow(0.09, elapsedtime);
position += vitesse * elapsedtime;
acceleration = Vector3d.Zero;
}
Sachant que le code que je viens de poster peu s'optimiser de facon très conséquente. (un indice => pow pour des réel est très gourmand)
voila j'espère que ca t'aidera encore :)
|
|
chandragon |
Posté le 29 Mar 2010 à 15:49 |

Messages : 36
|
Merci pour ta réponse.
En effet il fallait que je sépare le calcul de l'accélération de celui de la vitesse et de la position ! ^^'
Tel que mon code étais fait là, j'actualisait la position d'un vertice puis calculait l'accélération d'un de ses voisins (qui dépend de la position du vertice précédent), c'est donc normal que j'aie des résultats abérants.
J'ai modifié mon code en séparant les deux actualisations, et aussi en ne calculant qu'une seule fois une interaction entre deux vertices (c'est la même force qui est appliquée aux deux mais avec une force opposée):
Citation :public void update_acc(Vector3d force)
{
acceleration += force/masse;
if(voisins!=null)
for (int i = 0; i < voisins.Length; i++)
{
acc = Vector3d.Normalize(voisins[i].position - position) * raideur * ((position - voisins[i].position).Length - longueurs[i]);
acceleration += acc/masse;
voisins[i].acceleration -= acc/voisins[i].masse;
}
}
public void update_pos(double elapsedtime)
{
vitesse += acceleration * elapsedtime;
position += vitesse * elapsedtime;
acceleration = Vector3d.Zero;
}
Et là lors des tests, au début ça se passe tout à fait normalement: quand j'applique une force sur un vertice il s'étire puis reviens en créant une onde dans tout le solide et le solide avance lentement (sans accélérer comme avant).
Mais j'ai remarqué qu'à partir d'une certaine raideur, et à partir d'un certain moment, les ondes qui parcourent le solide commencent à s'intensifier de plus en plus, jusqu'à étirer le solide juqu'à l'infini xD
C'est assez surprenant ...
Ai-je fait encore une erreur d'implémentation ou ce coup-ci c'est des erreurs d'arrondis ?
|
|
SEB |
Posté le 29 Mar 2010 à 09:13 |

Messages : 554
|
J'ai regardé le code très rapidement mais ne l'ai pas testé. A priori, deux idées me viennent à l'esprit :
1 - attention aux variations de framerate qui peuvent avoir des conséquences assez spéciales sur les application physiques.
2 - tu effectue le calcul et l'application des forces de façon séquentielle et je suppose même toujours dans le même ordre, or je pense que dans ce cas tu devrais plutot effectuer une passe pour connaitre la somme des forces appliquées à chaque particules et une fois cela fait intégrer l'ensemble des vitesses et positions.
|
|
chandragon |
Posté le 29 Mar 2010 à 03:32 |

Messages : 36
|
Bonjour
En voulant modéliser un cube déformable, j'ai créé une grille cubique de vertices et ai soumis chaque vertices à des interactions avec leurs voisins. J'utilise comme interaction celle qui relie deux bouts d'un ressort.
Et je suis un peu sidéré par le résultat:
Quand on n'y touche pas tout va bien, le cube ne bouge pas, mais dès qu'on applique une petite force à l'un des vertices, ça chamboule tout, et petit à petit le cube commence à accèlérer et à se déformer de plus en plus jusqu'a disparaitre au loin xD
Voici le code que j'utilise pour actualiser la position des vertices:
Citation :public void update(double elapsedtime, Vector3d force)
{
acceleration = force/masse;
for (int i = 0; i < voisins.Length; i++)
acceleration += Vector3d.Normalize(voisins[i].position- position) * raideur * ( (position - voisins[i].position).Length - longueurs[i]) / masse;
vitesse += acceleration * elapsedtime;
position += vitesse * elapsedtime;
}
Après avoir pas mal cherché, je n'ai qu'un suspect: les erreurs d'arrondi dans les calculs en chaine ... mais ça fais un peu gros quand même je trouve comme erreurs !
Si vous avez d'autres idées elles sont les bienvenues.
|