Beispiel #1
0
        /**
         * The scale factor derived from this hand's motion between the current frame
         * and the specified frame.
         *
         * The scale factor is always positive. A value of 1.0 indicates no
         * scaling took place. Values between 0.0 and 1.0 indicate contraction
         * and values greater than 1.0 indicate expansion.
         *
         * \include Hand_scaleFactor.txt
         *
         * The Leap Motion software derives scaling from the relative inward or outward motion of
         * a hand and its associated fingers (independent of translation
         * and rotation).
         *
         * If a corresponding Hand object is not found in sinceFrame, or if either
         * this frame or sinceFrame are invalid Frame objects, then this method
         * returns 1.0.
         *
         * @param sinceFrame The starting frame for computing the relative scaling.
         * @returns A positive value representing the heuristically determined
         * scaling change ratio of the hand between the current frame and that
         * specified in the sinceFrame parameter.
         * @since 1.0
         */
        public float ScaleFactor(Frame sinceFrame)
        {
            Hand sinceHand = sinceFrame.Hand(this.Id);

            if (!sinceHand.IsValid)
            {
                return(1.0f);
            }

            float thisFactor  = 1 - Math.Max(this.PinchStrength, this.GrabStrength);
            float sinceFactor = 1 - Math.Max(sinceHand.PinchStrength, sinceHand.GrabStrength);

            if (thisFactor < Leap.Constants.EPSILON && sinceFactor < Leap.Constants.EPSILON)
            {
                return(1.0f);
            }

            //Contraction
            if (thisFactor > sinceFactor && thisFactor > Leap.Constants.EPSILON)
            {
                return((thisFactor - sinceFactor) / thisFactor);
            }

            //Expansion
            if (sinceFactor > thisFactor && sinceFactor > Leap.Constants.EPSILON)
            {
                return((sinceFactor - thisFactor) / sinceFactor);
            }

            return(1.0f);
        }
Beispiel #2
0
        /**
         * The transform matrix expressing the rotation derived from the change
         * in orientation of this hand, and any associated fingers,
         * between the current frame and the specified frame.
         *
         * \include Hand_rotationMatrix.txt
         *
         * If a corresponding Hand object is not found in sinceFrame, or if either
         * this frame or sinceFrame are invalid Frame objects, then this method
         * returns an identity matrix.
         *
         * @param sinceFrame The starting frame for computing the relative rotation.
         * @returns A transformation Matrix representing the heuristically determined
         * rotational change of the hand between the current frame and that specified
         * in the sinceFrame parameter.
         * @since 1.0
         */
        public Matrix RotationMatrix(Frame sinceFrame)
        {
            Hand sinceHand = sinceFrame.Hand(this.Id);

            if (!sinceHand.IsValid)
            {
                return(Matrix.Identity);
            }

            return(this.Basis * sinceHand.Basis.RigidInverse());
        }
Beispiel #3
0
        /**
         *
         * /**
         * The change of position of this hand between the current frame and
         * the specified frame.
         *
         * The returned translation vector provides the magnitude and direction of
         * the movement in millimeters.
         *
         * \include Hand_translation.txt
         *
         * If a corresponding Hand object is not found in sinceFrame, or if either
         * this frame or sinceFrame are invalid Frame objects, then this method
         * returns a zero vector.
         *
         * @param sinceFrame The starting frame for computing the translation.
         * @returns A Vector representing the heuristically determined change in
         * hand position between the current frame and that specified in the
         * sinceFrame parameter.
         * @since 1.0
         */
        public Vector Translation(Frame sinceFrame)
        {
            Hand sinceHand = sinceFrame.Hand(this.Id);

            if (!sinceHand.IsValid)
            {
                return(Vector.Zero);
            }

            return(this.PalmPosition - sinceHand.PalmPosition);
        }
Beispiel #4
0
    void Update()
    {
        if(leapInitialized && leapController != null)
        {
            Leap.Frame frame = leapController.Frame();

            if(frame.IsValid && (frame.Id != lastFrameID))
            {
                leapFrame = frame;
                lastFrameID = leapFrame.Id;
                leapFrameCounter++;

                // fix unfinished leap gesture progress
                if(fCircleProgress > 0f && fCircleProgress < 1f)
                    fCircleProgress = 0f;
                if(fSwipeProgress > 0f && fSwipeProgress < 1f)
                    fSwipeProgress = 0f;
                if(fKeyTapProgress > 0f && fKeyTapProgress < 1f)
                    fKeyTapProgress = 0f;
                if(fScreenTapProgress > 0f && fScreenTapProgress < 1f)
                    fScreenTapProgress = 0f;

                // get a suitable pointable
                leapPointable = leapFrame.Pointable(leapPointableID);

                if(!leapPointable.IsValid)
                    leapPointable = leapFrame.Pointables.Frontmost;

                Leap.Vector stabilizedPosition = Leap.Vector.Zero;
                Leap.Hand handPrim = leapFrame.Hands.Count > 0 ? leapFrame.Hands[leapFrame.Hands.Count - 1] : null;

                if(leapPointable != null && leapPointable.IsValid &&
                    leapPointable.Hand != null && leapPointable.Hand.IsValid &&
                    handPrim != null && leapPointable.Hand.Id == handPrim.Id)
                {
                    leapPointableID = leapPointable.Id;
                    leapPointableHandID = leapPointable.Hand != null && leapPointable.Hand.IsValid ? leapPointable.Hand.Id : 0;

                    leapPointablePos = LeapToUnity(leapPointable.StabilizedTipPosition, true);
                    leapPointableDir = LeapToUnity(leapPointable.Direction, false);
                    //leapPointableQuat = Quaternion.LookRotation(leapPointableDir);

                    leapPointableZone = leapPointable.TouchZone;
                    //stabilizedPosition = leapPointable.StabilizedTipPosition;

                    leapHand = leapPointable.Hand;
                    leapHandID = leapHand.Id;
                }
                else
                {
                    leapPointableID = 0;
                    leapPointable = null;

                    // get leap hand
                    leapHand = leapFrame.Hand(leapHandID);
                    if(leapHand == null || !leapHand.IsValid)
                    {
                        leapHandID = 0;

                        if(leapFrame.Hands.Count > 0)
                        {
                            for(int i = leapFrame.Hands.Count - 1; i >= 0; i--)
                            {
                                leapHand = leapFrame.Hands[i];

                                if(leapHand.IsValid /**&& leapHand.Fingers.Count > 0*/)
                                {
                                    leapHandID = leapHand.Id;
                                    break;
                                }
                            }
                        }
                    }

                }

                if(leapHandID != 0)
                {
                    leapHandPos = LeapToUnity(leapHand.StabilizedPalmPosition, true);
                    stabilizedPosition = leapHand.StabilizedPalmPosition;
                    leapHandFingersCount = leapHand.Fingers.Count;
                }

                // estimate the cursor coordinates
                if(stabilizedPosition != Leap.Vector.Zero)
                {
                    Leap.InteractionBox iBox = frame.InteractionBox;
                    Leap.Vector normalizedPosition = iBox.NormalizePoint(stabilizedPosition);

                    cursorNormalPos.x = normalizedPosition.x;
                    cursorNormalPos.y = normalizedPosition.y;
                    cursorScreenPos.x = cursorNormalPos.x * UnityEngine.Screen.width;
                    cursorScreenPos.y = cursorNormalPos.y * UnityEngine.Screen.height;
                }

                // do fingers count filter
                if(leapHandID != fingersCountHandID)
                {
                    fingersCountHandID = leapHandID;
                    fingersCountPrev = -1;
                    fingersCountPrevPrev = -1;

                    handGripDetected = false;
                    fingersCountFilter.Reset();
                }

                if(leapHandID != 0)
                {
                    fingersCountFiltered = leapHandFingersCount;
                    fingersCountFilter.UpdateFilter(ref fingersCountFiltered);

                    if((leapFrameCounter - handGripFrameCounter) >= FramesToSkip)
                    {
                        handGripFrameCounter = leapFrameCounter;
                        int fingersCountNow = (int)(fingersCountFiltered + 0.5f);
                        //int fingersCountNow = leapHandFingersCount;

                        if(fingersCountPrev == fingersCountPrevPrev)
                        {
                            if(!handGripDetected)
                            {
                                if(fingersCountNow < fingersCountPrev)
                                {
                                    Finger leftFinger = leapHand.Finger(leapHandLFingerId);
                                    Finger rightFinger = leapHand.Finger(leapHandRFingerId);
                                    bool bThumbOff = !LeftHandedUser ? leapHandLFingerId != 0 && (leftFinger == null || !leftFinger.IsValid) :
                                        leapHandRFingerId != 0 && (rightFinger == null || !rightFinger.IsValid);

                                    if(bThumbOff)
                                    {
                                        handGripDetected = true;
                                        handGripFingersCount = fingersCountPrev;
                                    }
                                }
                                else
                                {
                                    leapHandLFingerId = leapHand != null && leapHand.Fingers.Count > 0 ? leapHand.Fingers.Leftmost.Id : 0;
                                    leapHandRFingerId = leapHand != null && leapHand.Fingers.Count > 0 ? leapHand.Fingers.Rightmost.Id : 0;
                                }
                            }
                            else
                            {
                                if(fingersCountNow >= fingersCountPrev/**handGripFingersCount*/)
                                {
                                    Finger leftFinger = leapHand.Finger(leapHandLFingerId);
                                    Finger rightFinger = leapHand.Finger(leapHandRFingerId);

                                    bool bThumbOn = !LeftHandedUser ? (leftFinger != null && leftFinger.IsValid) :
                                        (rightFinger != null && rightFinger.IsValid);

                                    if(bThumbOn || fingersCountNow >= handGripFingersCount)
                                    {
                                        handGripDetected = false;
                                    }
                                }
                                else if(leapHand == null || !leapHand.IsValid)
                                {
                                    // stop pinching if the hand is lost
                                    handGripDetected = false;
                                }
                            }
                        }

                        fingersCountPrevPrev = fingersCountPrev;
                        fingersCountPrev = fingersCountNow;
                    }
                }

                if(Time.realtimeSinceStartup >= gestureTrackingAtTime)
                {
                    GestureList gestures = frame.Gestures ();
                    for (int i = 0; i < gestures.Count; i++)
                    {
                        Gesture gesture = gestures[i];

                        switch (gesture.Type)
                        {
                            case Gesture.GestureType.TYPECIRCLE:
                                CircleGesture circle = new CircleGesture(gesture);

                                if((leapFrameCounter - iCircleFrameCounter) >= FramesToSkip &&
                                    iCircleGestureID != circle.Id &&
                                    circle.State == Gesture.GestureState.STATESTOP)
                                {
                                    iCircleFrameCounter = leapFrameCounter;
                                    iCircleGestureID = circle.Id;
                                    fCircleProgress = 1f;

                                    gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                                }
                                else if(circle.Progress < 1f)
                                {
                                    fCircleProgress = circle.Progress;
                                }
                                break;

                            case Gesture.GestureType.TYPESWIPE:
                                SwipeGesture swipe = new SwipeGesture(gesture);

                                if((leapFrameCounter - iSwipeFrameCounter) >= FramesToSkip &&
                                    iSwipeGestureID != swipe.Id &&
                                    swipe.State == Gesture.GestureState.STATESTOP)
                                {
                                    iSwipeFrameCounter = leapFrameCounter;
                                    iSwipeGestureID = swipe.Id;
                                    fSwipeProgress = 1f;  // swipe.Progress

                                    gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;

                                    leapSwipeDir = LeapToUnity(swipe.Direction, false);
                                    leapSwipeSpeed = LeapToUnity(swipe.Position - swipe.StartPosition, true);

                                    if(swipe.DurationSeconds != 0)
                                        leapSwipeSpeed /= swipe.DurationSeconds;
                                    else
                                        leapSwipeSpeed = Vector3.zero;
                                }
                                else if(swipe.State != Gesture.GestureState.STATESTOP)
                                {
                                    fSwipeProgress = 0.5f;
                                }
                                break;

                            case Gesture.GestureType.TYPEKEYTAP:
                                KeyTapGesture keytap = new KeyTapGesture (gesture);

                                if((leapFrameCounter - iKeyTapFrameCounter) >= FramesToSkip &&
                                    iKeyTapGestureID != keytap.Id &&
                                    keytap.State == Gesture.GestureState.STATESTOP)
                                {
                                    iKeyTapFrameCounter = leapFrameCounter;
                                    iKeyTapGestureID = keytap.Id;
                                    fKeyTapProgress = 1f;

                                    gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                                }
                                else if(keytap.Progress < 1f)
                                {
                                    fKeyTapProgress = keytap.Progress;
                                }
                                break;

                            case Gesture.GestureType.TYPESCREENTAP:
                                ScreenTapGesture screentap = new ScreenTapGesture (gesture);

                                if((leapFrameCounter - iScreenTapFrameCounter) >= FramesToSkip &&
                                    iScreenTapGestureID != screentap.Id &&
                                    screentap.State == Gesture.GestureState.STATESTOP)
                                {
                                    iScreenTapFrameCounter = leapFrameCounter;
                                    iScreenTapGestureID = screentap.Id;
                                    fScreenTapProgress = 1f;

                                    gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                                }
                                else if(screentap.Progress < 1f)
                                {
                                    fScreenTapProgress = screentap.Progress;
                                }
                                break;

                            default:
                                Debug.LogError("Unknown gesture type.");
                                break;
                        }
                    }

                    // check for extra gestures
                    int listGestureSize = extraGesturesData.Count;
                    float timestampNow = Time.realtimeSinceStartup;

                    for(int g = 0; g < listGestureSize; g++)
                    {
                        LeapExtraGestures.ExtraGestureData gestureData = extraGesturesData[g];

                        if(timestampNow >= gestureData.startTrackingAtTime)
                        {
                            LeapExtraGestures.CheckForGesture(ref gestureData, Time.realtimeSinceStartup, this);
                            extraGesturesData[g] = gestureData;

                            if(gestureData.complete)
                            {
                                gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                            }
                        }
                    }
                }

                if(DebugCamera)
                {
                    DoDisplayFingers();
                }
            }
        }
    }
Beispiel #5
0
    void Update()
    {
        if(leapInitialized && leapController != null)
        {
            Leap.Frame frame = leapController.Frame();

            if(frame.IsValid && (frame.Id != lastFrameID))
            {
                leapFrame = frame;
                lastFrameID = leapFrame.Id;
                leapFrameCounter++;

                // get the prime hand
                leapHand = leapFrame.Hand(leapHandID);
                if(leapHand == null || !leapHand.IsValid)
                {
                    leapHand = GetFrontmostHand();
                    leapHandID = leapHand != null && leapHand.IsValid ? leapHand.Id : 0;
                }

                leapPointable = leapFrame.Pointable(leapPointableID);
                if(leapPointable == null || !leapPointable.IsValid)
                {
                    leapPointable = leapHand.IsValid ? GetPointingFigner(leapHand) : leapFrame.Pointables.Frontmost;

                    leapPointableID = leapPointable != null && leapPointable.IsValid ? leapPointable.Id : 0;
                    leapPointableHandID = leapPointable != null && leapPointable.IsValid && leapPointable.Hand.IsValid ? leapPointable.Hand.Id : 0;
                }

                if(leapPointable != null && leapPointable.IsValid &&
                   leapPointable.Hand != null && leapPointable.Hand.IsValid &&
                   leapHand != null && leapHand.IsValid && leapPointable.Hand.Id == leapHand.Id)
                {
                    leapPointablePos = LeapToUnity(leapPointable.StabilizedTipPosition, true);
                    leapPointableDir = LeapToUnity(leapPointable.Direction, false);
                }
                else
                {
                    leapPointable = null;

                    leapPointableID = 0;
                    leapPointableHandID = 0;
                }

                Leap.Vector stabilizedPosition = Leap.Vector.Zero;
                if(leapHandID != 0)
                {
                    leapHandPos = LeapToUnity(leapHand.StabilizedPalmPosition, true);
                    stabilizedPosition = leapHand.StabilizedPalmPosition;

                    leapHandFingersCount = leapHand.Fingers.Count;

                    bool bCurrentHandGrip = handGripDetected;
                    handGripDetected = !isHandOpen(leapHand);
                    handReleaseDetected = !handGripDetected;

                }
                else
                {
                    leapHandFingersCount = 0;
                    handGripDetected = false;
                    handReleaseDetected = false;
                }

                if(stabilizedPosition.MagnitudeSquared != 0f)
                {
                    Leap.InteractionBox iBox = frame.InteractionBox;
                    Leap.Vector normalizedPosition = iBox.NormalizePoint(stabilizedPosition);

                    cursorNormalPos.x = normalizedPosition.x;
                    cursorNormalPos.y = normalizedPosition.y;
                    cursorScreenPos.x = cursorNormalPos.x * UnityEngine.Screen.width;
                    cursorScreenPos.y = cursorNormalPos.y * UnityEngine.Screen.height;

                }
            }
        }
    }
        private void HandsController_HandsDetected(object sender, HandCollection e)
        {
            // Display the results!
            if (e.HandRight != null)
            {
                // Draw contour.
                foreach (var point in e.HandRight.ContourDepth)
                {
                    DrawEllipse(point, Brushes.Blue, 2.0);
                }
                // Draw fingers.
                foreach (var finger in e.HandRight.Fingers)
                {
                    DrawEllipse(finger.DepthPoint, Brushes.White, 4.0);
                }

                //added by lu for calib
                if (!calib_finished)
                {
                    if (e.HandRight.Fingers.Count == 5)// if there are five fingers than than do calibration
                    {
                        //do_calib
                        //first get fingers from leap
                        Controller controller = new Controller();
                        Leap.Frame leapframe  = controller.Frame();


                        if (leapframe.Fingers.Count == 5)
                        {
                            if (MessageBox.Show("Is the data qualified?", "Calibration", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
                            {
                                //then sort the fingers of kinect
                                Sort_Kinect_Points(e.HandRight.Fingers);
                                for (int i = 0; i < 5; i++)
                                {
                                    Matrix <float> leapfinger_m = new Matrix <float>(3, 1);
                                    leapfinger_m[0, 0] = leapframe.Fingers[i].StabilizedTipPosition.x;
                                    leapfinger_m[1, 0] = leapframe.Fingers[i].StabilizedTipPosition.y;
                                    leapfinger_m[2, 0] = leapframe.Fingers[i].StabilizedTipPosition.z;
                                    l_list.Add(leapfinger_m);
                                }
                                int k_list_num = k_list.Count();
                                int l_list_num = l_list.Count();
                                using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"F:\\calib_data\\calib_data.txt", true))
                                {
                                    for (int write_num = 5; write_num > 0; write_num--)
                                    {
                                        file.Write(k_list[k_list_num - write_num].X + " ");
                                        file.Write(k_list[k_list_num - write_num].Y + " ");
                                        file.Write(k_list[k_list_num - write_num].Z + " ");
                                        file.Write(l_list[l_list_num - write_num][0, 0] + " ");
                                        file.Write(l_list[l_list_num - write_num][1, 0] + " ");
                                        file.Write(l_list[l_list_num - write_num][2, 0] + "\r\n");
                                    }
                                }
                                //calibration
                                bool calib_done = do_calib(k_list, l_list);
                                if (calib_done)
                                {
                                    List <Matrix <float> > points_test = transform_points(leapframe.Fingers, leapframe.Hand(0));
                                    for (int pointn = 0; pointn < points_test.Count(); pointn++)
                                    {
                                        DrawEllipse(points_test[pointn], Brushes.Red, 5.0);
                                    }


                                    if (MessageBox.Show("Is calibration finished?", "Calibration", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
                                    {
                                        calib_finished = true;
                                        using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"F:\\calib_data\\calib_matrix.txt", true))
                                        {
                                            file.WriteLine(R[0, 0]);
                                            file.WriteLine(R[0, 1]);
                                            file.WriteLine(R[0, 2]);
                                            file.WriteLine(R[1, 0]);
                                            file.WriteLine(R[1, 1]);
                                            file.WriteLine(R[1, 2]);
                                            file.WriteLine(R[2, 0]);
                                            file.WriteLine(R[2, 1]);
                                            file.WriteLine(R[2, 2]);
                                            file.WriteLine(T[0, 0]);
                                            file.WriteLine(T[1, 0]);
                                            file.WriteLine(T[2, 0]);
                                        }
                                    }
                                    else
                                    {
                                        calib_finished = false;
                                    }
                                }
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                }
                else
                {
                    frame_freeze = true;
                    //draw_leap
                    Controller controller = new Controller();
                    Leap.Frame leapframe  = controller.Frame();
                    if (leapframe.Fingers.Count() != 0)
                    {
                        Leap.Hand leap_hand = leapframe.Hands.First();
                        List <Matrix <float> > points_kl = transform_points(leapframe.Fingers, leap_hand);
                        for (int pointn = 0; pointn < 5; pointn++)
                        {
                            DrawEllipse(points_kl[pointn], Brushes.Red, 5.0); // 0 ~ 4 fingertips
                        }
                        DrawEllipse(points_kl[5], Brushes.BlueViolet, 7.0);   //palm position
                        for (int pointn = 6; pointn < points_kl.Count(); pointn++)
                        {
                            DrawEllipse(points_kl[pointn], Brushes.Yellow, 3.0);// finger bones
                        }

                        //MessageBox.Show("projection done!");
                        if (MessageBox.Show("Start adjusting?", "Projection done!", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
                        {
                            adjust.Show();
                            return;
                        }
                        else
                        {
                        }
                    }
                    frame_freeze = false;
                }
            }
        }
Beispiel #7
0
    void Update()
    {
        if(leapInitialized && leapController != null)
        {
            Leap.Frame frame = leapController.Frame();

            if(frame.IsValid && (frame.Id != lastFrameID))
            {
                leapFrame = frame;
                lastFrameID = leapFrame.Id;
                leapFrameCounter++;

        //				// fix unfinished leap gesture progress
        //				if(fCircleProgress > 0f && fCircleProgress < 1f)
        //					fCircleProgress = 0f;
        //				if(fSwipeProgress > 0f && fSwipeProgress < 1f)
        //					fSwipeProgress = 0f;
        //				if(fKeyTapProgress > 0f && fKeyTapProgress < 1f)
        //					fKeyTapProgress = 0f;
        //				if(fScreenTapProgress > 0f && fScreenTapProgress < 1f)
        //					fScreenTapProgress = 0f;

                // get the prime hand
                leapHand = leapFrame.Hand(leapHandID);
                if(leapHand == null || !leapHand.IsValid)
                {
                    leapHand = GetFrontmostHand();
                    leapHandID = leapHand != null && leapHand.IsValid ? leapHand.Id : 0;
                }

                // get the prime pointable
                leapPointable = leapFrame.Pointable(leapPointableID);
                if(leapPointable == null || !leapPointable.IsValid)
                {
                    leapPointable = leapHand.IsValid ? GetPointingFigner(leapHand) : leapFrame.Pointables.Frontmost;

                    leapPointableID = leapPointable != null && leapPointable.IsValid ? leapPointable.Id : 0;
                    leapPointableHandID = leapPointable != null && leapPointable.IsValid && leapPointable.Hand.IsValid ? leapPointable.Hand.Id : 0;
                }

                if(leapPointable != null && leapPointable.IsValid &&
                    leapPointable.Hand != null && leapPointable.Hand.IsValid &&
                    leapHand != null && leapHand.IsValid && leapPointable.Hand.Id == leapHand.Id)
                {
                    leapPointablePos = LeapToUnity(leapPointable.StabilizedTipPosition, true);
                    leapPointableDir = LeapToUnity(leapPointable.Direction, false);
                    //leapPointableQuat = Quaternion.LookRotation(leapPointableDir);
                }
                else
                {
                    leapPointable = null;

                    leapPointableID = 0;
                    leapPointableHandID = 0;
                }

                Leap.Vector stabilizedPosition = Leap.Vector.Zero;
                if(leapHandID != 0)
                {
                    leapHandPos = LeapToUnity(leapHand.StabilizedPalmPosition, true);
                    stabilizedPosition = leapHand.StabilizedPalmPosition;

                    leapHandFingersCount = leapHand.Fingers.Count;

                    bool bCurrentHandGrip = handGripDetected;
                    handGripDetected = !isHandOpen(leapHand);
                    handReleaseDetected = !handGripDetected;

                    if(controlMouseCursor)
                    {
                        if(!bCurrentHandGrip && handGripDetected)
                        {
                            MouseControl.MouseDrag();
                        }
                        else if(bCurrentHandGrip && handReleaseDetected)
                        {
                            MouseControl.MouseRelease();
                        }
                    }
                }
                else
                {
                    if(controlMouseCursor && handGripDetected)
                    {
                        MouseControl.MouseRelease();
                    }

                    leapHandFingersCount = 0;
                    handGripDetected = false;
                    handReleaseDetected = false;
                }

                // estimate the cursor coordinates
                if(stabilizedPosition.MagnitudeSquared != 0f)
                {
                    Leap.InteractionBox iBox = frame.InteractionBox;
                    Leap.Vector normalizedPosition = iBox.NormalizePoint(stabilizedPosition);

                    cursorNormalPos.x = normalizedPosition.x;
                    cursorNormalPos.y = normalizedPosition.y;
                    cursorScreenPos.x = cursorNormalPos.x * UnityEngine.Screen.width;
                    cursorScreenPos.y = cursorNormalPos.y * UnityEngine.Screen.height;

                    if(controlMouseCursor)
                    {
                        MouseControl.MouseMove(cursorNormalPos);
                    }
                }

                // Gesture analysis
                GestureList gestures = frame.Gestures ();
                for (int i = 0; i < gestures.Count; i++)
                {
                    Gesture gesture = gestures[i];

                    if(Time.realtimeSinceStartup < gestureTrackingAtTime)
                        continue;

                    switch (gesture.Type)
                    {
                        case Gesture.GestureType.TYPECIRCLE:
                            CircleGesture circle = new CircleGesture(gesture);

                            if(iCircleGestureID != circle.Id &&
                                circle.State == Gesture.GestureState.STATESTOP)
                            {
                                iCircleGestureID = circle.Id;
                                fCircleProgress = 1f;

                                gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                            }
                            else if(circle.Progress < 1f)
                            {
                                fCircleProgress = circle.Progress;
                            }
                            break;

                        case Gesture.GestureType.TYPESWIPE:
                            SwipeGesture swipe = new SwipeGesture(gesture);

                            if(iSwipeGestureID != swipe.Id &&
                                swipe.State == Gesture.GestureState.STATESTOP)
                            {
                                iSwipeGestureID = swipe.Id;
                                fSwipeProgress = 1f;  // swipe.Progress

                                gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;

                                leapSwipeDir = LeapToUnity(swipe.Direction, false);
                                leapSwipeSpeed = LeapToUnity(swipe.Position - swipe.StartPosition, true);

                                if(swipe.DurationSeconds != 0)
                                    leapSwipeSpeed /= swipe.DurationSeconds;
                                else
                                    leapSwipeSpeed = Vector3.zero;
                            }
                            else if(swipe.State != Gesture.GestureState.STATESTOP)
                            {
                                fSwipeProgress = 0.5f;
                            }
                            break;

                        case Gesture.GestureType.TYPEKEYTAP:
                            KeyTapGesture keytap = new KeyTapGesture (gesture);

        //							if(iKeyTapGestureID != keytap.Id &&
        //								keytap.State == Gesture.GestureState.STATESTOP)
                            {
                                iKeyTapGestureID = keytap.Id;
                                fKeyTapProgress = 1f;

                                gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                            }
        //							else if(keytap.Progress < 1f)
        //							{
        //								fKeyTapProgress = keytap.Progress;
        //							}
                            break;

                        case Gesture.GestureType.TYPESCREENTAP:
                            ScreenTapGesture screentap = new ScreenTapGesture (gesture);

        //							if(iScreenTapGestureID != screentap.Id &&
        //								screentap.State == Gesture.GestureState.STATESTOP)
                            {
                                iScreenTapGestureID = screentap.Id;
                                fScreenTapProgress = 1f;

                                gestureTrackingAtTime = Time.realtimeSinceStartup + MinTimeBetweenGestures;
                            }
        //							else if(screentap.Progress < 1f)
        //							{
        //								fScreenTapProgress = screentap.Progress;
        //							}
                            break;

                        default:
                            Debug.LogError("Unknown gesture type.");
                            break;
                    }
                }

                if(DebugCamera)
                {
                    DoDisplayFingers();
                }
            }
        }
    }