From 7d956198cda66c95dded909d51438b0f3a180fca Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Sep 2019 16:00:09 -0700 Subject: [PATCH 01/27] re-enable prefer finger over stylus --- interface/src/Application.h | 4 +--- interface/src/ui/PreferencesDialog.cpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 198f5ef7cf..684ff6bdaa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -223,9 +223,7 @@ public: bool getPreferStylusOverLaser() { return _preferStylusOverLaserSetting.get(); } void setPreferStylusOverLaser(bool value); - // FIXME: Remove setting completely or make available through JavaScript API? - //bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); } - bool getPreferAvatarFingerOverStylus() { return false; } + bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); } void setPreferAvatarFingerOverStylus(bool value); bool getMiniTabletEnabled() { return _miniTabletEnabledSetting.get(); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 7e11406808..34cacb733e 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -223,13 +223,11 @@ void setupPreferences() { preferences->addPreference(preference); } - /* - // FIXME: Remove setting completely or make available through JavaScript API? { auto getter = []()->bool { return qApp->getPreferAvatarFingerOverStylus(); }; auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); }; preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter)); - }*/ + } // Snapshots static const QString SNAPSHOTS { "Snapshots" }; From 3d4de67c49d65144559630cbb61c76e5c816d903 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Sep 2019 12:40:03 -0700 Subject: [PATCH 02/27] allow thumb+index finger pinch to mean same as trigger click --- .../controllers/controllerDispatcher.js | 38 ++++++++++++++++++- .../controllerModules/nearGrabEntity.js | 2 +- .../controllerModules/stylusInput.js | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index f0d3ec0c03..d73e5de7e7 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -35,7 +35,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var DEBUG = false; var SHOW_GRAB_SPHERE = false; - if (typeof Test !== "undefined") { PROFILE = true; } @@ -97,11 +96,15 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.runningPluginNames = {}; + this.leftTriggerValue = 0; this.leftTriggerClicked = 0; + this.leftTrackerClicked = false; // is leftTriggerClicked == 1 because a hand tracker set it? + this.leftSecondaryValue = 0; + this.rightTriggerValue = 0; this.rightTriggerClicked = 0; - this.leftSecondaryValue = 0; + this.rightTrackerClicked = false; // is rightTriggerClicked == 1 because a hand tracker set it? this.rightSecondaryValue = 0; this.leftTriggerPress = function (value) { @@ -162,6 +165,34 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } }; + this.checkForHandTrackingClick = function() { + + var pinchOnBelowDistance = 0.016; + var pinchOffAboveDistance = 0.04; + + var leftIndexPose = Controller.getPoseValue(Controller.Standard.LeftHandIndex4); + var leftThumbPose = Controller.getPoseValue(Controller.Standard.LeftHandThumb4); + var leftThumbToIndexDistance = Vec3.distance(leftIndexPose.translation, leftThumbPose.translation); + if (leftIndexPose.valid && leftThumbPose.valid && leftThumbToIndexDistance < pinchOnBelowDistance) { + _this.leftTriggerClicked = 1; + _this.leftTrackerClicked = true; + } else if (_this.leftTrackerClicked && leftThumbToIndexDistance > pinchOffAboveDistance) { + _this.leftTriggerClicked = 0; + _this.leftTrackerClicked = false; + } + + var rightIndexPose = Controller.getPoseValue(Controller.Standard.RightHandIndex4); + var rightThumbPose = Controller.getPoseValue(Controller.Standard.RightHandThumb4); + var rightThumbToIndexDistance = Vec3.distance(rightIndexPose.translation, rightThumbPose.translation); + if (rightIndexPose.valid && rightThumbPose.valid && rightThumbToIndexDistance < pinchOnBelowDistance) { + _this.rightTriggerClicked = 1; + _this.rightTrackerClicked = true; + } else if (_this.rightTrackerClicked && rightThumbToIndexDistance > pinchOffAboveDistance) { + _this.rightTriggerClicked = 0; + _this.rightTrackerClicked = false; + } + }; + this.update = function () { try { _this.updateInternal(); @@ -369,6 +400,9 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } } + // check for hand-tracking "click" + _this.checkForHandTrackingClick(); + // bundle up all the data about the current situation var controllerData = { triggerValues: [_this.leftTriggerValue, _this.rightTriggerValue], diff --git a/scripts/system/controllers/controllerModules/nearGrabEntity.js b/scripts/system/controllers/controllerModules/nearGrabEntity.js index 763c1a1ce0..45d518bb39 100644 --- a/scripts/system/controllers/controllerModules/nearGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearGrabEntity.js @@ -151,7 +151,7 @@ Script.include("/~/system/libraries/controllers.js"); this.run = function (controllerData, deltaTime) { if (this.grabbing) { - if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && + if (!controllerData.triggerClicks[this.hand] && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.endNearGrabEntity(); return makeRunningValues(false, [], []); diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index c4aa9efd50..544fbb9277 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -67,7 +67,7 @@ Script.include("/~/system/libraries/controllers.js"); var nearTabletHighlightModuleReady = nearTabletHighlightModule ? nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); return grabOverlayModuleReady.active || farGrabModuleReady.active || grabEntityModuleReady.active - || nearTabletHighlightModuleReady.active; + /* || nearTabletHighlightModuleReady.active */ ; }; this.overlayLaserActive = function(controllerData) { From 2c535fa204ab97ca7bfb4f772d978dfd64c3c205 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Sep 2019 12:41:14 -0700 Subject: [PATCH 03/27] touching tips of index-fingers together means walk forward --- scripts/defaultScripts.js | 3 +- scripts/system/hand-track-walk.js | 69 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 scripts/system/hand-track-walk.js diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 1eac2ae0aa..a19bb9c41a 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -35,7 +35,8 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/miniTablet.js", "system/audioMuteOverlay.js", "system/inspect.js", - "system/keyboardShortcuts/keyboardShortcuts.js" + "system/keyboardShortcuts/keyboardShortcuts.js", + "system/hand-track-walk.js" ]; var DEFAULT_SCRIPTS_SEPARATE = [ "system/controllers/controllerScripts.js", diff --git a/scripts/system/hand-track-walk.js b/scripts/system/hand-track-walk.js new file mode 100644 index 0000000000..cb9b700ae5 --- /dev/null +++ b/scripts/system/hand-track-walk.js @@ -0,0 +1,69 @@ + +/* global Script, Controller, Vec3 */ +/* jshint loopfunc:true */ + +(function() { + + var mappingName = 'hand-track-walk-' + Math.random(); + var inputMapping = Controller.newMapping(mappingName); + + var leftIndexPos = null; + var rightIndexPos = null; + + var pinchOnBelowDistance = 0.016; + var pinchOffAboveDistance = 0.04; + + var walking = false; + + function updateWalking() { + if (leftIndexPos && rightIndexPos) { + var tipDistance = Vec3.distance(leftIndexPos, rightIndexPos); + if (tipDistance < pinchOnBelowDistance) { + print("qqqq walking"); + walking = true; + } else if (walking && tipDistance > pinchOffAboveDistance) { + print("qqqq stopping"); + walking = false; + } + } + } + + function leftIndexChanged(pose) { + if (pose.valid) { + leftIndexPos = pose.translation; + } else { + leftIndexPos = null; + } + updateWalking(); + } + + function rightIndexChanged(pose) { + if (pose.valid) { + rightIndexPos = pose.translation; + } else { + rightIndexPos = null; + } + updateWalking(); + } + + function cleanUp() { + inputMapping.disable(); + } + + Script.scriptEnding.connect(function () { + cleanUp(); + }); + + inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(leftIndexChanged); + inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(rightIndexChanged); + + inputMapping.from(function() { + if (walking) { + return -1; + } else { + return Controller.getActionValue(Controller.Standard.TranslateZ); + } + }).to(Controller.Actions.TranslateZ); + + Controller.enableMapping(mappingName); +})(); From 296617977ce4121fa5426d8c565841117bb160ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Oct 2019 09:14:55 -0700 Subject: [PATCH 04/27] get near-grab working with camera-tracked hands --- scripts/system/controllers/controllerDispatcher.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index d73e5de7e7..24d0e2703d 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -168,16 +168,18 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.checkForHandTrackingClick = function() { var pinchOnBelowDistance = 0.016; - var pinchOffAboveDistance = 0.04; + var pinchOffAboveDistance = 0.035; var leftIndexPose = Controller.getPoseValue(Controller.Standard.LeftHandIndex4); var leftThumbPose = Controller.getPoseValue(Controller.Standard.LeftHandThumb4); var leftThumbToIndexDistance = Vec3.distance(leftIndexPose.translation, leftThumbPose.translation); if (leftIndexPose.valid && leftThumbPose.valid && leftThumbToIndexDistance < pinchOnBelowDistance) { _this.leftTriggerClicked = 1; + _this.leftTriggerValue = 1; _this.leftTrackerClicked = true; } else if (_this.leftTrackerClicked && leftThumbToIndexDistance > pinchOffAboveDistance) { _this.leftTriggerClicked = 0; + _this.leftTriggerValue = 0; _this.leftTrackerClicked = false; } @@ -186,9 +188,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var rightThumbToIndexDistance = Vec3.distance(rightIndexPose.translation, rightThumbPose.translation); if (rightIndexPose.valid && rightThumbPose.valid && rightThumbToIndexDistance < pinchOnBelowDistance) { _this.rightTriggerClicked = 1; + _this.rightTriggerValue = 1; _this.rightTrackerClicked = true; } else if (_this.rightTrackerClicked && rightThumbToIndexDistance > pinchOffAboveDistance) { _this.rightTriggerClicked = 0; + _this.rightTriggerValue = 0; _this.rightTrackerClicked = false; } }; From 1c926db2db6e350baeaad2c68aded09a12e41b6a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Oct 2019 11:45:33 -0700 Subject: [PATCH 05/27] if hands are tracked, make mini-tablet be just a big open-tablet button (remove mute and goto buttons) --- scripts/system/html/css/miniHandTablet.css | 56 ++++++++++++++++++++++ scripts/system/html/js/miniTablet.js | 34 +++++++++---- scripts/system/html/miniHandsTablet.html | 26 ++++++++++ scripts/system/miniTablet.js | 47 ++++++++++-------- 4 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 scripts/system/html/css/miniHandTablet.css create mode 100644 scripts/system/html/miniHandsTablet.html diff --git a/scripts/system/html/css/miniHandTablet.css b/scripts/system/html/css/miniHandTablet.css new file mode 100644 index 0000000000..ef2c27ff14 --- /dev/null +++ b/scripts/system/html/css/miniHandTablet.css @@ -0,0 +1,56 @@ +/* +miniTablet.css + +Copyright 2019 High Fidelity, Inc. + +Distributed under the Apache License, Version 2.0. +See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +* { + box-sizing: border-box; + padding: 0; + margin: 0; + user-select: none; +} + +html { + background-color: #404040; +} + +body { + height: 100%; +} + +section { + background-color: #404040; + position: relative; + padding: 32px 0px; +} + +.button { + text-align: center; +} + +img { + width: 149px; + height: 149px; +} + +#expand { + width: 149px; + height: 149px; + background-size: 100% 100%; + background-image: url("./img/mt-expand-normal.svg"); +} + +#expand:hover { + background-image: url("./img/mt-expand-hover.svg"); +} + +#expand:hover.unhover { + background-image: url("./img/mt-expand-normal.svg"); +} + +#expand img { +} diff --git a/scripts/system/html/js/miniTablet.js b/scripts/system/html/js/miniTablet.js index c48201cef5..b02c6ae213 100644 --- a/scripts/system/html/js/miniTablet.js +++ b/scripts/system/html/js/miniTablet.js @@ -35,7 +35,9 @@ function setUnhover() { if (!isUnhover) { - gotoButton.classList.add("unhover"); + if (gotoButton) { + gotoButton.classList.add("unhover"); + } expandButton.classList.add("unhover"); isUnhover = true; } @@ -43,7 +45,9 @@ function clearUnhover() { if (isUnhover) { - gotoButton.classList.remove("unhover"); + if (gotoButton) { + gotoButton.classList.remove("unhover"); + } expandButton.classList.remove("unhover"); isUnhover = false; } @@ -62,10 +66,14 @@ switch (message.type) { case MUTE_MESSAGE: - muteImage.src = message.icon; + if (muteImage) { + muteImage.src = message.icon; + } break; case GOTO_MESSAGE: - gotoImage.src = message.icon; + if (gotoImage) { + gotoImage.src = message.icon; + } break; } } @@ -130,9 +138,7 @@ function onLoad() { muteButton = document.getElementById("mute"); - muteImage = document.getElementById("mute-img"); gotoButton = document.getElementById("goto"); - gotoImage = document.getElementById("goto-img"); expandButton = document.getElementById("expand"); connectEventBridge(); @@ -140,11 +146,19 @@ document.body.addEventListener("mouseenter", onBodyHover, false); document.body.addEventListener("mouseleave", onBodyUnhover, false); - muteButton.addEventListener("mouseenter", onButtonHover, false); - gotoButton.addEventListener("mouseenter", onButtonHover, false); + if (muteButton) { + muteImage = document.getElementById("mute-img"); + muteButton.addEventListener("mouseenter", onButtonHover, false); + muteButton.addEventListener("click", onMuteButtonClick, true); + } + + if (gotoButton) { + gotoImage = document.getElementById("goto-img"); + gotoButton.addEventListener("mouseenter", onButtonHover, false); + gotoButton.addEventListener("click", onGotoButtonClick, true); + } + expandButton.addEventListener("mouseenter", onButtonHover, false); - muteButton.addEventListener("click", onMuteButtonClick, true); - gotoButton.addEventListener("click", onGotoButtonClick, true); expandButton.addEventListener("click", onExpandButtonClick, true); document.body.onunload = function () { diff --git a/scripts/system/html/miniHandsTablet.html b/scripts/system/html/miniHandsTablet.html new file mode 100644 index 0000000000..1d140797f4 --- /dev/null +++ b/scripts/system/html/miniHandsTablet.html @@ -0,0 +1,26 @@ + + + + + + + + + + +
+
+ +
+
+ + + diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index f5b5ecf0a1..bc9bcfe36d 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -8,7 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global getTabletWidthFromSettings, TRIGGER_OFF_VALUE */ +/* global getTabletWidthFromSettings, TRIGGER_OFF_VALUE, Controller, Script, Camera, Tablet, MyAvatar, + Quat, SoundCache, HMD, Overlays, Vec3, Uuid, Messages */ (function () { @@ -80,6 +81,10 @@ return hand === LEFT_HAND ? RIGHT_HAND : LEFT_HAND; } + function handsAreTracked() { + return Controller.getPoseValue(Controller.Standard.LeftHandIndex3).valid || + Controller.getPoseValue(Controller.Standard.RightHandIndex3).valid; + } UI = function () { @@ -114,6 +119,7 @@ uiHand = LEFT_HAND, miniUIOverlay = null, MINI_UI_HTML = Script.resolvePath("./html/miniTablet.html"), + MINI_HAND_UI_HTML = Script.resolvePath("./html/miniHandsTablet.html"), MINI_UI_DIMENSIONS = { x: 0.059, y: 0.0865, z: 0.001 }, MINI_UI_WIDTH_PIXELS = 150, METERS_TO_INCHES = 39.3701, @@ -291,6 +297,7 @@ visible: true }); Overlays.editOverlay(miniUIOverlay, { + url: handsAreTracked() ? MINI_HAND_UI_HTML : MINI_UI_HTML, localPosition: Vec3.multiply(MyAvatar.sensorToWorldScale, MINI_UI_LOCAL_POSITION), localRotation: MINI_UI_LOCAL_ROTATION, dimensions: Vec3.multiply(initialScale, MINI_UI_DIMENSIONS), @@ -353,8 +360,8 @@ localRotation, localPosition; - tabletScaleFactor = MyAvatar.sensorToWorldScale - * (1 + scaleFactor * (miniTargetWidth - miniInitialWidth) / miniInitialWidth); + tabletScaleFactor = MyAvatar.sensorToWorldScale * + (1 + scaleFactor * (miniTargetWidth - miniInitialWidth) / miniInitialWidth); dimensions = Vec3.multiply(tabletScaleFactor, MINI_DIMENSIONS); localRotation = Quat.mix(miniExpandLocalRotation, miniTargetLocalRotation, scaleFactor); localPosition = @@ -469,11 +476,11 @@ solid: true, grabbable: true, showKeyboardFocusHighlight: false, - drawInFront: true, + drawInFront: false, visible: false }); miniUIOverlay = Overlays.addOverlay("web3d", { - url: MINI_UI_HTML, + url: handsAreTracked() ? MINI_HAND_UI_HTML : MINI_UI_HTML, parentID: miniOverlay, localPosition: Vec3.multiply(MyAvatar.sensorToWorldScale, MINI_UI_LOCAL_POSITION), localRotation: MINI_UI_LOCAL_ROTATION, @@ -482,7 +489,7 @@ alpha: 0, // Hide overlay while its content is being created. grabbable: false, showKeyboardFocusHighlight: false, - drawInFront: true, + drawInFront: false, visible: false }); @@ -642,8 +649,8 @@ // is grabbing something) or the other hand's trigger is pressed unless it is pointing at the mini tablet. Allow // the triggers to be pressed briefly to allow for the grabbing process. if (show) { - isLeftTriggerOff = Controller.getValue(Controller.Standard.LT) < TRIGGER_OFF_VALUE - && Controller.getValue(Controller.Standard.LeftGrip) < TRIGGER_OFF_VALUE; + isLeftTriggerOff = Controller.getValue(Controller.Standard.LT) < TRIGGER_OFF_VALUE && + Controller.getValue(Controller.Standard.LeftGrip) < TRIGGER_OFF_VALUE; if (!isLeftTriggerOff) { if (leftTriggerOn === 0) { leftTriggerOn = Date.now(); @@ -653,8 +660,8 @@ } else { leftTriggerOn = 0; } - isRightTriggerOff = Controller.getValue(Controller.Standard.RT) < TRIGGER_OFF_VALUE - && Controller.getValue(Controller.Standard.RightGrip) < TRIGGER_OFF_VALUE; + isRightTriggerOff = Controller.getValue(Controller.Standard.RT) < TRIGGER_OFF_VALUE && + Controller.getValue(Controller.Standard.RightGrip) < TRIGGER_OFF_VALUE; if (!isRightTriggerOff) { if (rightTriggerOn === 0) { rightTriggerOn = Date.now(); @@ -665,8 +672,8 @@ rightTriggerOn = 0; } - show = (hand === LEFT_HAND ? wasLeftTriggerOff : wasRightTriggerOff) - && ((hand === LEFT_HAND ? wasRightTriggerOff : wasLeftTriggerOff) || ui.isLaserPointingAt()); + show = (hand === LEFT_HAND ? wasLeftTriggerOff : wasRightTriggerOff) && + ((hand === LEFT_HAND ? wasRightTriggerOff : wasLeftTriggerOff) || ui.isLaserPointingAt()); } // Should show mini tablet if it would be oriented toward the camera. @@ -691,10 +698,10 @@ normalDot = Vec3.dot(normalHandVector, miniToCameraDirection); medialAngle = Math.atan2(medialDot, normalDot); lateralAngle = Math.atan2(lateralDot, normalDot); - show = -MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD <= medialAngle - && medialAngle <= MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD - && -MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD <= lateralAngle - && lateralAngle <= MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD; + show = -MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD <= medialAngle && + medialAngle <= MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD && + -MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD <= lateralAngle && + lateralAngle <= MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD; // Camera looking at mini tablet? cameraToMini = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); @@ -972,8 +979,8 @@ function setState(state, data) { if (state !== miniState) { - debug("State transition from " + STATE_STRINGS[miniState] + " to " + STATE_STRINGS[state] - + ( data ? " " + JSON.stringify(data) : "")); + debug("State transition from " + STATE_STRINGS[miniState] + " to " + STATE_STRINGS[state] + + ( data ? " " + JSON.stringify(data) : "")); if (STATE_MACHINE[STATE_STRINGS[miniState]].exit) { STATE_MACHINE[STATE_STRINGS[miniState]].exit(data); } @@ -1061,8 +1068,8 @@ return; } - if (miniState.getState() === miniState.MINI_DISABLED - || (message.grabbedEntity !== HMD.tabletID && message.grabbedEntity !== ui.getMiniTabletID())) { + if (miniState.getState() === miniState.MINI_DISABLED || + (message.grabbedEntity !== HMD.tabletID && message.grabbedEntity !== ui.getMiniTabletID())) { return; } From fa4d055ab16614b99da59f0354053898614deb01 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Oct 2019 14:52:33 -0700 Subject: [PATCH 06/27] disable far-trigger and grab if using hand tracker --- .../controllerModules/farActionGrabEntity.js | 5 ++++- .../controllers/controllerModules/farGrabEntity.js | 8 +++++--- .../system/controllers/controllerModules/farTrigger.js | 5 ++++- scripts/system/libraries/controllerDispatcherUtils.js | 10 ++++++++-- scripts/system/miniTablet.js | 7 +------ 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 1eaed44ce2..8f18be9c27 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -14,7 +14,7 @@ TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager, getEntityParents, Selection, DISPATCHER_HOVERING_LIST, - worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES, Uuid, Picks + worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES, Uuid, Picks, handsAreTracked, Messages */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -374,6 +374,9 @@ Script.include("/~/system/libraries/controllers.js"); this.isReady = function (controllerData) { if (HMD.active) { + if (handsAreTracked()) { + return makeRunningValues(false, [], []); + } if (this.notPointingAtEntity(controllerData)) { return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index ecafa3cb26..c486d46c33 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -12,7 +12,7 @@ HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager, getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGrabbableGroupParent, - worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES + worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES, handsAreTracked */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -63,7 +63,6 @@ Script.include("/~/system/libraries/controllers.js"); this.endedGrab = 0; this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms this.disabled = false; - var _this = this; this.initialControllerRotation = Quat.IDENTITY; this.currentControllerRotation = Quat.IDENTITY; this.manipulating = false; @@ -99,7 +98,7 @@ Script.include("/~/system/libraries/controllers.js"); this.getOffhand = function () { return (this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND); - } + }; // Activation criteria for rotating a fargrabbed entity. If we're changing the mapping, this is where to do it. this.shouldManipulateTarget = function (controllerData) { @@ -406,6 +405,9 @@ Script.include("/~/system/libraries/controllers.js"); this.isReady = function (controllerData) { if (HMD.active) { + if (handsAreTracked()) { + return makeRunningValues(false, [], []); + } if (this.notPointingAtEntity(controllerData)) { return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index c9c9d3deee..2a8a4d7246 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -8,7 +8,7 @@ /* global Script, RIGHT_HAND, LEFT_HAND, MyAvatar, makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters, - getGrabbableData, makeLaserParams, DISPATCHER_PROPERTIES + getGrabbableData, makeLaserParams, DISPATCHER_PROPERTIES, RayPick, handsAreTracked */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -63,6 +63,9 @@ Script.include("/~/system/libraries/controllers.js"); this.isReady = function (controllerData) { this.targetEntityID = null; + if (handsAreTracked()) { + return makeRunningValues(false, [], []); + } if (controllerData.triggerClicks[this.hand] === 0) { return makeRunningValues(false, [], []); } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 3b81e17473..fc2306fe28 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -63,7 +63,8 @@ clearHighlightedEntities:true, unhighlightTargetEntity:true, distanceBetweenEntityLocalPositionAndBoundingBox: true, - worldPositionToRegistrationFrameMatrix: true + worldPositionToRegistrationFrameMatrix: true, + handsAreTracked: true */ MSECS_PER_SEC = 1000.0; @@ -600,6 +601,10 @@ worldPositionToRegistrationFrameMatrix = function(wptrProps, pos) { return offsetMat; }; +handsAreTracked = function () { + return Controller.getPoseValue(Controller.Standard.LeftHandIndex3).valid || + Controller.getPoseValue(Controller.Standard.RightHandIndex3).valid; +} if (typeof module !== 'undefined') { module.exports = { @@ -624,6 +629,7 @@ if (typeof module !== 'undefined') { TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE: TRIGGER_ON_VALUE, DISPATCHER_HOVERING_LIST: DISPATCHER_HOVERING_LIST, - worldPositionToRegistrationFrameMatrix: worldPositionToRegistrationFrameMatrix + worldPositionToRegistrationFrameMatrix: worldPositionToRegistrationFrameMatrix, + handsAreTracked: handsAreTracked }; } diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index bc9bcfe36d..1650cb60f4 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global getTabletWidthFromSettings, TRIGGER_OFF_VALUE, Controller, Script, Camera, Tablet, MyAvatar, +/* global getTabletWidthFromSettings, handsAreTracked, TRIGGER_OFF_VALUE, Controller, Script, Camera, Tablet, MyAvatar, Quat, SoundCache, HMD, Overlays, Vec3, Uuid, Messages */ (function () { @@ -81,11 +81,6 @@ return hand === LEFT_HAND ? RIGHT_HAND : LEFT_HAND; } - function handsAreTracked() { - return Controller.getPoseValue(Controller.Standard.LeftHandIndex3).valid || - Controller.getPoseValue(Controller.Standard.RightHandIndex3).valid; - } - UI = function () { if (!(this instanceof UI)) { From 5511b18432b69942d408ea84defca9d1bde5eb17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Oct 2019 14:56:48 -0700 Subject: [PATCH 07/27] don't allow the hand with the mini-tablet to trigger opening the tablet --- scripts/system/controllers/controllerModules/stylusInput.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index 544fbb9277..c04edbe085 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -121,7 +121,8 @@ Script.include("/~/system/libraries/controllers.js"); } // Add the mini tablet. - if (HMD.miniTabletScreenID && Overlays.getProperty(HMD.miniTabletScreenID, "visible")) { + if (HMD.miniTabletScreenID && Overlays.getProperty(HMD.miniTabletScreenID, "visible") && + this.hand != HMD.miniTabletHand) { stylusTarget = getOverlayDistance(controllerPosition, HMD.miniTabletScreenID); if (stylusTarget) { stylusTargets.push(stylusTarget); From 17ceda0d3e331e5b8a8d2ca25649179199be6701 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Oct 2019 15:25:03 -0700 Subject: [PATCH 08/27] quiet jshint --- .../system/controllers/controllerModules/stylusInput.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index c04edbe085..f19b023545 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -7,7 +7,7 @@ /* global Script, MyAvatar, Controller, Uuid, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, makeRunningValues, Vec3, makeDispatcherModuleParameters, Overlays, HMD, Settings, getEnabledModuleByName, Pointers, - Picks, PickType + Picks, PickType, Keyboard */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -64,8 +64,8 @@ Script.include("/~/system/libraries/controllers.js"); var nearTabletHighlightModuleName = this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"; var nearTabletHighlightModule = getEnabledModuleByName(nearTabletHighlightModuleName); - var nearTabletHighlightModuleReady = nearTabletHighlightModule - ? nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); + var nearTabletHighlightModuleReady = nearTabletHighlightModule ? + nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); return grabOverlayModuleReady.active || farGrabModuleReady.active || grabEntityModuleReady.active /* || nearTabletHighlightModuleReady.active */ ; }; @@ -129,7 +129,7 @@ Script.include("/~/system/libraries/controllers.js"); } } - const WEB_DISPLAY_STYLUS_DISTANCE = (Keyboard.raised && Keyboard.preferMalletsOverLasers) ? 0.2 : 0.5; + var WEB_DISPLAY_STYLUS_DISTANCE = (Keyboard.raised && Keyboard.preferMalletsOverLasers) ? 0.2 : 0.5; var nearStylusTarget = isNearStylusTarget(stylusTargets, WEB_DISPLAY_STYLUS_DISTANCE * sensorScaleFactor); if (nearStylusTarget.length !== 0) { From 63dcf0e1c92b6187273d6ef0e11ea2caebd647d3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Oct 2019 11:24:05 -0700 Subject: [PATCH 09/27] use same near-grab module to grab entities and overlays --- .../controllers/controllerDispatcher.js | 56 +++++++++++++++++-- .../controllerModules/nearGrabEntity.js | 2 +- .../controllerModules/stylusInput.js | 16 ++++-- .../system/controllers/controllerScripts.js | 2 +- scripts/system/libraries/WebTablet.js | 1 + .../libraries/controllerDispatcherUtils.js | 5 +- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 24d0e2703d..de583b8f0c 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -53,6 +53,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.pointerManager = new PointerManager(); this.grabSphereOverlays = [null, null]; this.targetIDs = {}; + this.debugPanelID = null; + this.debugLines = []; // a module can occupy one or more "activity" slots while it's running. If all the required slots for a module are // not set to false (not in use), a module cannot start. When a module is using a slot, that module's name @@ -206,6 +208,18 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.setTimeout(_this.update, BASIC_TIMER_INTERVAL_MS); }; + this.addDebugLine = function(line) { + if (this.debugLines.length > 8) { + this.debugLines.shift(); + } + this.debugLines.push(line); + var debugPanelText = ""; + this.debugLines.forEach(function(debugLine) { + debugPanelText += debugLine + "\n"; + }); + Entities.editEntity(this.debugPanelID, { text: debugPanelText }); + }; + this.updateInternal = function () { if (PROFILE) { Script.beginProfileRange("dispatch.pre"); @@ -309,6 +323,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } var nearbyEntityIDs = Entities.findEntities(controllerPosition, findRadius); + nearbyEntityIDs = nearbyEntityIDs.concat(nearbyOverlayIDs[h]); // overlays are now entities + for (var j = 0; j < nearbyEntityIDs.length; j++) { var entityID = nearbyEntityIDs[j]; var props = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); @@ -444,7 +460,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); _this.markSlots(candidatePlugin, orderedPluginName); _this.pointerManager.makePointerVisible(candidatePlugin.parameters.handLaser); if (DEBUG) { - print("controllerDispatcher running " + orderedPluginName); + _this.addDebugLine("running " + orderedPluginName); } } if (PROFILE) { @@ -476,8 +492,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); if (DEBUG) { if (JSON.stringify(_this.targetIDs[runningPluginName]) != JSON.stringify(runningness.targets)) { - print("controllerDispatcher targetIDs[" + runningPluginName + "] = " + - JSON.stringify(runningness.targets)); + _this.addDebugLine("targetIDs[" + runningPluginName + "] = " + + JSON.stringify(runningness.targets)); } } @@ -488,12 +504,12 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); delete _this.runningPluginNames[runningPluginName]; delete _this.targetIDs[runningPluginName]; if (DEBUG) { - print("controllerDispatcher deleted targetIDs[" + runningPluginName + "]"); + _this.addDebugLine("deleted targetIDs[" + runningPluginName + "]"); } _this.markSlots(plugin, false); _this.pointerManager.makePointerInvisible(plugin.parameters.handLaser); if (DEBUG) { - print("controllerDispatcher stopping " + runningPluginName); + _this.addDebugLine("stopping " + runningPluginName); } } _this.pointerManager.lockPointerEnd(plugin.parameters.handLaser, runningness.laserLockInfo); @@ -637,7 +653,33 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Overlays.mousePressOnOverlay.disconnect(mousePress); Entities.mousePressOnEntity.disconnect(mousePress); Messages.messageReceived.disconnect(controllerDispatcher.handleMessage); + if (_this.debugPanelID) { + Entities.deleteEntity(_this.debugPanelID); + _this.debugPanelID = null; + } }; + + if (DEBUG) { + this.debugPanelID = Entities.addEntity({ + name: "controllerDispatcher debug panel", + type: "Text", + dimensions: { x: 1.0, y: 0.3, z: 0.01 }, + parentID: MyAvatar.sessionUUID, + // parentJointIndex: MyAvatar.getJointIndex("_CAMERA_MATRIX"), + parentJointIndex: -1, + localPosition: { x: -0.25, y: 0.8, z: -1.2 }, + textColor: { red: 255, green: 255, blue: 255}, + backgroundColor: { red: 0, green: 0, blue: 0}, + text: "", + lineHeight: 0.03, + leftMargin: 0.015, + topMargin: 0.01, + backgroundAlpha: 0.7, + textAlpha: 1.0, + unlit: true, + ignorePickIntersection: true + }, "local"); + } } function mouseReleaseOnOverlay(overlayID, event) { @@ -667,6 +709,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); Messages.messageReceived.connect(controllerDispatcher.handleMessage); - Script.scriptEnding.connect(controllerDispatcher.cleanup); + Script.scriptEnding.connect(function () { + controllerDispatcher.cleanup(); + }); Script.setTimeout(controllerDispatcher.update, BASIC_TIMER_INTERVAL_MS); }()); diff --git a/scripts/system/controllers/controllerModules/nearGrabEntity.js b/scripts/system/controllers/controllerModules/nearGrabEntity.js index 45d518bb39..381197badf 100644 --- a/scripts/system/controllers/controllerModules/nearGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearGrabEntity.js @@ -28,7 +28,7 @@ Script.include("/~/system/libraries/controllers.js"); this.grabID = null; this.parameters = makeDispatcherModuleParameters( - 500, + 90, this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], [], 100); diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index f19b023545..fabfb91f02 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -52,21 +52,25 @@ Script.include("/~/system/libraries/controllers.js"); this.disable = false; this.otherModuleNeedsToRun = function(controllerData) { - var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; - var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName); - var grabEntityModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity"; + // var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; + // var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName); + // var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []); + + var grabEntityModuleName = this.hand === RIGHT_HAND ? "RightNearGrabEntity" : "LeftNearGrabEntity"; var grabEntityModule = getEnabledModuleByName(grabEntityModuleName); - var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []); var grabEntityModuleReady = grabEntityModule ? grabEntityModule.isReady(controllerData) : makeRunningValues(false, [], []); - var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity"; + + var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarGrabEntity" : "LeftFarGrabEntity"; var farGrabModule = getEnabledModuleByName(farGrabModuleName); var farGrabModuleReady = farGrabModule ? farGrabModule.isReady(controllerData) : makeRunningValues(false, [], []); + var nearTabletHighlightModuleName = this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"; var nearTabletHighlightModule = getEnabledModuleByName(nearTabletHighlightModuleName); var nearTabletHighlightModuleReady = nearTabletHighlightModule ? nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); - return grabOverlayModuleReady.active || farGrabModuleReady.active || grabEntityModuleReady.active + + return /* grabOverlayModuleReady.active || */ farGrabModuleReady.active || grabEntityModuleReady.active /* || nearTabletHighlightModuleReady.active */ ; }; diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index c9cb61b5f5..fdc81e0780 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -18,7 +18,7 @@ var CONTOLLER_SCRIPTS = [ //"toggleAdvancedMovementForHandControllers.js", "handTouch.js", "controllerDispatcher.js", - "controllerModules/nearParentGrabOverlay.js", + // "controllerModules/nearParentGrabOverlay.js", "controllerModules/stylusInput.js", "controllerModules/equipEntity.js", "controllerModules/nearTrigger.js", diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index b7593656a3..9f2142504c 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -164,6 +164,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { parentID: this.tabletEntityID, parentJointIndex: -1, showKeyboardFocusHighlight: false, + grabbable: false, visible: visible }); diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index fc2306fe28..5cfd899da0 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -6,7 +6,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html /* global module, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform, Mat4, - Selection, Uuid, + Selection, Uuid, Controller, MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true, HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true, DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true, @@ -56,6 +56,7 @@ TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, TEAR_AWAY_CHECK_TIME:true, + TELEPORT_DEADZONE: true, NEAR_GRAB_DISTANCE: true, distanceBetweenPointAndEntityBoundingBox:true, entityIsEquipped:true, @@ -604,7 +605,7 @@ worldPositionToRegistrationFrameMatrix = function(wptrProps, pos) { handsAreTracked = function () { return Controller.getPoseValue(Controller.Standard.LeftHandIndex3).valid || Controller.getPoseValue(Controller.Standard.RightHandIndex3).valid; -} +}; if (typeof module !== 'undefined') { module.exports = { From 4d3da24c33eb9ec340f4e9902e41d5a500a67dd2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Oct 2019 16:19:08 -0700 Subject: [PATCH 10/27] fix angularVelocity reported by leap-motion plugin --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 5c5b975676..3f0cad02b4 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -281,6 +281,7 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In glm::vec3 pos; glm::quat rot; + glm::quat prevRot; if (_isLeapOnHMD) { auto jointPosition = joints[i].position; const glm::vec3 HMD_EYE_TO_LEAP_OFFSET = glm::vec3(0.0f, 0.0f, -0.09f); // Eyes to surface of Leap Motion. @@ -291,17 +292,33 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In glm::quat jointOrientation = joints[i].orientation; jointOrientation = glm::quat(jointOrientation.w, -jointOrientation.x, -jointOrientation.z, -jointOrientation.y); rot = controllerToAvatarRotation * hmdSensorOrientation * jointOrientation; + + glm::quat prevJointOrientation = prevJoints[i].orientation; + prevJointOrientation = + glm::quat(prevJointOrientation.w, -prevJointOrientation.x, -prevJointOrientation.z, -prevJointOrientation.y); + prevRot = controllerToAvatarRotation * hmdSensorOrientation * prevJointOrientation; + } else { pos = controllerToAvatarRotation * (joints[i].position - leapMotionOffset); const glm::quat ZERO_HAND_ORIENTATION = glm::quat(glm::vec3(PI_OVER_TWO, PI, 0.0f)); rot = controllerToAvatarRotation * joints[i].orientation * ZERO_HAND_ORIENTATION; + prevRot = controllerToAvatarRotation * prevJoints[i].orientation * ZERO_HAND_ORIENTATION; } + // glm::vec3 linearVelocity, angularVelocity; + // if (i < prevJoints.size()) { + // linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s + // glm::quat dQ = rot * glm::inverse(prevRot); + // float angle = glm::angle(dQ); + // glm::vec3 axis = glm::axis(dQ); + // angularVelocity = (angle / deltaTime) * axis; + // } + glm::vec3 linearVelocity, angularVelocity; if (i < prevJoints.size()) { linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s // quat log imaginary part points along the axis of rotation, with length of one half the angle of rotation. - glm::quat d = glm::log(rot * glm::inverse(prevJoints[i].orientation)); + glm::quat d = glm::log(rot * glm::inverse(prevRot)); angularVelocity = glm::vec3(d.x, d.y, d.z) / (0.5f * deltaTime); // radians/s } From 865584e7e35f963c533c6e7279de9584652865c1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Oct 2019 17:25:17 -0700 Subject: [PATCH 11/27] put tracked hand walk into a controller-dispatcher module --- scripts/defaultScripts.js | 1 - .../controllerModules/trackedHandWalk.js | 106 ++++++++++++++++++ .../system/controllers/controllerScripts.js | 4 +- scripts/system/hand-track-walk.js | 69 ------------ 4 files changed, 108 insertions(+), 72 deletions(-) create mode 100644 scripts/system/controllers/controllerModules/trackedHandWalk.js delete mode 100644 scripts/system/hand-track-walk.js diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index a19bb9c41a..0efabd7773 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -34,7 +34,6 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/emote.js", "system/miniTablet.js", "system/audioMuteOverlay.js", - "system/inspect.js", "system/keyboardShortcuts/keyboardShortcuts.js", "system/hand-track-walk.js" ]; diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js new file mode 100644 index 0000000000..ab1e3534b2 --- /dev/null +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -0,0 +1,106 @@ +"use strict"; + +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +/* global Script, RIGHT_HAND, LEFT_HAND, makeRunningValues, enableDispatcherModule, disableDispatcherModule, + makeDispatcherModuleParameters, handsAreTracked, Controller, Vec3 +*/ + +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllers.js"); + +(function() { + + function TrackedHandWalk(hand) { + this.mappingName = 'hand-track-walk-' + Math.random(); + this.inputMapping = Controller.newMapping(this.mappingName); + this.leftIndexPos = null; + this.rightIndexPos = null; + this.pinchOnBelowDistance = 0.016; + this.pinchOffAboveDistance = 0.04; + this.walking = false; + + this.parameters = makeDispatcherModuleParameters( + 80, + this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], + [], + 100); + + this.updateWalking = function () { + if (this.leftIndexPos && this.rightIndexPos) { + var tipDistance = Vec3.distance(this.leftIndexPos, this.rightIndexPos); + if (tipDistance < this.pinchOnBelowDistance) { + this.walking = true; + } else if (this.walking && tipDistance > this.pinchOffAboveDistance) { + this.walking = false; + } + } + }; + + this.leftIndexChanged = function (pose) { + if (pose.valid) { + this.leftIndexPos = pose.translation; + } else { + this.leftIndexPos = null; + } + this.updateWalking(); + }; + + this.rightIndexChanged = function (pose) { + if (pose.valid) { + this.rightIndexPos = pose.translation; + } else { + this.rightIndexPos = null; + } + this.updateWalking(); + }; + + this.isReady = function (controllerData) { + if (!handsAreTracked()) { + return makeRunningValues(false, [], []); + } + if (this.walking) { + return makeRunningValues(true, [], []); + } + }; + + this.run = function (controllerData) { + return this.isReady(controllerData); + }; + + this.setup = function () { + var _this = this; + this.inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(function (pose) { + _this.leftIndexChanged(pose); + }); + this.inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(function (pose) { + _this.rightIndexChanged(pose); + }); + + this.inputMapping.from(function() { + if (_this.walking) { + return -1; + } else { + return Controller.getActionValue(Controller.Standard.TranslateZ); + } + }).to(Controller.Actions.TranslateZ); + + Controller.enableMapping(this.mappingName); + }; + + this.cleanUp = function () { + this.inputMapping.disable(); + }; + } + + var trackedHandWalk = new TrackedHandWalk(LEFT_HAND); + trackedHandWalk.setup(); + enableDispatcherModule("TrackedHandWalk", trackedHandWalk); + + function cleanup() { + trackedHandWalk.cleanUp(); + disableDispatcherModule("TrackedHandWalk"); + } + Script.scriptEnding.connect(cleanup); +}()); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index fdc81e0780..a75ba164b5 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -18,7 +18,6 @@ var CONTOLLER_SCRIPTS = [ //"toggleAdvancedMovementForHandControllers.js", "handTouch.js", "controllerDispatcher.js", - // "controllerModules/nearParentGrabOverlay.js", "controllerModules/stylusInput.js", "controllerModules/equipEntity.js", "controllerModules/nearTrigger.js", @@ -34,7 +33,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/nearTabletHighlight.js", "controllerModules/nearGrabEntity.js", "controllerModules/farGrabEntity.js", - "controllerModules/pushToTalk.js" + "controllerModules/pushToTalk.js", + "controllerModules/trackedHandWalk.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; diff --git a/scripts/system/hand-track-walk.js b/scripts/system/hand-track-walk.js deleted file mode 100644 index cb9b700ae5..0000000000 --- a/scripts/system/hand-track-walk.js +++ /dev/null @@ -1,69 +0,0 @@ - -/* global Script, Controller, Vec3 */ -/* jshint loopfunc:true */ - -(function() { - - var mappingName = 'hand-track-walk-' + Math.random(); - var inputMapping = Controller.newMapping(mappingName); - - var leftIndexPos = null; - var rightIndexPos = null; - - var pinchOnBelowDistance = 0.016; - var pinchOffAboveDistance = 0.04; - - var walking = false; - - function updateWalking() { - if (leftIndexPos && rightIndexPos) { - var tipDistance = Vec3.distance(leftIndexPos, rightIndexPos); - if (tipDistance < pinchOnBelowDistance) { - print("qqqq walking"); - walking = true; - } else if (walking && tipDistance > pinchOffAboveDistance) { - print("qqqq stopping"); - walking = false; - } - } - } - - function leftIndexChanged(pose) { - if (pose.valid) { - leftIndexPos = pose.translation; - } else { - leftIndexPos = null; - } - updateWalking(); - } - - function rightIndexChanged(pose) { - if (pose.valid) { - rightIndexPos = pose.translation; - } else { - rightIndexPos = null; - } - updateWalking(); - } - - function cleanUp() { - inputMapping.disable(); - } - - Script.scriptEnding.connect(function () { - cleanUp(); - }); - - inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(leftIndexChanged); - inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(rightIndexChanged); - - inputMapping.from(function() { - if (walking) { - return -1; - } else { - return Controller.getActionValue(Controller.Standard.TranslateZ); - } - }).to(Controller.Actions.TranslateZ); - - Controller.enableMapping(mappingName); -})(); From 600c2c3947fa557021ffcba0897b371e843bd4bb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 3 Oct 2019 10:37:18 -0700 Subject: [PATCH 12/27] double OK to open/close tablet. touch thumb-tips to walk backwards --- .../controllerModules/trackedHandTablet.js | 142 ++++++++++++++++++ .../controllerModules/trackedHandWalk.js | 90 +++++++++-- .../system/controllers/controllerScripts.js | 3 +- 3 files changed, 218 insertions(+), 17 deletions(-) create mode 100644 scripts/system/controllers/controllerModules/trackedHandTablet.js diff --git a/scripts/system/controllers/controllerModules/trackedHandTablet.js b/scripts/system/controllers/controllerModules/trackedHandTablet.js new file mode 100644 index 0000000000..d0a4ac8af1 --- /dev/null +++ b/scripts/system/controllers/controllerModules/trackedHandTablet.js @@ -0,0 +1,142 @@ +"use strict"; + +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +/* global Script, makeRunningValues, enableDispatcherModule, disableDispatcherModule, + makeDispatcherModuleParameters, handsAreTracked, Controller, Vec3, Tablet, HMD, MyAvatar +*/ + +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllers.js"); + +(function() { + + function TrackedHandTablet() { + this.mappingName = 'hand-track-tablet-' + Math.random(); + this.inputMapping = Controller.newMapping(this.mappingName); + this.leftIndexPos = null; + this.leftThumbPos = null; + this.rightIndexPos = null; + this.rightThumbPos = null; + this.touchOnBelowDistance = 0.016; + this.touchOffAboveDistance = 0.045; + + this.gestureCompleted = false; + this.previousGestureCompleted = false; + + this.parameters = makeDispatcherModuleParameters( + 70, + ["rightHand", "leftHand"], + [], + 100); + + this.checkForGesture = function () { + if (this.leftThumbPos && this.leftIndexPos && this.rightThumbPos && this.rightIndexPos) { + var leftTipDistance = Vec3.distance(this.leftThumbPos, this.leftIndexPos); + var rightTipDistance = Vec3.distance(this.rightThumbPos, this.rightIndexPos); + if (leftTipDistance < this.touchOnBelowDistance && rightTipDistance < this.touchOnBelowDistance) { + this.gestureCompleted = true; + } else if (leftTipDistance > this.touchOffAboveDistance || rightTipDistance > this.touchOffAboveDistance) { + this.gestureCompleted = false; + } + } else { + this.gestureCompleted = false; + } + + if (this.gestureCompleted && !this.previousGestureCompleted) { + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + if (HMD.showTablet) { + HMD.closeTablet(false); + } else if (!HMD.showTablet && !tablet.toolbarMode && !MyAvatar.isAway) { + tablet.gotoHomeScreen(); + HMD.openTablet(false); + } + } + + this.previousGestureCompleted = this.gestureCompleted; + }; + + this.leftIndexChanged = function (pose) { + if (pose.valid) { + this.leftIndexPos = pose.translation; + } else { + this.leftIndexPos = null; + } + this.checkForGesture(); + }; + + this.leftThumbChanged = function (pose) { + if (pose.valid) { + this.leftThumbPos = pose.translation; + } else { + this.leftThumbPos = null; + } + this.checkForGesture(); + }; + + this.rightIndexChanged = function (pose) { + if (pose.valid) { + this.rightIndexPos = pose.translation; + } else { + this.rightIndexPos = null; + } + this.checkForGesture(); + }; + + this.rightThumbChanged = function (pose) { + if (pose.valid) { + this.rightThumbPos = pose.translation; + } else { + this.rightThumbPos = null; + } + this.checkForGesture(); + }; + + this.isReady = function (controllerData) { + if (!handsAreTracked()) { + return makeRunningValues(false, [], []); + } else if (this.gestureCompleted) { + return makeRunningValues(true, [], []); + } else { + return makeRunningValues(false, [], []); + } + }; + + this.run = function (controllerData) { + return this.isReady(controllerData); + }; + + this.setup = function () { + var _this = this; + this.inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(function (pose) { + _this.leftIndexChanged(pose); + }); + this.inputMapping.from(Controller.Standard.LeftHandThumb4).peek().to(function (pose) { + _this.leftThumbChanged(pose); + }); + this.inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(function (pose) { + _this.rightIndexChanged(pose); + }); + this.inputMapping.from(Controller.Standard.RightHandThumb4).peek().to(function (pose) { + _this.rightThumbChanged(pose); + }); + + Controller.enableMapping(this.mappingName); + }; + + this.cleanUp = function () { + this.inputMapping.disable(); + }; + } + + var trackedHandWalk = new TrackedHandTablet(); + trackedHandWalk.setup(); + enableDispatcherModule("TrackedHandTablet", trackedHandWalk); + + function cleanup() { + trackedHandWalk.cleanUp(); + disableDispatcherModule("TrackedHandTablet"); + } + Script.scriptEnding.connect(cleanup); +}()); diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js index ab1e3534b2..b721797d34 100644 --- a/scripts/system/controllers/controllerModules/trackedHandWalk.js +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -3,7 +3,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -/* global Script, RIGHT_HAND, LEFT_HAND, makeRunningValues, enableDispatcherModule, disableDispatcherModule, +/* global Script, makeRunningValues, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters, handsAreTracked, Controller, Vec3 */ @@ -12,28 +12,46 @@ Script.include("/~/system/libraries/controllers.js"); (function() { - function TrackedHandWalk(hand) { + function TrackedHandWalk() { this.mappingName = 'hand-track-walk-' + Math.random(); this.inputMapping = Controller.newMapping(this.mappingName); this.leftIndexPos = null; + this.leftThumbPos = null; this.rightIndexPos = null; - this.pinchOnBelowDistance = 0.016; - this.pinchOffAboveDistance = 0.04; - this.walking = false; + this.rightThumbPos = null; + this.touchOnBelowDistance = 0.016; + this.touchOffAboveDistance = 0.045; + this.walkingForward = false; + this.walkingBackward = false; this.parameters = makeDispatcherModuleParameters( 80, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], + ["rightHand", "leftHand"], [], 100); + this.getControlPoint = function () { + return Vec3.multiply(Vec3.sum(this.leftIndexPos, this.rightIndexPos), 0.5); + }; + this.updateWalking = function () { if (this.leftIndexPos && this.rightIndexPos) { - var tipDistance = Vec3.distance(this.leftIndexPos, this.rightIndexPos); - if (tipDistance < this.pinchOnBelowDistance) { - this.walking = true; - } else if (this.walking && tipDistance > this.pinchOffAboveDistance) { - this.walking = false; + var indexTipDistance = Vec3.distance(this.leftIndexPos, this.rightIndexPos); + if (indexTipDistance < this.touchOnBelowDistance) { + this.walkingForward = true; + this.controlPoint = this.getControlPoint(); + } else if (this.walkingForward && indexTipDistance > this.touchOffAboveDistance) { + this.walkingForward = false; + } + } + + if (this.leftThumbPos && this.rightThumbPos) { + var thumbTipDistance = Vec3.distance(this.leftThumbPos, this.rightThumbPos); + if (thumbTipDistance < this.touchOnBelowDistance) { + this.walkingBackward = true; + this.controlPoint = this.getControlPoint(); + } else if (this.walkingBackward && thumbTipDistance > this.touchOffAboveDistance) { + this.walkingBackward = false; } } }; @@ -47,6 +65,15 @@ Script.include("/~/system/libraries/controllers.js"); this.updateWalking(); }; + this.leftThumbChanged = function (pose) { + if (pose.valid) { + this.leftThumbPos = pose.translation; + } else { + this.leftThumbPos = null; + } + this.updateWalking(); + }; + this.rightIndexChanged = function (pose) { if (pose.valid) { this.rightIndexPos = pose.translation; @@ -56,12 +83,22 @@ Script.include("/~/system/libraries/controllers.js"); this.updateWalking(); }; + this.rightThumbChanged = function (pose) { + if (pose.valid) { + this.rightThumbPos = pose.translation; + } else { + this.rightThumbPos = null; + } + this.updateWalking(); + }; + this.isReady = function (controllerData) { if (!handsAreTracked()) { return makeRunningValues(false, [], []); - } - if (this.walking) { + } else if (this.walkingForward || this.walkingBackward) { return makeRunningValues(true, [], []); + } else { + return makeRunningValues(false, [], []); } }; @@ -74,18 +111,39 @@ Script.include("/~/system/libraries/controllers.js"); this.inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(function (pose) { _this.leftIndexChanged(pose); }); + this.inputMapping.from(Controller.Standard.LeftHandThumb4).peek().to(function (pose) { + _this.leftThumbChanged(pose); + }); this.inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(function (pose) { _this.rightIndexChanged(pose); }); + this.inputMapping.from(Controller.Standard.RightHandThumb4).peek().to(function (pose) { + _this.rightThumbChanged(pose); + }); this.inputMapping.from(function() { - if (_this.walking) { - return -1; + if (_this.walkingForward) { + // var currentPoint = _this.getControlPoint(); + // return currentPoint.z - _this.controlPoint.z; + return -0.5; + } else if (_this.walkingBackward) { + // var currentPoint = _this.getControlPoint(); + // return currentPoint.z - _this.controlPoint.z; + return 0.5; } else { return Controller.getActionValue(Controller.Standard.TranslateZ); } }).to(Controller.Actions.TranslateZ); + // this.inputMapping.from(function() { + // if (_this.walkingForward) { + // var currentPoint = _this.getControlPoint(); + // return currentPoint.x - _this.controlPoint.x; + // } else { + // return Controller.getActionValue(Controller.Standard.Yaw); + // } + // }).to(Controller.Actions.Yaw); + Controller.enableMapping(this.mappingName); }; @@ -94,7 +152,7 @@ Script.include("/~/system/libraries/controllers.js"); }; } - var trackedHandWalk = new TrackedHandWalk(LEFT_HAND); + var trackedHandWalk = new TrackedHandWalk(); trackedHandWalk.setup(); enableDispatcherModule("TrackedHandWalk", trackedHandWalk); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index a75ba164b5..f41dcbd445 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -34,7 +34,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/nearGrabEntity.js", "controllerModules/farGrabEntity.js", "controllerModules/pushToTalk.js", - "controllerModules/trackedHandWalk.js" + "controllerModules/trackedHandWalk.js", + "controllerModules/trackedHandTablet.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; From a799d305ee495f43e155f029ef5a3804b164ada1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 8 Oct 2019 11:13:34 -0700 Subject: [PATCH 13/27] don't mess with TranslateZ unless module is active --- .../system/controllers/controllerModules/trackedHandWalk.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js index b721797d34..62ce3fdfbd 100644 --- a/scripts/system/controllers/controllerModules/trackedHandWalk.js +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -131,7 +131,8 @@ Script.include("/~/system/libraries/controllers.js"); // return currentPoint.z - _this.controlPoint.z; return 0.5; } else { - return Controller.getActionValue(Controller.Standard.TranslateZ); + // return Controller.getActionValue(Controller.Standard.TranslateZ); + return null; } }).to(Controller.Actions.TranslateZ); From 4f7252a0d8a6f474c0dac71ab45c7a8bf2f52b2e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 15 Oct 2019 10:06:53 -0700 Subject: [PATCH 14/27] enable and disable TranslateZ mapping, as needed --- .../controllerModules/trackedHandWalk.js | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js index 62ce3fdfbd..2d589f8747 100644 --- a/scripts/system/controllers/controllerModules/trackedHandWalk.js +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -13,6 +13,8 @@ Script.include("/~/system/libraries/controllers.js"); (function() { function TrackedHandWalk() { + this.gestureMappingName = 'hand-track-walk-gesture-' + Math.random(); + this.inputGestureMapping = Controller.newMapping(this.gestureMappingName); this.mappingName = 'hand-track-walk-' + Math.random(); this.inputMapping = Controller.newMapping(this.mappingName); this.leftIndexPos = null; @@ -24,6 +26,8 @@ Script.include("/~/system/libraries/controllers.js"); this.walkingForward = false; this.walkingBackward = false; + this.mappingEnabled = false; + this.parameters = makeDispatcherModuleParameters( 80, ["rightHand", "leftHand"], @@ -54,6 +58,14 @@ Script.include("/~/system/libraries/controllers.js"); this.walkingBackward = false; } } + + if ((this.walkingForward || this.walkingBackward) && !this.mappingEnabled) { + Controller.enableMapping(this.mappingName); + this.mappingEnabled = true; + } else if (!(this.walkingForward || this.walkingBackward) && this.mappingEnabled) { + this.inputMapping.disable(); + this.mappingEnabled = false; + } }; this.leftIndexChanged = function (pose) { @@ -108,16 +120,16 @@ Script.include("/~/system/libraries/controllers.js"); this.setup = function () { var _this = this; - this.inputMapping.from(Controller.Standard.LeftHandIndex4).peek().to(function (pose) { + this.inputGestureMapping.from(Controller.Standard.LeftHandIndex4).peek().to(function (pose) { _this.leftIndexChanged(pose); }); - this.inputMapping.from(Controller.Standard.LeftHandThumb4).peek().to(function (pose) { + this.inputGestureMapping.from(Controller.Standard.LeftHandThumb4).peek().to(function (pose) { _this.leftThumbChanged(pose); }); - this.inputMapping.from(Controller.Standard.RightHandIndex4).peek().to(function (pose) { + this.inputGestureMapping.from(Controller.Standard.RightHandIndex4).peek().to(function (pose) { _this.rightIndexChanged(pose); }); - this.inputMapping.from(Controller.Standard.RightHandThumb4).peek().to(function (pose) { + this.inputGestureMapping.from(Controller.Standard.RightHandThumb4).peek().to(function (pose) { _this.rightThumbChanged(pose); }); @@ -132,7 +144,7 @@ Script.include("/~/system/libraries/controllers.js"); return 0.5; } else { // return Controller.getActionValue(Controller.Standard.TranslateZ); - return null; + return 0.0; } }).to(Controller.Actions.TranslateZ); @@ -145,10 +157,11 @@ Script.include("/~/system/libraries/controllers.js"); // } // }).to(Controller.Actions.Yaw); - Controller.enableMapping(this.mappingName); + Controller.enableMapping(this.gestureMappingName); }; this.cleanUp = function () { + this.inputGestureMapping.disable(); this.inputMapping.disable(); }; } From 07034721c77a01b1188fb95b590174fb0e6a11bd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Nov 2019 10:18:09 -0800 Subject: [PATCH 15/27] adjust when stylus input is active --- .../system/controllers/controllerModules/stylusInput.js | 7 +------ .../controllers/controllerModules/trackedHandTablet.js | 2 +- .../controllers/controllerModules/trackedHandWalk.js | 6 +++--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index fabfb91f02..cbef45050e 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -52,10 +52,6 @@ Script.include("/~/system/libraries/controllers.js"); this.disable = false; this.otherModuleNeedsToRun = function(controllerData) { - // var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; - // var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName); - // var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []); - var grabEntityModuleName = this.hand === RIGHT_HAND ? "RightNearGrabEntity" : "LeftNearGrabEntity"; var grabEntityModule = getEnabledModuleByName(grabEntityModuleName); var grabEntityModuleReady = grabEntityModule ? grabEntityModule.isReady(controllerData) : makeRunningValues(false, [], []); @@ -70,8 +66,7 @@ Script.include("/~/system/libraries/controllers.js"); var nearTabletHighlightModuleReady = nearTabletHighlightModule ? nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); - return /* grabOverlayModuleReady.active || */ farGrabModuleReady.active || grabEntityModuleReady.active - /* || nearTabletHighlightModuleReady.active */ ; + return farGrabModuleReady.active || grabEntityModuleReady.active; }; this.overlayLaserActive = function(controllerData) { diff --git a/scripts/system/controllers/controllerModules/trackedHandTablet.js b/scripts/system/controllers/controllerModules/trackedHandTablet.js index d0a4ac8af1..6bb9d67ef8 100644 --- a/scripts/system/controllers/controllerModules/trackedHandTablet.js +++ b/scripts/system/controllers/controllerModules/trackedHandTablet.js @@ -39,7 +39,7 @@ Script.include("/~/system/libraries/controllers.js"); this.gestureCompleted = true; } else if (leftTipDistance > this.touchOffAboveDistance || rightTipDistance > this.touchOffAboveDistance) { this.gestureCompleted = false; - } + } // else don't change gestureCompleted } else { this.gestureCompleted = false; } diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js index 2d589f8747..92549eaa81 100644 --- a/scripts/system/controllers/controllerModules/trackedHandWalk.js +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -46,7 +46,7 @@ Script.include("/~/system/libraries/controllers.js"); this.controlPoint = this.getControlPoint(); } else if (this.walkingForward && indexTipDistance > this.touchOffAboveDistance) { this.walkingForward = false; - } + } // else don't change walkingForward } if (this.leftThumbPos && this.rightThumbPos) { @@ -56,7 +56,7 @@ Script.include("/~/system/libraries/controllers.js"); this.controlPoint = this.getControlPoint(); } else if (this.walkingBackward && thumbTipDistance > this.touchOffAboveDistance) { this.walkingBackward = false; - } + } // else don't change this.walkingBackward } if ((this.walkingForward || this.walkingBackward) && !this.mappingEnabled) { @@ -65,7 +65,7 @@ Script.include("/~/system/libraries/controllers.js"); } else if (!(this.walkingForward || this.walkingBackward) && this.mappingEnabled) { this.inputMapping.disable(); this.mappingEnabled = false; - } + } // else don't change mappingEnabled }; this.leftIndexChanged = function (pose) { From a0031c6f1046f303bcf9b8e484422d086094e761 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Aug 2019 09:28:58 -0700 Subject: [PATCH 16/27] eye and hand tracking for htc vive pro --- cmake/ports/hifi-client-deps/CONTROL | 2 +- plugins/openvr/CMakeLists.txt | 2 + plugins/openvr/src/ViveControllerManager.cpp | 530 ++++++++++++++++++- plugins/openvr/src/ViveControllerManager.h | 41 ++ 4 files changed, 570 insertions(+), 5 deletions(-) diff --git a/cmake/ports/hifi-client-deps/CONTROL b/cmake/ports/hifi-client-deps/CONTROL index 7070cb6fb9..5b9b0bcce0 100644 --- a/cmake/ports/hifi-client-deps/CONTROL +++ b/cmake/ports/hifi-client-deps/CONTROL @@ -1,4 +1,4 @@ Source: hifi-client-deps Version: 0.1 Description: Collected dependencies for High Fidelity applications -Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr (windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator +Build-Depends: hifi-deps, glslang, nlohmann-json, openvr (windows), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), vulkanmemoryallocator, aristo (windows), sranipal (windows) diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index dcb2e39e1b..e80b2215bf 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -15,5 +15,7 @@ if (WIN32 AND (NOT USE_GLES)) include_hifi_library_headers(octree) target_openvr() + target_sranipal() + target_aristo() target_link_libraries(${TARGET_NAME} Winmm.lib) endif() diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8aa7311de4..b1d3b791d6 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -13,6 +13,21 @@ #include #include +#ifdef _WIN32 +#pragma warning( push ) +#pragma warning( disable : 4091 ) +#pragma warning( disable : 4334 ) +#endif + +#include +#include +#include +#include + +#ifdef _WIN32 +#pragma warning( pop ) +#endif + #include #include #include @@ -37,6 +52,8 @@ #include #include +#include "OpenVrDisplayPlugin.h" + extern PoseData _nextSimPoseData; vr::IVRSystem* acquireOpenVrSystem(); @@ -130,6 +147,51 @@ static glm::mat4 calculateResetMat() { return glm::mat4(); } +class ViveProEyeReadThread : public QThread { +public: + ViveProEyeReadThread() { + setObjectName("OpenVR ViveProEye Read Thread"); + } + void run() override { + while (!quit) { + ViveSR::anipal::Eye::EyeData eyeData; + int result = ViveSR::anipal::Eye::GetEyeData(&eyeData); + { + QMutexLocker locker(&eyeDataMutex); + eyeDataBuffer.getEyeDataResult = result; + if (result == ViveSR::Error::WORK) { + uint64_t leftValids = eyeData.verbose_data.left.eye_data_validata_bit_mask; + uint64_t rightValids = eyeData.verbose_data.right.eye_data_validata_bit_mask; + + eyeDataBuffer.leftDirectionValid = + (leftValids & (uint64_t)ViveSR::anipal::Eye::SINGLE_EYE_DATA_GAZE_DIRECTION_VALIDITY) > (uint64_t)0; + eyeDataBuffer.rightDirectionValid = + (rightValids & (uint64_t)ViveSR::anipal::Eye::SINGLE_EYE_DATA_GAZE_DIRECTION_VALIDITY) > (uint64_t)0; + eyeDataBuffer.leftOpennessValid = + (leftValids & (uint64_t)ViveSR::anipal::Eye::SINGLE_EYE_DATA_EYE_OPENNESS_VALIDITY) > (uint64_t)0; + eyeDataBuffer.rightOpennessValid = + (rightValids & (uint64_t)ViveSR::anipal::Eye::SINGLE_EYE_DATA_EYE_OPENNESS_VALIDITY) > (uint64_t)0; + + float *leftGaze = eyeData.verbose_data.left.gaze_direction_normalized.elem_; + float *rightGaze = eyeData.verbose_data.right.gaze_direction_normalized.elem_; + eyeDataBuffer.leftEyeGaze = glm::vec3(leftGaze[0], leftGaze[1], leftGaze[2]); + eyeDataBuffer.rightEyeGaze = glm::vec3(rightGaze[0], rightGaze[1], rightGaze[2]); + + eyeDataBuffer.leftEyeOpenness = eyeData.verbose_data.left.eye_openness; + eyeDataBuffer.rightEyeOpenness = eyeData.verbose_data.right.eye_openness; + } + } + } + } + + bool quit { false }; + + // mutex and buffer for moving data from this thread to the other one + QMutex eyeDataMutex; + EyeDataBuffer eyeDataBuffer; +}; + + static QString outOfRangeDataStrategyToString(ViveControllerManager::OutOfRangeDataStrategy strategy) { switch (strategy) { default: @@ -211,6 +273,81 @@ QString ViveControllerManager::configurationLayout() { return OPENVR_LAYOUT; } +bool isDeviceIndexActive(vr::IVRSystem*& system, uint32_t deviceIndex) { + if (!system) { + return false; + } + if (deviceIndex != vr::k_unTrackedDeviceIndexInvalid && + system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && + system->IsTrackedDeviceConnected(deviceIndex)) { + vr::EDeviceActivityLevel activityLevel = system->GetTrackedDeviceActivityLevel(deviceIndex); + if (activityLevel == vr::k_EDeviceActivityLevel_UserInteraction) { + return true; + } + } + return false; +} + +bool isHandControllerActive(vr::IVRSystem*& system, vr::ETrackedControllerRole deviceRole) { + if (!system) { + return false; + } + auto deviceIndex = system->GetTrackedDeviceIndexForControllerRole(deviceRole); + return isDeviceIndexActive(system, deviceIndex); +} + +bool areBothHandControllersActive(vr::IVRSystem*& system) { + return + isHandControllerActive(system, vr::TrackedControllerRole_LeftHand) && + isHandControllerActive(system, vr::TrackedControllerRole_RightHand); +} + + +void ViveControllerManager::enableGestureDetection() { + if (_viveCameraHandTracker) { + return; + } + if (!ViveSR::anipal::Eye::IsViveProEye()) { + return; + } + +// #define HAND_TRACKER_USE_EXTERNAL_TRANSFORM 1 + +#ifdef HAND_TRACKER_USE_EXTERNAL_TRANSFORM + UseExternalTransform(true); // camera hand tracker results are in HMD frame +#else + UseExternalTransform(false); // camera hand tracker results are in sensor frame +#endif + GestureOption options; // defaults are GestureBackendAuto and GestureModeSkeleton + GestureFailure gestureFailure = StartGestureDetection(&options); + switch (gestureFailure) { + case GestureFailureNone: + qDebug() << "StartGestureDetection success"; + _viveCameraHandTracker = true; + break; + case GestureFailureOpenCL: + qDebug() << "StartGestureDetection (Only on Windows) OpenCL is not supported on the machine"; + break; + case GestureFailureCamera: + qDebug() << "StartGestureDetection Start camera failed"; + break; + case GestureFailureInternal: + qDebug() << "StartGestureDetection Internal errors"; + break; + case GestureFailureCPUOnPC: + qDebug() << "StartGestureDetection CPU backend is not supported on Windows"; + break; + } +} + +void ViveControllerManager::disableGestureDetection() { + if (!_viveCameraHandTracker) { + return; + } + StopGestureDetection(); + _viveCameraHandTracker = false; +} + bool ViveControllerManager::activate() { InputPlugin::activate(); @@ -230,6 +367,28 @@ bool ViveControllerManager::activate() { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; + + if (ViveSR::anipal::Eye::IsViveProEye()) { + qDebug() << "Vive Pro eye-tracking detected"; + + int error = ViveSR::anipal::Initial(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE, NULL); + if (error == ViveSR::Error::WORK) { + _viveProEye = true; + qDebug() << "Successfully initialize Eye engine."; + } else if (error == ViveSR::Error::RUNTIME_NOT_FOUND) { + _viveProEye = false; + qDebug() << "please follows SRanipal SDK guide to install SR_Runtime first"; + } else { + _viveProEye = false; + qDebug() << "Failed to initialize Eye engine. please refer to ViveSR error code:" << error; + } + + if (_viveProEye) { + _viveProEyeReadThread = std::make_shared(); + _viveProEyeReadThread->start(QThread::HighPriority); + } + } + return true; } @@ -251,6 +410,13 @@ void ViveControllerManager::deactivate() { userInputMapper->removeDevice(_inputDevice->_deviceID); _registeredWithInputMapper = false; + if (_viveProEyeReadThread) { + _viveProEyeReadThread->quit = true; + _viveProEyeReadThread->wait(); + _viveProEyeReadThread = nullptr; + ViveSR::anipal::Release(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE); + } + saveSettings(); } @@ -262,6 +428,311 @@ bool ViveControllerManager::isHeadControllerMounted() const { return activityLevel == vr::k_EDeviceActivityLevel_UserInteraction; } +void ViveControllerManager::invalidateEyeInputs() { + _inputDevice->_poseStateMap[controller::LEFT_EYE].valid = false; + _inputDevice->_poseStateMap[controller::RIGHT_EYE].valid = false; + _inputDevice->_axisStateMap[controller::LEFT_EYE_BLINK].valid = false; + _inputDevice->_axisStateMap[controller::RIGHT_EYE_BLINK].valid = false; +} + + +void ViveControllerManager::updateEyeTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + if (!isHeadControllerMounted()) { + invalidateEyeInputs(); + return; + } + + EyeDataBuffer eyeDataBuffer; + { + // GetEyeData takes around 4ms to finish, so we run it on a thread. + QMutexLocker locker(&_viveProEyeReadThread->eyeDataMutex); + memcpy(&eyeDataBuffer, &_viveProEyeReadThread->eyeDataBuffer, sizeof(eyeDataBuffer)); + } + + if (eyeDataBuffer.getEyeDataResult != ViveSR::Error::WORK) { + invalidateEyeInputs(); + return; + } + + // only update from buffer values if the new data is "valid" + if (!eyeDataBuffer.leftDirectionValid) { + eyeDataBuffer.leftEyeGaze = _prevEyeData.leftEyeGaze; + eyeDataBuffer.leftDirectionValid = _prevEyeData.leftDirectionValid; + } + if (!eyeDataBuffer.rightDirectionValid) { + eyeDataBuffer.rightEyeGaze = _prevEyeData.rightEyeGaze; + eyeDataBuffer.rightDirectionValid = _prevEyeData.rightDirectionValid; + } + if (!eyeDataBuffer.leftOpennessValid) { + eyeDataBuffer.leftEyeOpenness = _prevEyeData.leftEyeOpenness; + eyeDataBuffer.leftOpennessValid = _prevEyeData.leftOpennessValid; + } + if (!eyeDataBuffer.rightOpennessValid) { + eyeDataBuffer.rightEyeOpenness = _prevEyeData.rightEyeOpenness; + eyeDataBuffer.rightOpennessValid = _prevEyeData.rightOpennessValid; + } + _prevEyeData = eyeDataBuffer; + + // transform data into what the controller system expects. + + // in the data from sranipal, left=+x, up=+y, forward=+z + mat4 localLeftEyeMat = glm::lookAt(vec3(0.0f, 0.0f, 0.0f), + glm::vec3(-eyeDataBuffer.leftEyeGaze[0], + eyeDataBuffer.leftEyeGaze[1], + eyeDataBuffer.leftEyeGaze[2]), + vec3(0.0f, 1.0f, 0.0f)); + quat localLeftEyeRot = glm::quat_cast(localLeftEyeMat); + quat avatarLeftEyeRot = _inputDevice->_poseStateMap[controller::HEAD].rotation * localLeftEyeRot; + + mat4 localRightEyeMat = glm::lookAt(vec3(0.0f, 0.0f, 0.0f), + glm::vec3(-eyeDataBuffer.rightEyeGaze[0], + eyeDataBuffer.rightEyeGaze[1], + eyeDataBuffer.rightEyeGaze[2]), + vec3(0.0f, 1.0f, 0.0f)); + quat localRightEyeRot = glm::quat_cast(localRightEyeMat); + quat avatarRightEyeRot = _inputDevice->_poseStateMap[controller::HEAD].rotation * localRightEyeRot; + + // TODO -- figure out translations for eyes + if (eyeDataBuffer.leftDirectionValid) { + _inputDevice->_poseStateMap[controller::LEFT_EYE] = controller::Pose(glm::vec3(), avatarLeftEyeRot); + _inputDevice->_poseStateMap[controller::LEFT_EYE].valid = true; + } else { + _inputDevice->_poseStateMap[controller::LEFT_EYE].valid = false; + } + if (eyeDataBuffer.rightDirectionValid) { + _inputDevice->_poseStateMap[controller::RIGHT_EYE] = controller::Pose(glm::vec3(), avatarRightEyeRot); + _inputDevice->_poseStateMap[controller::RIGHT_EYE].valid = true; + } else { + _inputDevice->_poseStateMap[controller::RIGHT_EYE].valid = false; + } + + quint64 now = usecTimestampNow(); + + // in hifi, 0 is open 1 is closed. in SRanipal 1 is open, 0 is closed. + if (eyeDataBuffer.leftOpennessValid) { + _inputDevice->_axisStateMap[controller::LEFT_EYE_BLINK] = + controller::AxisValue(1.0f - eyeDataBuffer.leftEyeOpenness, now); + } else { + _inputDevice->_poseStateMap[controller::LEFT_EYE_BLINK].valid = false; + } + if (eyeDataBuffer.rightOpennessValid) { + _inputDevice->_axisStateMap[controller::RIGHT_EYE_BLINK] = + controller::AxisValue(1.0f - eyeDataBuffer.rightEyeOpenness, now); + } else { + _inputDevice->_poseStateMap[controller::RIGHT_EYE_BLINK].valid = false; + } +} + +glm::vec3 ViveControllerManager::getRollingAverageHandPoint(int handIndex, int pointIndex) const { +#if 0 + return _handPoints[0][handIndex][pointIndex]; +#else + glm::vec3 result; + for (int s = 0; s < NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES; s++) { + result += _handPoints[s][handIndex][pointIndex]; + } + return result / NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES; +#endif +} + + +controller::Pose ViveControllerManager::trackedHandDataToPose(int hand, const glm::vec3& palmFacing, + int nearHandPositionIndex, int farHandPositionIndex) { + glm::vec3 nearPoint = getRollingAverageHandPoint(hand, nearHandPositionIndex); + + glm::quat poseRot; + if (nearHandPositionIndex != farHandPositionIndex) { + glm::vec3 farPoint = getRollingAverageHandPoint(hand, farHandPositionIndex); + + glm::vec3 pointingDir = farPoint - nearPoint; // y axis + glm::vec3 otherAxis = glm::cross(pointingDir, palmFacing); + + glm::mat4 rotMat; + rotMat = glm::mat4(glm::vec4(otherAxis, 0.0f), + glm::vec4(pointingDir, 0.0f), + glm::vec4(palmFacing * (hand == 0 ? 1.0f : -1.0f), 0.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + poseRot = glm::normalize(glmExtractRotation(rotMat)); + } + + if (!isNaN(poseRot)) { + controller::Pose pose(nearPoint, poseRot); + return pose; + } else { + controller::Pose pose; + pose.valid = false; + return pose; + } +} + + +void ViveControllerManager::trackFinger(int hand, int jointIndex1, int jointIndex2, int jointIndex3, int jointIndex4, + controller::StandardPoseChannel joint1, controller::StandardPoseChannel joint2, + controller::StandardPoseChannel joint3, controller::StandardPoseChannel joint4) { + + glm::vec3 point1 = getRollingAverageHandPoint(hand, jointIndex1); + glm::vec3 point2 = getRollingAverageHandPoint(hand, jointIndex2); + glm::vec3 point3 = getRollingAverageHandPoint(hand, jointIndex3); + glm::vec3 point4 = getRollingAverageHandPoint(hand, jointIndex4); + + glm::vec3 wristPos = getRollingAverageHandPoint(hand, 0); + glm::vec3 thumb2 = getRollingAverageHandPoint(hand, 2); + glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, 17); + + // 1st + glm::vec3 palmFacing = glm::normalize(glm::cross(pinkie1 - wristPos, thumb2 - wristPos)); + glm::vec3 handForward = glm::normalize(point1 - wristPos); + glm::vec3 x = glm::normalize(glm::cross(palmFacing, handForward)); + glm::vec3 y = glm::normalize(point2 - point1); + glm::vec3 z = (hand == 0) ? glm::cross(y, x) : glm::cross(x, y); + glm::mat4 rotMat1 = glm::mat4(glm::vec4(x, 0.0f), + glm::vec4(y, 0.0f), + glm::vec4(z, 0.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + glm::quat rot1 = glm::normalize(glmExtractRotation(rotMat1)); + if (!isNaN(rot1)) { + _inputDevice->_poseStateMap[joint1] = controller::Pose(point1, rot1); + } + + + // 2nd + glm::vec3 x2 = x; // glm::normalize(glm::cross(point3 - point2, point2 - point1)); + glm::vec3 y2 = glm::normalize(point3 - point2); + glm::vec3 z2 = (hand == 0) ? glm::cross(y2, x2) : glm::cross(x2, y2); + + glm::mat4 rotMat2 = glm::mat4(glm::vec4(x2, 0.0f), + glm::vec4(y2, 0.0f), + glm::vec4(z2, 0.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + glm::quat rot2 = glm::normalize(glmExtractRotation(rotMat2)); + if (!isNaN(rot2)) { + _inputDevice->_poseStateMap[joint2] = controller::Pose(point2, rot2); + } + + + // 3rd + glm::vec3 x3 = x; // glm::normalize(glm::cross(point4 - point3, point3 - point1)); + glm::vec3 y3 = glm::normalize(point4 - point3); + glm::vec3 z3 = (hand == 0) ? glm::cross(y3, x3) : glm::cross(x3, y3); + + glm::mat4 rotMat3 = glm::mat4(glm::vec4(x3, 0.0f), + glm::vec4(y3, 0.0f), + glm::vec4(z3, 0.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + glm::quat rot3 = glm::normalize(glmExtractRotation(rotMat3)); + if (!isNaN(rot3)) { + _inputDevice->_poseStateMap[joint3] = controller::Pose(point3, rot3); + } + + + // 4th + glm::quat rot4 = rot3; + if (!isNaN(rot4)) { + _inputDevice->_poseStateMap[joint4] = controller::Pose(point4, rot4); + } +} + + +void ViveControllerManager::updateCameraHandTracker(float deltaTime, + const controller::InputCalibrationData& inputCalibrationData) { + + if (areBothHandControllersActive(_system)) { + // if both hand-controllers are in use, don't do camera hand tracking + disableGestureDetection(); + } else { + enableGestureDetection(); + } + + if (!_viveCameraHandTracker) { + return; + } + + const GestureResult* results = NULL; + int handTrackerFrameIndex { -1 }; + int resultsHandCount = GetGestureResult(&results, &handTrackerFrameIndex); + + if (handTrackerFrameIndex >= 0 /* && handTrackerFrameIndex != _lastHandTrackerFrameIndex */) { +#ifdef HAND_TRACKER_USE_EXTERNAL_TRANSFORM + glm::mat4 trackedHandToAvatar = + glm::inverse(inputCalibrationData.avatarMat) * + inputCalibrationData.sensorToWorldMat * + inputCalibrationData.hmdSensorMat; + // glm::mat4 trackedHandToAvatar = _inputDevice->_poseStateMap[controller::HEAD].getMatrix() * Matrices::Y_180; +#else + DisplayPluginPointer displayPlugin = _container->getActiveDisplayPlugin(); + std::shared_ptr openVRDisplayPlugin = + std::dynamic_pointer_cast(displayPlugin); + glm::mat4 sensorResetMatrix; + if (openVRDisplayPlugin) { + sensorResetMatrix = openVRDisplayPlugin->getSensorResetMatrix(); + } + + glm::mat4 trackedHandToAvatar = + glm::inverse(inputCalibrationData.avatarMat) * + inputCalibrationData.sensorToWorldMat * + sensorResetMatrix; +#endif + + // roll all the old points in the rolling average + memmove(&(_handPoints[1]), + &(_handPoints[0]), + sizeof(_handPoints[0]) * (NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES - 1)); + + for (int handIndex = 0; handIndex < resultsHandCount; handIndex++) { + bool isLeftHand = results[handIndex].isLeft; + + vr::ETrackedControllerRole controllerRole = + isLeftHand ? vr::TrackedControllerRole_LeftHand : vr::TrackedControllerRole_RightHand; + if (isHandControllerActive(_system, controllerRole)) { + continue; // if the controller for this hand is tracked, ignore camera hand tracking + } + + int hand = isLeftHand ? 0 : 1; + for (int pointIndex = 0; pointIndex < NUMBER_OF_HAND_POINTS; pointIndex++) { + glm::vec3 pos(results[handIndex].points[3 * pointIndex], + results[handIndex].points[3 * pointIndex + 1], + -results[handIndex].points[3 * pointIndex + 2]); + _handPoints[0][hand][pointIndex] = transformPoint(trackedHandToAvatar, pos); + } + + glm::vec3 wristPos = getRollingAverageHandPoint(hand, 0); + glm::vec3 thumb2 = getRollingAverageHandPoint(hand, 2); + glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, 17); + glm::vec3 palmFacing = glm::cross(pinkie1 - wristPos, thumb2 - wristPos); // z axis + + _inputDevice->_poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = + trackedHandDataToPose(hand, palmFacing, 0, 9); + trackFinger(hand, 1, 2, 3, 4, + isLeftHand ? controller::LEFT_HAND_THUMB1 : controller::RIGHT_HAND_THUMB1, + isLeftHand ? controller::LEFT_HAND_THUMB2 : controller::RIGHT_HAND_THUMB2, + isLeftHand ? controller::LEFT_HAND_THUMB3 : controller::RIGHT_HAND_THUMB3, + isLeftHand ? controller::LEFT_HAND_THUMB4 : controller::RIGHT_HAND_THUMB4); + trackFinger(hand, 5, 6, 7, 8, + isLeftHand ? controller::LEFT_HAND_INDEX1 : controller::RIGHT_HAND_INDEX1, + isLeftHand ? controller::LEFT_HAND_INDEX2 : controller::RIGHT_HAND_INDEX2, + isLeftHand ? controller::LEFT_HAND_INDEX3 : controller::RIGHT_HAND_INDEX3, + isLeftHand ? controller::LEFT_HAND_INDEX4 : controller::RIGHT_HAND_INDEX4); + trackFinger(hand, 9, 10, 11, 12, + isLeftHand ? controller::LEFT_HAND_MIDDLE1 : controller::RIGHT_HAND_MIDDLE1, + isLeftHand ? controller::LEFT_HAND_MIDDLE2 : controller::RIGHT_HAND_MIDDLE2, + isLeftHand ? controller::LEFT_HAND_MIDDLE3 : controller::RIGHT_HAND_MIDDLE3, + isLeftHand ? controller::LEFT_HAND_MIDDLE4 : controller::RIGHT_HAND_MIDDLE4); + trackFinger(hand, 13, 14, 15, 16, + isLeftHand ? controller::LEFT_HAND_RING1 : controller::RIGHT_HAND_RING1, + isLeftHand ? controller::LEFT_HAND_RING2 : controller::RIGHT_HAND_RING2, + isLeftHand ? controller::LEFT_HAND_RING3 : controller::RIGHT_HAND_RING3, + isLeftHand ? controller::LEFT_HAND_RING4 : controller::RIGHT_HAND_RING4); + trackFinger(hand, 17, 18, 19, 20, + isLeftHand ? controller::LEFT_HAND_PINKY1 : controller::RIGHT_HAND_PINKY1, + isLeftHand ? controller::LEFT_HAND_PINKY2 : controller::RIGHT_HAND_PINKY2, + isLeftHand ? controller::LEFT_HAND_PINKY3 : controller::RIGHT_HAND_PINKY3, + isLeftHand ? controller::LEFT_HAND_PINKY4 : controller::RIGHT_HAND_PINKY4); + } + } + _lastHandTrackerFrameIndex = handTrackerFrameIndex; +} + + void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { if (!_system) { @@ -297,6 +768,12 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; } + + if (_viveProEye) { + updateEyeTracker(deltaTime, inputCalibrationData); + } + + updateCameraHandTracker(deltaTime, inputCalibrationData); } void ViveControllerManager::loadSettings() { @@ -830,9 +1307,7 @@ void ViveControllerManager::InputDevice::handleHmd(uint32_t deviceIndex, const c void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { - if (_system->IsTrackedDeviceConnected(deviceIndex) && - _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && - _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { + if (isDeviceIndexActive(_system, deviceIndex) && _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { // process pose const mat4& mat = _nextSimPoseData.poses[deviceIndex]; @@ -1401,9 +1876,52 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(LEFT_GRIP, "LeftGrip"), makePair(RIGHT_GRIP, "RightGrip"), - // 3d location of controller + // 3d location of left controller and fingers makePair(LEFT_HAND, "LeftHand"), + makePair(LEFT_HAND_THUMB1, "LeftHandThumb1"), + makePair(LEFT_HAND_THUMB2, "LeftHandThumb2"), + makePair(LEFT_HAND_THUMB3, "LeftHandThumb3"), + makePair(LEFT_HAND_THUMB4, "LeftHandThumb4"), + makePair(LEFT_HAND_INDEX1, "LeftHandIndex1"), + makePair(LEFT_HAND_INDEX2, "LeftHandIndex2"), + makePair(LEFT_HAND_INDEX3, "LeftHandIndex3"), + makePair(LEFT_HAND_INDEX4, "LeftHandIndex4"), + makePair(LEFT_HAND_MIDDLE1, "LeftHandMiddle1"), + makePair(LEFT_HAND_MIDDLE2, "LeftHandMiddle2"), + makePair(LEFT_HAND_MIDDLE3, "LeftHandMiddle3"), + makePair(LEFT_HAND_MIDDLE4, "LeftHandMiddle4"), + makePair(LEFT_HAND_RING1, "LeftHandRing1"), + makePair(LEFT_HAND_RING2, "LeftHandRing2"), + makePair(LEFT_HAND_RING3, "LeftHandRing3"), + makePair(LEFT_HAND_RING4, "LeftHandRing4"), + makePair(LEFT_HAND_PINKY1, "LeftHandPinky1"), + makePair(LEFT_HAND_PINKY2, "LeftHandPinky2"), + makePair(LEFT_HAND_PINKY3, "LeftHandPinky3"), + makePair(LEFT_HAND_PINKY4, "LeftHandPinky4"), + + // 3d location of right controller and fingers makePair(RIGHT_HAND, "RightHand"), + makePair(RIGHT_HAND_THUMB1, "RightHandThumb1"), + makePair(RIGHT_HAND_THUMB2, "RightHandThumb2"), + makePair(RIGHT_HAND_THUMB3, "RightHandThumb3"), + makePair(RIGHT_HAND_THUMB4, "RightHandThumb4"), + makePair(RIGHT_HAND_INDEX1, "RightHandIndex1"), + makePair(RIGHT_HAND_INDEX2, "RightHandIndex2"), + makePair(RIGHT_HAND_INDEX3, "RightHandIndex3"), + makePair(RIGHT_HAND_INDEX4, "RightHandIndex4"), + makePair(RIGHT_HAND_MIDDLE1, "RightHandMiddle1"), + makePair(RIGHT_HAND_MIDDLE2, "RightHandMiddle2"), + makePair(RIGHT_HAND_MIDDLE3, "RightHandMiddle3"), + makePair(RIGHT_HAND_MIDDLE4, "RightHandMiddle4"), + makePair(RIGHT_HAND_RING1, "RightHandRing1"), + makePair(RIGHT_HAND_RING2, "RightHandRing2"), + makePair(RIGHT_HAND_RING3, "RightHandRing3"), + makePair(RIGHT_HAND_RING4, "RightHandRing4"), + makePair(RIGHT_HAND_PINKY1, "RightHandPinky1"), + makePair(RIGHT_HAND_PINKY2, "RightHandPinky2"), + makePair(RIGHT_HAND_PINKY3, "RightHandPinky3"), + makePair(RIGHT_HAND_PINKY4, "RightHandPinky4"), + makePair(LEFT_FOOT, "LeftFoot"), makePair(RIGHT_FOOT, "RightFoot"), makePair(HIPS, "Hips"), @@ -1411,6 +1929,10 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(HEAD, "Head"), makePair(LEFT_ARM, "LeftArm"), makePair(RIGHT_ARM, "RightArm"), + makePair(LEFT_EYE, "LeftEye"), + makePair(RIGHT_EYE, "RightEye"), + makePair(LEFT_EYE_BLINK, "LeftEyeBlink"), + makePair(RIGHT_EYE_BLINK, "RightEyeBlink"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index dbd248dc53..66462cbe85 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -31,6 +31,23 @@ namespace vr { class IVRSystem; } +class ViveProEyeReadThread; + +class EyeDataBuffer { +public: + int getEyeDataResult { 0 }; + bool leftDirectionValid { false }; + bool rightDirectionValid { false }; + bool leftOpennessValid { false }; + bool rightOpennessValid { false }; + glm::vec3 leftEyeGaze; + glm::vec3 rightEyeGaze; + float leftEyeOpenness { 0.0f }; + float rightEyeOpenness { 0.0f }; +}; + + + class ViveControllerManager : public InputPlugin { Q_OBJECT public: @@ -49,12 +66,18 @@ public: bool isHeadController() const override { return true; } bool isHeadControllerMounted() const; + void enableGestureDetection(); + void disableGestureDetection(); + bool activate() override; void deactivate() override; QString getDeviceName() { return QString::fromStdString(_inputDevice->_headsetName); } void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + void invalidateEyeInputs(); + void updateEyeTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData); + void updateCameraHandTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData); void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; virtual void saveSettings() const override; @@ -229,6 +252,24 @@ private: vr::IVRSystem* _system { nullptr }; std::shared_ptr _inputDevice { std::make_shared(_system) }; + bool _viveProEye { false }; + mutable std::recursive_mutex _getEyeDataLock; + std::shared_ptr _viveProEyeReadThread; + EyeDataBuffer _prevEyeData; + + bool _viveCameraHandTracker { false }; + int _lastHandTrackerFrameIndex { -1 }; + + const static int NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES { 6 }; + const static int NUMBER_OF_HAND_POINTS { 21 }; + glm::vec3 _handPoints[NUMBER_OF_HAND_TRACKER_SMOOTHING_FRAMES][2][NUMBER_OF_HAND_POINTS]; // 2 for number of hands + glm::vec3 getRollingAverageHandPoint(int handIndex, int pointIndex) const; + controller::Pose trackedHandDataToPose(int hand, const glm::vec3& palmFacing, + int nearHandPositionIndex, int farHandPositionIndex); + void trackFinger(int hand, int jointIndex1, int jointIndex2, int jointIndex3, int jointIndex4, + controller::StandardPoseChannel joint1, controller::StandardPoseChannel joint2, + controller::StandardPoseChannel joint3, controller::StandardPoseChannel joint4); + static const char* NAME; }; From 67f4811c2b858bf0b4cab6ff153bc93c5e667582 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 18 Nov 2019 16:59:28 -0800 Subject: [PATCH 17/27] blink actions were renamed --- plugins/openvr/src/ViveControllerManager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index b1d3b791d6..6e224f21fe 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -431,8 +431,8 @@ bool ViveControllerManager::isHeadControllerMounted() const { void ViveControllerManager::invalidateEyeInputs() { _inputDevice->_poseStateMap[controller::LEFT_EYE].valid = false; _inputDevice->_poseStateMap[controller::RIGHT_EYE].valid = false; - _inputDevice->_axisStateMap[controller::LEFT_EYE_BLINK].valid = false; - _inputDevice->_axisStateMap[controller::RIGHT_EYE_BLINK].valid = false; + _inputDevice->_axisStateMap[controller::EYEBLINK_L].valid = false; + _inputDevice->_axisStateMap[controller::EYEBLINK_R].valid = false; } @@ -510,16 +510,16 @@ void ViveControllerManager::updateEyeTracker(float deltaTime, const controller:: // in hifi, 0 is open 1 is closed. in SRanipal 1 is open, 0 is closed. if (eyeDataBuffer.leftOpennessValid) { - _inputDevice->_axisStateMap[controller::LEFT_EYE_BLINK] = + _inputDevice->_axisStateMap[controller::EYEBLINK_L] = controller::AxisValue(1.0f - eyeDataBuffer.leftEyeOpenness, now); } else { - _inputDevice->_poseStateMap[controller::LEFT_EYE_BLINK].valid = false; + _inputDevice->_poseStateMap[controller::EYEBLINK_L].valid = false; } if (eyeDataBuffer.rightOpennessValid) { - _inputDevice->_axisStateMap[controller::RIGHT_EYE_BLINK] = + _inputDevice->_axisStateMap[controller::EYEBLINK_R] = controller::AxisValue(1.0f - eyeDataBuffer.rightEyeOpenness, now); } else { - _inputDevice->_poseStateMap[controller::RIGHT_EYE_BLINK].valid = false; + _inputDevice->_poseStateMap[controller::EYEBLINK_R].valid = false; } } @@ -1931,8 +1931,8 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(RIGHT_ARM, "RightArm"), makePair(LEFT_EYE, "LeftEye"), makePair(RIGHT_EYE, "RightEye"), - makePair(LEFT_EYE_BLINK, "LeftEyeBlink"), - makePair(RIGHT_EYE_BLINK, "RightEyeBlink"), + makePair(EYEBLINK_L, "EyeBlink_L"), + makePair(EYEBLINK_R, "EyeBlink_R"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), From 3f249dfcd8cca9688e4748adcc4b530b4de751c8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 20 Nov 2019 09:48:52 -0800 Subject: [PATCH 18/27] fix controller-module run order so that equip works again --- .../system/controllers/controllerModules/disableOtherModule.js | 2 +- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/disableOtherModule.js b/scripts/system/controllers/controllerModules/disableOtherModule.js index 7636c56f65..549735b658 100644 --- a/scripts/system/controllers/controllerModules/disableOtherModule.js +++ b/scripts/system/controllers/controllerModules/disableOtherModule.js @@ -17,7 +17,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.hand = hand; this.disableModules = false; this.parameters = makeDispatcherModuleParameters( - 90, + 82, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 54b56ff271..534231f407 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -278,7 +278,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.handHasBeenRightsideUp = false; this.parameters = makeDispatcherModuleParameters( - 115, + 85, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip"] : ["leftHand", "leftHandEquip"], [], 100); From cb83e4e6c9852abceee7982c716828ef7caf0e85 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 13 Dec 2019 16:22:13 -0800 Subject: [PATCH 19/27] adjust to new eye matrix --- plugins/openvr/src/ViveControllerManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6e224f21fe..24a0c7588b 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -477,17 +477,17 @@ void ViveControllerManager::updateEyeTracker(float deltaTime, const controller:: // in the data from sranipal, left=+x, up=+y, forward=+z mat4 localLeftEyeMat = glm::lookAt(vec3(0.0f, 0.0f, 0.0f), - glm::vec3(-eyeDataBuffer.leftEyeGaze[0], + glm::vec3(eyeDataBuffer.leftEyeGaze[0], eyeDataBuffer.leftEyeGaze[1], - eyeDataBuffer.leftEyeGaze[2]), + -eyeDataBuffer.leftEyeGaze[2]), vec3(0.0f, 1.0f, 0.0f)); quat localLeftEyeRot = glm::quat_cast(localLeftEyeMat); quat avatarLeftEyeRot = _inputDevice->_poseStateMap[controller::HEAD].rotation * localLeftEyeRot; mat4 localRightEyeMat = glm::lookAt(vec3(0.0f, 0.0f, 0.0f), - glm::vec3(-eyeDataBuffer.rightEyeGaze[0], + glm::vec3(eyeDataBuffer.rightEyeGaze[0], eyeDataBuffer.rightEyeGaze[1], - eyeDataBuffer.rightEyeGaze[2]), + -eyeDataBuffer.rightEyeGaze[2]), vec3(0.0f, 1.0f, 0.0f)); quat localRightEyeRot = glm::quat_cast(localRightEyeMat); quat avatarRightEyeRot = _inputDevice->_poseStateMap[controller::HEAD].rotation * localRightEyeRot; From 2fdbd0ab7898520f9e62637fba417fbaed403943 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Feb 2020 09:52:49 -0800 Subject: [PATCH 20/27] update urls for vive eye and hand tracking libraries, fix cmake for same --- cmake/ports/aristo/portfile.cmake | 4 +++- cmake/ports/sranipal/CONTROL | 2 +- cmake/ports/sranipal/portfile.cmake | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cmake/ports/aristo/portfile.cmake b/cmake/ports/aristo/portfile.cmake index 532e1304f4..94efe6f7ea 100644 --- a/cmake/ports/aristo/portfile.cmake +++ b/cmake/ports/aristo/portfile.cmake @@ -2,10 +2,12 @@ include(vcpkg_common_functions) set(ARISTO_VERSION 0.8.1) set(MASTER_COPY_SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + if (WIN32) vcpkg_download_distfile( ARISTO_SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/seth/aristo-0.8.1-windows.zip + URLS "${EXTERNAL_BUILD_ASSETS}/seth/aristo-0.8.1-windows.zip" SHA512 05179c63b72a1c9f5be8a7a2b7389025da683400dbf819e5a6199dd6473c56774d2885182dc5a11cb6324058d228a4ead832222e8b3e1bebaa4c61982e85f0a8 FILENAME aristo-0.8.1-windows.zip ) diff --git a/cmake/ports/sranipal/CONTROL b/cmake/ports/sranipal/CONTROL index 3f878b1c4d..b7d510595e 100644 --- a/cmake/ports/sranipal/CONTROL +++ b/cmake/ports/sranipal/CONTROL @@ -1,3 +1,3 @@ Source: sranipal Version: 1.1.0.1 -Description: SRanipal +Description: super reality animation pal! diff --git a/cmake/ports/sranipal/portfile.cmake b/cmake/ports/sranipal/portfile.cmake index da4646be1a..2e6acea361 100644 --- a/cmake/ports/sranipal/portfile.cmake +++ b/cmake/ports/sranipal/portfile.cmake @@ -2,10 +2,12 @@ include(vcpkg_common_functions) set(SRANIPAL_VERSION 1.1.0.1) set(MASTER_COPY_SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + if (WIN32) vcpkg_download_distfile( SRANIPAL_SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/seth/sranipal-1.1.0.1-windows.zip + URLS "${EXTERNAL_BUILD_ASSETS}/seth/sranipal-1.1.0.1-windows.zip" SHA512 b09ce012abe4e3c71e8e69626bdd7823ff6576601a821ab365275f2764406a3e5f7b65fcf2eb1d0962eff31eb5958a148b00901f67c229dc6ace56eb5e6c9e1b FILENAME sranipal-1.1.0.1-windows.zip ) From 10830cf68cdfab6fc5fe1cf28419704889c6184a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 26 Apr 2020 14:50:43 -0700 Subject: [PATCH 21/27] recover from rebase errors --- cmake/ports/hifi-client-deps/CONTROL | 2 +- scripts/defaultScripts.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/ports/hifi-client-deps/CONTROL b/cmake/ports/hifi-client-deps/CONTROL index 5b9b0bcce0..7070cb6fb9 100644 --- a/cmake/ports/hifi-client-deps/CONTROL +++ b/cmake/ports/hifi-client-deps/CONTROL @@ -1,4 +1,4 @@ Source: hifi-client-deps Version: 0.1 Description: Collected dependencies for High Fidelity applications -Build-Depends: hifi-deps, glslang, nlohmann-json, openvr (windows), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), vulkanmemoryallocator, aristo (windows), sranipal (windows) +Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr (windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 0efabd7773..a19bb9c41a 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -34,6 +34,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/emote.js", "system/miniTablet.js", "system/audioMuteOverlay.js", + "system/inspect.js", "system/keyboardShortcuts/keyboardShortcuts.js", "system/hand-track-walk.js" ]; From c0e36b796026515552cea85013faa85feee8ce9f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 16 May 2020 14:37:40 +1200 Subject: [PATCH 22/27] Address code review comments --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 9 --- plugins/openvr/src/ViveControllerManager.cpp | 60 ++++++++++++++----- plugins/openvr/src/ViveControllerManager.h | 1 - 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 3f0cad02b4..0989d28d23 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -305,15 +305,6 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In prevRot = controllerToAvatarRotation * prevJoints[i].orientation * ZERO_HAND_ORIENTATION; } - // glm::vec3 linearVelocity, angularVelocity; - // if (i < prevJoints.size()) { - // linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s - // glm::quat dQ = rot * glm::inverse(prevRot); - // float angle = glm::angle(dQ); - // glm::vec3 axis = glm::axis(dQ); - // angularVelocity = (angle / deltaTime) * axis; - // } - glm::vec3 linearVelocity, angularVelocity; if (i < prevJoints.size()) { linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 24a0c7588b..2c9eb296ab 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -79,6 +79,32 @@ static const int SECOND_FOOT = 1; static const int HIP = 2; static const int CHEST = 3; +enum ViveHandJointIndex { + HAND = 0, + THUMB_1, + THUMB_2, + THUMB_3, + THUMB_4, + INDEX_1, + INDEX_2, + INDEX_3, + INDEX_4, + MIDDLE_1, + MIDDLE_2, + MIDDLE_3, + MIDDLE_4, + RING_1, + RING_2, + RING_3, + RING_4, + PINKY_1, + PINKY_2, + PINKY_3, + PINKY_4, + + Size +}; + const char* ViveControllerManager::NAME { "OpenVR" }; const std::map TRACKING_RESULT_TO_STRING = { @@ -307,7 +333,7 @@ void ViveControllerManager::enableGestureDetection() { if (_viveCameraHandTracker) { return; } - if (!ViveSR::anipal::Eye::IsViveProEye()) { + if (!ViveSR::anipal::Eye::IsViveProEye()) { return; } @@ -368,7 +394,7 @@ bool ViveControllerManager::activate() { userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; - if (ViveSR::anipal::Eye::IsViveProEye()) { + if (ViveSR::anipal::Eye::IsViveProEye()) { qDebug() << "Vive Pro eye-tracking detected"; int error = ViveSR::anipal::Initial(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE, NULL); @@ -575,9 +601,9 @@ void ViveControllerManager::trackFinger(int hand, int jointIndex1, int jointInde glm::vec3 point3 = getRollingAverageHandPoint(hand, jointIndex3); glm::vec3 point4 = getRollingAverageHandPoint(hand, jointIndex4); - glm::vec3 wristPos = getRollingAverageHandPoint(hand, 0); - glm::vec3 thumb2 = getRollingAverageHandPoint(hand, 2); - glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, 17); + glm::vec3 wristPos = getRollingAverageHandPoint(hand, ViveHandJointIndex::HAND); + glm::vec3 thumb2 = getRollingAverageHandPoint(hand, ViveHandJointIndex::THUMB_2); + glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, ViveHandJointIndex::PINKY_1); // 1st glm::vec3 palmFacing = glm::normalize(glm::cross(pinkie1 - wristPos, thumb2 - wristPos)); @@ -651,6 +677,7 @@ void ViveControllerManager::updateCameraHandTracker(float deltaTime, int handTrackerFrameIndex { -1 }; int resultsHandCount = GetGestureResult(&results, &handTrackerFrameIndex); + // FIXME: Why the commented-out condition? if (handTrackerFrameIndex >= 0 /* && handTrackerFrameIndex != _lastHandTrackerFrameIndex */) { #ifdef HAND_TRACKER_USE_EXTERNAL_TRANSFORM glm::mat4 trackedHandToAvatar = @@ -695,34 +722,39 @@ void ViveControllerManager::updateCameraHandTracker(float deltaTime, _handPoints[0][hand][pointIndex] = transformPoint(trackedHandToAvatar, pos); } - glm::vec3 wristPos = getRollingAverageHandPoint(hand, 0); - glm::vec3 thumb2 = getRollingAverageHandPoint(hand, 2); - glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, 17); + glm::vec3 wristPos = getRollingAverageHandPoint(hand, ViveHandJointIndex::HAND); + glm::vec3 thumb2 = getRollingAverageHandPoint(hand, ViveHandJointIndex::THUMB_2); + glm::vec3 pinkie1 = getRollingAverageHandPoint(hand, ViveHandJointIndex::PINKY_1); glm::vec3 palmFacing = glm::cross(pinkie1 - wristPos, thumb2 - wristPos); // z axis _inputDevice->_poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = - trackedHandDataToPose(hand, palmFacing, 0, 9); - trackFinger(hand, 1, 2, 3, 4, + trackedHandDataToPose(hand, palmFacing, ViveHandJointIndex::HAND, ViveHandJointIndex::MIDDLE_1); + trackFinger(hand, ViveHandJointIndex::THUMB_1, ViveHandJointIndex::THUMB_2, ViveHandJointIndex::THUMB_3, + ViveHandJointIndex::THUMB_4, isLeftHand ? controller::LEFT_HAND_THUMB1 : controller::RIGHT_HAND_THUMB1, isLeftHand ? controller::LEFT_HAND_THUMB2 : controller::RIGHT_HAND_THUMB2, isLeftHand ? controller::LEFT_HAND_THUMB3 : controller::RIGHT_HAND_THUMB3, isLeftHand ? controller::LEFT_HAND_THUMB4 : controller::RIGHT_HAND_THUMB4); - trackFinger(hand, 5, 6, 7, 8, + trackFinger(hand, ViveHandJointIndex::INDEX_1, ViveHandJointIndex::INDEX_2, ViveHandJointIndex::INDEX_3, + ViveHandJointIndex::INDEX_4, isLeftHand ? controller::LEFT_HAND_INDEX1 : controller::RIGHT_HAND_INDEX1, isLeftHand ? controller::LEFT_HAND_INDEX2 : controller::RIGHT_HAND_INDEX2, isLeftHand ? controller::LEFT_HAND_INDEX3 : controller::RIGHT_HAND_INDEX3, isLeftHand ? controller::LEFT_HAND_INDEX4 : controller::RIGHT_HAND_INDEX4); - trackFinger(hand, 9, 10, 11, 12, + trackFinger(hand, ViveHandJointIndex::MIDDLE_1, ViveHandJointIndex::MIDDLE_2, ViveHandJointIndex::MIDDLE_3, + ViveHandJointIndex::MIDDLE_4, isLeftHand ? controller::LEFT_HAND_MIDDLE1 : controller::RIGHT_HAND_MIDDLE1, isLeftHand ? controller::LEFT_HAND_MIDDLE2 : controller::RIGHT_HAND_MIDDLE2, isLeftHand ? controller::LEFT_HAND_MIDDLE3 : controller::RIGHT_HAND_MIDDLE3, isLeftHand ? controller::LEFT_HAND_MIDDLE4 : controller::RIGHT_HAND_MIDDLE4); - trackFinger(hand, 13, 14, 15, 16, + trackFinger(hand, ViveHandJointIndex::RING_1, ViveHandJointIndex::RING_2, ViveHandJointIndex::RING_3, + ViveHandJointIndex::RING_4, isLeftHand ? controller::LEFT_HAND_RING1 : controller::RIGHT_HAND_RING1, isLeftHand ? controller::LEFT_HAND_RING2 : controller::RIGHT_HAND_RING2, isLeftHand ? controller::LEFT_HAND_RING3 : controller::RIGHT_HAND_RING3, isLeftHand ? controller::LEFT_HAND_RING4 : controller::RIGHT_HAND_RING4); - trackFinger(hand, 17, 18, 19, 20, + trackFinger(hand, ViveHandJointIndex::PINKY_1, ViveHandJointIndex::PINKY_2, ViveHandJointIndex::PINKY_3, + ViveHandJointIndex::PINKY_4, isLeftHand ? controller::LEFT_HAND_PINKY1 : controller::RIGHT_HAND_PINKY1, isLeftHand ? controller::LEFT_HAND_PINKY2 : controller::RIGHT_HAND_PINKY2, isLeftHand ? controller::LEFT_HAND_PINKY3 : controller::RIGHT_HAND_PINKY3, diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 66462cbe85..714be87842 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -253,7 +253,6 @@ private: std::shared_ptr _inputDevice { std::make_shared(_system) }; bool _viveProEye { false }; - mutable std::recursive_mutex _getEyeDataLock; std::shared_ptr _viveProEyeReadThread; EyeDataBuffer _prevEyeData; From c05225ca2f4e8d35449a50f5e2b0a42ac61234b9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 26 May 2020 14:58:13 +1200 Subject: [PATCH 23/27] Reinstate nearParentGrabOverlay controller module Fixes regression where tablet becomes large when grabbed if avatar is small. --- scripts/system/controllers/controllerDispatcher.js | 1 - scripts/system/controllers/controllerScripts.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index de583b8f0c..5af86d3bbd 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -323,7 +323,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } var nearbyEntityIDs = Entities.findEntities(controllerPosition, findRadius); - nearbyEntityIDs = nearbyEntityIDs.concat(nearbyOverlayIDs[h]); // overlays are now entities for (var j = 0; j < nearbyEntityIDs.length; j++) { var entityID = nearbyEntityIDs[j]; diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index f41dcbd445..fb422ebdf7 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -18,6 +18,7 @@ var CONTOLLER_SCRIPTS = [ //"toggleAdvancedMovementForHandControllers.js", "handTouch.js", "controllerDispatcher.js", + "controllerModules/nearParentGrabOverlay.js", "controllerModules/stylusInput.js", "controllerModules/equipEntity.js", "controllerModules/nearTrigger.js", From b32bdba1115a6cbef30b87579c91de727402c997 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 26 May 2020 14:58:27 +1200 Subject: [PATCH 24/27] Reinstate controller module priorities per master --- .../system/controllers/controllerModules/disableOtherModule.js | 2 +- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- scripts/system/controllers/controllerModules/nearGrabEntity.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/disableOtherModule.js b/scripts/system/controllers/controllerModules/disableOtherModule.js index 549735b658..d49776f06a 100644 --- a/scripts/system/controllers/controllerModules/disableOtherModule.js +++ b/scripts/system/controllers/controllerModules/disableOtherModule.js @@ -17,7 +17,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.hand = hand; this.disableModules = false; this.parameters = makeDispatcherModuleParameters( - 82, + 95, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 534231f407..54b56ff271 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -278,7 +278,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.handHasBeenRightsideUp = false; this.parameters = makeDispatcherModuleParameters( - 85, + 115, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip"] : ["leftHand", "leftHandEquip"], [], 100); diff --git a/scripts/system/controllers/controllerModules/nearGrabEntity.js b/scripts/system/controllers/controllerModules/nearGrabEntity.js index 381197badf..45d518bb39 100644 --- a/scripts/system/controllers/controllerModules/nearGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearGrabEntity.js @@ -28,7 +28,7 @@ Script.include("/~/system/libraries/controllers.js"); this.grabID = null; this.parameters = makeDispatcherModuleParameters( - 90, + 500, this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], [], 100); From 54c0223808546398782ab16ba2540bbdc8d1f405 Mon Sep 17 00:00:00 2001 From: kasenvr <52365539+kasenvr@users.noreply.github.com> Date: Thu, 11 Jun 2020 21:16:16 -0400 Subject: [PATCH 25/27] Update README.md --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e57063b499..a138b843d4 100644 --- a/README.md +++ b/README.md @@ -12,23 +12,25 @@ Vircadia is a 3D social software project seeking to incrementally bring about a ### How to build the Interface -[For Windows](https://github.com/kasenvr/project-athena/blob/master/BUILD_WIN.md) +[For Windows](https://docs.vircadia.dev/developer/build/BUILD_WIN.html) -[For Linux](https://github.com/kasenvr/project-athena/blob/master/BUILD_LINUX.md) +[For Mac](https://docs.vircadia.dev/developer/build/BUILD_OSX.html) -[For Linux - Athena Builder](https://github.com/kasenvr/vircadia-builder) +[For Linux](https://docs.vircadia.dev/developer/build/BUILD_LINUX.html) + +[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder) ### How to deploy a Server -[For Windows and Linux](https://vircadia.com/download-vircadia/#server) +[For Windows and Linux](https://vircadia.com/deploy-a-server/) ### How to build a Server -[For Linux - Athena Builder](https://github.com/kasenvr/vircadia-builder) +[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder) ### Boot to Metaverse: The Goal -Having a place to experience adventure, a place to relax with calm breath, that's a world to live in. An engine to support infinite combinations and possibilities of worlds without censorship and interruption, that's a metaverse. Finding a way to make infinite realities our reality, that's the dream. +Having a place to experience adventure, a place to relax with calm breath, that's a world to live in. An engine to support infinite combinations and possibilities of worlds without censorship and interruption, that's a metaverse. Finding a way to make infinite realities our reality is the dream. ### Boot to Metaverse: The Technicals From 099646cd66eedaa47912c3c3d8f5ab4eb10d1fa7 Mon Sep 17 00:00:00 2001 From: kasenvr <52365539+kasenvr@users.noreply.github.com> Date: Fri, 12 Jun 2020 17:03:51 -0400 Subject: [PATCH 26/27] Update README.md --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a138b843d4..baf333d81f 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ Vircadia is a 3D social software project seeking to incrementally bring about a ### How to build the Interface -[For Windows](https://docs.vircadia.dev/developer/build/BUILD_WIN.html) +[For Windows](https://github.com/kasenvr/project-athena/blob/master/BUILD_WIN.md) -[For Mac](https://docs.vircadia.dev/developer/build/BUILD_OSX.html) +[For Mac](https://github.com/kasenvr/project-athena/blob/master/BUILD_OSX.md) -[For Linux](https://docs.vircadia.dev/developer/build/BUILD_LINUX.html) +[For Linux](https://github.com/kasenvr/project-athena/blob/master/BUILD_LINUX.md) [For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder) @@ -28,6 +28,12 @@ Vircadia is a 3D social software project seeking to incrementally bring about a [For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder) +### How to generate an Installer + +[For Windows](https://github.com/kasenvr/project-athena/blob/master/INSTALL.md) + +[For Linux - AppImage - Vircadia Builder](https://github.com/kasenvr/vircadia-builder/blob/master/README.md#building-appimages) + ### Boot to Metaverse: The Goal Having a place to experience adventure, a place to relax with calm breath, that's a world to live in. An engine to support infinite combinations and possibilities of worlds without censorship and interruption, that's a metaverse. Finding a way to make infinite realities our reality is the dream. From 189f6f544061a3a65abdcc88b32261dc20b0f55e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 15 Jun 2020 08:04:51 +1200 Subject: [PATCH 27/27] Code review --- .../controllers/controllerModules/trackedHandTablet.js | 8 +------- .../controllers/controllerModules/trackedHandWalk.js | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/scripts/system/controllers/controllerModules/trackedHandTablet.js b/scripts/system/controllers/controllerModules/trackedHandTablet.js index 6bb9d67ef8..66cf408af8 100644 --- a/scripts/system/controllers/controllerModules/trackedHandTablet.js +++ b/scripts/system/controllers/controllerModules/trackedHandTablet.js @@ -94,13 +94,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.isReady = function (controllerData) { - if (!handsAreTracked()) { - return makeRunningValues(false, [], []); - } else if (this.gestureCompleted) { - return makeRunningValues(true, [], []); - } else { - return makeRunningValues(false, [], []); - } + return makeRunningValues(handsAreTracked() && this.gestureCompleted, [], []); }; this.run = function (controllerData) { diff --git a/scripts/system/controllers/controllerModules/trackedHandWalk.js b/scripts/system/controllers/controllerModules/trackedHandWalk.js index 92549eaa81..9ecc53a1fa 100644 --- a/scripts/system/controllers/controllerModules/trackedHandWalk.js +++ b/scripts/system/controllers/controllerModules/trackedHandWalk.js @@ -105,13 +105,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.isReady = function (controllerData) { - if (!handsAreTracked()) { - return makeRunningValues(false, [], []); - } else if (this.walkingForward || this.walkingBackward) { - return makeRunningValues(true, [], []); - } else { - return makeRunningValues(false, [], []); - } + return makeRunningValues(handsAreTracked() && (this.walkingForward || this.walkingBackward), [], []); }; this.run = function (controllerData) {