From 1362e7f3613949ea967b87306ed231bd5c0076b3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 08:26:54 +1300 Subject: [PATCH 1/5] Fix near parent grab entity tear away distance calc --- .../controllerModules/nearParentGrabEntity.js | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index f354067a77..e5d3b055bc 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -24,15 +24,6 @@ Script.include("/~/system/libraries/controllers.js"); // XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true; // XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC; - // this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 - var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral - - function getGrabOffset(handController) { - var offset = getGrabPointSphereOffset(handController, true); - offset.y = -offset.y; - return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); - } - function NearParentingGrabEntity(hand) { this.hand = hand; this.targetEntityID = null; @@ -178,8 +169,10 @@ Script.include("/~/system/libraries/controllers.js"); this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { var tearAwayDistance = TEAR_AWAY_DISTANCE * MyAvatar.sensorToWorldScale; - var controllerIndex = (this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); - var controllerGrabOffset = getGrabOffset(controllerIndex); + var controllerIndex = + this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true); + controllerGrabOffset = Vec3.multiply(-1, controllerGrabOffset); var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset); if (distance > tearAwayDistance) { this.autoUnequipCounter++; @@ -242,13 +235,15 @@ Script.include("/~/system/libraries/controllers.js"); // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var tearAwayDistance = TEAR_AWAY_DISTANCE * sensorScaleFactor; + var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; - var handPosition = controllerData.controllerLocations[this.hand].position; - var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); - var distance = Vec3.distance(handPosition, props.position); - if ((dist > TEAR_AWAY_DISTANCE) || - (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. + var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); + var distance = Vec3.distance(grabPosition, props.position); + if ((dist > tearAwayDistance) || + (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { From f1dad3c465b3bcc07605470db8a6a75fca168733 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 08:35:02 +1300 Subject: [PATCH 2/5] Add hystersis between near parent grabbing and tearing away --- .../controllers/controllerModules/nearParentGrabEntity.js | 7 ++++--- scripts/system/libraries/controllerDispatcherUtils.js | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index e5d3b055bc..db10fff69a 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -12,7 +12,8 @@ findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity, - distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES + distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES, + NEAR_GRAB_DISTANCE */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -235,14 +236,14 @@ Script.include("/~/system/libraries/controllers.js"); // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var tearAwayDistance = TEAR_AWAY_DISTANCE * sensorScaleFactor; + var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor; var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); var distance = Vec3.distance(grabPosition, props.position); - if ((dist > tearAwayDistance) || + if ((dist > nearGrabDistance) || (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. continue; } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index e9d5255d28..ab2801087e 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -53,6 +53,7 @@ TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, TEAR_AWAY_CHECK_TIME:true, + NEAR_GRAB_DISTANCE: true, distanceBetweenPointAndEntityBoundingBox:true, entityIsEquipped:true, entityIsFarGrabbedByOther:true, @@ -99,6 +100,10 @@ NEAR_GRAB_RADIUS = 1.0; TEAR_AWAY_DISTANCE = 0.15; // ungrab an entity if its bounding-box moves this far from the hand TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks + +NEAR_GRAB_DISTANCE = 0.14; // Grab an entity if its bounding box is within this distance. +// Smaller than TEAR_AWAY_DISTANCE for hysteresis. + DISPATCHER_HOVERING_LIST = "dispactherHoveringList"; DISPATCHER_HOVERING_STYLE = { isOutlineSmooth: true, From 29c268df5ae0e4c9bf03543d9b96047da74f8490 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:38:54 +1300 Subject: [PATCH 3/5] Remove extraneous grab entity haptic pulses --- .../controllers/controllerModules/farParentGrabEntity.js | 6 ------ .../controllerModules/nearActionGrabEntity.js | 7 ------- .../controllerModules/nearParentGrabEntity.js | 9 --------- 3 files changed, 22 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index f85869aa7f..4b85c6d046 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -256,7 +256,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endFarParentGrab = function (controllerData) { - this.hapticTargetID = null; // var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (this.thisFarGrabJointIsParent(endProps)) { @@ -410,11 +409,6 @@ Script.include("/~/system/libraries/controllers.js"); if (targetEntity) { var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); if (entityIsGrabbable(gtProps)) { - // give haptic feedback - if (gtProps.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = gtProps.id; - } // if we've attempted to grab a child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, gtProps); if (entityIsGrabbable(groupRootProps)) { diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 5ced6080a2..1d1f89e2c7 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -24,7 +24,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.hand = hand; this.targetEntityID = null; this.actionID = null; // action this script created... - this.hapticTargetID = null; this.parameters = makeDispatcherModuleParameters( 500, @@ -171,10 +170,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); break; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -206,7 +201,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); return makeRunningValues(true, [this.targetEntityID], []); } } else { - this.hapticTargetID = null; return makeRunningValues(false, [], []); } }; @@ -216,7 +210,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.endNearGrabAction(); - this.hapticTargetID = null; return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index db10fff69a..3be6f602c2 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -32,7 +32,6 @@ Script.include("/~/system/libraries/controllers.js"); this.previousParentID = {}; this.previousParentJointIndex = {}; this.previouslyUnhooked = {}; - this.hapticTargetID = null; this.lastUnequipCheckTime = 0; this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; @@ -138,7 +137,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endNearParentingGrabEntity = function (controllerData) { - this.hapticTargetID = null; var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (this.thisHandIsParent(props) && !this.robbed) { Entities.editEntity(this.targetEntityID, { @@ -248,11 +246,6 @@ Script.include("/~/system/libraries/controllers.js"); continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - // give haptic feedback - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -295,7 +288,6 @@ Script.include("/~/system/libraries/controllers.js"); unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } @@ -316,7 +308,6 @@ Script.include("/~/system/libraries/controllers.js"); this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } From f2abf8e398a733fbe804c1168b6011cf5095abbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:43:05 +1300 Subject: [PATCH 4/5] Debounce haptic pulses at start of near parent grab --- .../controllerModules/farParentGrabEntity.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index 4b85c6d046..230c4f06db 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -61,6 +61,8 @@ Script.include("/~/system/libraries/controllers.js"); this.reticleMinY = MARGIN; this.reticleMaxY = 0; this.lastUnexpectedChildrenCheckTime = 0; + this.endedGrab = 0; + this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX @@ -144,7 +146,12 @@ Script.include("/~/system/libraries/controllers.js"); // compute the mass for the purpose of energy and how quickly to move object this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density); - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + // Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to + // changing positions and floating point rounding. + if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) { + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + } + unhighlightTargetEntity(this.targetEntityID); var message = { hand: this.hand, @@ -256,6 +263,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endFarParentGrab = function (controllerData) { + this.endedGrab = Date.now(); // var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (this.thisFarGrabJointIsParent(endProps)) { From c96cd422e186180dde2b2ce95e4e2059ad38ad66 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:58:40 +1300 Subject: [PATCH 5/5] Fix near parent grab tear away calc for avatar scale --- .../controllers/controllerModules/nearParentGrabEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 3be6f602c2..433ad9ef53 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -171,7 +171,7 @@ Script.include("/~/system/libraries/controllers.js"); var controllerIndex = this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand; var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true); - controllerGrabOffset = Vec3.multiply(-1, controllerGrabOffset); + controllerGrabOffset = Vec3.multiply(-MyAvatar.sensorToWorldScale, controllerGrabOffset); var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset); if (distance > tearAwayDistance) { this.autoUnequipCounter++;