Vous obtenez peut-être des faux positifs. Collisions détectées mais pas vraiment en collision.
Le nombre 15 vient de
- 3 axes de l'objet A (normales de face)
- 3 axes à partir de l'objet B (faces normales)
- 9 axes de toutes les paires d'arêtes de A et d'arêtes de B (3x3)
- = 15 au total
Les 9 axes sont constitués de produits croisés des bords de A et des bords de B
- Ae1 x Be1 (arête 1 de A arête transversale 1 de B)
- Ae1 x Be2
- Ae1 x Be3
- Ae2 x Be1
- ... etc
Les 6 premiers axes (à partir des normales de face) sont utilisés pour vérifier s'il y a un coin d'un objet qui coupe une face de l'autre objet. (ou plus correctement pour éliminer ces types de collisions)
L'ensemble des 9 axes formés par les produits croisés des bords est utilisé pour considérer la détection de collision bord à bord, où aucun sommet ne pénètre dans l'autre objet. Comme la collision «presque» sur la photo ci-dessous. Supposons pour le reste de cette réponse que les deux cases de l'image ne se heurtent pas réellement, mais sont séparées par une petite distance.
Regardons ce qui se passe si nous utilisons simplement les normales à 6 faces pour SAT. La première image ci-dessous montre un axe de la boîte bleue et 2 axes de la boîte jaune. Si nous projetons les deux objets sur ces axes, nous obtiendrons un chevauchement sur les trois. La deuxième image ci-dessous montre les deux axes restants de la boîte bleue et l'axe restant de la boîte jaune. Une nouvelle projection sur ces axes montrera des chevauchements sur les 3.
Ainsi, la simple vérification des 6 normales de face affichera des chevauchements sur les 6 axes, ce qui, selon le SAT, signifie que les objets entrent en collision, car nous n'avons pas pu trouver de séparation. Mais bien sûr, ces objets ne se heurtent pas. La raison pour laquelle nous n'avons pas trouvé de séparation est parce que nous n'avons pas regardé assez fort!
Alors, comment allons-nous trouver cet écart? L'image ci-dessous montre un axe sur lequel la projection des deux objets révélera une séparation.
D'où tirons-nous cet axe?
Si vous imaginez glisser un morceau de carte rigide dans l'espace, cette carte fera partie du plan de séparation. Si nous projetons sur la normale de ce plan (flèche noire dans l'image ci-dessus), nous verrons la séparation. Nous savons ce que ce plan est parce que nous avons deux vecteurs qui se trouvent sur ce plan) Un vecteur est aligné avec le bord de bleu et l'autre vecteur est aligné avec le bord de jaune et comme nous le savons tous, la normale à un plan est simplement le produit croisé de deux vecteurs se trouvant sur le plan.
Ainsi, pour les OOBB, nous devons vérifier chaque combinaison (9 d'entre eux) de produits croisés des bords des deux objets pour nous assurer de ne manquer aucune séparation bord-bord.
Les notes de réponse de Ken :
Il est un peu déroutant de se référer aux bords, car il y a 12 bords par rapport à 6 normales, alors vous pourriez aussi bien utiliser les trois normales principales pour la même sortie - les bords sont tous alignés avec les normales, donc je recommande de les utiliser à la place !
Notez également que les normales pointant le long du même axe, mais dans une direction différente, sont ignorées, et nous nous retrouvons donc avec trois axes uniques.
Une autre chose que j'aimerais ajouter, c'est que vous pouvez optimiser ce calcul en quittant tôt si vous trouvez un axe de séparation, avant de calculer tous les axes que vous souhaitez tester. Donc, non, vous n'avez pas besoin de tester tous les axes dans tous les cas, mais vous devez être prêt à les tester tous :)
Voici une liste complète des axes à tester, étant donné deux OBB, A et B, où x, y et z font référence aux vecteurs de base / trois normales uniques. 0 = axe x, 1 = axe y, 2 = axe z
Il y a aussi une petite mise en garde, que vous devez savoir.
Le produit croisé vous donnera un vecteur nul {0,0,0} lorsque deux axes quelconques entre les objets pointent dans la même direction.
De plus, puisque cette partie a été omise, voici mon implémentation pour vérifier si la projection se chevauche ou non. Il y a probablement une meilleure façon, mais cela a fonctionné pour moi! (Utilisation d'Unity et de son API C #)
la source
exemple c # de travail basé sur la réponse d'Acegikmo (en utilisant des API d'unité):
la source