OBB проти виявлення зіткнень OBB


20

Скажімо, у вас є два Обмежувальні об'єкти поля, кожен з яких зберігає поточні вершини поля у векторному, при цьому всі вершини об'єкта повертаються та переводяться відносно загальної осі.

Ось зображення для ілюстрації моєї проблеми:

Як я можу розібратися, якщо два OBB перекривають будь-які посилання, щоб допомогти пояснити рішення проблеми, було б вітатися. Нічого занадто перекрученого, будь ласка ...

Відповіді:


16

ОББ - опуклий корпус. Опуклий корпус - це форма 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 ;
}

Hullinator впроваджує тест SAT для опуклих корпусів
bobobobo

дивовижне пояснення! Спасибі. Я думаю , що ви , можливо, помилка в рядку: «так що дозволяє спробувати кілька осей на шоу були перекриття не відбувається.», Тому що тоді ви продовжуєте давати приклади , коли вони роблять перекриття. знову дякую!

Чи не потрібно робити тести також для всіх поперечних продуктів від норм? У цій статті geometrictools.com/Documentation/DynamicCollisionDetection.pdf йдеться про це.
iNFINITEi

Варто констатувати, що цей специфічний метод SAT працює лише у 2D. У 3D потрібно отримати більше, ніж просто нормали кожного обличчя. Коли ви отримаєте правильні норми, однак, решта процесу (проектуйте, порівняйте) точно така ж.
Позов по

Дійсно важко сказати зі своїх 2D-картинок, в якому напрямку стрілки йдуть.
WDUK

7

Ви обов'язково повинні шукати роздільну теорему осі . Це для опуклих об’єктів. Існує правило: "Якщо два опуклі об’єкти не перетинаються, то є площина, де проекція цих двох об'єктів не перетинатиметься".

На вікі можна знайти кілька прикладів . Але це трохи складніше, ніж для вашого випадку.

Щось більш підходяще для вашої проблеми можна знайти тут (зіткнулися дві машини).


1

Більше статей SAT .

Остання стаття на цьому сайті постачається з повним кодом, я думаю, це в FLASH, я не маю уявлення, але у мене було рівно 0 питань перетворення його на C ++, коли мені довелося використовувати SAT вперше, не повинно бути важким зробіть те ж саме для інших мов. Єдине, що вам доведеться додати - це зберігання вектора переміщення у кожному обчисленні (якщо це найменший, звичайно, ви це зрозумієте, коли дізнаєтесь про SAT), код у цьому підручнику не робить цього, так ви закінчуєте останній обчислений вектор.

http://rocketmandevelopment.com/tag/separation-axis-theorem/

Гарні, старі підручники з N-гри. Краща теорія SAT в Інтернеті.

http://www.metanetsoftware.com/technique/tutorialA.html


Це так дратує, що ніхто не публікує повне робоче джерело з усіма необхідними класами. Я переніс його код на демо-версію, але він просто не працює. :( Це мій проект поки що, якщо хтось міг би допомогти мені налагодити це, було б чудово. Посилання
Джошуа Барнетт

що ти означає, що це не працює? зверніть увагу на те, як ви зберігаєте свої вершини, на зображенні ви їх маєте в декартовій системі координат, у підручнику він зберігає вершини як вектори відносно центроїда (все, що вам потрібно зробити, це відняти центроїд від власних вершин або видаліть рядки, де він модифікує власні вершини), такі функції, як крапковий продукт, який ви можете створити самостійно, вам не потрібен посібник для тих, відпочинок повинен бути прямо вперед, це не копіюючи вставити матеріал, вивчіть SAT, перш ніж намагатися його реалізувати.
дрета

Ось як я це реалізував: SAT.as , Shape2D.as , що ви маєте на увазі під центроїдом? Центр багатокутника, такий як (x, y)?
Джошуа Барнетт

На даний момент у мене є функція getOBB (), яка повертає вершини, як детально описано в моєму вихідному зображенні. Це обчислюється з вектора <b2Vec2>, що містить вершини фігури, змінну кута та змінну положення.
Джошуа Барнетт

так, центр, те, як цей хлопець створює свої багатокутники, - надаючи зсуви від центру, idk AS3, але з того, що я бачу, ти проектуєш вершини такими, якими вони є, під час обчислення точкового продукту намагайся відняти центроїд від вершин (вектор віднімання ), окрім цього ви не перевіряєте, який вектор розділення найменший, ви зберігаєте лише останній обчислений
дрета
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.