Теорема о разделяющей оси — AABB и круг

Мне удалось реализовать другие коллизии: AABB против AABB, Circle против Circle, Poly против Poly и т. Д., Но введение круга вызывает странные проблемы, хотя в теории реализация должна быть прямой после реализации этих других коллизий. Из того, что я понимаю, реализация AABB vs Circle должна работать так:

  1. Испытание на ось X для столкновения
  2. Испытание на ось Y для столкновения
  3. Проверьте ось, которая находится от центра круга до ближайшей вершины AABB

Я подозреваю, что это может быть проблемой, когда я делаю проекцию на 3-м шаге, но я использовал ту же технику проекции для поли, что я использовал здесь для AABB, и минимальная и максимальная проекция для круга должны будь центром круга, то минус и плюс радиус соответственно — по крайней мере, как я понимаю.

Я также добавил несколько эталонных изображений (желтый = нет столкновения, красный = столкновение)
http://imgur.com/a/C2fDO

bool AABBCircleCollision(Point center1, int halfWidth1, int halfHeight1, Point center2, int radius2)
{

/***** TEST THE X-AXIS *****/
double min1, max1, min2, max2;

min1 = (center1.x - halfWidth1);
max1 = (center1.x + halfWidth1);
min2 = (center2.x - radius2);
max2 = (center2.x + radius2);

if(max1 <= min2 || max2 <= min1) {
return false;
}

// At this point it is intersecting on the X-axis, now find out if it is on the left or right
bool onRight;
if(min2 - max1 > min1 - max2)
onRight = true;
else
onRight = false;

/***** TEST THE Y-AXIS *****/
min1 = (center1.y - halfHeight1);
max1 = (center1.y +  halfHeight1);
min2 = (center2.y - radius2);
max2 = (center2.y + radius2);

if(max1 <= min2 || max2 <= min1) {
return false;
}

// Like for the X-axis, find if the circle is above or below the AABB
bool onBottom;
if(min2 - max1 > min1 - max2)
onBottom = true;
else
onBottom = false;

/***** START TESTING THE AXIS BETWEEN CIRCLE'S CENTER AND CLOSEST VERTEX *****/
// Get the point of the AABB closest to the circles center
double vertX, vertY;
if(onRight)
vertX = center1.x + halfWidth1;
else
vertX = center1.x - halfWidth1;

if(onBottom)
vertY = center1.y + halfHeight1;
else
vertY = center1.y - halfHeight1;

// Get the axis vector between the closest point and the circles center
double axisX = center2.x - vertX;
double axisY = center2.y - vertY;

// Normalise it
double magV = sqrt(axisX * axisX + axisY * axisY);
axisX /= magV;
axisY /= magV;

// Project the AABB onto the axis
std::vector<Point> verts; // Here i'm creating the verts on the fly to see if this thing works. USE A BETTER WAY TO HANDLE THIS
verts.push_back(Point(center1.x - halfWidth1, center1.y - halfHeight1));
verts.push_back(Point(center1.x + halfWidth1, center1.y - halfHeight1));
verts.push_back(Point(center1.x + halfWidth1, center1.y + halfHeight1));
verts.push_back(Point(center1.x - halfWidth1, center1.y + halfHeight1));

min1 = std::numeric_limits<double>::max(), max1 = -min1; // Reset min and max values

for(int j=0; j < verts.size(); j++) {
double proj = (axisX * verts[j].x + axisY * verts[j].y);
min1 = std::min(proj, min1);
max1 = std::max(proj, max1);
}

// Project the circle onto the axis
min2 = axisX * (center2.x - radius2) + axisY * (center2.y - radius2);
max2 = axisX * (center2.x + radius2) + axisY * (center2.y + radius2);

printf("%f <= %f || %f <= %f\n", max1, min2, max2, min1);
if(max1 <= min2 || max2 <= min1) {
return false;
}

return true;
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector