diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index b030a67e17..8157c32a93 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -89,6 +89,8 @@ glm::vec3 RayPick::intersectRayWithEntityXYPlane(const QUuid& entityID, const gl return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint()); } + + glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) { glm::quat invRot = glm::inverse(rotation); glm::vec3 localPos = invRot * (worldPos - position); @@ -102,6 +104,19 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3 return pos2D; } +glm::vec2 RayPick::projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) { + glm::quat invRot = glm::inverse(rotation); + glm::vec3 localPos = invRot * (worldPos - position); + + glm::vec3 normalizedPos = (localPos / dimensions) + registrationPoint; + + glm::vec2 pos2D = glm::vec2(normalizedPos.x, (1.0f - normalizedPos.z)); + if (unNormalized) { + pos2D *= glm::vec2(dimensions.x, dimensions.z); + } + return pos2D; +} + glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_POSITION; diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 7625146408..161c930fef 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -86,6 +86,7 @@ public: static glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized = true); static glm::vec2 projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized); + static glm::vec2 projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNoemalized); private: static glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat& rotation, const glm::vec3& registration); diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index cf19b68a45..2bd371c506 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -155,15 +155,33 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { const auto entityRotation = entity->getWorldOrientation(); const auto entityPosition = entity->getWorldPosition(); + const auto entityType = entity->getType(); + glm::vec3 normal; - glm::vec3 normal = entityRotation * Vectors::UNIT_Z; + // TODO: Use the xz projection method for Sphere and Quad. + if (entityType == EntityTypes::Gizmo) { + normal = entityRotation * Vectors::UNIT_NEG_Y; + } else { + normal = entityRotation * Vectors::UNIT_Z; + } float distance = glm::dot(pick.position - entityPosition, normal); if (distance < nearestTarget.distance) { const auto entityDimensions = entity->getScaledDimensions(); const auto entityRegistrationPoint = entity->getRegistrationPoint(); glm::vec3 intersection = pick.position - (normal * distance); - glm::vec2 pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation, - entityDimensions, entityRegistrationPoint, false); + glm::vec2 pos2D; + + + auto entityType = entity->getType(); + + if (entityType == EntityTypes::Gizmo) { + pos2D = RayPick::projectOntoXZPlane(intersection, entityPosition, entityRotation, + entityDimensions, entityRegistrationPoint, false); + } else { + pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation, + entityDimensions, entityRegistrationPoint, false); + } + if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { IntersectionType type = IntersectionType::ENTITY; if (getFilter().doesPickLocalEntities()) { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 28edf2e1a2..363a7f39d1 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -85,7 +85,7 @@ public: void setUnscaledDimensions(const glm::vec3& value) override; bool shouldBePhysical() const override { return !isDead(); } - + bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance,