also add unit tests for indRayRectangleIntersection()
Showing the changes to libraries/shared/src/GeometryUtil.cpp (1 of 3 files). Show all
Unified · Split
| @@ -11,10 +11,10 @@ · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | #include <cstring> | 12 | #include <cstring> |
| 13 | #include <cmath> | 13 | #include <cmath> |
| 14 | #include <glm/gtx/quaternion.hpp> | ||
| 14 | 15 | ||
| 15 | #include "GeometryUtil.h" | 16 | #include "GeometryUtil.h" |
| 16 | #include "NumericalConstants.h" | 17 | #include "NumericalConstants.h" |
| 17 | #include "PlaneShape.h" | ||
| 18 | #include "RayIntersectionInfo.h" | 18 | #include "RayIntersectionInfo.h" |
| 19 | 19 | ||
| 20 | glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { | 20 | glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { |
| @@ -496,31 +496,45 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len · 475 unmodified lines | |||
| 496 | 496 | ||
| 497 | bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, | 497 | bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, |
| 498 | const glm::vec3& position, const glm::vec2& dimensions, float& distance) { | 498 | const glm::vec3& position, const glm::vec2& dimensions, float& distance) { |
| 499 | RayIntersectionInfo rayInfo; | ||
| 500 | rayInfo._rayStart = origin; | ||
| 501 | rayInfo._rayDirection = direction; | ||
| 502 | rayInfo._rayLength = std::numeric_limits<float>::max(); | ||
| 503 | |||
| 504 | PlaneShape plane; | ||
| 505 | |||
| 506 | const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); | 499 | const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); |
| 507 | glm::vec3 normal = rotation * UNROTATED_NORMAL; | 500 | glm::vec3 normal = rotation * UNROTATED_NORMAL; |
| 508 | plane.setNormal(normal); | ||
| 509 | plane.setPoint(position); // the position is definitely a point on our plane | ||
| 510 | |||
| 511 | bool intersects = plane.findRayIntersection(rayInfo); | ||
| 512 | 501 | ||
| 513 | if (intersects) { | 502 | bool maybeIntersects = false; |
| 514 | distance = rayInfo._hitDistance; | 503 | float denominator = glm::dot(normal, direction); |
| 504 | glm::vec3 offset = origin - position; | ||
| 505 | float normDotOffset = glm::dot(offset, normal); | ||
| 506 | float d = 0.0f; | ||
| 507 | if (fabsf(denominator) < EPSILON) { | ||
| 508 | // line is perpendicular to plane | ||
| 509 | if (fabsf(normDotOffset) < EPSILON) { | ||
| 510 | // ray starts on the plane | ||
| 511 | maybeIntersects = true; | ||
| 512 | |||
| 513 | // compute distance to closest approach | ||
| 514 | d = - glm::dot(offset, direction); // distance to closest approach of center of rectangle | ||
| 515 | if (d < 0.0f) { | ||
| 516 | // ray points away from center of rectangle, so ray's start is the closest approach | ||
| 517 | d = 0.0f; | ||
| 518 | } | ||
| 519 | } | ||
| 520 | } else { | ||
| 521 | d = - normDotOffset / denominator; | ||
| 522 | if (d > 0.0f) { | ||
| 523 | // ray points toward plane | ||
| 524 | maybeIntersects = true; | ||
| 525 | } | ||
| 526 | } | ||
| 515 | 527 | ||
| 516 | glm::vec3 hitPosition = origin + (distance * direction); | 528 | if (maybeIntersects) { |
| 529 | glm::vec3 hitPosition = origin + (d * direction); | ||
| 517 | glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); | 530 | glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); |
| 518 | |||
| 519 | glm::vec2 halfDimensions = 0.5f * dimensions; | 531 | glm::vec2 halfDimensions = 0.5f * dimensions; |
| 520 | 532 | if (fabsf(localHitPosition.x) < halfDimensions.x && fabsf(localHitPosition.y) < halfDimensions.y) { | |
| 521 | intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x | 533 | // only update distance on intersection |
| 522 | && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; | 534 | distance = d; |
| 535 | return true; | ||
| 536 | } | ||
| 523 | } | 537 | } |
| 524 | 538 | ||
| 525 | return intersects; | 539 | return false; |
| 526 | } | 540 | } |