/* 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
}