На правах рекламы:
ISSN 0236-235X (P)
ISSN 2311-2735 (E)

Авторитетность издания

ВАК - К1
RSCI, ядро РИНЦ

Добавить в закладки

Следующий номер на сайте

4
Ожидается:
09 Сентября 2024

Ускорение модификации пространственных деревьев методом оболочек

The acceleration of spatial trees update by shells method
Статья опубликована в выпуске журнала № 4 за 2011 год. [ на стр. 151 – 155 ]
Аннотация:Рассматривается применение метода оболочек объектов для ускорения изменения пространственных структур на примере KD-дерева. Подход применяется для визуализации динамических сцен методом трассировки лучей. Результаты экспериментов показали снижение временных задержек при визуализации по сравнению с методами, исполь-зующими полное перестроение дерева.
Abstract:The method of objects' shells was applied for acceleration of spatial structures update based on the KD-tree. The method was used for dynamic scene visualization by raytracing technique. The results show the significantly reduced time on scene updates compared with method based on fully reconstruction.
Авторы: Коробицын В.В. (korobits@rambler.ru) - Омский государственный университет им. Ф.М. Достоевского, кандидат физико-математических наук, Сибара С.А. (Sib.Sergey@gmail.com) - Омский государственный университет им. Ф.М. Достоевского
Ключевые слова: ускоряющие структуры данных, kd-дерево, метод оболочек, динамическая трассировка лучей
Keywords: accelerating data structures, KD-tree, shells method, dynamic ray tracing
Количество просмотров: 8027
Версия для печати
Выпуск в формате PDF (5.83Мб)
Скачать обложку в формате PDF (1.28Мб)

Размер шрифта:       Шрифт:

Использование метода трассировки лучей вместо растрирования для визуализации сцен становится все более актуальным. Данный метод эффективно применяется для фотореалистичной визуализации статических сцен. Предпринимаются попытки использовать его и для динамичных сцен.

Уже существуют разработки, где трассировка статических сцен из сотен тысяч примитивов с использованием GPU достигает 50 fps и более. Чтобы достичь такой скорости, некоторые возможности трассировки лучей игнорируются, вследствие чего реалистичность сцены падает, но получаемое качество изображений в большинстве случаев вполне устраивает.

Столь высокая производительность достигается прежде всего за счет хранения сцены в пространственной структуре. При трассировке эта структура позволяет ускорить поиск пересечений поверхностей объектов с лучом.

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

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

Описание алгоритма

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

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

Определение оболочки изменяемого объекта. Оболочка объекта создается при добавлении объекта на сцену и изменяется при его деформации. Наиболее простой вариант создания оболочки – поиск наименьших и наибольших координат x, y, z среди всех вершин примитивов, содержащихся в объекте. В итоге будут получены координаты двух точек, ограничивающих объект бокса.

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

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

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

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

Но так как хранение либо подсчет числа примитивов в каждом узле требует значительных расходов, достаточно ограничиться размерами оболочек.

При введении дополнительного условия продолжения поиска появляется задача распределения примитивов оболочки по дочерним узлам. Есть два варианта ее решения:

1) присвоение примитивов, находящихся в оболочке, обоим узлам;

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

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

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

В ходе поиска узлов дерева возможны три варианта для любой его ветви:

-      узел является листом;

-      оболочка объекта расположена одновременно в правой и в левой частях текущего узла;

-      оболочка объекта расположена в несуществующей части текущего узла.

Пример процесса поиска наименьшего участка дерева, целиком содержащего оболочку объекта, приведен на рисунке 1. Стрелки показывают, что у текущего узла есть дочерние. Отсутствие буквы L или R означает отсутствие наследника. Закрашенные прямоугольники – части оболочки искомого объекта. Полосы, делящие их на две части, – оси, по которым происходит деление узлов (определены при построении дерева и не зависят от процесса поиска).

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

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

-      указатель на текущий узел;

-      уровень текущего узла в дереве;

-      бокс текущей части объекта;

-      бокс текущего узла;

-      указатель на массив примитивов текущей части бокса;

-      переменную, показывающую, что узел является левосторонним или правосторонним.

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

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

Выполнение операций над найденными узлами. Суть этапа состоит в изменении структуры пространственного дерева. При этом удаляются поддеревья, попавшие в изменяемую область дерева сцены, и затем создаются новые с учетом добавленного/удаленного объекта. Описываемые здесь алгоритмы выполняются для каждого узла в списке, полученном на втором этапе.

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

-      подсчитывается количество примитивов в узле;

-      создается пустой список, который будет хранить примитивы для создания нового поддерева;

-      сравнивается номер каждого примитива в списке узла со всеми элементами в списке примитивов объекта; эту задачу можно упростить, если в каждом примитиве хранить номер объекта, которому он принадлежит, либо в объекте хранить номера первого и последнего примитивов, предлежащих ему;

-      если примитив в объекте отсутствует, он добавляется в созданный на втором шаге список;

-      если новый список не пустой, он присваивается текущему узлу, иначе текущий узел удаляется;

-      если на предыдущем шаге узел удаляется, далее выполняется восходящее удаление, иначе – восходящее присваивание.

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

Во второй ситуации, когда изменяется поддерево, следует:

-      выполнить рекурсивный поиск в поддереве (в результате получается список примитивов всех найденных узлов, при этом пройденные узлы удаляются);

-      для полученного списка примитивов создать новое поддерево на месте старого.

При удалении объекта необходимо:

-      создать пустой список для дальнейшего добавления в него примитивов;

-      в текущем узле вызвать рекурсивную функцию обхода всех дочерних узлов;

-      в каждом конечном узле провести сравнение каждого его примитива со всеми примитивами в создаваемом списке;

-      выполнить сравнение с примитивами удаляемого объекта;

-      если примитив узла отсутствует и в создаваемом списке, и в удаляемом объекте, добавить его в создаваемый список.

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

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

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

При добавлении объекта создается новый дочерний узел для текущего узла и вызывается функция создания новых узлов.

Восходящие удаление и присваивание. Данные операции выполняются после обработки ситуаций 1 и 2 в алгоритме удаления объекта с целью оптимизации структуры изменяемой части дерева. Здесь необходим стек пройденных родительских узлов, полученный на втором этапе.

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

Для родительского узла выполняются следующие действия:

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

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

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

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

Оптимизация: работа с группами оболочек

Подпись:  а) б)Рис. 2. Графики зависимости времени визуализации сцены а) от количества динамических примитивов, б) от количества статических примитивов

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

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

Если объекты располагаются недостаточно близко, они все равно могут иметь общие изменяемые поддеревья в сцене. Поэтому, чтобы свести к минимуму изменения в дереве, необходимо все полученные массивы отсортировать по размеру оболочек.

Результаты экспериментов

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

В первом тесте определялась зависимость времени изменения сцены от числа динамических примитивов (рис. 2а). По горизонтальной оси было отложено число перемещающихся примитивов, по вертикальной – время визуализации сцены с учетом построения или модификации пространственного дерева. Помимо движущихся примитивов, на сцене присутствовало 10 000 статических примитивов. Из графиков видно, что при количестве движущихся примитивов, меньшем 3 500 (что составляет приблизительно четверть сцены), использование предложенного подхода эффективнее, чем полное перестроение дерева.

Во втором тесте определялась зависимость времени изменения сцены от числа статических примитивов (рис. 2б). По горизонтальной оси отложено число статических примитивов, по вертикальной – время визуализации. Помимо статических примитивов, на сцене присутствует 500 движущихся примитивов. Из графиков видно, что число статических примитивов незначительно влияет на время изменения дерева. Стоит учитывать, что увеличение числа статических примитивов увеличивает время трассировки, что также сказывается на графике «изменение дерева и трассировка».

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

Литература

1.     Bikker J. RayTracing: Theory & Implementation. 2005. URL: http://www.devmaster.net/articles /raytracing_series/ part7. php (дата обращения: 2.06.2010).

2.     State of the Art in Ray Tracing Animated Scenes. In State of the Art Report / WALD I., [et al.] // Proceedings of the Eurographics Symposium on Rendering. 2007.

3.     Yoon S.-E., Curtis S., Manocha D. Ray Tracing Dynamic Scenes using Selective Restructuring // Proceedings of the Eurographics Symposium on Rendering. 2007.

4.     Фролов В. Ray-tracing.ru: 3d движок, трассировка лучей в реальном времени, интерактивная трассировка лучей. URL: http://www.ray-tracing.ru (дата обращения: 17.06.2010).


Постоянный адрес статьи:
http://swsys.ru/index.php?page=article&id=2937&lang=
Версия для печати
Выпуск в формате PDF (5.83Мб)
Скачать обложку в формате PDF (1.28Мб)
Статья опубликована в выпуске журнала № 4 за 2011 год. [ на стр. 151 – 155 ]

Назад, к списку статей