Согласно странице Википедии о вокселях, «[...] положение вокселя определяется на основе его положения относительно других вокселей (т. Е. Его положения в структуре данных, которая составляет одно объемное изображение)».
Как реализовать такую структуру данных? Я думал об октрее, но мне интересно, есть ли что-то еще, о чем я никогда не слышал.
Ответы:
Первый. Давайте напишем, что мы знаем о каждом вокселе:
Общее хранение
Общий способ таков:
Обратите внимание, что триплет (x, y, z) уникально идентифицирует каждый воксел, поскольку воксель - это точка в пространстве, и нет двух точек, занимающих одно место (я полагаю, мы говорим о статических данных вокселей).
Это должно быть хорошо для простых данных. Но это ни в коем случае не быстрая структура данных.
Рендеринг AFAIK осуществляется по алгоритму сканирования. Статья Tom's Hardware о вокселях содержит изображение алгоритма сканирования .
Быстрый поиск
Если требуется быстрый поиск, то самой быстрой структурой данных для поиска является хеш (он же массив, карта ...). Таким образом, вы должны сделать из этого хэш. Итак, наивно мы хотим просто самый быстрый способ получить произвольный элемент:
Это имеет O (1) для поиска вокселя по координатам x, y, z.
Проблема состоит в том, что его требования к пространству составляют O (D ^ 3), где D - диапазон каждого числа x, y и z (забудьте реальное число, поскольку, если бы они были символами с диапазоном 256 значений, было бы 256 ^ 3 = 2 ^ 24 == 16 777 216 элементов в массиве).
Но это зависит от того, что вы хотите сделать с вокселями. Если рендеринг - это то, что вы хотите, то, вероятно, именно этот массив вам нужен. Но проблема хранения все еще остается ...
Если проблема в хранении
Одним из методов является использование сжатия RLE в массиве. Представьте себе фрагмент вокселей (набор вокселей, где вокселы имеют одно значение постоянной координаты ... например, плоскость, где z = 13). Такой кусок вокселей будет выглядеть как простой рисунок в MSPaint . Воксельная модель, я бы сказал, обычно занимает долю всех возможных мест (пространство D ^ 3 всех возможных вокселей). Я полагаю, что «взять пару из тройки координат и сжать оставшуюся ось» сделает свое дело (например, возьмите [x] [y] и для каждого элемента сожмите все вокселы на оси z при заданных x, y .. . должно быть от 0 до нескольких элементов, RLE будет хорошо здесь):
Другой метод решения проблемы хранения - вместо массива использовать древовидную структуру данных:
Если воксели - это упрощенная карта высот, вы можете хранить только это. Или Вы можете сохранить параметры для функции, которая генерирует карту высот, иначе говоря, генерировать ее ...
И конечно Вы можете комбинировать все возможные подходы. Но не переусердствуйте, если только вы не проверите, что ваш код работает, и измерите, что он ДЕЙСТВИТЕЛЬНО быстрее (так что это стоит оптимизации).
TL; DR
Кроме Octrees - это сжатие RLE с вокселями, google "voxlap", "ken silverman" ...
Ресурсы
Существует список ресурсов и обсуждение того, как сделать быстрый рендеринг вокселей, включает в себя документы и исходный код .
источник
Есть два разных аспекта структуры данных, о которых они могут говорить.
Структуры массивов
Когда вы ссылаетесь на элемент массива любого числа измерений, учтите, что сам массив, как только вы передадите индексы (например
myArray[4][6][15]
), знает, что находится в этом месте. Если то, что находится в этом месте, является вокселем, то этому вокселю не нужно дополнительно записывать свои собственные координаты x, y и z - массив, содержащий воксель, неявно указывает свое местоположение в мире на основе его индексации по массиву.Это хорошо по той причине, что арифметика указателей, используемая для такого типа доступа к массивам, по своей природе является быстрой и, вообще говоря, обеспечивает основу для большинства быстрых (часто называемых «родными») массивов, найденных в разных языках. Недостатком этих массивов является то, что они должны иметь элементы одинакового размера в байтах, чтобы указанная арифметика указателя была применимой.
Octrees
(Я отмечаю это второе, потому что это менее вероятно, что то, на что ссылается Википедия, и реализации вокселей не требуют использования октодеревьев, хотя почти все современные используют октуды.)
Корневой узел октодерева - это отдельный неделимый куб. Давайте создадим пример. Скажем, корень вашей октры, самый центр куба, находится
{0, 0, 0}
в трехмерном пространстве. Как только вы начинаете размещать объекты в этом пространстве (читай: более одного объекта), настало время разделить октре далее. Здесь вы делите на 8 ( окт ), разрезая его, используя 3 плоскости, причем эти плоскости являются плоскостями xy, xz и yz. Ваш оригинальный куб теперь содержит ровно 8 кубиков меньшего размера. Каждый из этих подузлов позиционируется как смещение от центрального родительского куба . То есть, например, куб, лежащий в положительном октанте xyz, будет иметь смещение от центра родительского / содержащего куба точно{root.width / 4, root.height / 4, root.depth / 4}
, Вместо того, чтобы указывать абсолютную позицию для каждого подузла, логичнее рассматривать родительский узел как источник его дочернего пространства. Это то же самое, что графы сцены работают.Достаточно просто увидеть это на двухмерном чертеже, где вы рисуете квадрат и подразделяете его на 4 равные области. Если бы, как и в случае с нашим корневым узлом, центром родительского квадрата считались
{0, 0}
, то 4 центра дочерних квадратов{root.width / 4, root.height / 4}
,{-root.width / 4, root.height / 4}
,{root.width / 4, -root.height / 4}
,{-root.width / 4, -root.height / 4}
... По отношению к родителю - тот же принцип, что и в 3D.
источник
Вы можете использовать RLE. Но вы можете использовать SVO (Sparse Voxel Octree), id Tech 6 использует SVO. SVO - это технология рендеринга трехмерной компьютерной графики, использующая подход с лучевой передачей или иногда с трассировкой лучей в представлении данных октодерева.
Техника несколько варьируется, но в основном основывается на генерации и обработке корпуса точек (разреженных вокселей), которые видны или могут быть видны, учитывая разрешение и размер экрана.
Используйте raycasting, потому что это быстрее.
источник
Как правило, вы можете избежать 3D-структуры данных для местности. Вместо этого вы можете использовать карту высот . Это может быть очень дешево и эффективно вокселизировано во время выполнения. Обычно (по моему опыту) платит за отслеживание минимальной высоты, которую вам нужно визуализировать в каждом столбце, а также иногда углов начала-остановки-верха, чтобы вы также могли отбрасывать столбцы с задним торцом.
Вот один, который я сделал очень давно: http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash
Если у вашего ландшафта есть небольшое количество выступов или пещер или других объектов, которые не могут быть представлены картой высот, вы можете иметь отверстия в карте высот и иметь альтернативное представление, например, настоящие трехмерные объекты вокселей, которые заполняют только те локализованные места, где затраты времени выполнения гарантировано.
Разреженные воксельные представления того стоят, когда у вас большие настоящие воксельные миры. Джон Кармак говорит их последние несколько лет ...
источник