From 89c10ca2ece60d44f330a4b4d410f8f92a7eafef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 14:36:24 -0800 Subject: [PATCH 1/4] Fix BillboardOverlay::findRayIntersection --- .../src/ui/overlays/BillboardOverlay.cpp | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 27bd0c9102..4ea0e55710 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -12,6 +12,7 @@ #include "Application.h" #include "BillboardOverlay.h" +#include BillboardOverlay::BillboardOverlay() : _fromImage(), @@ -191,18 +192,51 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float& distance, BoxFace& face) { if (_texture) { + // This is taken from Planar3DOverlay. Although it probably makes more sense for this + // overlay type to extend from Planar3DOverlay, the interfaces are different enough (scale vs. dimensions) + // that it would break existing scripts and would require other changes to make up for unique + // features like `isFacingAvatar`. + + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + bool isNull = _fromImage.isNull(); float width = isNull ? _texture->getWidth() : _fromImage.width(); float height = isNull ? _texture->getHeight() : _fromImage.height(); - float maxSize = glm::max(width, height); - float x = width / (2.0f * maxSize); - float y = -height / (2.0f * maxSize); - float maxDimension = glm::max(x,y); - float scaledDimension = maxDimension * _scale; - glm::vec3 corner = getCenter() - glm::vec3(scaledDimension, scaledDimension, scaledDimension) ; - AACube myCube(corner, scaledDimension * 2.0f); - return myCube.findRayIntersection(origin, direction, distance, face); + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::quat rotation; + if (_isFacingAvatar) { + // rotate about vertical to face the camera + rotation = Application::getInstance()->getCamera()->getRotation(); + rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + } else { + rotation = _rotation; + } + glm::vec3 normal = rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + distance = rayInfo._hitDistance; + + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - _position); + + // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. + float maxSize = glm::max(width, height); + glm::vec2 halfDimensions = 0.5f * _scale * glm::vec2(width / maxSize, height / maxSize); + + intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x + && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; + } + return intersects; } return false; } From 03b10b6cb02fbf281844b02dc3e3b41242e5d0c6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:00:30 -0800 Subject: [PATCH 2/4] Add findRayRectangleIntersection --- libraries/shared/src/GeometryUtil.cpp | 35 ++++++++++++++++++++++++++- libraries/shared/src/GeometryUtil.h | 3 +++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index aaec8b3e4a..cf15830a10 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -12,8 +12,10 @@ #include #include -#include "SharedUtil.h" #include "GeometryUtil.h" +#include "PlaneShape.h" +#include "RayIntersectionInfo.h" +#include "SharedUtil.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector @@ -491,3 +493,34 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len } } } + +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions) { + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::vec3 normal = rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + float distance = rayInfo._hitDistance; + + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); + + glm::vec2 halfDimensions = 0.5f * dimensions; + + intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x + && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; + } + + return intersects; +} diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index a6889ef73e..e0de536e97 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,6 +76,9 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions); + bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); From be7959bbcddb1f45c8e92989ed7cceee18cc4251 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:00:55 -0800 Subject: [PATCH 3/4] Fix BillboardOverlay findRayIntersection implementation --- .../src/ui/overlays/BillboardOverlay.cpp | 46 ++++--------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 4ea0e55710..a82da0ee5f 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -10,9 +10,10 @@ // #include "Application.h" +#include "GeometryUtil.h" +#include "PlaneShape.h" #include "BillboardOverlay.h" -#include BillboardOverlay::BillboardOverlay() : _fromImage(), @@ -192,23 +193,6 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float& distance, BoxFace& face) { if (_texture) { - // This is taken from Planar3DOverlay. Although it probably makes more sense for this - // overlay type to extend from Planar3DOverlay, the interfaces are different enough (scale vs. dimensions) - // that it would break existing scripts and would require other changes to make up for unique - // features like `isFacingAvatar`. - - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - bool isNull = _fromImage.isNull(); - float width = isNull ? _texture->getWidth() : _fromImage.width(); - float height = isNull ? _texture->getHeight() : _fromImage.height(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); glm::quat rotation; if (_isFacingAvatar) { // rotate about vertical to face the camera @@ -217,27 +201,17 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v } else { rotation = _rotation; } - glm::vec3 normal = rotation * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(_position); // the position is definitely a point on our plane - bool intersects = plane.findRayIntersection(rayInfo); + // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. + bool isNull = _fromImage.isNull(); + float width = isNull ? _texture->getWidth() : _fromImage.width(); + float height = isNull ? _texture->getHeight() : _fromImage.height(); + float maxSize = glm::max(width, height); + glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize); - if (intersects) { - distance = rayInfo._hitDistance; - - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - _position); - - // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. - float maxSize = glm::max(width, height); - glm::vec2 halfDimensions = 0.5f * _scale * glm::vec2(width / maxSize, height / maxSize); - - intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x - && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; - } - return intersects; + return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions); } + return false; } From eb21b7443989000e1eb495985c12de686e4120d7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:01:24 -0800 Subject: [PATCH 4/4] Replace Planar3DOverlay::findRayIntersection with GeometryUtil::findRayRectangleIntersection --- interface/src/ui/overlays/Planar3DOverlay.cpp | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 508b5c4227..925725d261 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -17,6 +17,8 @@ #include #include +#include "GeometryUtil.h" + #include "Planar3DOverlay.h" const float DEFAULT_SIZE = 1.0f; @@ -93,29 +95,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); - glm::vec3 normal = _rotation * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(_position); // the position is definitely a point on our plane - - bool intersects = plane.findRayIntersection(rayInfo); - - if (intersects) { - distance = rayInfo._hitDistance; - - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position); - glm::vec2 halfDimensions = _dimensions / 2.0f; - - intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x - && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; - } - return intersects; + return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions); }