Comment puis-je corriger les objets qui «sautent» ou tremblent dans le moteur physique?

11

J'ai un moteur physique simple qui résout les collisions en corrigeant simplement la position des corps qui se chevauchent (juste des cercles pour l'instant) directement, au lieu de simplement changer la vitesse ou d'appliquer une impulsion. La vitesse n'est modifiée qu'après que les impacts sont déjà résolus ou pendant la partie d'intégration.

J'ai eu le problème que dans les tas d'objets, les objets du haut appliquent trop de pression (cela existe implicitement, il n'y a pas de modélisation de la pression dans l'algorithme) sur les objets au bas du tas, ce qui les fait passer à travers les étages, etc.

Je voulais résoudre ce problème en triant les objets par leur coordonnée y, afin que les collisions soient résolues de bas en haut. Mais maintenant, le moteur affiche un comportement de pop-up étrange pour les objets qui devraient en fait être au repos (voir gif)

entrez la description de l'image ici

Sans simplement vous donner le code source - qu'est-ce que cela pourrait être?

TravisG
la source
5
Dans l'ensemble, cela revient à résoudre un système linéaire d'équations de manière itérative (ou système non linéaire, selon vos contraintes / conditions / etc.). Dans les deux cas, vous voyez ces artefacts parce qu'ils sont numériquement la bonne chose à voir: les états intermédiaires d'un processus convergent. Éviter cela est assez difficile et pourrait impliquer beaucoup de hacks désagréables (de toute façon, cela se produit dans la vraie vie, au niveau moléculaire, et c'est ce que vous avez là pour mieux ressembler à quelque chose dans la vraie vie :)). Il est probablement bon d'étudier box2d pour voir leur solution pour la dynamique basée sur les impulsions.
teodron
@TravisG comment avez-vous résolu le problème? J'examine un problème similaire en essayant d'implémenter un moteur physique très simple.
Cheesus dit d'arrêter de tirer les mods
1
@cheeesus Cela fait un moment que je n'y ai pas travaillé, mais je crois que je viens d'utiliser plus d'itérations avec des pas de temps plus petits.
TravisG

Réponses:

5

Une solution que j'ai trouvée lors de l'utilisation de la correction de position est d'avoir quelques itérations et de varier la force à chaque itération.

doPhysics();

int num_iterations = 5;
for(int iteration=0; iteration<num_iterations; ++iteration)
{
    float strength = float(iteration+1)/num_iterations;
    correctPositions(strength);
}

Ainsi, la première itération a une force de 1 / num_iterations et la dernière a une force de 1. Cela rend mes simulations plus fluides et plus stables que d'utiliser simplement le même nombre d'itérations avec une force fixe.

DaleyPaley
la source
2
Belle solution, mais pourquoi ça marche?
Gustavo Maciel
5

Votre problème réside dans le fait que vous n'avez pas d'état de «repos» pour votre corps. Tout système physique a une quantité d'énergie, cinétique, thermique, etc. En réalité, les objets solides se déforment légèrement et transforment une certaine énergie cinétique en chaleur, bien qu'elle soit difficilement mesurable. Il convient également de noter qu'en réalité, il n'existe pas d'objet complètement solide. Même les matériaux denses, comme le diamant, ont un espace entre les atomes, ce qui donne à la structure atomique la possibilité de fléchir et d'absorber l'énergie cinétique.

Pour rendre cela pertinent, les corps au repos sont dans un état où les seules forces en vigueur sont la "force normale", c'est-à-dire la force qui empêche les corps de flotter les uns dans les autres. L'ampleur de cette force normale est proportionnelle à la densité des objets et à leur distance de pénétration.

Les moteurs physiques appellent cette valeur "slop".

Voici l'astuce: calculez la pente, corrigez la position des corps et appliquez la force normale, en fonction de la vitesse relative des deux corps. lors de la mise à jour des corps eux-mêmes, calculez l'énergie cinétique de chaque corps. Si elle est inférieure à une valeur minimale, endormez le corps jusqu'à ce qu'une force d'amplitude suffisante lui soit appliquée. (généralement deux fois la valeur minimale).

Ian Young
la source
0

Pourquoi ne pas leur ajouter une surface "collante" et les faire coller progressivement à une position de repos et lorsqu'un autre objet le frappe, il y transfère de l'énergie, ce qui le fait bouger mais la surface collante lui fera perdre une partie de cette énergie et s'arrêtera en position de repos. le gif semble n'avoir aucune friction.

anon
la source