Похоже, вы хотите узнать о деревьях!
И я серьезно, если вы в настоящее время просматриваете массив всех своих кубов, то вам действительно следует изучить различные структуры пространственных данных. В этом случае лучший способ переосмыслить свой кубический мир - это дерево.
Прежде чем мы рассмотрим причины, давайте подумаем о нашей проблеме. Мы ищем решение, где за минимальную стоимость мы можем получить список соседних кубов, с которыми может столкнуться игрок. Этот список должен быть как можно меньше, но точнее.
Теперь, чтобы определить эту зону, нам нужно отобразить координатное пространство нашего игрока в координатное пространство карты куба; то есть нам нужно отобразить положение игрока с плавающей запятой на дискретный индекс многомерного массива кубов (примерная нотация может быть world[31][31][31]
, то есть точная середина для многомерного массива 64 * 64 * 64).
Мы могли бы просто вычислить окружающие блоки, используя ту же самую дискретную индексацию, возможно, выбирая только близлежащие кубы, но это все еще требует постоянного пересчета и не учитывает какие-либо объекты, которые не являются дискретными в размещении (то есть могут не отображаться на куб карта).
Идеальная ситуация - это набор блоков, которые содержат наши наборы кубов для определенных разделов нашей карты кубов, разделенные поровну, поэтому вместо пересчета окружающей области мы просто перемещаемся в эти зоны и из них . Для любого нетривиального вычисления, хранение наших данных таким образом может устранить итерацию всех кубов и только этих отдельных наборов, которые находятся рядом.
Вопрос в том, как мы это реализуем?
Для мира 64 * 64 * 64 представьте, что он разбит на 8 * 8 * 8 зон . Это означает, что в вашем мире у вас будет 8 зон на ось (X, Y, Z). Каждая из этих зон будет содержать 8 кубов, которые можно легко найти с помощью этого нового упрощенного индекса.
Если вам нужно выполнить операцию с набором соседних кубов, вместо того, чтобы выполнять итерации каждого куба в вашем мире, вы можете просто выполнить итерацию по этим зонам , разбив максимальное число итераций от исходного 64 * 64 * 64 (262144) до всего 520 (8 * 8 * 8 + 8).
Теперь отойдите от этого мира зон и поместите зоны в большие суперзоны ; где каждая суперзона содержит 2 * 2 * 2 регулярных зоны . Поскольку ваш мир в настоящее время содержит 512 (8 * 8 * 8) зон , мы можем разбить 8 * 8 * 8 зон на 64 (4 * 4 * 4) суперзоны , разделив 8 зон на 2 зоны на суперзону . Применяя ту же логику сверху, это сломало бы максимальные итерации от 512 до 8, чтобы найти супер-зону ; а затем максимум 64, чтобы найти исходящую зону(всего макс. 72)! Вы можете видеть, как это уже экономит много итераций (262144: 72).
Я уверен, что теперь вы можете видеть, насколько полезны деревья. Каждая зона - это ветвь на дереве, и каждая суперзона является предыдущей ветвью. Вы просто пересекаете дерево, чтобы найти то, что вам нужно; используя меньшие наборы данных, чтобы минимизировать общую стоимость.
Диаграмма ниже должна помочь вам визуализировать концепцию. (изображение из Википедии: Octrees ):
Отказ от ответственности:
В идеальной конфигурации, описанной выше, где ваш воксельный мир уже расположен в многомерном массиве фиксированного размера, вы можете просто запросить позицию игрока, а затем проиндексировать окружающие блоки с затратами O (1)! (См. Объяснение Ольховского) Но это становится сложнее, когда вы начинаете считать, что ваш мир редко имеет фиксированный размер в игре на вокселях; и вам может потребоваться, чтобы ваша структура данных могла загружать целые суперзоны с жесткого диска в память. В отличие от многомерного массива фиксированного размера, деревья легко позволяют это, не тратя слишком много времени на комбинаторные алгоритмы.