Пересечение Ray-Mesh или реализация дерева AABB на C++ с небольшими накладными расходами?

Можете ли вы порекомендовать мне...

  • либо проверенная легкая реализация C/C++ дерева AABB?
  • или, как вариант, другую эффективную структуру данных, плюс легковесную реализацию на C/C++, чтобы решить проблему пересечения большого количества лучей с большим количеством треугольников?

«Большое число» означает несколько сотен тысяч как для лучей, так и для треугольников.

Я знаю, что деревья AABB являются частью библиотеки CGAL и, возможно, библиотек игровой физики, таких как Bullet. Однако мне не нужны накладные расходы на огромную дополнительную библиотеку в моем проекте. В идеале я хотел бы использовать небольшую реализацию шаблона только для заголовка плавающего типа. Я бы также выбрал что-то с кучей файлов CPP, если они легко интегрируются в мой проект. Зависимость от boost в порядке.

Да, я гуглил, но безуспешно.

Я должен упомянуть, что мой контекст приложения — это обработка сетки, а не рендеринг. В двух словах, я переношу топологию эталонной сетки в геометрию сетки из 3D-скана. Я стреляю лучами из вершин и по нормалям эталонной сетки в сторону 3D-скана, и мне нужно восстановить пересечение этих лучей со сканом.

Изменить

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

введите здесь описание изображения


person DCS    schedule 08.02.2013    source источник
comment
Это в помещении, на улице, CAD, FPS? Является ли геометрия динамической или статической? Какой процент полигонов виден? Это для рендеринга из одной точки (или нескольких точек == теневой буфер) или множества точек (излучение)?   -  person Aki Suihkonen    schedule 08.02.2013
comment
Контекст моего приложения — это обработка сетки, а не рендеринг. В частности, я переношу топологию эталонной сетки в геометрию сетки из 3D-скана. Я снимаю лучи вдоль нормалей эталонной сетки по направлению к 3D-скану, и мне нужно восстановить пересечение этих лучей со сканом. Вопросы наглядности к этой проблеме не относятся. Геометрия статична. Лучи снимаются из множества точек (хотя это не имеет никакого отношения к рендерингу, как указано выше).   -  person DCS    schedule 08.02.2013
comment
Как насчет октодеревьев? Они достаточно просты в реализации.   -  person Bartek Banachewicz    schedule 15.02.2013
comment
@BartekBanachewicz: Я думаю, что проблема с октодеревьями для хранения треугольников заключается в том, что треугольники перекрываются, а ячейки октодерева — нет, или я ошибаюсь? Я почти уверен, что ячейки дерева AABB (то есть ограничивающие рамки) действительно перекрываются, и поэтому они используются для таких задач.   -  person DCS    schedule 15.02.2013
comment
Разве вы не можете поместить ссылку на тот же треугольник в ячейку листа ›1 октодерева?   -  person Pete    schedule 22.02.2013


Ответы (3)


Хотя этот код немного устарел и использует SDK 3DS Max, он дает довольно хорошую древовидную систему для деформаций столкновения объектов в C++. С первого взгляда не скажешь, это Quad-tree, AABB-tree или даже OBB-tree (комментарии тоже немного скудны).

http://www.max3dstuff.com/max4/objectDeform/help.html

Это потребует перевода из Max в вашу собственную систему, но это может стоить затраченных усилий.

person Robert Templeton    schedule 03.03.2013
comment
+1 за первый ответ, указывающий на код, связанный с пересечением! Я посмотрю на это. - person DCS; 04.03.2013

Попробуйте библиотеку ANN: http://www.cs.umd.edu/~mount/ANN/

Это «приблизительные ближайшие соседи». Я знаю, вы ищете что-то немного другое, но вот как вы можете использовать это, чтобы ускорить обработку данных:

  1. Подача точек в ANN.
  2. Запросите выбираемый пользователем (подумайте об этом как о «ручке для каждой сетки») радиус вокруг каждой вершины, из которой вы хотите провести луч, и найдите вершины сетки, которые находятся в пределах диапазона.
  3. Выберите только те треугольники, которые находятся в пределах этого диапазона, и проведите луч по нормали, чтобы найти нужный.

Разумно выбрав радиус поиска, вы обязательно получите значительное ускорение без ущерба для точности.

person Rahul Banerjee    schedule 19.02.2013
comment
У вас была возможность посмотреть на ANN? Я должен добавить, что эта библиотека не является реентерабельной. - person Rahul Banerjee; 20.02.2013
comment
Извините за поздний ответ, я в командировке. Я знаю ANN (и другие библиотеки для задач ближайшего соседа). Проблема в том, что поиск ближайшего соседа может быть хорошей эвристикой для пересечения сетки лучей, но он не гарантирует правильный ответ во всех случаях (как это делает дерево AABB). Бывают случаи, когда вершины правильного пересекаемого треугольника не входят в число ближайших соседей исходной вершины. Как указано в моем комментарии к Аки Суихконену, представьте себе, что луч просто проходит через сетку, а затем попадает в совершенно другое место. Кроме того, радиус может быть сложно определить. - person DCS; 20.02.2013
comment
Я отредактировал вопрос, добавив иллюстрацию проблем, упомянутых в комментарии выше. - person DCS; 20.02.2013
comment
Спасибо за иллюстрацию этих угловых (буквально!) случаев. Я понимаю, почему это сложная проблема. Структура ускорения кажется вашим лучшим выбором. - person Rahul Banerjee; 22.02.2013

Если нет требований в реальном времени, я бы сначала попробовал грубую силу.

Тесты 1M * 1M ray->triangle не должны занимать больше нескольких минут (на процессоре).

Если это проблема, вторым лучшим решением будет ограничение области поиска путем вычисления графа смежности/отношения между треугольниками/полигонами в целевой сетке. После того, как первоначальная догадка не удалась, можно попробовать соседние треугольники. Это, конечно, зависит от отсутствия самоокклюзии/множества очков жизни. (что, я думаю, является одной из интерпретаций «видимость не относится к этой проблеме»).

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

Учитывая отзывы, можно рассмотреть еще один простой вариант — разделение пространства на простую трехмерную сетку, где каждое измерение может быть разделено на гистограмму местоположений x/y/z или даже регулярно.

  • Сетка 100 x 100 x 100 имеет очень управляемый размер 1e6 элементов.
  • максимальное количество кубов для посещения пропорционально диаметру (максимум 300)
  • Есть ~ 60000 крайних ячеек, что предполагает порядка 10 треугольников на ячейку.

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

person Aki Suihkonen    schedule 15.02.2013
comment
К сожалению, есть требования по времени. В противном случае я бы не беспокоился о структурах данных, не так ли? ;-) Топологии в порядке, но формы могут быть сложными. Отображение их на единичном кубе/сфере/цилиндре не сработает (уже пробовал). Поиск в окрестностях первого предположения может быть довольно далеким от пересечения сетки лучей — представьте себе, что луч просто проходит через ближайший треугольник к его началу, а затем попадает в совершенно другое место. На самом деле, дерево AABB является канонической структурой данных для этой задачи. Мне просто не хватает реализации, и я не решаюсь написать ее сам. - person DCS; 15.02.2013
comment
Предлагаемое вами решение с трехмерной сеткой интересно, но это почти определение дерева AABB, которое только добавляет идею иерархического разбиения. Если я реализую ваше решение, я очень близок к реализации дерева AABB, чего я хотел избежать, задав свой вопрос в духе отказа от повторной реализации колеса. Кроме того, вычисления пересечений могут быть неприятными в числовом отношении, что является еще одной причиной, по которой я предпочитаю проверенный код. Однако, учитывая полученные до сих пор отзывы, кажется вероятным, что готовой к использованию облегченной реализации деревьев AABB на C++ не существует. - person DCS; 21.02.2013