diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 50e627fe5d..975ec3fc22 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -14,6 +14,7 @@ var CONTOLLER_SCRIPTS = [ "controllerDisplayManager.js", "grab.js", "toggleAdvancedMovementForHandControllers.js", + "handTouch.js", "controllerDispatcher.js", "controllerModules/nearParentGrabEntity.js", "controllerModules/nearParentGrabOverlay.js", diff --git a/scripts/system/controllers/handTouch.js b/scripts/system/controllers/handTouch.js index 345ba7a1d7..c20b86b775 100644 --- a/scripts/system/controllers/handTouch.js +++ b/scripts/system/controllers/handTouch.js @@ -14,29 +14,29 @@ /* global Script, Overlays, Controller, Vec3, MyAvatar, Entities */ -(function(){ +(function() { + + var MSECONDS_AFTER_LOAD = 2000; var updateFingerWithIndex = 0; + // Keys to access finger data var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"]; // Additionally close the hands to achieve a grabbing effect - var grabPercent = { left: 0, - right: 0 }; - - // var isGrabbing = false; + var grabPercent = { left: 0, right: 0 }; var Palm = function() { - this.position = {x:0, y:0, z:0}; - this.perpendicular = {x:0, y:0, z:0}; + this.position = {x: 0, y: 0, z: 0}; + this.perpendicular = {x: 0, y: 0, z: 0}; this.distance = 0; this.fingers = { - pinky: {x:0, y:0, z:0}, - middle: {x:0, y:0, z:0}, - ring: {x:0, y:0, z:0}, - thumb: {x:0, y:0, z:0}, - index: {x:0, y:0, z:0} + pinky: {x: 0, y: 0, z: 0}, + middle: {x: 0, y: 0, z: 0}, + ring: {x: 0, y: 0, z: 0}, + thumb: {x: 0, y: 0, z: 0}, + index: {x: 0, y: 0, z: 0} }; this.set = false; }; @@ -72,52 +72,132 @@ right: 0 }; - // joint data for opened pose - + // joint data for open pose var dataOpen = { left: { - pinky:[{x: -0.0066, y:-0.0224, z:-0.2174, w:0.9758},{x: 0.0112, y:0.0001, z:0.0093, w:0.9999},{x: -0.0346, y:0.0003, z:-0.0073, w:0.9994}], - ring:[{x: -0.0029, y:-0.0094, z:-0.1413, w:0.9899},{x: 0.0112, y:0.0001, z:0.0059, w:0.9999},{x: -0.0346, y:0.0002, z:-0.006, w:0.9994}], - middle:[{x: -0.0016, y:0, z:-0.0286, w:0.9996},{x: 0.0112, y:-0.0001, z:-0.0063, w:0.9999},{x: -0.0346, y:-0.0003, z:0.0073, w:0.9994}], - index:[{x: -0.0016, y:0.0001, z:0.0199, w:0.9998},{x: 0.0112, y:0, z:0.0081, w:0.9999},{x: -0.0346, y:0.0008, z:-0.023, w:0.9991}], - thumb:[{x: 0.0354, y:0.0363, z:0.3275, w:0.9435},{x: -0.0945, y:0.0938, z:0.0995, w:0.9861},{x: -0.0952, y:0.0718, z:0.1382, w:0.9832}] + pinky: [ + {x: -0.0066, y: -0.0224, z: -0.2174, w: 0.9758}, + {x: 0.0112, y: 0.0001, z: 0.0093, w: 0.9999}, + {x: -0.0346, y: 0.0003, z: -0.0073, w: 0.9994} + ], + ring: [ + {x: -0.0029, y: -0.0094, z: -0.1413, w: 0.9899}, + {x: 0.0112, y: 0.0001, z: 0.0059, w: 0.9999}, + {x: -0.0346, y: 0.0002, z: -0.006, w: 0.9994} + ], + middle: [ + {x: -0.0016, y: 0, z: -0.0286, w: 0.9996}, + {x: 0.0112, y: -0.0001, z: -0.0063, w: 0.9999}, + {x: -0.0346, y: -0.0003, z: 0.0073, w: 0.9994} + ], + index: [ + {x: -0.0016, y: 0.0001, z: 0.0199, w: 0.9998}, + {x: 0.0112, y: 0, z: 0.0081, w: 0.9999}, + {x: -0.0346, y: 0.0008, z: -0.023, w: 0.9991} + ], + thumb: [ + {x: 0.0354, y: 0.0363, z: 0.3275, w: 0.9435}, + {x: -0.0945, y: 0.0938, z: 0.0995, w: 0.9861}, + {x: -0.0952, y: 0.0718, z: 0.1382, w: 0.9832} + ] }, right: { - pinky:[{x: -0.0034, y:0.023, z:0.1051, w:0.9942},{x: 0.0106, y:-0.0001, z:-0.0091, w:0.9999},{x: -0.0346, y:-0.0003, z:0.0075, w:0.9994}], - ring:[{x: -0.0013, y:0.0097, z:0.0311, w:0.9995},{x: 0.0106, y:-0.0001, z:-0.0056, w:0.9999},{x: -0.0346, y:-0.0002, z:0.0061, w:0.9994}], - middle:[{x: -0.001, y:0, z:0.0285, w:0.9996},{x: 0.0106, y:0.0001, z:0.0062, w:0.9999},{x: -0.0346, y:0.0003, z:-0.0074, w:0.9994}], - index:[{x: -0.001, y:0, z:-0.0199, w:0.9998},{x: 0.0106, y:-0.0001, z:-0.0079, w:0.9999},{x: -0.0346, y:-0.0008, z:0.0229, w:0.9991}], - thumb:[{x: 0.0355, y:-0.0363, z:-0.3263, w:0.9439},{x: -0.0946, y:-0.0938, z:-0.0996, w:0.9861},{x: -0.0952, y:-0.0719, z:-0.1376, w:0.9833}] + pinky: [ + {x: -0.0034, y: 0.023, z: 0.1051, w: 0.9942}, + {x: 0.0106, y: -0.0001, z: -0.0091, w: 0.9999}, + {x: -0.0346, y: -0.0003, z: 0.0075, w: 0.9994} + ], + ring: [ + {x: -0.0013, y: 0.0097, z: 0.0311, w: 0.9995}, + {x: 0.0106, y: -0.0001, z: -0.0056, w: 0.9999}, + {x: -0.0346, y: -0.0002, z: 0.0061, w: 0.9994} + ], + middle: [ + {x: -0.001, y: 0, z: 0.0285, w: 0.9996}, + {x: 0.0106, y: 0.0001, z: 0.0062, w: 0.9999}, + {x: -0.0346, y: 0.0003, z: -0.0074, w: 0.9994} + ], + index: [ + {x: -0.001, y: 0, z: -0.0199, w: 0.9998}, + {x: 0.0106, y: -0.0001, z: -0.0079, w: 0.9999}, + {x: -0.0346, y: -0.0008, z: 0.0229, w: 0.9991} + ], + thumb: [ + {x: 0.0355, y: -0.0363, z: -0.3263, w: 0.9439}, + {x: -0.0946, y: -0.0938, z: -0.0996, w: 0.9861}, + {x: -0.0952, y: -0.0719, z: -0.1376, w: 0.9833} + ] } }; + + // joint data for close pose var dataClose = { left: { - pinky:[{x: 0.5878, y:-0.1735, z:-0.1123, w:0.7821},{x: 0.5704, y:0.0053, z:0.0076, w:0.8213},{x: 0.6069, y:-0.0044, z:-0.0058, w:0.7947}], - ring:[{x: 0.5761, y:-0.0989, z:-0.1025, w:0.8048},{x: 0.5332, y:0.0032, z:0.005, w:0.846},{x: 0.5773, y:-0.0035, z:-0.0049, w:0.8165}], - middle:[{x: 0.543, y:-0.0469, z:-0.0333, w:0.8378},{x: 0.5419, y:-0.0034, z:-0.0053, w:0.8404},{x: 0.5015, y:0.0037, z:0.0063, w:0.8651}], - index:[{x: 0.3051, y:-0.0156, z:-0.014, w:0.9521},{x: 0.6414, y:0.0051, z:0.0063, w:0.7671},{x: 0.5646, y:-0.013, z:-0.019, w:0.8251}], - thumb:[{x: 0.313, y:-0.0348, z:0.3192, w:0.8938},{x: 0, y:0, z:-0.37, w:0.929},{x: 0, y:0, z:-0.2604, w:0.9655}] + pinky: [ + {x: 0.5878, y: -0.1735, z: -0.1123, w: 0.7821}, + {x: 0.5704, y: 0.0053, z: 0.0076, w: 0.8213}, + {x: 0.6069, y: -0.0044, z: -0.0058, w: 0.7947} + ], + ring: [ + {x: 0.5761, y: -0.0989, z: -0.1025, w: 0.8048}, + {x: 0.5332, y: 0.0032, z: 0.005, w: 0.846}, + {x: 0.5773, y: -0.0035, z: -0.0049, w: 0.8165} + ], + middle: [ + {x: 0.543, y: -0.0469, z: -0.0333, w: 0.8378}, + {x: 0.5419, y: -0.0034, z: -0.0053, w: 0.8404}, + {x: 0.5015, y: 0.0037, z: 0.0063, w: 0.8651} + ], + index: [ + {x: 0.3051, y: -0.0156, z: -0.014, w: 0.9521}, + {x: 0.6414, y: 0.0051, z: 0.0063, w: 0.7671}, + {x: 0.5646, y: -0.013, z: -0.019, w: 0.8251} + ], + thumb: [ + {x: 0.313, y: -0.0348, z: 0.3192, w: 0.8938}, + {x: 0, y: 0, z: -0.37, w: 0.929}, + {x: 0, y: 0, z: -0.2604, w: 0.9655} + ] }, right: { - pinky:[{x: 0.5881, y:0.1728, z:0.1114, w:0.7823},{x: 0.5704, y:-0.0052, z:-0.0075, w:0.8213},{x: 0.6069, y:0.0046, z:0.006, w:0.7947}], - ring:[{x: 0.5729, y:0.1181, z:0.0898, w:0.8061},{x: 0.5332, y:-0.003, z:-0.0048, w:0.846},{x: 0.5773, y:0.0035, z:0.005, w:0.8165}], - middle:[{x: 0.543, y:0.0468, z:0.0332, w:0.8378},{x: 0.5419, y:0.0034, z:0.0052, w:0.8404},{x: 0.5047, y:-0.0037, z:-0.0064, w:0.8632}], - index:[{x: 0.306, y:-0.0076, z:-0.0584, w:0.9502},{x: 0.6409, y:-0.005, z:-0.006, w:0.7675},{x: 0.5646, y:0.0129, z:0.0189, w:0.8251}], - thumb:[{x: 0.313, y:0.0352, z:-0.3181, w:0.8942},{x: 0, y:0, z:0.3698, w:0.9291},{x: 0, y:0, z:0.2609, w:0.9654}] + pinky: [ + {x: 0.5881, y: 0.1728, z: 0.1114, w: 0.7823}, + {x: 0.5704, y: -0.0052, z: -0.0075, w: 0.8213}, + {x: 0.6069, y: 0.0046, z: 0.006, w: 0.7947} + ], + ring: [ + {x: 0.5729, y: 0.1181, z: 0.0898, w: 0.8061}, + {x: 0.5332, y: -0.003, z: -0.0048, w: 0.846}, + {x: 0.5773, y: 0.0035, z: 0.005, w: 0.8165} + ], + middle: [ + {x: 0.543, y: 0.0468, z: 0.0332, w: 0.8378}, + {x: 0.5419, y: 0.0034, z: 0.0052, w: 0.8404}, + {x: 0.5047, y: -0.0037, z: -0.0064, w: 0.8632} + ], + index: [ + {x: 0.306, y: -0.0076, z: -0.0584, w: 0.9502}, + {x: 0.6409, y: -0.005, z: -0.006, w: 0.7675}, + {x: 0.5646, y: 0.0129, z: 0.0189, w: 0.8251} + ], + thumb: [ + {x: 0.313, y: 0.0352, z: -0.3181, w: 0.8942}, + {x: 0, y: 0, z: 0.3698, w: 0.9291}, + {x: 0, y: 0, z: 0.2609, w: 0.9654} + ] } }; // snapshot for the default pose - var dataDefault = { - left:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + left: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], set: false }, - right:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + right: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], @@ -127,17 +207,16 @@ }; // joint data for the current frame - var dataCurrent = { - left:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + left: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] }, - right:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + right: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], @@ -146,17 +225,16 @@ }; // interpolated values on joint data to smooth movement - var dataDelta = { - left:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + left: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] }, - right:{ - pinky:[{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], + right: { + pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], @@ -165,35 +243,30 @@ }; // Acquire an updated value per hand every 5 frames when finger is touching (faster in) - var touchAnimationSteps = 5; - // Acquire an updated value per hand every 10 frames when finger is returning to default position (slower out) - + // Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out) var defaultAnimationSteps = 10; // Debugging info - var showSphere = false; var showLines = false; // This get setup on creation - var linesCreated = false; var sphereCreated = false; // Register object with API Debugger - var varsToDebug = { scriptLoaded: false, - toggleDebugSphere: function(){ + toggleDebugSphere: function() { showSphere = !showSphere; if (showSphere && !sphereCreated) { createDebugSphere(); sphereCreated = true; } }, - toggleDebugLines: function(){ + toggleDebugLines: function() { showLines = !showLines; if (showLines && !linesCreated) { createDebugLines(); @@ -228,16 +301,17 @@ left: new Palm(), right: new Palm() }, - offset: {x:0, y:0, z:0}, + offset: {x: 0, y: 0, z: 0}, avatarLoaded: false }; // Add/Subtract the joint data - per finger joint - function addVals(val1, val2, sign) { var val = []; - if (val1.length != val2.length) return; + if (val1.length !== val2.length) { + return; + } for (var i = 0; i < val1.length; i++) { val.push({x: 0, y: 0, z: 0, w: 0}); val[i].x = val1[i].x + sign*val2[i].x; @@ -249,7 +323,6 @@ } // Multiply/Divide the joint data - per finger joint - function multiplyValsBy(val1, num) { var val = []; for (var i = 0; i < val1.length; i++) { @@ -263,7 +336,6 @@ } // Calculate the finger lengths by adding its joint lengths - function getJointDistances(jointNamesArray) { var result = {distances: [], totalDistance: 0}; for (var i = 1; i < jointNamesArray.length; i++) { @@ -282,12 +354,13 @@ var handJoint = handJointNames[side]; var jointIndex = MyAvatar.getJointIndex(handJoint); - var worldPosHand = MyAvatar.jointToWorldPoint({x:0, y:0, z:0}, jointIndex); + var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); dataOut.position = MyAvatar.jointToWorldPoint(dataIn.position, jointIndex); - // dataOut.perpendicular = Vec3.subtract(MyAvatar.jointToWorldPoint(dataIn.perpendicular, jointIndex), worldPosHand); - var localPerpendicular = side == "right" ? {x:0.2, y:0, z:1} : {x:-0.2, y:0, z:1}; - dataOut.perpendicular = Vec3.normalize(Vec3.subtract(MyAvatar.jointToWorldPoint(localPerpendicular, jointIndex), worldPosHand)); + var localPerpendicular = side === "right" ? {x: 0.2, y: 0, z: 1} : {x: -0.2, y: 0, z: 1}; + dataOut.perpendicular = Vec3.normalize( + Vec3.subtract(MyAvatar.jointToWorldPoint(localPerpendicular, jointIndex), worldPosHand) + ); dataOut.distance = dataIn.distance; for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; @@ -299,7 +372,7 @@ var handJoint = handJointNames[side]; var jointIndex = MyAvatar.getJointIndex(handJoint); - var worldPosHand = MyAvatar.jointToWorldPoint({x:0, y:0, z:0}, jointIndex); + var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); dataOut.position = MyAvatar.worldToJointPoint(dataIn.position, jointIndex); dataOut.perpendicular = MyAvatar.worldToJointPoint(Vec3.sum(worldPosHand, dataIn.perpendicular), jointIndex); @@ -310,7 +383,8 @@ } } - // Calculate the sphere that look up for entities, the center of the palm, perpendicular vector from the palm plane and origin of the the finger rays + // Calculate touch field; Sphere at the center of the palm, + // perpendicular vector from the palm plane and origin of the the finger rays function estimatePalmData(side) { // Return data object @@ -323,7 +397,7 @@ // Store position of the hand joint var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand); - var minusWorldPosHand = {x:-worldPosHand.x, y:-worldPosHand.y, z:-worldPosHand.z}; + var minusWorldPosHand = {x: -worldPosHand.x, y: -worldPosHand.y, z: -worldPosHand.z}; // Data for finger rays var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; @@ -337,7 +411,7 @@ var handJointWeight = 1; var fingerJointWeight = 2; - var palmCenter = {x:0, y:0, z:0}; + var palmCenter = {x: 0, y: 0, z: 0}; palmCenter = Vec3.sum(worldPosHand, palmCenter); weightCount += handJointWeight; @@ -352,7 +426,7 @@ positions[finger] = MyAvatar.jointToWorldPoint(jointOffset, jointIndex); directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand)); data.fingers[finger] = Vec3.sum(positions[finger], Vec3.multiply(fingerLength, directions[finger])); - if (finger != "thumb") { + if (finger !== "thumb") { // finger joints have double the weight than the hand joint // This would better position the palm estimation @@ -364,23 +438,25 @@ } // perpendicular change direction depending on the side - - data.perpendicular = (side == "right") ? - Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): - Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); + data.perpendicular = (side === "right") ? + Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): + Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); data.position = Vec3.multiply(1.0/weightCount, palmCenter); - if (side == "right") varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand); + if (side === "right") { + varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand); + } var palmDistanceMultiplier = 1.55; // 1.55 based on test/error for the sphere radius that best fits the hand data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index); // move back thumb ray origin var thumbBackMultiplier = 0.2; - data.fingers.thumb = Vec3.sum(data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular)); + data.fingers.thumb = Vec3.sum( + data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular)); - //return getDataRelativeToHandJoint(side, data); + // return getDataRelativeToHandJoint(side, data); dataRelativeToHandJoint(side, data, palmData[side]); palmData[side].set = true; // return palmData[side]; @@ -389,19 +465,16 @@ // Register GlobalDebugger for API Debugger Script.registerValue("GlobalDebugger", varsToDebug); - - // store the rays for the fingers - only for debug purposes - var fingerRays = { - left:{ + left: { pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined }, - right:{ + right: { pinky: undefined, middle: undefined, ring: undefined, @@ -419,14 +492,14 @@ for (var i = 0; i < fingerKeys.length; i++) { fingerRays.left[fingerKeys[i]] = Overlays.addOverlay("line3d", { color: { red: 0, green: 0, blue: 255 }, - start: { x:0, y:0, z:0 }, - end: { x:0, y:1, z:0 }, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 1, z: 0 }, visible: showLines }); fingerRays.right[fingerKeys[i]] = Overlays.addOverlay("line3d", { color: { red: 0, green: 0, blue: 255 }, - start: { x:0, y:0, z:0 }, - end: { x:0, y:1, z:0 }, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 1, z: 0 }, visible: showLines }); } @@ -434,14 +507,14 @@ palmRay = { left: Overlays.addOverlay("line3d", { color: { red: 255, green: 0, blue: 0 }, - start: { x:0, y:0, z:0 }, - end: { x:0, y:1, z:0 }, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 1, z: 0 }, visible: showLines }), right: Overlays.addOverlay("line3d", { color: { red: 255, green: 0, blue: 0 }, - start: { x:0, y:0, z:0 }, - end: { x:0, y:1, z:0 }, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 1, z: 0 }, visible: showLines }) }; @@ -481,6 +554,98 @@ dataDefault[side].set = true; } + var rayPicks = { + left: { + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, + index: undefined + }, + right: { + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, + index: undefined + } + }; + + var dataFailed = { + left: { + pinky: 0, + middle: 0, + ring: 0, + thumb: 0, + index: 0 + }, + right: { + pinky: 0, + middle: 0, + ring: 0, + thumb: 0, + index: 0 + } + }; + + function clearRayPicks(side) { + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + if (rayPicks[side][finger] !== undefined) { + RayPick.removeRayPick(rayPicks[side][finger]); + rayPicks[side][finger] = undefined; + } + } + } + + function createRayPicks(side) { + var data = palmData[side]; + clearRayPicks(side); + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + var LOOKUP_DISTANCE_MULTIPLIER = 1.5; + var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; + console.log("distance: " + dist); + var checkOffset = { + x: data.perpendicular.x * dist, + y: data.perpendicular.y * dist, + z: data.perpendicular.z * dist + }; + + var checkPoint = Vec3.sum(data.position, Vec3.multiply(2, checkOffset)); + var sensorToWorldScale = MyAvatar.getSensorToWorldScale(); + + var origin = data.fingers[finger]; + + var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); + + origin = Vec3.multiply(1/sensorToWorldScale, origin); + + rayPicks[side][finger] = RayPick.createRayPick( + { + "enabled": false, + "joint": handJointNames[side], + "posOffset": origin, + "dirOffset": direction, + "filter": RayPick.PICK_ENTITIES + } + ); + + RayPick.setPrecisionPicking(rayPicks[side][finger], true); + } + } + function activateNextRay(side, index) { + var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0; + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + if (i === nextIndex) { + RayPick.enableRayPick(rayPicks[side][finger]); + } else { + RayPick.disableRayPick(rayPicks[side][finger]); + } + } + } + function updateSphereHand(side) { var data = new Palm(); @@ -493,11 +658,12 @@ // Situate the debugging overlays - var checkOffset = { x: data.perpendicular.x * dist, - y: data.perpendicular.y * dist, - z: data.perpendicular.z * dist }; - - + var checkOffset = { + x: data.perpendicular.x * dist, + y: data.perpendicular.y * dist, + z: data.perpendicular.z * dist + }; + var spherePos = Vec3.sum(palmPoint, checkOffset); var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset)); @@ -529,21 +695,32 @@ } // Update the intersection of only one finger at a time - - var finger = fingerKeys[updateFingerWithIndex]; + + var finger = fingerKeys[updateFingerWithIndex]; + var grabbables = Entities.findEntities(spherePos, dist); - var newFingerData = dataDefault[side][finger]; - var animationSteps = defaultAnimationSteps; + var intersection; + if (rayPicks[side][finger] !== undefined) { + intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]); + } + + var animationSteps = defaultAnimationSteps; + var newFingerData = dataDefault[side][finger]; + var isAbleToGrab = false; if (grabbables.length > 0) { - var origin = data.fingers[finger]; - var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); - var intersection = Entities.findRayIntersection({origin: origin, direction: direction}, true, grabbables, [], true, false); + + RayPick.setIncludeItems(rayPicks[side][finger], grabbables); + + if (intersection === undefined) { + return; + } + var percent = 0; // Initialize - var isAbleToGrab = intersection.intersects && intersection.distance < LOOKUP_DISTANCE_MULTIPLIER*dist; + isAbleToGrab = intersection.intersects && intersection.distance < LOOKUP_DISTANCE_MULTIPLIER*dist; if (isAbleToGrab && !getTouching(side)) { - acquireDefaultPose(side); // take a snapshot of the default pose before touch starts + acquireDefaultPose(side); // take a snapshot of the default pose before touch starts newFingerData = dataDefault[side][finger]; // assign default pose to finger data } // Store if this finger is touching something @@ -558,20 +735,30 @@ var THUMB_FACTOR = 0.2; var FINGER_FACTOR = 0.05; - var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; // Amount of grab coefficient added to the fingers - thumb is higher + // Amount of grab coefficient added to the fingers - thumb is higher + var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; percent += grabMultiplier * grabPercent[side]; // Calculate new interpolation data var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1); - newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); // assign close/open ratio to finger to simulate touch + // Assign close/open ratio to finger to simulate touch + newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); animationSteps = touchAnimationSteps; } varsToDebug.fingerPercent[side][finger] = percent; - } - - // Calculate animation increments - dataDelta[side][finger] = multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); - + + } + if (!isAbleToGrab) { + dataFailed[side][finger] = dataFailed[side][finger] === 0 ? 1 : 2; + } else { + dataFailed[side][finger] = 0; + } + // If it only fails once it will not update increments + if (dataFailed[side][finger] !== 1) { + // Calculate animation increments + dataDelta[side][finger] = + multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); + } } // Recreate the finger joint names @@ -643,31 +830,39 @@ } function reEstimatePalmData() { - ["right", "left"].forEach(function(side){ + ["right", "left"].forEach(function(side) { estimatePalmData(side); }); } + function recreateRayPicks() { + ["right", "left"].forEach(function(side) { + createRayPicks(side); + }); + } + MyAvatar.onLoadComplete.connect(function () { // Sometimes the rig is not ready when this signal is trigger console.log("avatar loaded"); - Script.setInterval(function(){ + Script.setTimeout(function() { reEstimatePalmData(); - }, 2000); + recreateRayPicks(); + }, MSECONDS_AFTER_LOAD); }); - MyAvatar.sensorToWorldScaleChanged.connect(function(){ + MyAvatar.sensorToWorldScaleChanged.connect(function() { reEstimatePalmData(); }); Script.scriptEnding.connect(function () { - ["right", "left"].forEach(function(side){ + ["right", "left"].forEach(function(side) { if (linesCreated) { Overlays.deleteOverlay(palmRay[side]); } if (sphereCreated) { Overlays.deleteOverlay(sphereHand[side]); } + clearRayPicks(side); for (var i = 0; i < fingerKeys.length; i++) { var finger = fingerKeys[i]; @@ -684,27 +879,24 @@ } } }); - - - }); - Script.update.connect(function(){ + Script.update.connect(function() { // index of the finger that needs to be updated this frame - - updateFingerWithIndex = (updateFingerWithIndex < fingerKeys.length-1) ? updateFingerWithIndex + 1 : 0; - - ["right", "left"].forEach(function(side){ - + ["right", "left"].forEach(function(side) { + if (!palmData[side].set) { reEstimatePalmData(); + recreateRayPicks(); } + // recalculate the base data updateSphereHand(side); + activateNextRay(side, updateFingerWithIndex); // this vars manage the transition to default pose var isHandTouching = getTouching(side); @@ -725,7 +917,8 @@ for (var j = 0; j < names.length; j++) { var index = MyAvatar.getJointIndex(names[j]); // if no finger is touching restate the default poses - if (isHandTouching || (dataDefault[side].set && countToDefault[side] < 5*touchAnimationSteps)) { + if (isHandTouching || (dataDefault[side].set && + countToDefault[side] < fingerKeys.length*touchAnimationSteps)) { var quatRot = dataCurrent[side][finger][j]; MyAvatar.setJointRotation(index, quatRot); } else { @@ -735,5 +928,4 @@ } }); }); - }());