| 423 | } |
| 424 | |
| 425 | bool pointInsidePolygon(const Polygon* poly, Vec2f p) |
| 426 | { |
| 427 | if (p.x < poly->bounds[0].x + eps || p.x > poly->bounds[1].x - eps || p.z < poly->bounds[0].z + eps || p.z > poly->bounds[1].z - eps) |
| 428 | { |
| 429 | return false; |
| 430 | } |
| 431 | |
| 432 | const s32 edgeCount = (s32)poly->edge.size(); |
| 433 | const Edge* edge = poly->edge.data(); |
| 434 | const Edge* last = &edge[edgeCount - 1]; |
| 435 | const Vec2f* vtx = poly->vtx.data(); |
| 436 | |
| 437 | const Vec2f* w0 = &vtx[last->i0]; |
| 438 | const Vec2f* w1 = &vtx[last->i1]; |
| 439 | f32 dzLast = w1->z - w0->z; |
| 440 | s32 crossings = 0; |
| 441 | |
| 442 | for (s32 e = 0; e < edgeCount; e++, edge++) |
| 443 | { |
| 444 | w0 = &vtx[edge->i0]; |
| 445 | w1 = &vtx[edge->i1]; |
| 446 | |
| 447 | const f32 x0 = w0->x; |
| 448 | const f32 x1 = w1->x; |
| 449 | const f32 z0 = w0->z; |
| 450 | const f32 z1 = w1->z; |
| 451 | const f32 dz = z1 - z0; |
| 452 | |
| 453 | if (dz != 0) |
| 454 | { |
| 455 | if (p.z == z0 && p.x == x0) |
| 456 | { |
| 457 | return true; |
| 458 | } |
| 459 | else if (p.z != z0) |
| 460 | { |
| 461 | if (p.z != z1) |
| 462 | { |
| 463 | PointSegSide side = lineSegmentSide(p, { x0, z0 }, { x1, z1 }); |
| 464 | if (side == PS_OUTSIDE) |
| 465 | { |
| 466 | crossings++; |
| 467 | } |
| 468 | else if (side == PS_ON_LINE) |
| 469 | { |
| 470 | return true; |
| 471 | } |
| 472 | } |
| 473 | dzLast = dz; |
| 474 | } |
| 475 | else if (p.x != x0) |
| 476 | { |
| 477 | if (p.x < x0) |
| 478 | { |
| 479 | //f32 dzSignMatches = ((dz >= 0.0f && dzLast >= 0.0f) || (dz <= 0.0f && dzLast <= 0.0f)) ? 1.0f : -1.0f; |
| 480 | bool dzSignMatches = sign(dz) == sign(dzLast); |
| 481 | if (dzSignMatches || dzLast == 0) // the signs match OR dz or dz0 are positive OR dz0 EQUALS 0. |
| 482 | { |
no test coverage detected