From 0211492d96838c111bfbbf284b0f7957036e1e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Thu, 4 Jan 2024 20:12:20 +0100 Subject: [PATCH] Change point-in-polygon algorithm --- src/r_main.c | 75 +++++++++++++--------------------------------------- 1 file changed, 19 insertions(+), 56 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 5b01ddfc5..940104d7d 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1020,76 +1020,39 @@ void R_Init(void) boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y) { size_t i; - line_t *closest = NULL; - fixed_t closestdist = INT32_MAX; + size_t passes = 0; for (i = 0; i < sector->linecount; i++) { - vertex_t v, *v1, *v2; - fixed_t dist; - - // find the line closest to the point we're looking for. - P_ClosestPointOnLine(x, y, sector->lines[i], &v); + vertex_t *v1, *v2; v1 = sector->lines[i]->v1; v2 = sector->lines[i]->v2; - // do some correction in order to prevent points outside the line from being measured. - if (abs(v1->x - v2->x) > abs(v1->y - v2->y)) + // make sure v1 is below v2 + if (v1->y > v2->y) { - if (v.x < v1->x && v.x < v2->x) - v = v1->x < v2->x ? *v1 : *v2; - else if (v.x > v1->x && v.x > v2->x) - v = v1->x > v2->x ? *v1 : *v2; + vertex_t *tmp = v1; + v1 = v2; + v2 = tmp; } - else + else if (v1->y == v2->y) + // horizontal line, we can't match this + continue; + + if (v1->y <= y && y < v2->y) { - if (v.y < v1->y && v.y < v2->y) - v = v1->y < v2->y ? *v1 : *v2; - else if (v.y > v1->y && v.y > v2->y) - v = v1->y > v2->y ? *v1 : *v2; - } + // if the y axis in inside the line, find the point where we intersect on the x axis... + fixed_t vx = v1->x + (INT64)(v2->x - v1->x) * (y - v1->y) / (v2->y - v1->y); - dist = R_PointToDist2(v.x, v.y, x, y); - if (dist < closestdist) - { - closest = sector->lines[i]; - closestdist = dist; - } - else if (dist == closestdist) - { - // coordinates are the same; we're most likely matching against a corner here. - // check closest angle instead. - vertex_t *cv, *dv; - angle_t angle = R_PointToAngle2(v.x, v.y, x, y); - angle_t ca, da; - if (closest->v1->x == v.x && closest->v1->y == v.y) - cv = closest->v2; - else - cv = closest->v1; - - if (v1->x == v.x && v1->y == v.y) - dv = v2; - else - dv = v1; - - ca = R_PointToAngle2(v.x, v.y, cv->x, cv->y) - angle; - da = R_PointToAngle2(v.x, v.y, dv->x, dv->y) - angle; - if (ca > ANGLE_180) - ca = -ca; - if (da > ANGLE_180) - da = -da; - - if (ca > da) - { - closest = sector->lines[i]; - closestdist = dist; - } + // ...and if that point is to the left of the point, count it as inside. + if (vx < x) + passes++; } } - // if the side of the closest line is in this sector, we're inside of it. - return P_PointOnLineSide(x, y, closest) == 0 ? closest->frontsector == sector : closest->backsector == sector; + // and odd number of passes means we're inside the polygon. + return passes % 2; } //