From 8a7c68829d9db8bf059cdf94c643e55277b041fb Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Sun, 7 Jan 2018 11:56:30 -0700 Subject: [PATCH] Optimizations, cleanings and globals --- interface/src/avatar/MySkeletonModel.cpp | 11 +- scripts/system/controllers/handTouch.js | 493 +++++++++++++++-------- 2 files changed, 341 insertions(+), 163 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 61236a0ff1..e64547dacc 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -323,22 +323,25 @@ void MySkeletonModel::updateFingers() { for (auto& link : chain) { int index = _rig.indexOfJoint(link.second); if (index >= 0) { - if (_jointRotationFrameOffsetMap.find(index) == _jointRotationFrameOffsetMap.end()) { + auto rotationFrameOffset = _jointRotationFrameOffsetMap.find(index); + if (rotationFrameOffset == _jointRotationFrameOffsetMap.end()) { _jointRotationFrameOffsetMap.insert(std::pair(index, 0)); + rotationFrameOffset = _jointRotationFrameOffsetMap.find(index); } auto pose = myAvatar->getControllerPoseInSensorFrame(link.first); + if (pose.valid) { glm::quat relRot = glm::inverse(prevAbsRot) * pose.getRotation(); // only set the rotation for the finger joints, not the hands. if (link.first != controller::Action::LEFT_HAND && link.first != controller::Action::RIGHT_HAND) { _rig.setJointRotation(index, true, relRot, CONTROLLER_PRIORITY); - _jointRotationFrameOffsetMap.find(index)->second = 0; + rotationFrameOffset->second = 0; } prevAbsRot = pose.getRotation(); - } else if (_jointRotationFrameOffsetMap.find(index)->second == 1) { // if the pose is invalid and was set on previous frame we do clear ( current frame offset = 1 ) + } else if (rotationFrameOffset->second == 1) { // if the pose is invalid and was set on previous frame we do clear ( current frame offset = 1 ) _rig.clearJointAnimationPriority(index); } - _jointRotationFrameOffsetMap.find(index)->second++; + rotationFrameOffset->second++; } } } diff --git a/scripts/system/controllers/handTouch.js b/scripts/system/controllers/handTouch.js index 709d16939c..345ba7a1d7 100644 --- a/scripts/system/controllers/handTouch.js +++ b/scripts/system/controllers/handTouch.js @@ -11,7 +11,7 @@ /* jslint bitwise: true */ -/* global Script, Overlays, Controller, Vec3, Quat, MyAvatar, Entities +/* global Script, Overlays, Controller, Vec3, MyAvatar, Entities */ (function(){ @@ -27,6 +27,27 @@ // var isGrabbing = false; + var Palm = function() { + 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} + }; + this.set = false; + }; + + var palmData = { + left: new Palm(), + right: new Palm() + }; + + var handJointNames = {left: "LeftHand", right: "RightHand"}; + // Store which fingers are touching - if all false restate the default poses var isTouching = { left: { @@ -42,109 +63,106 @@ thumb: false, index: false } - } - + }; + // frame count for transition to default pose var countToDefault = { left: 0, right: 0 - } + }; // joint data for opened pose var dataOpen = { left: { - pinky: [{x: -0.18262, y:-2.666, z:-25.11229}, {x: 1.28845, y:0, z:1.06604}, {x: -3.967, y:0, z:-0.8351} ], - middle: [{x: -0.18262, y:0, z:-3.2809}, {x: 1.28845, y:0, z:-0.71834}, {x: -3.967, y:0, z:0.83978}], - ring: [{x: -0.18262, y:-1.11078, z:-16.24391}, {x: 1.28845, y:0, z:0.68153}, {x: -3.967, y:0, z:-0.69295}], - thumb: [{x: 5.207, y:2.595, z:38.40092}, {x: -9.869, y:11.755, z:10.50012}, {x: -9.778, y:9.647, z:15.16963}], - index: [{x: -0.18262, y:0.0099, z:2.28085}, {x: 1.28845, y:-0.01107, z:0.93037}, {x: -3.967, y:0, z:-2.64018}] + 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.111, y: 2.66601, z: 12.06423}, {x: 1.217, y: 0, z: -1.03973}, {x: -3.967, y: 0, z: 0.86424}], - middle: [{x: -0.111, y: 0, z: 3.26538}, {x: 1.217, y: 0, z: 0.71427}, {x: -3.967, y: 0, z: -0.85103}], - ring: [{x: -0.111, y: 1.11101, z: 3.56312}, {x: 1.217, y: 0, z: -0.64524}, {x: -3.967, y: 0, z: 0.69807}], - thumb: [{x: 5.207, y: -2.595, z: -38.26131}, {x: -9.869, y: -11.755, z: -10.51778}, {x: -9.77799, y: -9.647, z: -15.10783}], - index: [{x: -0.111, y: 0, z: -2.2816}, {x: 1.217, y: 0, z: -0.90168}, {x: -3.967, y: 0, z: 2.62649}] + 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 closed hand - + }; var dataClose = { left: { - pinky:[{x: 75.45709, y:-8.01347, z:-22.54823}, {x: 69.562, y:0, z:1.06604}, {x: 74.73801, y:0, z:-0.8351}], - middle: [{x: 66.0237, y:-2.42536, z:-6.13193}, {x: 65.63042, y:0, z:-0.71834}, {x: 60.19901, y:0, z:0.83978}], - ring: [{x: 71.52988, y:-2.35423, z:-16.21694}, {x: 64.44739, y:0, z:0.68153}, {x: 70.518, y:0, z:-0.69295}], - thumb: [{x: 33.83371, y:-15.19106, z:34.66116}, {x: 0, y:0, z:-43.42915}, {x: 0, y:0, z:-30.18613}], - index: [{x: 35.56082, y:-1.21056, z:-2.07362}, {x: 79.79845, y:-0.01107, z:0.93037}, {x: 68.767, y:0, z:-2.64018}] + 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: 75.45702, y: 8.013, z: 22.41022}, {x: 69.562, y: 0, z: -1.03973}, {x: 74.738, y: 0, z: 0.86424}], - middle: [{x: 66.02399, y: 2.425, z: 6.11638}, {x: 65.63002, y: 0, z: 0.71427}, {x: 60.63, y: 0, z: -0.85103}], - ring: [{x: 71.53, y: 5.022, z: 16.33612}, {x: 64.447, y: 0, z: -0.64524}, {x: 70.51801, y: 0, z: 0.69807}], - thumb: [{x: 33.834, y: 15.191, z: -34.52131}, {x: 0, y: 0, z: 43.41122}, {x: 0, y: 0, z: 30.24818}], - index: [{x: 35.633, y: 1.215, z: -6.6376}, {x: 79.72701, y: 0, z: -0.90168}, {x: 68.76701, y: 0, z: 2.62649}] + 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},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], + 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},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], + 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 } - } + }; // joint data for the current frame var dataCurrent = { left:{ - pinky:[{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}] + 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},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}] + 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}] } - } + }; // interpolated values on joint data to smooth movement var dataDelta = { left:{ - pinky:[{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}] + 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},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - middle: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - ring: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - thumb: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}], - index: [{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0},{x: 0, y: 0, z: 0}] + 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}] } - } + }; // Acquire an updated value per hand every 5 frames when finger is touching (faster in) @@ -159,21 +177,28 @@ var showSphere = false; var showLines = false; - // store the rays for the fingers - only for debug purposes + // This get setup on creation - var fingerRays = { - left:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}, - right:{pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined} - }; + var linesCreated = false; + var sphereCreated = false; // Register object with API Debugger var varsToDebug = { + scriptLoaded: false, toggleDebugSphere: function(){ showSphere = !showSphere; + if (showSphere && !sphereCreated) { + createDebugSphere(); + sphereCreated = true; + } }, toggleDebugLines: function(){ showLines = !showLines; + if (showLines && !linesCreated) { + createDebugLines(); + linesCreated = true; + } }, fingerPercent: { left: { @@ -198,8 +223,15 @@ rightTriggerClicked: 0, leftSecondaryValue: 0, rightSecondaryValue: 0 - } - } + }, + palmData: { + left: new Palm(), + right: new Palm() + }, + offset: {x:0, y:0, z:0}, + avatarLoaded: false + }; + // Add/Subtract the joint data - per finger joint @@ -207,10 +239,11 @@ var val = []; if (val1.length != val2.length) return; for (var i = 0; i < val1.length; i++) { - val.push({x: 0, y: 0, z: 0}); + val.push({x: 0, y: 0, z: 0, w: 0}); val[i].x = val1[i].x + sign*val2[i].x; val[i].y = val1[i].y + sign*val2[i].y; val[i].z = val1[i].z + sign*val2[i].z; + val[i].w = val1[i].w + sign*val2[i].w; } return val; } @@ -220,10 +253,11 @@ function multiplyValsBy(val1, num) { var val = []; for (var i = 0; i < val1.length; i++) { - val.push({x: 0, y: 0, z: 0}); + val.push({x: 0, y: 0, z: 0, w: 0}); val[i].x = val1[i].x * num; val[i].y = val1[i].y * num; val[i].z = val1[i].z * num; + val[i].w = val1[i].w * num; } return val; } @@ -231,7 +265,7 @@ // Calculate the finger lengths by adding its joint lengths function getJointDistances(jointNamesArray) { - var result = {distances: [], totalDistance: 0} + var result = {distances: [], totalDistance: 0}; for (var i = 1; i < jointNamesArray.length; i++) { var index0 = MyAvatar.getJointIndex(jointNamesArray[i-1]); var index1 = MyAvatar.getJointIndex(jointNamesArray[i]); @@ -244,11 +278,43 @@ return result; } + function dataRelativeToWorld(side, dataIn, dataOut) { + + var handJoint = handJointNames[side]; + var jointIndex = MyAvatar.getJointIndex(handJoint); + 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)); + dataOut.distance = dataIn.distance; + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + dataOut.fingers[finger] = MyAvatar.jointToWorldPoint(dataIn.fingers[finger], jointIndex); + } + } + + function dataRelativeToHandJoint(side, dataIn, dataOut) { + + var handJoint = handJointNames[side]; + var jointIndex = MyAvatar.getJointIndex(handJoint); + 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); + dataOut.distance = dataIn.distance; + for (var i = 0; i < fingerKeys.length; i++) { + var finger = fingerKeys[i]; + dataOut.fingers[finger] = MyAvatar.worldToJointPoint(dataIn.fingers[finger], jointIndex); + } + } + // 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 function estimatePalmData(side) { // Return data object - var data = {position: undefined, perpendicular: undefined, distance: undefined, fingers: {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}}; + var data = new Palm(); var jointOffset = { x: 0, y: 0, z: 0 }; @@ -300,69 +366,105 @@ // 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"])); + Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): + Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); data.position = Vec3.multiply(1.0/weightCount, palmCenter); - 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"]); + 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 data; + //return getDataRelativeToHandJoint(side, data); + dataRelativeToHandJoint(side, data, palmData[side]); + palmData[side].set = true; + // return palmData[side]; } // Register GlobalDebugger for API Debugger Script.registerValue("GlobalDebugger", varsToDebug); + + + // store the rays for the fingers - only for debug purposes + + var fingerRays = { + left:{ + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, + index: undefined + }, + right:{ + pinky: undefined, + middle: undefined, + ring: undefined, + thumb: undefined, + index: undefined + } + }; + // Create debug overlays - finger rays + palm rays + spheres - 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 }, - 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 }, - visible: showLines - }); + var palmRay, sphereHand; + + function createDebugLines() { + + 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 }, + 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 }, + visible: showLines + }); + } + + 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 }, + 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 }, + visible: showLines + }) + }; + linesCreated = true; } - var 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 }, - 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 }, - visible: showLines - }) - } - - var sphereHand = { - right: Overlays.addOverlay("sphere", { - position: MyAvatar.position, - color: { red: 0, green: 255, blue: 0 }, - scale: { x: 0.01, y: 0.01, z: 0.01 }, - visible: showSphere - }), - left: Overlays.addOverlay("sphere", { - position: MyAvatar.position, - color: { red: 0, green: 255, blue: 0 }, - scale: { x: 0.01, y: 0.01, z: 0.01 }, - visible: showSphere - }) + function createDebugSphere() { + + sphereHand = { + right: Overlays.addOverlay("sphere", { + position: MyAvatar.position, + color: { red: 0, green: 255, blue: 0 }, + scale: { x: 0.01, y: 0.01, z: 0.01 }, + visible: showSphere + }), + left: Overlays.addOverlay("sphere", { + position: MyAvatar.position, + color: { red: 0, green: 255, blue: 0 }, + scale: { x: 0.01, y: 0.01, z: 0.01 }, + visible: showSphere + }) + }; + sphereCreated = true; } function acquireDefaultPose(side) { @@ -372,7 +474,7 @@ var names = getJointNames(side, finger, jointSuffixes); for (var j = 0; j < names.length; j++) { var index = MyAvatar.getJointIndex(names[j]); - var rotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(index)); + var rotation = MyAvatar.getJointRotation(index); dataDefault[side][finger][j] = dataCurrent[side][finger][j] = rotation; } } @@ -380,44 +482,51 @@ } function updateSphereHand(side) { + + var data = new Palm(); + dataRelativeToWorld(side, palmData[side], data); + varsToDebug.palmData[side] = palmData[side]; - var palmData = estimatePalmData(side); - var palmPoint = palmData.position; - var dist = 1.5*palmData.distance; + var palmPoint = data.position; + var LOOKUP_DISTANCE_MULTIPLIER = 1.5; + var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; // Situate the debugging overlays - var checkOffset = { x: palmData.perpendicular.x * dist, - y: palmData.perpendicular.y * dist, - z: palmData.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)); - Overlays.editOverlay(palmRay[side], { - start: palmPoint, - end: checkPoint, - visible: showLines - }); - - Overlays.editOverlay(sphereHand[side], { - position: spherePos, - scale: { - x: 2*dist, - y: 2*dist, - z: 2*dist - }, - visible: showSphere - }); - - for (var i = 0; i < fingerKeys.length; i++) { - Overlays.editOverlay(fingerRays[side][fingerKeys[i]], { - start: palmData.fingers[fingerKeys[i]], + if (showLines) { + Overlays.editOverlay(palmRay[side], { + start: palmPoint, end: checkPoint, visible: showLines - }); - } + }); + for (var i = 0; i < fingerKeys.length; i++) { + Overlays.editOverlay(fingerRays[side][fingerKeys[i]], { + start: data.fingers[fingerKeys[i]], + end: checkPoint, + visible: showLines + }); + } + } + + if (showSphere) { + Overlays.editOverlay(sphereHand[side], { + position: spherePos, + scale: { + x: 2*dist, + y: 2*dist, + z: 2*dist + }, + visible: showSphere + }); + } // Update the intersection of only one finger at a time @@ -428,11 +537,11 @@ var animationSteps = defaultAnimationSteps; if (grabbables.length > 0) { - var origin = palmData.fingers[finger]; + 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); var percent = 0; // Initialize - var isAbleToGrab = intersection.intersects && intersection.distance < 1.5*dist; + var 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 newFingerData = dataDefault[side][finger]; // assign default pose to finger data @@ -441,9 +550,15 @@ isTouching[side][finger] = isAbleToGrab; if (isAbleToGrab) { // update the open/close percentage for this finger - var distanceMultiplier = 2.5; - percent = intersection.distance/(distanceMultiplier*dist); - var grabMultiplier = finger === "thumb" ? 0.2 : 0.05; + + var FINGER_REACT_MULTIPLIER = 2.8; + + percent = intersection.distance/(FINGER_REACT_MULTIPLIER*dist); + + 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 percent += grabMultiplier * grabPercent[side]; // Calculate new interpolation data @@ -456,6 +571,7 @@ // Calculate animation increments dataDelta[side][finger] = multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); + } // Recreate the finger joint names @@ -474,7 +590,7 @@ var leftTriggerPress = function (value) { varsToDebug.triggerValues.leftTriggerValue = value; // the value for the trigger increments the hand-close percentage - grabPercent["left"] = value; + grabPercent.left = value; }; var leftTriggerClick = function (value) { varsToDebug.triggerValues.leftTriggerClicked = value; @@ -482,7 +598,7 @@ var rightTriggerPress = function (value) { varsToDebug.triggerValues.rightTriggerValue = value; // the value for the trigger increments the hand-close percentage - grabPercent["right"] = value; + grabPercent.right = value; }; var rightTriggerClick = function (value) { varsToDebug.triggerValues.rightTriggerClicked = value; @@ -508,6 +624,14 @@ Controller.enableMapping(MAPPING_NAME); + if (showLines && !linesCreated) { + createDebugLines(); + linesCreated = true; + } + if (showSphere && !sphereCreated) { + createDebugSphere(); + sphereCreated = true; + } function getTouching(side) { var animating = false; @@ -518,16 +642,67 @@ return animating; // return false only if none of the fingers are touching } + function reEstimatePalmData() { + ["right", "left"].forEach(function(side){ + estimatePalmData(side); + }); + } + + MyAvatar.onLoadComplete.connect(function () { + // Sometimes the rig is not ready when this signal is trigger + console.log("avatar loaded"); + Script.setInterval(function(){ + reEstimatePalmData(); + }, 2000); + }); + + MyAvatar.sensorToWorldScaleChanged.connect(function(){ + reEstimatePalmData(); + }); + + Script.scriptEnding.connect(function () { + ["right", "left"].forEach(function(side){ + if (linesCreated) { + Overlays.deleteOverlay(palmRay[side]); + } + if (sphereCreated) { + Overlays.deleteOverlay(sphereHand[side]); + } + for (var i = 0; i < fingerKeys.length; i++) { + + var finger = fingerKeys[i]; + var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints + var names = getJointNames(side, finger, jointSuffixes); + + for (var j = 0; j < names.length; j++) { + var index = MyAvatar.getJointIndex(names[j]); + MyAvatar.clearJointData(index); + } + + if (linesCreated) { + Overlays.deleteOverlay(fingerRays[side][finger]); + } + } + }); + + + + }); + 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){ - + + if (!palmData[side].set) { + reEstimatePalmData(); + } // recalculate the base data updateSphereHand(side); @@ -551,7 +726,7 @@ var index = MyAvatar.getJointIndex(names[j]); // if no finger is touching restate the default poses if (isHandTouching || (dataDefault[side].set && countToDefault[side] < 5*touchAnimationSteps)) { - var quatRot = Quat.fromVec3Degrees(dataCurrent[side][finger][j]); + var quatRot = dataCurrent[side][finger][j]; MyAvatar.setJointRotation(index, quatRot); } else { MyAvatar.clearJointData(index); @@ -561,4 +736,4 @@ }); }); -}()) +}());