Leap motion的一些手勢

 


/* Version Info
 * Author: Wilson
 * Time: 2019年5月11日
 * Function: 手勢數據接口
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Leap;
using Leap.Unity;

/// <summary>
/// 手勢數據
/// </summary>
public class HandData
{
    #region Interface

    /// <summary>
    /// 是否檢測到手部
    /// </summary>
    public static bool handState
    {
        get
        {
            return LeapGestures.handState;
        }
    }

    /// <summary>
    /// 握拳狀態
    /// </summary>
    public static bool fistState
    {
        get
        {
            return LeapGestures.GestureFist;
        }
    }

    /// <summary>
    /// 向左移動
    /// </summary>
    public static bool moveLeft
    {
        get
        {
            return LeapGestures.Gesture_left;
        }
    }

    /// <summary>
    /// 向右移動
    /// </summary>
    public static bool moveRight
    {
        get
        {
            return LeapGestures.Gesture_right;
        }
    }

    /// <summary>
    /// 進度狀態
    /// </summary>
    public static bool moveState
    {
        get
        {
            return LeapGestures.processState;
        }
        set
        {
            LeapGestures.processState = value;
        }
    }

    /// <summary>
    /// 進度控制
    /// </summary>
    public static float ProcessData {
        get {
            return LeapGestures.GestureProcess;
        }
        set
        {
            LeapGestures.GestureProcess = Mathf.Clamp(value, 0f, 1f);
        }
    }

    /// <summary>
    /// 左右控制開關
    /// </summary>
    public static bool allControl;

    #endregion
}
/// <summary>
/// 手勢控制
/// </summary>
public class LeapGestures : MonoBehaviour
{

    #region Gesture data
    /// <summary>
    /// 握拳臨界值
    /// </summary>
    float deltaCloseFinger = 0.1f;
    /// <summary>
    /// 手掌速度(m/s)
    /// </summary>
    float smallestVelocity = 0.01f;//手掌移動的最小速度
    /// <summary>
    /// 單向速度(m/s)
    /// </summary>
    float deltaVelocity = 0.1f;//單方向上手掌移動的速度
    /// <summary>
    /// Hand speed
    /// </summary>
    float HandVelocity;
    float LerpValue = 0.1f;

    public Transform leftPalm;
    /// <summary>
    /// Left hand
    /// </summary>
    Vector3 leftAngle;

    /// <summary>
    /// Right hand
    /// </summary>
    Vector3 rightAngle;
    public Transform rightPalm;

    #endregion

    #region NoSerializable

    /// <summary>
    /// 是否檢測到手部
    /// </summary>
    public static bool handState = false;
    /// <summary>
    ///握拳狀態
    /// </summary>
    public static bool GestureFist = false;
    /// <summary>
    ///手掌方向
    /// </summary>
    public static bool Direction;
    /// <summary>
    /// 向左移動
    /// </summary>
    public static bool Gesture_left = false;
    /// <summary>
    ///向右移動
    /// </summary>
    public static bool Gesture_right = false;
    /// <summary>
    /// 進度狀態
    /// </summary>
    public static bool processState = true;
    /// <summary>
    /// 進度
    /// </summary>
    public static float GestureProcess;

    public static bool Gesture_up = false;
    public static bool Gesture_down = false;
    public static bool Gesture_zoom = false;
    public static float movePOs = 0.0f;

    private LeapProvider mProvider;
    private Frame mFrame;
    private Hand mHand;

    private Vector leftPosition;
    private Vector rightPosition;
    public static float zoom = 1.0f;

    #endregion

    void Start()
    {
        mProvider = FindObjectOfType<LeapProvider>() as LeapProvider;
    }

    void Update()
    {
        leftAngle = leftPalm.eulerAngles;
        rightAngle = rightPalm.eulerAngles;
        //獲取當前幀,獲得手的個數
        mFrame = mProvider.CurrentFrame;
        //print ("hand num are " + mFrame.Hands.Count);
        //是否檢測到手
        handState = mFrame.Hands.Count > 0 ? true : false;
        if (mFrame.Hands.Count > 0)
        {
            if (mFrame.Hands.Count == 2)
                zoom = CalcuateDistance(mFrame);

            if (mFrame.Hands.Count == 1)
                LRUDGestures(mFrame, ref movePOs);
        }
        ProcessControl();
        DirectionControl();
    }

    #region Gestures control


    /// <summary>
    /// 刻度進度
    /// </summary>
    void ProcessControl()
    {
        if (HandData.allControl)
        {
            if (Direction && Gesture_right && HandData.moveState)
            {
                GestureProcess += HandVelocity * LerpValue * Time.deltaTime;
            }
            else if (!Direction && Gesture_left && HandData.moveState)
            {
                GestureProcess += HandVelocity * LerpValue * Time.deltaTime;
            }
        }
        else
        {
            if (Gesture_right && HandData.moveState)
            {
                GestureProcess += HandVelocity * LerpValue * Time.deltaTime;
            }
        }
        GestureProcess = Mathf.Clamp(GestureProcess, 0f, 1f);
    }

    /// <summary>
    /// 掌心方向
    /// </summary>
    void DirectionControl()
    {
        if (leftPalm.gameObject.activeInHierarchy && !rightPalm.gameObject.activeInHierarchy)
        {
            Direction = leftAngle.z <= 180 ? false : true;
        }
        else if (!leftPalm.gameObject.activeInHierarchy && rightPalm.gameObject.activeInHierarchy)
        {
            Direction = rightAngle.z <= 180 ? false : true;
        }
    }

    /// <summary>
    /// 兩隻手之間的距離
    /// </summary>
    /// <param name="mFrame"></param>
    /// <returns></returns>
    float CalcuateDistance(Frame mFrame)
    {
        Gesture_zoom = true;
        Gesture_left = false;
        Gesture_right = false;

        float distance = 0f;
        //print ("Two hands");
        foreach (var itemHands in mFrame.Hands)
        {
            if (itemHands.IsLeft)
            {
                leftPosition = itemHands.PalmPosition;
                //print ("leftPosition" + leftPosition);
            }
            if (itemHands.IsRight)
            {
                rightPosition = itemHands.PalmPosition;
                //print ("rightPosition" + rightPosition);
            }
        }

        if (leftPosition != Vector.Zero && rightPosition != Vector.Zero)
        {

            Vector3 leftPos = new Vector3(leftPosition.x, leftPosition.y, leftPosition.z);
            Vector3 rightPos = new Vector3(rightPosition.x, rightPosition.y, rightPosition.z);

            distance = 10 * Vector3.Distance(leftPos, rightPos);
            print("distance" + distance);
        }

        if (distance != 0)
            return distance;
        else
            return distance = 1;
    }

    /// <summary>
    /// 手勢判斷
    /// </summary>
    /// <param name="mFrame"></param>
    /// <param name="movePOs"></param>
    void LRUDGestures(Frame mFrame, ref float movePOs)
    {
        Gesture_zoom = false;
        foreach (var item in mFrame.Hands)
        {
            int numFinger = item.Fingers.Count;
            //print ("item is  " + numFinger);

            //print("hand are " + isOpenFullHand (item));
            // print ("isOpenFullHands is  " + isOpenFullHands(item));

            if (item.GrabStrength == 1)
            {
                print("num is 0, gestures is woquan");
                GestureFist = true;
                Gesture_left = Gesture_right = false;
            }
            else if (item.GrabStrength == 0)
            {
                //print ("num is 5, open your hand");
                //print("PalmVelocity" + item.PalmVelocity);
                //print("PalmPosition" + item.PalmPosition);
                movePOs = item.PalmPosition.x;
                if (isMoveLeft(item))
                {
                    if (!GestureFist)
                    {
                        Gesture_left = true;
                    }
                    Gesture_right = false;
                    print("move left");

                }
                else if (isMoveRight(item))
                {
                    Gesture_left = false;
                    if (!GestureFist)
                    {
                        Gesture_right = true;
                    }
                    print("move Right");

                }
                else if (isMoveUp(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Up");

                }
                else if (isMoveDown(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Down");

                }
                else if (isMoveForward(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Forward");

                }
                else if (isMoveBack(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move back");

                }
                else if (isStone(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                }
                else if (isStationary(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("isStationary");
                }
                GestureFist = isCloseHand(item);
            }
        }
    }

    /// <summary>
    /// 手的角度
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    private bool isStone(Hand hand)
    {
        //print ("hand.GrabAngle" + hand.GrabAngle);
        //GrabAngle = hand.GrabAngle;
        return hand.GrabAngle > 2.0f;
    }

    /// <summary>
    /// 是否抓取
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isGrabHand(Hand hand)
    {
        return hand.GrabStrength > 0.8f;        //抓取力 
    }

    /// <summary>
    /// 向右移動
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isMoveRight(Hand hand)
    {
        HandVelocity = hand.PalmVelocity.x;
        return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand);
    }

   /// <summary>
   /// 向左移動
   /// </summary>
   /// <param name="hand"></param>
   /// <returns></returns>
    public bool isMoveLeft(Hand hand)
    {
        HandVelocity = hand.PalmVelocity.x;
        //print (hand.PalmVelocity.x );
        return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand);
    }

    /// <summary>
    /// 向上移動
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isMoveUp(Hand hand)
    {
        //print ("hand.PalmVelocity.y" + hand.PalmVelocity.y);

        return hand.PalmVelocity.y > deltaVelocity && !isStationary(hand);
    }

    /// <summary>
    /// 向下移動
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isMoveDown(Hand hand)
    {
        return hand.PalmVelocity.y < -deltaVelocity && !isStationary(hand);
    }

    /// <summary>
    /// 向前移動
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isMoveForward(Hand hand)
    {
        //print (hand.PalmVelocity.z);
        return hand.PalmVelocity.z > deltaVelocity && !isStationary(hand);
    }

    /// <summary>
    /// 向後移動
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isMoveBack(Hand hand)
    {
        return hand.PalmVelocity.z < -deltaVelocity && !isStationary(hand);
    }

    /// <summary>
    /// 固定不動的
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isStationary(Hand hand)
    {
        return hand.PalmVelocity.Magnitude < smallestVelocity;      //Vector3.Magnitude返回向量的長度
    }

    /// <summary>
    /// 是否握拳
    /// </summary>
    /// <param name="hand"></param>
    /// <returns></returns>
    public bool isCloseHand(Hand hand)
    {
        List<Finger> listOfFingers = hand.Fingers;
        int count = 0;
        //循環遍歷所有的手
        for (int f = 0; f < listOfFingers.Count; f++)
        { 
            Finger finger = listOfFingers[f];
            if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger)    // Magnitude  向量的長度 。是(x*x+y*y+z*z)的平方根。
                                                                                          //float deltaCloseFinger = 0.05f;
            {
                count++;
                //if (finger.Type == Finger.FingerType.TYPE_THUMB)
                //Debug.Log ((finger.TipPosition - hand.PalmPosition).Magnitude);
            }
        }
        return (count == 5);
    }

    #endregion

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章