Я хочу знать приблизительную трехмерную позицию и трехмерную нормаль места столкновения между двумя трехмерными выпуклыми оболочками (A
против B
).
Процессор в скобках показывает относительное время процессора, необходимое в моей готовой программе.
Часть 1: Ранний выход (CPU 1%)
На первом этапе я использую очень дешевый алгоритм - теорема об отделении.
Например, я использую 15 осей для 2 кубов. (В реальных случаях формы являются более сложными.)
Если существует хотя бы одна ось, которая может разделяться, return "no-collide"
.
В противном случае сделайте следующую часть.
Часть 2: вершина против объема (процессор 10%)
- Проверьте каждую вершину
A
- находится ли она внутриB
- Проверьте каждую вершину
B
- находится ли она внутриA
Часть 3: Край против Края (ЦП> 20%)
Есть странный случай, например, https://gamedev.stackexchange.com/info/75437/collision-detection-3d-rectangles-using-sat. Я украл изображение оттуда: -
Таким образом, мне также нужен край против края.
- Для каждой пары ребер A & B (12 * 12 = 144 пар) найдите ближайшую точку на ребре
A
напротив ребраB
Проверьте, находится ли вершина внутриB
- (наоборот) Для каждой пары ребер B & A проверьте, находится ли такая вершина внутри
A
Вау, это много вычислений.
Однако это еще не конец.
проблема
-
Сообщаемая позиция столкновения не так точна (слева: текущее, справа: желание): -
Чтобы решить эту проблему, я подумал о создании новой выпуклой формы =
A intersect B
Существует несколько бесплатных библиотек C++ (например, OpenMesh), но я думаю, что это слишком дорого для процессора.
Обратите внимание, что мне не нужно, чтобы это было точно правильно. -
Он также иногда сообщает, что неправильно нормально (слева: текущее, справа: желание): -
^ Эта проблема может быть решена путем добавления проверки ребра (A) и грани (B), но это сделает обнаружение всех столкновений еще более дорогим.
Вопрос
Похоже, что распространенные алгоритмы в интернете (из которых я копирую) распознают только микрофункцию.
ИМХО, алгоритм вершин-объем/ребро-кромка фокусируется на топологии, а не на том факте, что обе фигуры являются сплошными объемами.
Какой алгоритм является более точным (1-й приоритет) и, возможно, дешевле?
Мой подход может быть неправильным на уровне фундамента.
Чтобы ускорить процесс, я уже провел некоторое сокращение, например, выбрал только пару ребер A и B, которые расположены близко друг к другу.
Рекомендации :-
-
Алгоритмы обнаружения столкновений между выпуклыми полигонами произвольного размера проверяют только наличие столкновения.
-
https://pybullet.org/Bullet/BulletFull/btBoxBoxDetector_8cpp_source.html: вдохновляющий полный код обнаружения коробок и коробок в библиотеке Bullet Physics - это трудно понять.
-
https://math.stackexchange.com/info/397413/determine-direction-of-minimum-overlap-of-convex-polygons Математический вопрос без ответа, который очень похож на этот.
Изменить (10 дней спустя)
Теперь я могу найти все пересекающиеся выпуклые точки (выпуклые изображены в виде розового треугольника/прямоугольника): -
Вот как я нахожу нормальное.
Для каждой разделяющей оси (все = 15 осей) я проецирую выпуклый розовый цвет на ось.
Ось, которая дает кратчайший диапазон проекционных расстояний, должна быть направлением нормали.
Мое вышеупомянутое предположение часто верно (например, слева), но иногда неправильно (например, справа).
Как улучшить это CPU-дешево?