From 70d718178d0e3fde167fbf0d994ba0d314e1bddc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Oct 2014 13:36:37 -0700 Subject: [PATCH 1/2] make all volume3DOverlays handle proper ray picking against their rotated bounding box, make model overlays property ray pick as well --- interface/src/ui/overlays/ModelOverlay.cpp | 52 ++++++++++++++++++- interface/src/ui/overlays/ModelOverlay.h | 2 + interface/src/ui/overlays/Volume3DOverlay.cpp | 26 ++++++++-- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 793ebbc3e3..807be00300 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -87,8 +87,56 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { } _updateModel = true; } - + + QScriptValue dimensionsValue = properties.property("dimensions"); + if (dimensionsValue.isValid()) { + QScriptValue x = dimensionsValue.property("x"); + QScriptValue y = dimensionsValue.property("y"); + QScriptValue z = dimensionsValue.property("z"); + if (x.isValid() && y.isValid() && z.isValid()) { + glm::vec3 dimensions; + dimensions.x = x.toVariant().toFloat(); + dimensions.y = y.toVariant().toFloat(); + dimensions.z = z.toVariant().toFloat(); + _model.setScaleToFit(true, dimensions); + } + _updateModel = true; + } + if (properties.property("position").isValid()) { _updateModel = true; } -} \ No newline at end of file +} + +bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face) const { + + // if our model isn't active, we can't ray pick yet... + if (!_model.isActive()) { + return false; + } + + // extents is the entity relative, scaled, centered extents of the entity + glm::vec3 position = getPosition(); + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 translation = glm::translate(position); + glm::mat4 entityToWorldMatrix = translation * rotation; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + + Extents modelExtents = _model.getMeshExtents(); // NOTE: unrotated + + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; + glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference + AABox overlayFrameBox(corner, dimensions); + + glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); + + // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame + // and testing intersection there. + if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { + return true; + } + + return false; +} diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index e0f979676f..a116958b7e 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -24,6 +24,8 @@ public: virtual void update(float deltatime); virtual void render(); virtual void setProperties(const QScriptValue& properties); + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + private: Model _model; diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index 11e3e5d8cf..e88b1ea5a7 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -8,6 +8,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include + // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" @@ -85,8 +88,23 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { - // TODO: this is not exactly accurate because it doesn't properly handle rotation... but it's close enough for our - // current use cases. We do need to improve it to be more accurate - AABox myBox(getCorner(), _dimensions); - return myBox.findRayIntersection(origin, direction, distance, face); + // extents is the entity relative, scaled, centered extents of the entity + glm::vec3 position = getPosition(); + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 translation = glm::translate(position); + glm::mat4 entityToWorldMatrix = translation * rotation; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + + glm::vec3 dimensions = _dimensions; + glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference + AABox overlayFrameBox(corner, dimensions); + glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); + + // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame + // and testing intersection there. + if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { + return true; + } + return false; } From 61b53701f33fd98b284136caf76dea08fbb4424f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Oct 2014 16:07:08 -0700 Subject: [PATCH 2/2] fix some comments --- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- interface/src/ui/overlays/Volume3DOverlay.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 807be00300..12f54f02d9 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -132,7 +132,7 @@ bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame + // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame // and testing intersection there. if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { return true; diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index e88b1ea5a7..cc12d41e2e 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -101,7 +101,7 @@ bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame + // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame // and testing intersection there. if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { return true;