diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index cc201f58f7..780dacf85e 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -251,11 +251,8 @@ } - function getUIPositionAndRotation(hand) { - return { - position: MINI_POSITIONS[hand], - rotation: MINI_ROTATIONS[hand] - }; + function getUIPosition(hand) { + return MINI_POSITIONS[hand]; } function getMiniTabletID() { @@ -493,7 +490,7 @@ create(); return { - getUIPositionAndRotation: getUIPositionAndRotation, + getUIPosition: getUIPosition, getMiniTabletID: getMiniTabletID, getMiniTabletProperties: getMiniTabletProperties, isLaserPointingAt: isLaserPointingAt, @@ -552,14 +549,23 @@ // Trigger values. leftTriggerOn = 0, rightTriggerOn = 0, - MAX_TRIGGER_ON_TIME = 100, + MAX_TRIGGER_ON_TIME = 400, // Visibility. - MAX_HAND_CAMERA_ANGLE = 30, - MAX_CAMERA_HAND_ANGLE = 30, + MAX_MEDIAL_FINGER_CAMERA_ANGLE = 25, // From palm normal along palm towards fingers. + MAX_MEDIAL_WRIST_CAMERA_ANGLE = 65, // From palm normal along palm towards wrist. + MAX_LATERAL_THUMB_CAMERA_ANGLE = 25, // From palm normal across palm towards of thumb. + MAX_LATERAL_PINKY_CAMERA_ANGLE = 25, // From palm normal across palm towards pinky. DEGREES_180 = 180, - MAX_HAND_CAMERA_ANGLE_COS = Math.cos(Math.PI * MAX_HAND_CAMERA_ANGLE / DEGREES_180), - MAX_CAMERA_HAND_ANGLE_COS = Math.cos(Math.PI * MAX_CAMERA_HAND_ANGLE / DEGREES_180), + DEGREES_TO_RADIANS = Math.PI / DEGREES_180, + MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_MEDIAL_FINGER_CAMERA_ANGLE, + MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_MEDIAL_WRIST_CAMERA_ANGLE, + MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_LATERAL_THUMB_CAMERA_ANGLE, + MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_LATERAL_PINKY_CAMERA_ANGLE, + MAX_CAMERA_MINI_ANGLE = 30, + MAX_CAMERA_MINI_ANGLE_COS = Math.cos(MAX_CAMERA_MINI_ANGLE * DEGREES_TO_RADIANS), + SHOWING_DELAY = 1000, // ms + lastInvisible = [0, 0], HIDING_DELAY = 1000, // ms lastVisible = [0, 0]; @@ -598,11 +604,18 @@ jointIndex, handPosition, handOrientation, - uiPositionAndOrientation, miniPosition, - miniOrientation, miniToCameraDirection, - cameraToHand; + normalHandVector, + medialHandVector, + lateralHandVector, + normalDot, + medialDot, + lateralDot, + medialAngle, + lateralAngle, + cameraToMini, + now; // Shouldn't show mini tablet if hand isn't being controlled. pose = Controller.getPoseValue(hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); @@ -647,27 +660,48 @@ Vec3.multiplyQbyV(MyAvatar.orientation, MyAvatar.getAbsoluteJointTranslationInObjectFrame(jointIndex))); handOrientation = Quat.multiply(MyAvatar.orientation, MyAvatar.getAbsoluteJointRotationInObjectFrame(jointIndex)); - uiPositionAndOrientation = ui.getUIPositionAndRotation(hand); + var uiPosition = ui.getUIPosition(hand); miniPosition = Vec3.sum(handPosition, Vec3.multiply(MyAvatar.sensorToWorldScale, - Vec3.multiplyQbyV(handOrientation, uiPositionAndOrientation.position))); - miniOrientation = Quat.multiply(handOrientation, uiPositionAndOrientation.rotation); + Vec3.multiplyQbyV(handOrientation, uiPosition))); miniToCameraDirection = Vec3.normalize(Vec3.subtract(Camera.position, miniPosition)); - show = Vec3.dot(miniToCameraDirection, Quat.getForward(miniOrientation)) > MAX_HAND_CAMERA_ANGLE_COS; - show = show || (-Vec3.dot(miniToCameraDirection, Quat.getForward(handOrientation)) > MAX_HAND_CAMERA_ANGLE_COS); - cameraToHand = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); - show = show && (cameraToHand > MAX_CAMERA_HAND_ANGLE_COS); + + // Mini tablet aimed toward camera? + medialHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_Y); + lateralHandVector = Vec3.multiplyQbyV(handOrientation, hand === LEFT_HAND ? Vec3.UNIT_X : Vec3.UNIT_NEG_X); + normalHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_Z); + medialDot = Vec3.dot(medialHandVector, miniToCameraDirection); + lateralDot = Vec3.dot(lateralHandVector, miniToCameraDirection); + 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; + + // Camera looking at mini tablet? + cameraToMini = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); + show = show && (cameraToMini > MAX_CAMERA_MINI_ANGLE_COS); + + // Delay showing for a while after it would otherwise be shown, unless it was showing on the other hand. + now = Date.now(); + if (show) { + show = now - lastInvisible[hand] >= SHOWING_DELAY || now - lastVisible[otherHand(hand)] <= HIDING_DELAY; + } else { + lastInvisible[hand] = now; + } // Persist showing for a while after it would otherwise be hidden. if (show) { - lastVisible[hand] = Date.now(); + lastVisible[hand] = now; } else { - show = Date.now() - lastVisible[hand] <= HIDING_DELAY; + show = now - lastVisible[hand] <= HIDING_DELAY; } } return { show: show, - cameraToHand: cameraToHand + cameraToMini: cameraToMini }; } @@ -690,7 +724,7 @@ showRight = shouldShowMini(RIGHT_HAND); if (showLeft.show && showRight.show) { // Both hands would be pointing at camera; show the one the camera is gazing at. - if (showLeft.cameraToHand > showRight.cameraToHand) { + if (showLeft.cameraToMini > showRight.cameraToMini) { setState(MINI_SHOWING, LEFT_HAND); } else { setState(MINI_SHOWING, RIGHT_HAND); @@ -752,7 +786,7 @@ showLeft = shouldShowMini(LEFT_HAND); showRight = shouldShowMini(RIGHT_HAND); if (showLeft.show && showRight.show) { - if (showLeft.cameraToHand > showRight.cameraToHand) { + if (showLeft.cameraToMini > showRight.cameraToMini) { if (miniHand !== LEFT_HAND) { setState(MINI_HIDING); }