В даний час я розробляю клон прориву, і я потрапив у блокпост, коли отримав виявлення зіткнення між кулькою (колом) та цеглою (опуклий багатокутник), що працює правильно. Я використовую тест на виявлення зіткнень кола-лінії, де кожна лінія являє собою і край на опуклій цегли багатокутника.
Більшу частину часу тест Circle-Line працює належним чином, і точки зіткнення вирішені правильно.
Функція виявлення зіткнень працює правильно.
Однак іноді мій код виявлення зіткнень повертається помилковим через негативний дискримінант, коли куля насправді перетинає цеглу.
Мені відомо про неефективність цього методу, і я використовую обмежувальні коробки, вирівнювані по осі, щоб зменшити кількість протестованих цеглин. Моя головна проблема - чи є в моєму коді якісь математичні помилки.
/*
* from and to are points at the start and end of the convex polygons edge.
* This function is called for every edge in the convex polygon until a
* collision is detected.
*/
bool circleLineCollision(Vec2f from, Vec2f to)
{
Vec2f lFrom, lTo, lLine;
Vec2f line, normal;
Vec2f intersectPt1, intersectPt2;
float a, b, c, disc, sqrt_disc, u, v, nn, vn;
bool one = false, two = false;
// set line vectors
lFrom = from - ball.circle.centre; // localised
lTo = to - ball.circle.centre; // localised
lLine = lFrom - lTo; // localised
line = from - to;
// calculate a, b & c values
a = lLine.dot(lLine);
b = 2 * (lLine.dot(lFrom));
c = (lFrom.dot(lFrom)) - (ball.circle.radius * ball.circle.radius);
// discriminant
disc = (b * b) - (4 * a * c);
if (disc < 0.0f)
{
// no intersections
return false;
}
else if (disc == 0.0f)
{
// one intersection
u = -b / (2 * a);
intersectPt1 = from + (lLine.scale(u));
one = pointOnLine(intersectPt1, from, to);
if (!one)
return false;
return true;
}
else
{
// two intersections
sqrt_disc = sqrt(disc);
u = (-b + sqrt_disc) / (2 * a);
v = (-b - sqrt_disc) / (2 * a);
intersectPt1 = from + (lLine.scale(u));
intersectPt2 = from + (lLine.scale(v));
one = pointOnLine(intersectPt1, from, to);
two = pointOnLine(intersectPt2, from, to);
if (!one && !two)
return false;
return true;
}
}
bool pointOnLine(Vec2f p, Vec2f from, Vec2f to)
{
if (p.x >= min(from.x, to.x) && p.x <= max(from.x, to.x) &&
p.y >= min(from.y, to.y) && p.y <= max(from.y, to.y))
return true;
return false;
}
sqrt_disc = sqrt(disc);
повернути. Дуже дякую за вашу відповідь нижче, він мені дуже допоміг.