web-dev-qa-db-fra.com

Quadtree pour la détection de collision 2D

J'essaie d'utiliser un quadtree pour la détection de collision 2D, mais je suis un peu perplexe sur la façon de l'implémenter. Tout d'abord, j'aurais un quadtree qui contient quatre sous-arbres (un représentant chaque quadrant), ainsi qu'une collection d'objets qui ne rentrent pas dans un seul sous-arbre.

Lors de la vérification d'un objet pour les collisions dans l'arbre, je ferais quelque chose comme ça (grâce à QuadTree pour la détection de collision 2D ):

  1. Vérifiez l'objet pour les collisions avec les objets du nœud actuel.
  2. Pour tout sous-arbre dont l'espace chevauche l'objet, récapitulez.

Pour rechercher toutes les collisions dans un arbre à quatre arbres:

  1. Vérifiez chaque objet dans le nœud actuel contre chaque autre objet dans le nœud actuel.
  2. Vérifiez chaque objet du nœud actuel par rapport à chaque sous-arbre.

Pour insérer dans un quadtree:

  1. Si l'objet tient dans plusieurs sous-arbres, ajoutez-le au nœud actuel et revenez.
  2. Sinon, récursivement dans le sous-arbre qui le contient.

Pour mettre à jour un quadtree:

  1. Reculez dans chaque sous-arbre.
  2. Si un élément du nœud actuel ne tient plus complètement dans l'arborescence actuelle, déplacez-le vers le parent.
  3. Si un élément du nœud actuel tient dans un sous-arbre, insérez-le dans le sous-arbre.

Est-ce que ça va? Peut-il être amélioré?

33
bfops

Votre structure à quatre arbres n'est pas optimale. Vous avez raison de stocker 4 sous-arbres par nœud, mais les objets réels ne doivent être stockés qu'à l'intérieur des feuilles, pas les nœuds intérieurs. Par conséquent, la collection contenant les objets réels doit être déplacée vers les feuilles.

Jetons un coup d'oeil à l'implémentation des opérations :

  1. Insérez un objet dans le quadtree:
    Vérifiez si l'objet intersecte le nœud actuel. Si c'est le cas, demandez de nouveau. Si vous avez atteint le niveau feuille, insérez l'objet dans la collection.
  2. Supprimer un objet du quadtree:
    Exécutez exactement les mêmes étapes que si vous insérez l'objet, mais lorsque vous avez atteint le niveau feuille, supprimez-le de la collection.
  3. Teste si un objet croise un objet à l'intérieur du quadtree:
    Exécutez exactement les mêmes étapes que si vous insérez l'objet, mais lorsque vous avez atteint le niveau de la feuille, vérifiez la collision avec tous les objets de la collection.
  4. Test de toutes les collisions entre tous les objets à l'intérieur du quadtree:
    Pour chaque objet dans le quadtree, exécutez le test de collision d'un seul objet.
  5. Mettre à jour le quadtree:
    Supprimez tous les objets du quadtree dont la position a été modifiée et réinsérez-les.

Cela présente plusieurs avantages :

  • En ne stockant que des objets dans les feuilles, il est très facile de gérer les opérations sur le quadtree (moins de cas spéciaux)
  • Le quadtre peut avoir des feuilles de différentes profondeurs, vous permettant ainsi d'adapter la densité du quadtre en fonction de la région spatiale qu'il recouvre. Cette adaptation peut se produire lors de l'exécution, gardant ainsi le rapport objet/nœud optimal.

Seul désavantage :

  • Les objets peuvent appartenir à plusieurs collections à l'intérieur du quadtree. Vous allez avoir besoin d'une collection linéaire supplémentaire en dehors du quadtree pour énumérer chaque objet sans doublons.
36
Dave O.

Les arbres quadruples ne sont pas toujours la meilleure structure de données pour la détection de collision. Le surdébit d'un quadtree peut potentiellement être illimité (si vous ne limitez pas la profondeur de l'arbre) et, dans le pire des cas, n'accélérez pas du tout. Au lieu de cela, vous voudrez peut-être envisager d'utiliser une grille clairsemée, qui donne de meilleures performances qu'un quadtree uniquement sans la surcharge supplémentaire de traverser plusieurs niveaux d'arborescence.

Il existe également d'autres approches complètement différentes qui pourraient être encore meilleures. Par exemple, vous pouvez essayer d'implémenter l'algorithme de Zomorodian et Edelsbrunner, comme je l'ai fait dans le module suivant:

Voici également quelques articles que j'ai écrits qui discutent de ces problèmes plus en détail:

En particulier, si vous regardez les benchmarks dans la dernière section, vous verrez que de toutes les bibliothèques étudiées, les quadtrees avaient tendance à fonctionner assez mal par rapport à d'autres méthodes de détection de collision comme les R-Trees, les grilles ou les arbres à segments.

7
Mikola

Je ne sais pas encore à quel point le processeur est efficace, mais il semble bien fonctionner sur mon duo de base dans Eclipse, fonctionne toujours à plus de 2400 fps lol ..

fondamentalement, j'ai ajouté une liste d'objets collidables pour stocker des références à des objets de noeud à quatre arbres auxquels j'ai associé l'objet (via l'insertion dans le quadtree). J'ai également ajouté une liste à chaque nœud quadtree, qui stocke les références à tous les objets jugés dans les limites de ce nœud. Ainsi, chaque nœud n'aura qu'une seule occurrence de chaque objet. chaque nœud stocke également une référence à son nœud parent, pour la navigation vers les nœuds voisins si je veux vérifier l'un d'eux après le nœud initial pour une précision de collision supplémentaire.

il est très facile d'obtenir des références à tous les autres objets dans une cellule:

list temp_checklist = object.cells[cell_index].objects
//('objects' being some sort of array or list of object references as described above)

espérons que cela aide quelqu'un;)

0
Lazouskie