Recast: fix bug in cylinder intersect detection code

If there's no movement on the x-y plane between sp and sq, there will be no magnitude, and thus also no discriminant. The code however will continue as it only checks if discriminant < 0. Due to this, the code  will no longer take the origin and radius of the cylinder into account and that will cause any ray that extends above or below the cylinder to be a hit, regardless of where it was emitted from in the world. If we have no magnitude, we should always check if the start point resides inside the cylinder area on the x-y plane and determine from there whether to perform a vertical intersection test.
This commit is contained in:
Kawe Mazidjatari 2024-11-02 20:46:51 +01:00
parent a229662a8e
commit 7ee884b39c

View File

@ -238,23 +238,34 @@ bool rdIntersectSegmentCylinder(const float* sp, const float* sq, const float* p
const float b = 2.0f * (px*dx + py*dy);
const float c = px*px + py*py - radius*radius;
// Discriminant for solving quadratic equation
float disc = b*b - 4.0f * a*c;
if (a > 0.0f)
{
// Discriminant for solving quadratic equation
float disc = b*b - 4.0f * a*c;
if (disc < 0.0f)
return false; // No intersection in the horizontal plane
if (disc < RD_EPS)
return false; // No intersection in the horizontal plane
disc = rdMathSqrtf(disc);
float t0 = (-b-disc) / (2.0f*a);
float t1 = (-b+disc) / (2.0f*a);
disc = rdMathSqrtf(disc);
float t0 = (-b-disc) / (2.0f*a);
float t1 = (-b+disc) / (2.0f*a);
if (t0 > t1) rdSwap(t0, t1);
if (t0 > t1) rdSwap(t0, t1);
tmin = rdMax(tmin, t0);
tmax = rdMin(tmax, t1);
tmin = rdMax(tmin, t0);
tmax = rdMin(tmax, t1);
if (tmin > tmax)
return false; // No intersection in the [tmin, tmax] range
if (tmin > tmax)
return false; // No intersection in the [tmin, tmax] range
}
else
{
// There is no shift in the start and end point on the x-y plane,
// ensure the starting point is within the radius of the cylinder
// before checking for vertical intersection
if (px*px + py*py > radius*radius)
return false;
}
// Vertical (z-axis) intersection test
const float dz = sq[2]-sp[2];