From cbf05436460d896f46465b4a1e9f627c030b3236 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 10 Nov 2017 13:22:38 -0800 Subject: [PATCH] deadspot --- interface/src/raypick/LaserPointer.cpp | 2 +- interface/src/raypick/LaserPointer.h | 2 +- interface/src/raypick/StylusPointer.cpp | 78 +++++++++++++-------- interface/src/raypick/StylusPointer.h | 11 ++- libraries/pointers/src/pointers/Pointer.cpp | 4 +- libraries/pointers/src/pointers/Pointer.h | 2 +- 6 files changed, 64 insertions(+), 35 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index bd54a24e97..5e0d61f24b 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -289,7 +289,7 @@ RenderState LaserPointer::buildRenderState(const QVariantMap& propMap) { return RenderState(startID, pathID, endID); } -PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult) const { +PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover) const { QUuid pickedID; glm::vec3 intersection, surfaceNormal, direction, origin; auto rayPickResult = std::static_pointer_cast(pickResult); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 4874cadf0a..59be58d4ac 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -70,7 +70,7 @@ public: static RenderState buildRenderState(const QVariantMap& propMap); protected: - PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult) const override; + PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const override; PickedObject getHoveredObject(const PickResultPointer& pickResult) override; Pointer::Buttons getPressedButtons() override; diff --git a/interface/src/raypick/StylusPointer.cpp b/interface/src/raypick/StylusPointer.cpp index 80e783cfe4..1a172b8894 100644 --- a/interface/src/raypick/StylusPointer.cpp +++ b/interface/src/raypick/StylusPointer.cpp @@ -17,8 +17,6 @@ #include "PickScriptingInterface.h" #include -using namespace controller; - // TODO: make these configurable per pointer static const float WEB_STYLUS_LENGTH = 0.2f; @@ -30,6 +28,10 @@ static const float TABLET_MAX_TOUCH_DISTANCE = 0.01f; static const float HOVER_HYSTERESIS = 0.01f; static const float TOUCH_HYSTERESIS = 0.02f; +static const float STYLUS_MOVE_DELAY = 0.33f * USECS_PER_SECOND; +static const float TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0481f; +static const float TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED = TOUCH_PRESS_TO_MOVE_DEADSPOT * TOUCH_PRESS_TO_MOVE_DEADSPOT; + StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled) : Pointer(DependencyManager::get()->createStylusPick(props), enabled, hover), _stylusOverlay(stylusOverlay) @@ -115,16 +117,10 @@ bool StylusPointer::shouldTrigger(const PickResultPointer& pickResult) { float distance = stylusPickResult->distance; // If we're triggering on an object, recalculate the distance instead of using the pickResult + glm::vec3 origin = vec3FromVariant(stylusPickResult->pickVariant["position"]); + glm::vec3 direction = -_state.surfaceNormal; if (!_state.triggeredObject.objectID.isNull() && stylusPickResult->objectID != _state.triggeredObject.objectID) { - glm::vec3 intersection; - glm::vec3 origin = vec3FromVariant(stylusPickResult->pickVariant["position"]); - glm::vec3 direction = -_state.surfaceNormal; - if (_state.triggeredObject.type == ENTITY) { - intersection = RayPick::intersectRayWithEntityXYPlane(_state.triggeredObject.objectID, origin, direction); - } else if (_state.triggeredObject.type == OVERLAY) { - intersection = RayPick::intersectRayWithOverlayXYPlane(_state.triggeredObject.objectID, origin, direction); - } - distance = glm::dot(intersection - origin, direction); + distance = glm::dot(findIntersection(_state.triggeredObject, origin, direction) - origin, direction); } float hysteresis = _state.triggering ? TOUCH_HYSTERESIS * sensorScaleFactor : 0.0f; @@ -132,6 +128,9 @@ bool StylusPointer::shouldTrigger(const PickResultPointer& pickResult) { TABLET_MAX_TOUCH_DISTANCE * sensorScaleFactor, hysteresis)) { if (_state.triggeredObject.objectID.isNull()) { _state.triggeredObject = PickedObject(stylusPickResult->objectID, stylusPickResult->type); + _state.intersection = findIntersection(_state.triggeredObject, origin, direction); + _state.triggerPos2D = findPos2D(_state.triggeredObject, origin); + _state.triggerStartTime = usecTimestampNow(); _state.surfaceNormal = stylusPickResult->surfaceNormal; _state.triggering = true; } @@ -140,6 +139,9 @@ bool StylusPointer::shouldTrigger(const PickResultPointer& pickResult) { } _state.triggeredObject = PickedObject(); + _state.intersection = glm::vec3(NAN); + _state.triggerPos2D = glm::vec2(NAN); + _state.triggerStartTime = 0; _state.surfaceNormal = glm::vec3(NAN); _state.triggering = false; return false; @@ -159,34 +161,30 @@ Pointer::Buttons StylusPointer::getPressedButtons() { return toReturn; } -PointerEvent StylusPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult) const { +PointerEvent StylusPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover) const { QUuid pickedID; + glm::vec2 pos2D; glm::vec3 intersection, surfaceNormal, direction, origin; auto stylusPickResult = std::static_pointer_cast(pickResult); if (stylusPickResult) { intersection = stylusPickResult->intersection; - surfaceNormal = _state.surfaceNormal; + surfaceNormal = hover ? stylusPickResult->surfaceNormal : _state.surfaceNormal; const QVariantMap& stylusTip = stylusPickResult->pickVariant; origin = vec3FromVariant(stylusTip["position"]); - direction = -_state.surfaceNormal; + direction = -surfaceNormal; + pos2D = findPos2D(target, origin); pickedID = stylusPickResult->objectID; } - if (pickedID != target.objectID) { - if (target.type == ENTITY) { - intersection = RayPick::intersectRayWithEntityXYPlane(target.objectID, origin, direction); - } else if (target.type == OVERLAY) { - intersection = RayPick::intersectRayWithOverlayXYPlane(target.objectID, origin, direction); - } - } - glm::vec2 pos2D; - if (target.type == ENTITY) { - pos2D = RayPick::projectOntoEntityXYPlane(target.objectID, origin); - } else if (target.type == OVERLAY) { - pos2D = RayPick::projectOntoOverlayXYPlane(target.objectID, origin); - } else if (target.type == HUD) { - pos2D = DependencyManager::get()->calculatePos2DFromHUD(origin); + // If we just started triggering and we haven't moved too much, don't update intersection and pos2D + if (!_state.triggeredObject.objectID.isNull() && usecTimestampNow() - _state.triggerStartTime < STYLUS_MOVE_DELAY && + glm::distance2(pos2D, _state.triggerPos2D) < TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED) { + pos2D = _state.triggerPos2D; + intersection = _state.intersection; + } else if (pickedID != target.objectID) { + intersection = findIntersection(target, origin, direction); } + return PointerEvent(pos2D, intersection, surfaceNormal, direction); } @@ -203,4 +201,28 @@ void StylusPointer::setRenderState(const std::string& state) { } else if (state == "disabled") { _renderState = DISABLED; } +} + +glm::vec3 StylusPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) { + switch (pickedObject.type) { + case ENTITY: + return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction); + case OVERLAY: + return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction); + default: + return glm::vec3(NAN); + } +} + +glm::vec2 StylusPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) { + switch (pickedObject.type) { + case ENTITY: + return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin); + case OVERLAY: + return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin); + case HUD: + return DependencyManager::get()->calculatePos2DFromHUD(origin); + default: + return glm::vec2(NAN); + } } \ No newline at end of file diff --git a/interface/src/raypick/StylusPointer.h b/interface/src/raypick/StylusPointer.h index cc7f2814db..fb2d492798 100644 --- a/interface/src/raypick/StylusPointer.h +++ b/interface/src/raypick/StylusPointer.h @@ -41,7 +41,7 @@ protected: bool shouldHover(const PickResultPointer& pickResult) override; bool shouldTrigger(const PickResultPointer& pickResult) override; - PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult) const override; + PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const override; private: void show(const StylusTip& tip); @@ -49,9 +49,13 @@ private: struct TriggerState { PickedObject triggeredObject; + glm::vec3 intersection { NAN }; + glm::vec2 triggerPos2D { NAN }; glm::vec3 surfaceNormal { NAN }; - bool hovering { false }; + quint64 triggerStartTime { 0 }; bool triggering { false }; + + bool hovering { false }; }; TriggerState _state; @@ -67,6 +71,9 @@ private: const OverlayID _stylusOverlay; static bool isWithinBounds(float distance, float min, float max, float hysteresis); + static glm::vec3 findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction); + static glm::vec2 findPos2D(const PickedObject& pickedObject, const glm::vec3& origin); + }; #endif // hifi_StylusPointer_h diff --git a/libraries/pointers/src/pointers/Pointer.cpp b/libraries/pointers/src/pointers/Pointer.cpp index e17fb8ec65..d5aa13d293 100644 --- a/libraries/pointers/src/pointers/Pointer.cpp +++ b/libraries/pointers/src/pointers/Pointer.cpp @@ -199,7 +199,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin // Trigger continue for (const std::string& button : sameButtons) { - PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult); + PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, false); triggeredEvent.setID(pointerID); triggeredEvent.setType(PointerEvent::Move); triggeredEvent.setButton(chooseButton(button)); @@ -214,7 +214,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin // Trigger end for (const std::string& button : _prevButtons) { - PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult); + PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, false); triggeredEvent.setID(pointerID); triggeredEvent.setType(PointerEvent::Release); triggeredEvent.setButton(chooseButton(button)); diff --git a/libraries/pointers/src/pointers/Pointer.h b/libraries/pointers/src/pointers/Pointer.h index 0415f00d1e..6acbcf9ca0 100644 --- a/libraries/pointers/src/pointers/Pointer.h +++ b/libraries/pointers/src/pointers/Pointer.h @@ -82,7 +82,7 @@ protected: bool _enabled; bool _hover; - virtual PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult) const = 0; + virtual PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const = 0; virtual PickedObject getHoveredObject(const PickResultPointer& pickResult) = 0; virtual Buttons getPressedButtons() = 0;