OBB является выпуклой оболочкой. Выпуклый корпус - это трехмерная фигура, на поверхности которой нет «щелей». Каждый «удар» (вершина) на выпуклой оболочке выступает наружу , а не внутрь. Если вы разрежете плоскость через выпуклый корпус, вы получите (только один) выпуклый многоугольник. Если вы находитесь внутри выпуклого корпуса и стреляете лазером, направленным наружу, вы будете пробивать поверхность корпуса только один раз (никогда дважды).
Тест теоремы о разделяющей оси может быть использован для обнаружения столкновения выпуклых оболочек. Тест SAT прост. Работает в 2D и 3D. Хотя изображения ниже будут в 2D, они также могут быть легко применены к 3D.
концепция
Это ключевая концепция, которую вы используете с SAT:
- Две фигуры пересекаются, только если они перекрываются, когда «проецируются» на каждую нормальную ось обеих фигур .
«Проекция» фигуры на одномерный вектор выглядит так (то, что я называю «дробление»)
Форма с красными вершинами и осью
«Проецирование фигуры на ось» означает опускание перпендикуляра из каждой точки фигуры, чтобы приземлиться на ось. Вы можете думать об этом как о «раздавливании» точек рукой, которая собирает все и перпендикулярно раздавливает ее до оси.
То, что у вас осталось: точки на оси
СБ говорит:
Чтобы пересечь 2 выпуклых корпуса, они должны перекрываться на каждой оси (где каждая нормаль любой формы считается осью, которую мы должны проверить).
Возьмите эти 2 формы:
Вы видите, что они не пересекаются, поэтому давайте попробуем показать несколько осей, если совпадения не происходит.
Пробуем верхнюю нормаль пятиугольника:
Это экстенты. Они перекрываются.
Попробуйте левую сторону прямоугольника. Теперь они не пересекаются в этой оси, поэтому нет пересечения.
Алгоритм:
Для каждого лица нормальны обе фигуры:
- Найти минимальное и максимальное экстенты (наибольшее и наименьшее значение) проекции всех угловых точек вершин обеих фигур на эту ось
- Если они не перекрываются, пересечения нет .
И это действительно так. Код для обеспечения работы SAT очень короткий и простой.
Вот некоторый код, который демонстрирует, как сделать проекцию оси SAT:
void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
minAlong=HUGE, maxAlong=-HUGE;
for( int i = 0 ; i < ptSet.size() ; i++ )
{
// just dot it to get the min/max along this axis.
float dotVal = ptSet[i].dot( axis ) ;
if( dotVal < minAlong ) minAlong=dotVal;
if( dotVal > maxAlong ) maxAlong=dotVal;
}
}
Телефонный код:
// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
// Get the normals for one of the shapes,
for( int i = 0 ; i < shape1.normals.size() ; i++ )
{
float shape1Min, shape1Max, shape2Min, shape2Max ;
SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
{
return 0 ; // NO INTERSECTION
}
// otherwise, go on with the next test
}
// TEST SHAPE2.normals as well
// if overlap occurred in ALL AXES, then they do intersect
return 1 ;
}
bool overlaps( float min1, float max1, float min2, float max2 )
{
return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}
inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
return lowerBound <= val && val <= upperBound ;
}