ОББ - опуклий корпус. Опуклий корпус - це форма 3D, яка не має на своїй поверхні жолобків. Кожна «шишка» (вершина) на опуклому корпусі виступає назовні , ніколи всередину. Якщо прорізати площину через опуклий корпус, ви отримаєте (лише один) опуклий багатокутник. Якщо ви знаходитесь всередині опуклого корпусу і стріляєте лазером, спрямований назовні, ви будете пробивати поверхню корпусу лише один раз (ніколи двічі).
Тест теоретичної роздільної осі може бути використаний для виявлення зіткнення опуклих корпусів. Тест SAT простий. Він працює в 2D і 3D. Хоча малюнки нижче будуть у форматі 2D, їх можна так само легко застосувати до 3D.
Концепція
Це ключова концепція, яку ви використовуєте в SAT:
- Дві фігури перетинаються лише в тому випадку, якщо вони перетинаються, коли "проектуються" на кожну нормальну вісь обох фігур .
"Проекція" фігури на 1D-вектор виглядає приблизно так (те, що я називаю "дробленням")
Форма з червоними вершинами та віссю
"Проектування форми на вісь" означає скидання перпендикуляра від кожної точки на фігурі просто для посадки на вісь. Ви можете подумати про це як про «руйнування» точок рукою, яка збирає все і перпендикулярно роздавлює її до осі.
Що вам залишилося: Очки на осі
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 ;
}