Яку структуру даних слід використовувати для представлення воксельної місцевості?


18

За даними сторінки Вікіпедії про вокселів, "[...] положення вокселя виводиться виходячи з його положення відносно інших вокселів (тобто його положення в структурі даних, що утворює єдине об'ємне зображення)".

Як слід реалізувати таку структуру даних? Я думав про октре, але мені цікаво, чи є ще щось, про що я ніколи не чув.


1
Це дещо важке запитання, оскільки це дуже залежить від того, які саме дані потребують ваші воксельні дані. Такі речі, як повнота вокселя, як він виглядає тощо, будуть досить залежні від того, що ви робите. По-друге, структура даних повинна надавати високошвидкісний доступ для маніпулювання даними в режимі реального часу та подальшого оновлення. Як зберегти низьку структуру пам’яті на воксель та швидкий швидкий доступ / маніпуляції даними - це в основному ключові технічні проблеми, які є досить специфічні наміри при роботі з воксельними движками. Не відповідь, так коментар.
Джеймс

Відповіді:


14

Спочатку. Давайте запишемо, що ми знаємо про кожен воксель:

voxel = (x, y, z, color) // or some other information

Загальне зберігання

Загальний спосіб просто такий:

set of voxels = set of (x,y,z, color)

Зауважте, що триплет (x, y, z) ідентифікує кожен воксель однозначно, оскільки воксель є точковою у просторі, і немає ніякого способу, щоб дві точки займали одне місце (я вважаю, що ми говоримо про статичні дані про вокселі).

Це повинно бути добре для простих даних. Але це аж ніяк не швидка структура даних.

Візуалізація AFAIK здійснюється алгоритмом сканування. Стаття Tom's Hardware про вокселів має зображення алгоритму сканування .

Швидкий пошук

Якщо потрібен швидкий пошук, то найшвидшою структурою даних для пошуку є хеш (він же масив, карта ...). Тож вам доведеться з неї робити хеш. Отже, наївно ми хочемо просто найшвидший спосіб отримати довільний елемент:

array [x][y][z] of (color)
  • Це має O (1) для пошуку вокселя за координатами x, y, z.

  • Проблема полягає в тому, що вимоги до простору - це O (D ^ 3), де D - діапазон кожного числа x, y і z (забудьте реальне число, оскільки якби вони були Chars, які мають діапазон 256 значень, було б 256 ^ 3 = 2 ^ 24 == 16 777 216 елементів у масиві).

Але це залежить від того, що ви хочете зробити з вокселями. Якщо візуалізація - це те, що ви хочете, то, ймовірно, це масив, який ви хочете. Але проблема зберігання все ще залишається ...

Якщо зберігання - проблема

Одним із методів є використання стиснення RLE в масиві. Уявіть фрагмент вокселів (набір вокселів, де вокселі мають одне постійне значення координат .... як площина, де, наприклад, z = 13). Такий фрагмент вокселів виглядав би як простий малюнок у MSPaint . Модель Voxel, я б сказав, зазвичай займає частку всіх можливих місць (D ^ 3 простір усіх можливих вокселів). Я вважаю, що "взяти пару з триплета координат і стиснути осі, що залишилися" зробив би трюк (наприклад, взяти [x] [y] і для кожного елемента стиснути всі вокселі на осі z в заданому x, y .. . повинно бути від 0 до декількох елементів, RLE тут буде чудово):

array [x][y] of RLE compressed z "lines" of voxel; each uncompressed voxel has color 

Іншим методом вирішення проблеми зберігання буде замість масиву, використовуючи структуру даних дерева:

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • Октре, як згадував Нік. Він повинен стискати вокселі. Octree має навіть гідну швидкість пошуку, я думаю, це якийсь O (log N), де N - кількість вокселів.
  • Octree повинен мати можливість пристойно зберігати дані про вокселі.

Якщо вокселі - це якась спрощена карта висоти, ви можете зберігати саме це. Або ви можете зберігати параметри для функції, яка генерує мапу висоти, а також процедурно генерувати її ...

І звичайно, ви можете поєднувати всі можливі підходи. Але не перестарайтеся, якщо ви не перевірите, чи працює ваш код, і не виміряєте, що він дійсно швидший (тому варто оптимізувати).

TL; DR

Окрім Octrees, це стиснення RLE з вокселями, google "voxlap", "ken silverman" ...

Ресурси

Існує перелік ресурсів та обговорення того, як зробити швидкий воксель-рендерір, включені документи та вихідний код .


1
"Якщо проблема зберігання": також ви можете використовувати VTC ( oss.sgi.com/projects/ogl-sample/registry/NV/… ) або стиснення
DXT

@KindDragon дякую за цю інформацію :) Це дуже гарна ідея.
користувач712092

Посилання на ресурс працює.
Єзекіїль

4

Є два різні аспекти структури даних, про які вони можуть говорити.

Структури масиву

Коли ви посилаєтесь на елемент масиву будь-якої кількості вимірів, врахуйте, що сам масив після передачі індексів (напр. myArray[4][6][15]) Знає, що знаходиться в цьому місці. Якщо те, що знаходиться в цьому місці, - це воксель, то йому не потрібно додатково записувати його власні координати x, y та z - масив, що містить воксель, вказує, що це місце розташування світу, неявно засноване на його місці, індексованому масивом.

Причина цього хороша в тому, що арифметика вказівника, що використовується для такого типу доступу до масиву, по своїй суті є швидкою і, загалом кажучи, дає основу для більшості швидких (часто називаються "рідними") масивів, що знаходяться на різних мовах. Недоліком цих масивів є те, що вони повинні мати елементи однакового розміру в байтах, щоб вказана арифметика вказівника була застосовною.

Жовтень

(Я зауважу цю секунду, тому що це менш ймовірно, про що йдеться у вікіпедії, і для реалізації вокселів не потрібно використання октрисів, хоча майже всі сучасні використовують октрей.)

Кореневий вузол octree - це єдиний нерозділений куб. Наведемо приклад. Скажіть, корінь вашої октриси, сам центр куба, знаходиться {0, 0, 0}в просторі 3D. Після того, як ви почнете розміщувати об’єкти всередині цього простору (читайте: більше одного об’єкта), саме час далі поділити октрису. Тут ви розділите на 8 ( окт- ), розрізавши їх за допомогою 3 площин, причому ці площини є площинами xy, xz та yz. Ваш оригінальний куб тепер точно містить 8 менших кубів. Кожен з цих підвузлів розміщується як зміщення від центрального батьківського куба . Тобто, наприклад, що куб, що лежить у позитивному октанті сизи, мав би зміститися від батьківського / містить кубного центру рівно{root.width / 4, root.height / 4, root.depth / 4}. Замість того, щоб задавати абсолютне положення для кожного підмережа, більш логічним є сенс розглядати батьківський вузол як джерело його дитячого простору. Це так само, як працюють графіки сцен.

Досить просто це побачити на 2D-малюнку, де ви намалюєте квадрат і поділили його на 4 рівні області. Якби, як наш кореневий вузол octree, вважався центром материнського квадрата {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.


Спасибі за вашу відповідь. У моєму випадку деякі великі ділянки місцевості будуть зроблені з одного типу вокселів, тому я думав про октриси (великий шматок не потрібно було б розділяти). Однак я дам 3D-масив, оскільки він виглядає більш простим у виконанні. Я впевнений, що мені вдасться достатньо абстрагувати деталі реалізації мого класу terrain, щоб переключити реалізацію не так складно, якщо виникне потреба.
pwny

Ласкаво просимо. Я, безумовно, запропонував би заглянути в октриси, насправді їх важко зрозуміти. Але так, ваш підхід має сенс наразі, безумовно, варто зробити початкове прототипування за допомогою 3D-масиву.
Інженер

У подальшому читанні, хорошу дискусію щодо впровадження октрисів, включаючи кілька корисних посилань, можна знайти в статті Intel Extension STL for Games від Intel .
Мартін Фут

1

Ви можете використовувати RLE. Але ви можете використовувати SVO (Sparse Voxel Octree), id Tech 6 використовує SVO. SVO - це технологія 3D-рендерингу комп'ютерної графіки за допомогою підключення радіомовлення або іноді підходу трасування променів у поданні даних octree.

Метод дещо відрізняється, але, як правило, покладається на формування та обробку корпусу точок (розріджених вокселів), які є видимими або можуть бути видимими, враховуючи роздільну здатність та розмір екрана.

Використовуйте радіомовлення, оскільки це швидше.


0

Як правило, ви можете уникнути 3D-структури даних для місцевості. Ви можете використовувати замість карти висоти . Це може бути дуже дешево та ефективно вимкнено під час виконання. Зазвичай, за моїм досвідом, слід відстежувати мінімальну висоту, яку потрібно візуалізувати в кожному стовпчику, а також іноді кути старт-стоп-вершини, щоб ви могли також зменшити стовпчики задньої поверхні.

Ось я давно зробив: http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash

Якщо на місцевості є невелика кількість нависів або печер або інших функцій, які не можна представити на карті висоти, то ви можете мати отвори у вашій карті висоти та мати альтернативне представлення, наприклад, справжні об’єкти 3D вокселів, які заповнюють лише ті локалізовані місця, де витрачається час виконання є гарантованим.

Рідкі представлення вокселів варті того, коли у вас є великі справжні світи вокселів. Джон Кармак розмовляє з ними вже останні кілька років ...


Я думав і про карти висоти, але пара речей відігнала мене від них. Річ у тім, що в моєму випадку місцевість не є справді великою, або дуже складною (думаю, лабіринт типу лабіринту, дуже декартовий). Я також хотів би, щоб частина місцевості була зруйнована або дозволяла користувачеві впливати на місцевість через будівництво. Це може призвести до того, що гравець створить "тунелі" на місцевості, які здаються складнішими для відображення на карті висоти.
pwny
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.