Пример #1
0
    private float GetAngle(Leap.Hand hand)
    {
        Vector3 proximalAxis = hand.DistalAxis() * -1f;
        Vector3 radialAxis   = hand.RadialAxis();

        if (hand.IsLeft)
        {
            radialAxis *= -1f;
        }

        List <float> fingerAngles = new List <float>
        {
            Vector3.SignedAngle(proximalAxis, hand.GetIndex().Direction.ToVector3(), radialAxis),
            Vector3.SignedAngle(proximalAxis, hand.GetMiddle().Direction.ToVector3(), radialAxis),
            Vector3.SignedAngle(proximalAxis, hand.GetRing().Direction.ToVector3(), radialAxis),
            Vector3.SignedAngle(proximalAxis, hand.GetPinky().Direction.ToVector3(), radialAxis)
        };

        List <float> fingerAnglesShifted = new List <float>();

        foreach (float angle in fingerAngles)
        {
            float shiftedAngle = angle;
            if (angle < -90f)
            {
                shiftedAngle += 360f;
            }
            fingerAnglesShifted.Add(shiftedAngle);
        }


        angle = 0.25f * (fingerAnglesShifted[0] + fingerAnglesShifted[1] + fingerAnglesShifted[2] + fingerAnglesShifted[3]);

        return(angle);
    }
Пример #2
0
    bool CheckHandForActivation(Leap.Hand hand, bool wasEligibleLastCheck)
    {
        bool  shouldActivate      = false;
        float latestPinchDistance = GetCustomPinchDistance(hand);

        Vector3 palmDir = hand.PalmarAxis();

        Vector3 middleDir             = hand.GetMiddle().bones[1].Direction.ToVector3();
        float   signedMiddlePalmAngle = Vector3.SignedAngle(palmDir, middleDir, hand.RadialAxis());

        if (hand.IsLeft)
        {
            signedMiddlePalmAngle *= -1f;
        }

        Vector3 ringDir             = hand.GetRing().bones[1].Direction.ToVector3();
        float   signedRingPalmAngle = Vector3.SignedAngle(palmDir, ringDir, hand.RadialAxis());

        if (hand.IsLeft)
        {
            signedRingPalmAngle *= -1f;
        }

        Vector3 indexDir       = hand.GetIndex().bones[1].Direction.ToVector3();
        float   indexPalmAngle = Vector3.Angle(indexDir, palmDir);

        Vector3 thumbDir       = hand.GetThumb().bones[2].Direction.ToVector3();
        float   thumbPalmAngle = Vector3.Angle(thumbDir, palmDir);

        // Eligibility checks-- necessary, but not sufficient conditions to start
        // a pinch, suitable for e.g. visual feedback on whether the gesture is
        // "able to occur" or "about to occur."
        if (

            ((!wasEligibleLastCheck &&
              signedMiddlePalmAngle >= minPalmMiddleAngle) ||
             (wasEligibleLastCheck &&
              signedMiddlePalmAngle >= minPalmMiddleAngle
              * ringMiddleSafetyHysteresisMult) ||
             !requireMiddleAndRingSafetyPinch)

            && ((!wasEligibleLastCheck &&
                 signedRingPalmAngle >= minPalmRingAngle) ||
                (wasEligibleLastCheck &&
                 signedRingPalmAngle >= minPalmRingAngle
                 * ringMiddleSafetyHysteresisMult) ||
                !requireMiddleAndRingSafetyPinch)

            // Index angle (eligibility state only)
            && ((!wasEligibleLastCheck &&
                 indexPalmAngle < maxIndexAngleForEligibilityActivation) ||
                (wasEligibleLastCheck &&
                 indexPalmAngle < maxIndexAngleForEligibilityDeactivation))

            // Thumb angle (eligibility state only)
            && ((!wasEligibleLastCheck &&
                 thumbPalmAngle < maxThumbAngleForEligibilityActivation) ||
                (wasEligibleLastCheck &&
                 thumbPalmAngle < maxThumbAngleForEligibilityDeactivation))

            // Must cross pinch threshold from a non-pinching / non-fist pose.
            && (!requiresRepinch)

            )
        {
            // Conceptually, this should be true when all but the most essential
            // parameters for the gesture are satisfied, so the user can be notified
            // that the gesture is imminent.
            _isGestureEligible = true;
        }

        #region Update Pinch Strength

        // Update global "pinch strength".
        // If the gesture is eligible, we'll have a non-zero pinch strength.
        if (_isGestureEligible)
        {
            _latestPinchStrength = latestPinchDistance.Map(0f, pinchActivateDistance,
                                                           1f, 0f);
        }
        else
        {
            _latestPinchStrength = 0f;
        }

        #endregion

        #region Check: Pinch Distance

        if (_isGestureEligible

            // Absolute pinch strength.
            && (latestPinchDistance < pinchActivateDistance)

            )
        {
            shouldActivate = true;
        }

        #endregion

        #region Hysteresis for Failed Pinches

        // "requiresRepinch" prevents a closed-finger configuration from beginning
        // a pinch when the index and thumb never actually actively close from a
        // valid position -- think, closed-fist to safety-pinch, as opposed to
        // open-hand to safety-pinch -- without introducing any velocity-based
        // requirement.
        if (latestPinchDistance < pinchActivateDistance && !shouldActivate)
        {
            requiresRepinch = true;
        }
        if (requiresRepinch && latestPinchDistance > failedPinchResetDistance)
        {
            requiresRepinch = false;
        }

        #endregion

        return(shouldActivate);
    }