From eb6a3b37d2e6549ffc6b3d5038e9960ce0122bb1 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 21 Sep 2024 12:22:02 +0200 Subject: [PATCH] Recast: implement intersection test for convex hulls Similar to the intersection test for cylindric volumes. The old convex hull intersection test in the raycast algorithm is inaccurate and also doesn't calculate the hit time, which prevents the editor from placing the cursor at the intersection. Raycast algorithm is pending a refactor and its convex hull isect test will be replaced with this. --- .../recast/Shared/Include/SharedCommon.h | 4 ++ .../recast/Shared/Source/SharedCommon.cpp | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/thirdparty/recast/Shared/Include/SharedCommon.h b/src/thirdparty/recast/Shared/Include/SharedCommon.h index 549de778..bc16011d 100644 --- a/src/thirdparty/recast/Shared/Include/SharedCommon.h +++ b/src/thirdparty/recast/Shared/Include/SharedCommon.h @@ -486,6 +486,10 @@ bool rdIntersectSegmentCylinder(const float* sp, const float* sq, const float* p const float radius, const float height, float& tmin, float& tmax); +bool rdIntersectSegmentConvexHull(const float* sp, const float* sq, const float* verts, + int nverts, float hmin, float hmax, + float& tmin, float& tmax); + bool rdIntersectSegSeg2D(const float* ap, const float* aq, const float* bp, const float* bq, float& s, float& t); diff --git a/src/thirdparty/recast/Shared/Source/SharedCommon.cpp b/src/thirdparty/recast/Shared/Source/SharedCommon.cpp index 24dbd3f9..3cfcaa11 100644 --- a/src/thirdparty/recast/Shared/Source/SharedCommon.cpp +++ b/src/thirdparty/recast/Shared/Source/SharedCommon.cpp @@ -282,6 +282,48 @@ bool rdIntersectSegmentCylinder(const float* sp, const float* sq, const float* p return true; } +bool rdIntersectSegmentConvexHull(const float* sp, const float* sq, + const float* verts, const int nverts, + const float hmin, const float hmax, + float& tmin, float& tmax) +{ + int segMin, segMax; + if (!rdIntersectSegmentPoly2D(sp, sq, verts, nverts, tmin, tmax, segMin, segMax)) + return false; // No intersection with the polygon base + + tmin = rdMax(0.0f, tmin); + tmax = rdMin(1.0f, tmax); + + if (tmin > tmax) + return false; // No valid intersection range + + // Vertical (z-axis) intersection test + const float dz = sq[2]-sp[2]; + + if (dz != 0.0f) + { + float tCapMin = (hmin-sp[2]) / dz; + float tCapMax = (hmax-sp[2]) / dz; + + if (tCapMin > tCapMax) rdSwap(tCapMin, tCapMax); + + // Update tmin and tmax for cap intersections + tmin = rdMax(tmin, tCapMin); + tmax = rdMin(tmax, tCapMax); + + if (tmin > tmax) + return false; + } + + const float z0 = sp[2] + tmin*dz; + const float z1 = sp[2] + tmax*dz; + + if ((z0 < hmin && z1 < hmin) || (z0 > hmax && z1 > hmax)) + return false; // No intersection within the vertical bounds + + return true; +} + float rdDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t) { float pqx = q[0] - p[0];