19.09.2022 • C3D Modeler

Что нового в модуле Collision Detection?

В этой заметке мы хотим сосредоточиться на основных новинках модуля Детектора столкновений (Collision Detection) и продемонстрировать примеры его использования. Напоминаем, что данный компонент входит в состав геометрического ядра C3D Modeler.

Основной задачей детектора столкновений является быстрый поиск пересечений между объектами геометрической сцены. Более того, детектор столкновений позволяет:

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



За счет узкой направленности Детектора столкновений – только поиск соударений двух граней тел – разработчикам удалось очень сильно оптимизировать его работу:

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



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

Новые случаи детектирования. Вложения тел

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




Для исследования вложенности тел вызывается существующая функция, которая используется также и для поиска соударений тел.

// Поиск пересечения луча и тела
cdet_result MbCollisionDetectionUtility::CheckCollision( cdet_query & cdQuery );

При наличии вложения детектор выдает новый тип сообщения.

// Найдена пара вложенных тел
cdet_query::message::CDET_INCLUDED

Ниже представлен фрагмент кода (С++) с описанием каждого шага. Он демонстрирует работу с модулем Collision Detection при регистрации вложенности тел.


Предположим, что в сцене ранее созданы два твердых тела MbSolid.

MbSolid  & solid1;
MbSolid  & solid2;

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

MbPlacement3D & placement1;
MbPlacement3D & placement2;

Предположим и то, что ранее создан детектор столкновений.

MbCollisionDetectionUtility cdet;

Тогда необходимо добавить эти тела в детектор.

cdet.AddSolid( solid1, placement1 );
cdet.AddSolid( solid2, placement2 );

Затем необходимо запустить поиск столкновений.

cdet.CheckCollisions();

Если тела пересекаются, т.е., например, solid1 находится внутри solid2, то эта функция вернет CDET_RESULT_Intersected. Для того чтобы уточнить, содержится ли solid1 внутри solid2, необходимо уточнить запрос поиска для детектора.

Для этого необходимо вызвать поиск столкновений с запросом:

cdet.CheckCollisions( colQuery ); ,

где colQuery - это пользовательский запрос на поиск столкновений.

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

cback_res (*cback_func)( cdet_query *, message, cback_data & ); ,

где параметр message – это перечисление с возможными типами столкновений, одним из которых является cdet_query::CDET_INCLUDED;

параметр cback_data – это тип, содержащий первое и второе тело события столкновения. Если тип столкновения – это вложение одного тела в другое, то детектор инициализирует переменную типа cback_data.

Таким образом, работа с событиями вложения тел ничем не отличается от работы с другими типами событий и происходит через callback функцию запроса поиска столкновений, в которой достаточно обработать тип события cdet_query::CDET_INCLUDED.


Новые случаи детектирования. Лучи

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




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

// Добавление луча в детектор столкновений
cdet_item MbCollisionDetectionUtility::AddRay( const MbCartPoint3D & origin, 
        						  const MbVector3D & direction,
  							  const MbPlacement3D & place, 
  							  cdet_app_item appItem );

Для регистрации соударений лучей используется упомянутая ранее функция API cdet_result MbCollisionDetectionUtility::CheckCollision(...).

Ниже представлен фрагмент кода (С++) с описанием каждого шага. Он демонстрирует работу с модулем Collision Detection при регистрации прохождения луча.


Предположим, что, как и в прошлом примере, создан детектор столкновений.

MbCollisionDetectionUtility cdet;

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

При запуске поиска столкновений через cdet.CheckCollisions(...) детектор обнаружит пересечение луча и твердого тела (в случае их пересечения), а если в детектор добавлены пересекающиеся лучи, то и пересечения лучей. При этом функция cdet_result MbCollisionDetectionUtility::CheckCollision(...) вернет результат CDET_RESULT_Intersected, а в callback функции переменная типа cback_data будет содержать информацию о соответствующей паре объектов.


Collision Detection. Планы

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


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

Поделиться материалом