Moteur physique et correction de la position

pour des réponses impulsionnelles

a marqué ce sujet comme résolu.

Bonjour ! Je développe un petit moteur de jeu avec des amis et je me m’occupe de toute la partie physique. J’ai déjà implémenté tout ce qui était découpage de l’espace et détection des collisions pour les primitives de base (point + normale + distance d’interpénétration).

Concernant la réponse aux collisions, j’ai choisi une réponse impulsionnelle. J’utilise donc une méthode itérative (Gauss-Seidel) pour approcher la solution et cela fonctionne plutôt bien pour la réponse en vitesse, même si il y a beaucoup de solides en contact.

Cependant je suis confronté à quelques petits problèmes pour la réponse en position. Lorsque le coefficient de restitution est strictement inférieur à 1 (plus de conservation de l’énergie durant le choc), la réponse en vitesse n’éloigne pas autant les objets après intégration que ce qu’ils s’étaient rapprochés le temps du pas de simulation.

Je m’explique, si j’ai deux objets avec une vitesse relative nulle, mais qui accélèrent l’un vers l’autre, exemple : le sol et un objet posé dessus, alors durant la simulation, l’accélération va être intégrée en vitesse et comme il n’y a pas conservation de l’énergie, la réponse en vitesse ne va pas annuler totalement celle-ci et, à la prochaine itération l’objet va un peu plus interpénétrer le sol. On voit donc l’objet passer très lentement à travers le sol.

La solution est donc de repositionner l’objet au point de collision juste avant de calculer la réponse en vitesse (réponse en position) en "remontant" dans le temps. J’ai donc posé les équations de mouvement et les ai inversées (elles sont horribles mais correctes), cependant, si ça fonctionne pour un objet, pour un problème à n objets, cela finit par diverger. En effet, la réponse en position créé de nouvelles collisions (en séparant d’autres objets), qui ne seront détectés qu’à l’itération d’après, le solveur va essayer de retrouver le point de collision avec les équations du mouvement, mais dans ce cas les objets n’étaient peut être pas en train de se rapprocher, le solveur ne peut donc trouver de solution valide avec uniquement ces équations et finit par diverger.

J’ai donc essayé quelques chose de plus simple, de séparer les objets uniquement selon la normale de contact et leur masse/opérateur d’inertie, mais ce modèle n’est pas cohérent et cause quelques inexactitudes visibles notamment lorsque les vitesses de rotations sont élevées et cela devient pire lorsqu’on ajoute les frottements.

Exemple : un objet en équilibre sur un sol en pente et un autre l’empêche de rouler/glisser. Durant l’itération, l’accélération gravitationnelle va donner une vitesse à l’objet, qui va être intégrée en déplacement, le solveur va détecter la collision, répondre en impulsion (quasi inversement de la vitesse normale et donner une vitesse de rotation à cause des frottements), le solveur de position replace l’objet au point de contact, mais la réponse en vitesse n’est pas nulle, après intégration, l’objet s’éloigne un petit peu du sol, cela fait apparaître un phénomène de léger "tremblement" et des réactions bizarres dues aux frottements.

Je me demandais donc si des solutions étaient connues à ce problème ou alors si je devrais considérer le fait de détecter lorsque des objets sont en contact durant plusieurs itérations et appliquer un autre modèle pour résoudre ces collisions.

Merci d’avance.

Salut,

Au lieu de t’y prendre après l’impact, tu ne peux pas t’y prendre avant (vérifier qu’un impact ne va pas arriver entre l’itération actuelle et la prochaine) ? Ça rajoute du calcul et il ne faut pas négliger si l’objet qui va être touché doit encore bouger ou non, mais ça resoudrait ton problème. Par contre, aucune idée si c’est envisageable comme solution.

Ou sinon, si il s’est passé un contact entre l’itération actuelle et celle précédente, tu reviens à la précédente en anticipant cette fois-ci (il peut arriver que tu aies à revenir plusieurs fois, si cette modification crée un autre impact).

J’ai balancé des idées à la mer, ça m’étonnerait que ça soit utilisable, mais bref.

Salut, Merci pour ta réponse! J’avais pensé à ce genre de solutions : pour ta première idée, j’avais implémenté une dichotomie dans le temps pour trouver l’instant exact du premier impact, c’est un bonne solution si on veut éviter totalement les interpénétrations, mais c’est quand même beaucoup plus lent. Mais dans mon cas, le problème survient quand les objets sont déjà en collision c’est à dire que le temps d’impact est t+0 et les objets ne s’éloigneront plus. Il faudrait donc calculer une réponse une infinité de fois entre deux itérations, impossible. J’avais aussi pensé à la deuxième, garder un graphe des contacts (ce que je suis en train d’implémenter pour des raisons d’optimisation). Mais justement, des objets en contact peuvent glisser ou rouler les uns sur les autres, le but étant juste de les empêcher de s’interpénétrer.

Nous avions commencé ce projet il y a deux ans et nous l’avions abandonné par manque de temps et notamment à cause de ce problème. Cependant, la réponse impulsionnelle est beaucoup trop complexe pour la déboguer facilement et ce n’est pas moi qui ai écrit toutes les fonctions de génération de contact (qui sont peut être boguées aussi).

Je suis en train de lire quelques papiers qui soulignent ce problème, je trouve la doc de Box2D assez intéressante et facilement généralisable à la 3D. Le moteur autorise une petite interpénétration et introduit un biais de vitesse proportionnel à la distance d’interpénétration (et inversement proportionnel au pas de simulation ???). J’étais en train d’essayer d’ajouter une réponse en position proportionnelle à la distance d’interpénétration pondérée pour chaque objet par rapport à sa masse et son moment d’inertie.

Je vais essayer de simplifier un peu pour le moment, enlever la friction et avoir un système fonctionnel avec des boites (dont j’ai écrit et testé les algos de contact) car il semble y avoir quelques problèmes pour le moment avec les réponses impulsionnelles impliquant de la friction et que le code écrit en C++ n’est pas trop optimisé (trop de polymorphisme :p). Puis essayer quelques autres solutions comme celle de Box2D.

Si vous avez d’autres idées (même farfelues) ou des papiers à me conseiller, n’hésitez pas :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte