Полностью динамический KD-Tree против Quadtree?


11

Работая над своей игрой, я нахожусь в точке, где мне нужно отследить все юниты в мире, чтобы я мог делать проверки ближайших соседей на бой. Это RTS-подобная игра, в которой могут перемещаться тысячи маленьких автоматических юнитов.

Я изучал KD-Trees и Quadtrees (особенно Point Quadtrees). Я все еще пытаюсь изучить детали того, как они работают, но до сих пор Point Quadtrees имеют для меня наибольшее значение. Тем не менее, у меня складывается впечатление, что KD-деревья быстрее искать, что важно, учитывая количество точек в дереве.

С другой стороны, в моем случае я собираюсь отслеживать огромное количество единиц, которые всегда движутся. От кадра к кадру их положение всегда будет отличаться. Очевидно, Quadtree быстрее перебалансируются, чем KD-Trees, но я не знаю, применимо ли это, когда вы перебалансируете каждую точку дерева.

Я задаюсь вопросом, что было бы лучше в этом случае просто очистить дерево каждого кадра и восстановить его с нуля, а не пытаться сбалансировать каждую точку дерева? Если Quadtree быстрее перебалансировать, значит ли это, что его быстрее построить с нуля? Если это так, это может быть важнее для производительности, чем скорость поиска в KD-Tree, в зависимости от того, насколько тяжело создать дерево, но я не знаю ...

Ответы:


12

Честно говоря, KD-деревья недостаточно динамичны, чтобы их можно было рассматривать. Перемещение нескольких юнитов может легко потребовать от вас восстановления всего дерева KD. Кроме того, KD-дерево очень эффективно для запросов, но не так много для поиска соседей.

Дерево квадратов со временем становится более гибким, поскольку модификации хранятся более локально. Недостатком является то, что если у вас есть много юнитов в одном месте, которые часто перемещаются, это может подразделить слишком много и потребовать много обновлений из-за движения юнитов. Вы можете установить порог, при котором никакие подразделения не могут возникать. Но будьте осторожны, это подразумевает, что множество юнитов потенциально может находиться в одном и том же квадрате листа.

Однако, если вы заинтересованы только в нахождении всех юнитов в пределах постоянного радиуса r , вам не нужно сразу использовать quadtree и kd-tree. Вы можете просто создать двумерный массив ячеек со стороной длины r и разместить свои единицы в каждой ячейке в соответствии с их положением. Таким образом, у вас всегда есть в худшем случае 9 ячеек для поиска. Только если ваша карта огромна , такая сетка будет слишком большой для реализации.

Есть еще две совершенно разные структуры, о которых мы не говорили: иерархические AABB и локально-чувствительная хеш-таблица. Если происхождение каждой иерархической AABB описано относительно родительской AABB, то преимущество имеет то, что, если большая группа единиц сохраняет свое формирование, вам не нужно обновлять меньшие AABB, поскольку они сохраняют одинаковые относительные позиции. Конечно, вращение пласта может вызвать много обновлений, в этом случае использование других ограничивающих объемов, таких как сферы или ориентированные ограничивающие рамки (OBB), может быть более эффективным.

Локально-чувствительные хеш-таблицы эффективно дают только приблизительные решения, поэтому я бы не стал их беспокоить.

Что бы я сделал? Вероятно, я бы начал с простой сетки, и когда мне это понадобится, я обновлю его до квадродерева и, если мне это понадобится, я объединю его с ограничивающей иерархией томов под некоторым порогом: квадри хорошо работают на больших масштаб, относительные ограничивающие объемы хорошо работают в небольших масштабах. Делать это постепенно, не придется тратить час с самого начала , чтобы получить оптимальную структуру данных немедленно .


Спасибо! Я не слышал об иерархических AABB и локально-чувствительных хеш-таблицах, я посмотрю их в будущем. На данный момент я собираюсь с простой сеткой и буду расширяться, если вы упомянули. :)
Nairou

4

Lærne предлагает отличные предложения, но я бы также предложил динамическое ограничивающее дерево томов AABB. Концептуально динамическое дерево ограничивающих томов поддерживает сбалансированное дерево узлов, которое можно в любое время запросить для близких элементов, передав AABB и получив перекрывающуюся пару. Дерево не перестраивается каждый кадр. Вместо этого AABB каждого узла слегка раздувается, когда помещается в дерево, и дерево перестраивается только тогда, когда фактическая AABB узла больше не содержится в надутой AABB. Я использую его в своем физическом движке, и он прекрасно работает.

Исходный код Box2D имеет отличную реализацию.

https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Collision/b2DynamicTree.h

Вот хороший обзор их реализации:

http://www.randygaul.net/2013/08/06/dynamic-aabb-tree/


Да, это более или менее то, что я имел в виду под иерархической AABB, я был не очень точен. Да, и в RTSes подразделения часто мобильны, но в формациях. Таким образом, использование координат относительно родительского узла AABB может быть достаточно эффективным с допустимой погрешностью «надувания».
Lærne

Не могли бы вы обновить ссылку на код Google?
Коленда
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.