web-dev-qa-db-fra.com

Détection de collision 3D: coque convexe vs coque convexe, besoin de position et normale

Je veux connaître une position 3D approximative et ​​normale 3D du site de collision entre deux coques convexes 3D (A vs B).

Le CPU entre parenthèses montre le temps CPU relatif nécessaire dans mon programme terminé.

Partie 1: Early-out (CPU 1%)

Dans la première étape, j'utilise un algorithme très bon marché - théorème de l'axe de séparation .
Par exemple, j'utilise 15 axes pour 2 cubes. (Dans les cas réels, les formes sont plus complexes.)
S'il y a au moins 1 axe qui peut se séparer, return "no-collide".
Sinon, passez à la partie suivante.

Partie 2: Vertex vs Volume (CPU 10%)

  • Vérifiez tous les sommets de A - si c'est à l'intérieur de B.
  • Vérifiez tous les sommets de B - si c'est à l'intérieur de A.

enter image description here

Partie: Edge vs Edge (CPU> 20%)

Il y a un cas étrange, par exemple https://gamedev.stackexchange.com/questions/75437/collision-detection-3d-rectangles-using-sat . J'ai volé l'image à partir de là: -

enter image description here

Ainsi, j'ai également besoin de Edge vs Edge.

  • Pour chaque paire d'arêtes A et B (12 * 12 = 144 paires), trouvez un point le plus proche dans Bord de A contre le Bord de B. Vérifiez si le sommet est à l'intérieur de B.
  • (vice versa) Pour chaque paire d'arêtes B & A, vérifiez si un tel sommet est à l'intérieur de A.

Wow, c'est beaucoup de calculs.
Cependant, ce n'est pas encore fini.

Problème

  1. La position de collision signalée n'est pas aussi précise (gauche: actuelle, droite: souhait): -

    enter image description here

    Pour le résoudre, j'ai pensé à générer une nouvelle forme convexe = A intersect B.
    Il existe des bibliothèques C++ gratuites (par exemple OpenMesh ), mais je pense que c'est trop cher pour le CPU.
    Notez que je n'ai pas besoin qu'elle soit exacte.

  2. Il signale également parfois une erreur normale (gauche: actuelle, droite: souhait): -

    enter image description here

    ^ Ce problème pourrait être résolu en ajoutant Edge (sur A) vs face (sur B), mais cela rendrait la détection de collision encore plus coûteuse.

Question

Il ressemble à des algorithmes courants sur Internet (à partir desquels je copie) ne reconnaît que les micro-fonctionnalités.
À mon humble avis, l'algorithme sommet-volume/bord-bord se concentre sur la topologie plutôt que sur le fait que les deux formes sont solides volumes.

Quel est l'algorithme le plus précis (1ère priorité) et peut-être le moins cher?
Mon approche pourrait être erronée au niveau de la fondation.

Pour accélérer les choses, j'ai déjà fait de la taille, par exemple sélectionnez uniquement une paire de bords A et B qui sont proches l'un de l'autre.

Références: -

Modifier (10 jours plus tard)

Maintenant, je peux trouver tous les points convexes qui se croisent (le convexe est représenté comme un triangle/rectangle rose): - enter image description here

Voici comment je trouve la normale.

Pour chaque axe de séparation (tous = 15 axes), I projet ​​le rose convexe sur l'axe.
L'axe qui donne la distance la plus courte projection (flèche rose) doit être la direction de la normale.

Mon hypothèse ci-dessus est souvent correcte (par exemple à gauche), mais parfois erronée (par exemple à droite).
Comment l'améliorer à moindre coût?

12
javaLover

Les moteurs de jeu simulent généralement le temps d'une série d'étapes discrètes. En conséquence, le système de collision peut entrer dans des cas difficiles (coûteux en calcul) en raison de l'interpénétration (votre cas) ou lorsque les choses évoluent rapidement - tunneling où A est d'un côté de B à l'étape N et entièrement de l'autre côté de B à l'étape N + 1. C'est encore plus difficile si vous devez traiter avec un contact à corps multiples ou un contact continu ou un objet non convexe ou articulé ou mou. Oui! nous simulons le monde entier.

Vous voulez faire de la "physique du jeu" et utiliser des approximations pour racheter la fréquence d'images ... Au final, vous pouvez couvrir beaucoup d'erreurs avec un tas de bouffées de fumée ou de fusées éclairantes. :-)

Il existe une classe d'algorithmes qui prennent explicitement en compte le temps simulé pour aider le système de collision. Il existe de nombreuses façons de mettre en œuvre un système de "détection de collision continue". Vous pouvez commencer ici, mais vous devez d'abord lire largement avant de vous engager à coder. Heureusement, il existe de nombreuses publications sur les collisions. voici un bon point de départ https://docs.unity3d.com/Manual/ContinuousCollisionDetection.htmlhttps://pybullet.org/Bullet/phpBB3/viewtopic.php?t = 2

Voici une heuristique suggérée qui pourrait fonctionner dans votre système existant .... Cette technique heuristique pourrait fonctionner dans un jeu comme les astroïdes 3d où les objets flottent librement dans l'espace. Cela pourrait suffire à ce dont vous avez besoin.

Image chaque objet stocke son vecteur d'état actuel (position, orientation, vitesse, accélération, rotation ...) et son vecteur d'état précédent du pas de temps précédent.

Supposons que vous ayez détecté une collision potentielle entre les objets A et B à l'instant = courant.

Pour time = previous, supposez que A et B ne sont pas en contact.

Calculez les points les plus proches sur les surfaces de A et B, respectivement à l'instant = prev en utilisant les vecteurs d'état précédents de A et B. (A le plus proche, B le plus proche).

Le segment de ligne (le plus procheA, le plus procheB) aura une longueur non nulle à l'instant = précédent. Vous pouvez simplement utiliser le plus procheB pour votre position et normal, mais cela aurait une erreur proportionnelle à la longueur du segment de ligne.

Faites donc une recherche binaire dans le temps, et minimisez l'erreur, en trouvant le moment où A est arbitrairement proche de B. À chaque étape de votre recherche, réduisez de moitié la taille des pas de recherche. 0,5, 0,25, 0,125 .. jusqu'à ce que la longueur de (le plus procheA, le plus procheB) soit inférieure à un seuil d'erreur ou que vous abandonniez.

Cela devrait vous donner une solution approximative acceptable pour les cas simples ...

De plus, vous avez dit que vous utilisiez le théorème de l'axe de séparation comme "première vérification". Cela me semble cher si c'est vraiment le "premier contrôle" ..

Le calcul le plus rapide est celui que vous ne faites pas, donc une collision rapide signifie beaucoup de pré-tests bon marché et évite les cas coûteux.

Vous pouvez envisager d'utiliser des techniques spatiales comme une grille spatiale grossière et ne vérifier que les objets dont vous savez déjà qu'ils sont proches les uns des autres.

En outre, le test sphère-sphère est un prétest très rapide pour voir si la sphère englobante de deux objets convexes se chevauchent même.

1
VerdeCode