Настройка запроса на поиск столкновений
Если возможности настроек структуры cdet_collided_faces не достаточны, пользователь геометрического ядра C3D может реализовать собственный запрос. Для этого необходимо определить наследника класса cdet_query и реализовать для него специальную функцию обратного вызова (call-back функцию) вида:
typedef cback_res (*cback_func)(cdet_query *, message, cback_data &).
Ниже приведен пример реализации на языке программирования С++ структуры cdet_query_result, являющейся наследником структуры запроса cdet_query. Пример задает поиск до первого найденного пересечения и определяет, есть ли хотя бы одно пересечение в контрольном наборе тел. Пример можно найти в файле cdet_data.h.
//------------------------------------------------------------
struct cdet_query_result: public cdet_query
{
cdet_result result;
cdet_query_result()
: cdet_query(QueryFunc)
, result(CDM_RESULT_NoCollisionDetected) {}
private:
static cback_res QueryFunc(cdet_query * query, message code, cback_data &)
{
cdet_query_result * q = static_cast<cdet_query_result*>(query);
switch( code )
{
case CDET_QUERY_STARTED: // The collision query is started for all solids of the set
{
q->result = CDM_RESULT_NoCollisionDetected;
return CBACK_VOID_RESULT;
}
case CDET_INTERSECTED: // First intersection is founded.
{
q->result = CDM_RESULT_CollisionDetected;
return CBACK_SUFFICIENT;
}
case CDET_FINISHED: // A pair of solids is finished.
return (q->result == CDM_RESULT_CollisionDetected) ? CBACK_BREAK:CBACK_VOID_RESULT;
default:
return CBACK_VOID;
}
}
};
В основе запроса лежит функция обратного вызова
static cback_res QueryFunc(cdet_query * query, message code, cback_data & cData),
которую пользователь может реализовать на свое усмотрение. Данная функция передается в алгоритм CheckCollisions через структуру cdet_query и будет вызываться при наступлении одного из следующих событий (enum cdet_query::message):
CDET_QUERY_STARTED (начат поиск столкновений в контрольной группе тел),
CDET_STARTED (начат поиск столкновений для пары объектов),
CDET_FINISHED (завершен поиск столкновений для пары объектов),
CDET_INTERSECTED (найдено пересечение граней от пары объектов),
CDET_TOUCHED (найдены соприкасающиеся грани пары объектов).
Входными параметрами функции QueryFunc являются:
query – указатель на структуру запроса,
code – целочисленное значение, кодирующее событие поиска,
cData – структура передачи данных.
Функция возвращает одно из значений перечисления cback_res:
CBACK_SUFFICIENT (Реакция клиентского приложения на события CDET_INTERSECTED или CDET_TOUCHED. Прерывает поиск для данной пары тел, но продолжает поиск столкновений других пар из контрольного набора тел),
CBACK_SKIP (Пропустить поиск для данной пары тел по событию CDET_STARTED: Поиск для других пар из набора будет продолжен),
CBACK_BREAK (Прерывает дальнейший поиск пересечений для всех событий),
CBACK_VOID (Не оказывает влияния на запрос столкновений, продолжает поиск), которое передает клиентское приложение ядру C3D для настройки алгоритма поиска.
Целочисленное значение code определяет событие поиска и может принимать одно из значений:
CDET_QUERY_STARTED,
CDET_STARTED,
CDET_FINISHED,
CDET_INTERSECTED,
CDET_TOUCHED,
Структура данных cData предназначена для передачи пары элементов типа cdet_query::geom_element и должна иметь вид:
struct cback_data
{
geom_element first, second;
};
где элемент пары cdet_query::geom_element – это структура деталей поиска, содержащая следующие:
geom_element::appItem – геометрический объект клиентского приложения,
geom_element::refItem – геометрический объект типа MbRefItem, как правило это грань MbFace,
geom_element::wMatrix – матрица перехода в общую, мировую СК из локальной СК тела.
Различная реализация метода обратного вызова QueryFunc позволяет выполнять следующие настройки процесса поиска:
Собрать все пары граней, участвующих в столкновении тел;
В любой момент исключать из рассмотрения определенные тела или пары тел;
Различать случай пересечения и касания граней;
Прерывать поиск всех пересечений при достижении определенного результата;
Прерывать поиск при обнаружении пересечения или касания;
Группировать тела, чтобы в пределах группы пересечения не искались.