History

remove PlaneShape dependency from GeometryUtils

also add unit tests for indRayRectangleIntersection()

Andrew Meadows committed 11 years ago

Commit ef5e7e91 parent c7f367b3 files · +222 −20Browse files

Showing the changes to libraries/shared/src/GeometryUtil.cpp (1 of 3 files). Show all

Unified · Split

libraries/shared/src/GeometryUtil.cpp+34−20
@@ -11,10 +11,10 @@ · 10 unmodified lines
1111
1212 #include <cstring>
1313 #include <cmath>
14+#include <glm/gtx/quaternion.hpp>
1415
1516 #include "GeometryUtil.h"
1617 #include "NumericalConstants.h"
17−#include "PlaneShape.h"
1818 #include "RayIntersectionInfo.h"
1919
2020 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
496496
497497 bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation,
498498 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−
506499 const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f);
507500 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);
512501
513− if (intersects) {
514− distance = rayInfo._hitDistance;
502+ bool maybeIntersects = false;
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+ }
515527
516− glm::vec3 hitPosition = origin + (distance * direction);
528+ if (maybeIntersects) {
529+ glm::vec3 hitPosition = origin + (d * direction);
517530 glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position);
518−
519531 glm::vec2 halfDimensions = 0.5f * dimensions;
520−
521− intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x
522− && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y;
532+ if (fabsf(localHitPosition.x) < halfDimensions.x && fabsf(localHitPosition.y) < halfDimensions.y) {
533+ // only update distance on intersection
534+ distance = d;
535+ return true;
536+ }
523537 }
524538
525− return intersects;
539+ return false;
526540 }