Проблема с огромными объектами в дереве квадрантов

Допустим, у меня есть круглые объекты. Каждый объект имеет диаметр 64 пикселя.

Ячейки моего четырехъядерного дерева имеют размер, скажем, 96x96 пикселей.

Все будет хорошо и хорошо работает, когда я проверю столкновение из ячейки, в которой находится круг, + все его соседние ячейки.

НО что, если у меня есть один круг диаметром 512 пикселей? Это охватило бы много ячеек, и поэтому это было бы проблемой при проверке только соседних ячеек. Но я не могу изменять размер сетки четырехъядерного дерева каждый раз, когда в дерево вставляется объект гораздо большего размера...


person Napoleon    schedule 07.08.2011    source источник
comment
Я не вижу здесь дерева. Вы описываете сетку фиксированного размера. Дерево квадрантов должно содержать квадраты разных размеров, а количество и размеры ячеек предполагается динамически изменяться при добавлении объектов в сцену.   -  person n. 1.8e9-where's-my-share m.    schedule 07.08.2011
comment
н.м.: Можете ли вы уточнить? Как это может быть так динамично?   -  person Gigamegs    schedule 08.08.2011


Ответы (3)


Это интересная проблема. Может быть, вы можете расширить узел или ячейку с информацией о высоте дерева? Если у вас есть объект больше, чем самая маленькая ячейка, вложенная в него с высотой дерева. Это то, что делает приложение карты, такое как карты Google или Bing.

Вот ссылка на похожее решение: http://www.gamedev.net/topic/588426-2d-quadtree-collision---variety-in-size. Я перепутал скрин с квадриком. Вы можете проверить столкновение с помощью простого отказа.

person Gigamegs    schedule 07.08.2011
comment
Итак, я должен хранить объект на узле выше, когда он, например, полностью перекрывает размер ячейки? Или помещать объект только в ту ячейку, в которую он полностью помещается, вообще не перекрывая никаких границ? - person Napoleon; 07.08.2011
comment
Я не уверен, потому что у вас есть движущиеся объекты. Моя идея заключается в том, что если вы храните более крупные объекты на другой высоте, вы можете использовать эту информацию для получения реальных границ объекта. Я не уверен, как вы можете перевести это в экранный адрес? В моем дереве я могу использовать это, потому что я храню все объекты в макс. высота, и когда я не хочу видеть все объекты, я путешествую по корню. - person Gigamegs; 07.08.2011

Вместо того, чтобы помещать объекты в одну ячейку, помещайте их во все ячейки, с которыми они сталкиваются. Таким образом, вы можете просто проверить каждую ячейку по отдельности. Используйте указатели на объект, чтобы не создавать копии. Кроме того, вам нужно сделать это только с узлами-выходами, поэтому нет необходимости объединять данные, содержащиеся в более высоких узлах, с более низкими.

person Bozemoto    schedule 11.12.2011

Обзор

Во время поиска, начиная с самых больших объектов в первую очередь...

Протестируйте Object.Position.X против QuadTreeNode.Centre.X, а также

проверить Object.Position.Y на QuadTreeNode.Centre.Y;

... Затем, принимая абсолютное значение разницы, рассматривайте объект как лежащий в пределах определенного дочернего узла, когда абсолютное значение НЕ превышает радиус объекта...

... то есть, когда какая-то часть объекта вторгается в этот квадрат :)

То же самое можно сделать с AABB (Ограничительные рамки, выровненные по осям).

Единственная реальная оговорка заключается в том, что ОЧЕНЬ большие объекты, занимающие большую часть экрана, заставят искать все дерево. В этих случаях может потребоваться другой подход.

Конечно, это заботится только об объекте, против которого тестируется все остальное. Чтобы убедиться, что все другие крупные объекты в мире правильно идентифицированы, вам нужно будет немного изменить свое дерево квадрантов...

Использовать несколько образов

В этом варианте QuadTree мы размещаем объекты ТОЛЬКО в конечных узлах QuadTree в качестве указателей. Более крупные объекты могут появляться в нескольких листовых узлах.

Поскольку некоторые объекты имеют несколько появлений в дереве, нам нужен способ избежать их, как только они уже были протестированы.

So...

Простой логический флаг WasHit позволяет избежать многократных проверок одного и того же объекта в проходе теста на попадание... а «очистку» можно выполнить для всех «попадающих» объектов, чтобы они были готовы к следующему тесту.

Хотя это и имеет смысл, это расточительно, если проводить тесты на попадание «все против всех».

Итак... Немного поумнев, мы можем вообще избежать какой-либо очистки, используя указатель 'ptrLastObjectTestedAgainst' внутри каждого объекта в сцене. Это позволяет избежать повторного тестирования одних и тех же объектов в этом запуске (указатель устанавливается после первого обнаружения)

Он не требует сброса при тестировании нового объекта на фоне сцены (новый объект имеет другое значение указателя, чем последний). Это позволяет избежать необходимости сбрасывать указатель, как если бы вы использовали простой логический флаг.

Я использовал последний подход в сценах с совершенно разными размерами объектов, и он работал хорошо.

Эластичные деревья QuadTree

Я также использовал «эластичный» QuadTree. По сути, вы устанавливаете ограничение на количество элементов, которые ИДЕАЛЬНО могут поместиться в каждом QuadTreeNode, но, в отличие от стандартного QuadTree, вы позволяете коду переопределять это ограничение в определенных случаях.

Основное правило здесь заключается в том, что объект НЕ может быть помещен в узел, который не может его удерживать ПОЛНОСТЬЮ... с верхним узлом, ловящим любые объекты, которые больше экрана.

Таким образом, небольшие объекты будут продолжать «проваливаться», образуя обычное QuadTree, но большие объекты не всегда будут проваливаться до конечного узла, а вместо этого будут расширять узел, который последним соответствовал им.

Думайте о нелистовых узлах как о «просеивании» объектов, когда они падают вниз по дереву.

Это оказывается очень эффективным выбором для многих сценариев :)

Заключение

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

Поэтому не просто учитесь применять алгоритмы... учитесь из этих алгоритмов и применяйте сами принципы новыми и подходящими способами. Это НЕ единственные инструменты, и они не обязательно лучше всего подходят для вашего приложения.

Надеюсь, некоторые из этих идей помогли.

person Gary C    schedule 27.06.2021