LeapMotion初步学习
贴几个直接能在Unity(2017.4.27f1)上测试的代码
1.测试手势的
1 using Leap; 2 using System.Collections; 3 using System.Collections.Generic; 4 using UnityEngine; 5 using Leap.Unity; 6 /// <summary> 7 /// 旋转/缩放/移动 8 /// </summary> 9 public class ControlAnimation : MonoBehaviour 10 { 11 12 LeapProvider provider; 13 public HandModelBase leftHandModel; 14 public HandModelBase rightHandModel; 15 private const float rotate_sensitive = 1500f; //旋转灵敏度 16 private const float displacement_sensitive = 0.015f; //位移灵敏度 17 private const float rotate_initial_value = 0f; //旋转初始位置值 18 19 /// <summary> 20 /// 判断条件 尽量勿动 21 /// </summary> 22 const float smallestVelocity = 0.1f; 23 const float deltaVelocity = 0.000001f; 24 const float deltaCloseFinger = 0.06f; 25 26 void Start() 27 { 28 provider = FindObjectOfType<LeapProvider>() as LeapProvider; 29 } 30 31 32 void Update() 33 { 34 Scale(); 35 Rotation(); 36 Position(); 37 } 38 39 40 /// <summary> 41 /// 缩小 42 /// </summary> 43 public void Scale() 44 { 45 Frame frame = provider.CurrentFrame; 46 foreach (Hand hand in frame.Hands) 47 { 48 if (isOpenFullHand(hand)) 49 { 50 Debug.Log("大"); 51 52 //Vector3 value = transform.localScale; 53 //value += new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); 54 //// Debug.Log(value); 55 //transform.localScale = value; 56 transform.Translate(Vector3.forward * Time.deltaTime * 5); 57 } 58 if (isCloseHand(hand)) 59 { 60 //Debug.Log("小"); 61 //Vector3 value = transform.localScale; 62 //value -= new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); 63 //// Debug.Log(value); 64 65 //transform.localScale = value; 66 } 67 } 68 } 69 70 71 /// <summary> 72 /// 旋转 73 /// </summary> 74 public void Rotation() 75 { 76 Frame frame = provider.CurrentFrame; 77 foreach (Hand hand in frame.Hands) 78 { 79 if (hand.IsLeft || hand.IsRight) 80 { 81 Vector3 value = transform.localEulerAngles; 82 value = new Vector3(/*hand.PalmPosition.y * rotate_sensitive + rotate_initial_value*/0, hand.PalmPosition.x * rotate_sensitive + rotate_initial_value, 0); 83 transform.localEulerAngles = value; 84 } 85 else 86 { 87 hand.PalmPosition.y = transform.localEulerAngles.x; 88 hand.PalmPosition.x = transform.localEulerAngles.y; 89 } 90 } 91 } 92 93 94 /// <summary> 95 /// 位移 96 /// </summary> 97 public void Position() 98 { 99 Frame frame = provider.CurrentFrame; 100 foreach (Hand hand in frame.Hands) 101 { 102 if (hand.IsLeft || hand.IsRight) 103 { 104 if (isMoveLeft(hand)) 105 { 106 transform.localPosition = new Vector3(hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; 107 } 108 if (isMoveRight(hand)) 109 { 110 transform.localPosition = new Vector3(-hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; 111 } 112 } 113 } 114 115 } 116 117 118 protected bool isMoveRight(Hand hand)// 手划向右边 119 { 120 Debug.Log("左滑"); 121 return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand); 122 } 123 124 125 protected bool isMoveLeft(Hand hand) // 手划向左边 126 { 127 Debug.Log("右滑"); 128 //x轴移动的速度 deltaVelocity = 0.7f isStationary (hand) 判断hand是否禁止 129 return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand); 130 } 131 132 protected bool isStationary(Hand hand)// 固定不动的 133 { 134 return hand.PalmVelocity.Magnitude < smallestVelocity; 135 } 136 137 protected bool isCloseHand(Hand hand) //是否握拳 138 { 139 Debug.Log("握拳"); 140 List<Finger> listOfFingers = hand.Fingers; 141 int count = 0; 142 for (int f = 0; f < listOfFingers.Count; f++) 143 { //循环遍历所有的手~~ 144 Finger finger = listOfFingers[f]; 145 if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger) // Magnitude 向量的长度 。是(x*x+y*y+z*z)的平方根。 //float deltaCloseFinger = 0.05f; 146 { 147 count++; 148 // if (finger.Type == Finger.FingerType.TYPE_THUMB) 149 // Debug.Log ((finger.TipPosition - hand.PalmPosition).Magnitude); 150 } 151 } 152 return (count == 5); 153 } 154 155 protected bool isOpenFullHand(Hand hand) //手掌全展开~ 156 { 157 Debug.Log("展开"); 158 //Debug.Log (hand.GrabStrength + " " + hand.PalmVelocity + " " + hand.PalmVelocity.Magnitude); 159 return hand.GrabStrength == 0; 160 } 161 }
2.食指点击UI按钮的,需要给按钮加个碰撞(触发)
1 using System.Collections; 2 using System.Collections.Generic; 3 using Leap; 4 using Leap.Unity; 5 using UnityEngine; 6 using UnityEngine.UI; 7 /// <summary> 8 /// 手指点击 9 /// </summary> 10 public class JudgeHandDetector : MonoBehaviour 11 { 12 13 public Transform[] bonesL; 14 public Transform[] bonesR; 15 public HandModelBase leftHand; 16 public HandModelBase rightHand; 17 18 List<HandModelBase> handModelList = new List<HandModelBase>(); 19 // Update is called once per frame 20 void Update() 21 { 22 23 // 如果两个手都没有识别 清空 list 表 24 if (!leftHand.IsTracked) 25 { 26 if (handModelList.Contains(leftHand)) 27 { 28 handModelList.Remove(leftHand); 29 } 30 } 31 if (!rightHand.IsTracked) 32 { 33 if (handModelList.Contains(rightHand)) 34 { 35 handModelList.Remove(rightHand); 36 } 37 } 38 // 鼠标移动 根据 list[0] 去操作,判断识别手的先后关系 39 if (leftHand != null && leftHand.IsTracked) 40 { 41 if (!handModelList.Contains(leftHand)) 42 { 43 handModelList.Add(leftHand); 44 } 45 } 46 if (rightHand != null && rightHand.IsTracked) 47 { 48 if (!handModelList.Contains(rightHand)) 49 { 50 handModelList.Add(rightHand); 51 } 52 } 53 if (handModelList.Count > 0) 54 { 55 IndexDetector(); 56 } 57 } 58 Ray ray; 59 /// <summary> 60 /// 左右手食指识别 进入相同的处理逻辑 61 /// </summary> 62 void IndexDetector() 63 { 64 if (handModelList[0] == leftHand) 65 { 66 JudgeIndexDetector(bonesL); 67 } 68 else 69 { 70 JudgeIndexDetector(bonesR); 71 } 72 } 73 74 /// <summary> 75 /// 判断食指识别 76 /// </summary> 77 /// <param name="bones"></param> 78 void JudgeIndexDetector(Transform[] bones) 79 { 80 if (bones[1].position.z > bones[0].position.z && bones[1].position.z > bones[2].position.z && 81 bones[1].position.z > bones[3].position.z && bones[1].position.z > bones[4].position.z) 82 { 83 print("这个傻逼伸出了邪恶的食指"); 84 DealRay(bones[1].position); 85 } 86 } 87 /// <summary> 88 /// 处理射线得到的信息 89 /// </summary> 90 void DealRay(Vector3 RayPointV3) 91 { 92 Vector2 screenPos = Camera.main.WorldToScreenPoint(RayPointV3); 93 ray = Camera.main.ScreenPointToRay(screenPos); 94 RaycastHit[] hit = Physics.RaycastAll(ray, 2000f, 1 << LayerMask.NameToLayer("UI")); ; 95 if (hit.Length > 0) 96 { 97 for (int i = 0; i < hit.Length; i++) 98 { 99 Debug.Log("检测到物体" + hit[i].collider.name); 100 BtnEvent(hit[i].transform); 101 } 102 } 103 } 104 105 106 void BtnEvent(Transform btn) 107 { 108 switch (btn.name) 109 { 110 case "Button1": 111 btn.GetComponentInChildren<Text>().text = "把你的脏手从 Button1 上拿开"; 112 break; 113 case "Button2": 114 break; 115 case "Button3": 116 break; 117 case "Button4": 118 break; 119 case "Button5": 120 break; 121 case "Button6": 122 break; 123 default: 124 break; 125 } 126 } 127 }
3.手部运动测试
1 using System.Collections; 2 using System.Collections.Generic; 3 using Leap; 4 using Leap.Unity; 5 using UnityEngine; 6 /// <summary> 7 /// 手部运动测试 8 /// </summary> 9 public class JudgeSwipe : MonoBehaviour 10 { 11 public HandModelBase leftHandModel; 12 [Tooltip("Velocity (m/s) move toward ")] 13 protected float deltaVelocity = 0.7f; 14 //这里传进来你要打开的手指 紧握手指 {} 传一个手指{Finger.FingerType.TYPE_RING}...以此类推,当传进5个值得时候代表 手张开,当传进0个值的时候代表 握手 15 Finger.FingerType[] arr = { Finger.FingerType.TYPE_INDEX, Finger.FingerType.TYPE_MIDDLE }; 16 17 // Update is called once per frame 18 void Update() 19 { 20 if (!leftHandModel.IsTracked) return; 21 Hand leftHand = leftHandModel.GetLeapHand(); 22 //if (IsMoveLeft(leftHand)) 23 //{ 24 // print("左手向左滑动"); 25 //} 26 //if (IsMoveRight(leftHand)) 27 //{ 28 // print("左手向右滑动"); 29 //} 30 //if (IsMoveUp(leftHand)) 31 //{ 32 // print("左手向上滑动"); 33 //} 34 //if (IsMoveDown(leftHand)) 35 //{ 36 // print("左手向下滑动"); 37 //} 38 39 //if (IsCloseHand(leftHand)) 40 //{ 41 // print("握拳"); 42 //} 43 //if (IsOpenFullHand(leftHand)) 44 //{ 45 // print("张手"); 46 //} 47 //if (CheckFingerCloseToHand(leftHand)) 48 //{ 49 // print("四指指向掌心"); 50 //} 51 52 //if (CheckFingerOpenToHand(leftHand, arr)) 53 //{ 54 // print("ok"); 55 //} 56 } 57 /// <summary> 58 /// 这个方法用来扩展哪几个手指打开,这里传进来你要判断是否打开的手指 紧握手指 {} 传一个手指{Finger.FingerType.TYPE_RING}... 59 /// 以此类推,当传进5个值得时候代表 手张开,当传进0个值的时候代表 握手 60 /// </summary> 61 /// <param name="hand"></param> 62 /// <param name="arr"></param> 63 /// <returns></returns> 64 bool CheckFingerOpenToHand(Hand hand, Finger.FingerType[] fingerTypesArr, float deltaCloseFinger = 0.05f) 65 { 66 List<Finger> listOfFingers = hand.Fingers; 67 float count = 0; 68 // 遍历5个手指 69 for (int f = 0; f < listOfFingers.Count; f++) 70 { 71 Finger finger = listOfFingers[f]; 72 // 判读每个手指的指尖位置和掌心位置的长度是不是小于某个值,以判断手指是否贴着掌心 73 if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger) 74 { 75 // 如果传进来的数组长度是0,有一个手指那么 count + 1,continue 跳出,不执行下面数组长度不是0 的逻辑 76 if (fingerTypesArr.Length == 0) 77 { 78 count++; 79 continue; 80 } 81 // 传进来的数组长度不是 0, 82 for (int i = 0; i < fingerTypesArr.Length; i++) 83 { 84 // 假如本例子传进来的是食指和中指,逻辑走到这里,如果你的食指是紧握的,下面会判断这个手指是不是食指,返回 false 85 if (finger.Type == fingerTypesArr[i]) 86 { 87 return false; 88 } 89 else 90 { 91 count++; 92 } 93 } 94 } 95 } 96 if (fingerTypesArr.Length == 0) 97 { 98 return count == 5; 99 } 100 // 这里除以length 是因为上面数组在每次 for 循环 count ++ 会执行 length 次 101 return (count / fingerTypesArr.Length == 5 - fingerTypesArr.Length); 102 } 103 104 /// <summary> 105 /// 判断是否抓取 106 /// </summary> 107 /// <param name="hand"></param> 108 /// <returns></returns> 109 bool isGrabHand(Hand hand) 110 { 111 return hand.GrabStrength > 0.8f; 112 } 113 114 /// <summary> 115 /// 判断是不是握拳 116 /// </summary> 117 /// <param name="hand"></param> 118 /// <returns></returns> 119 bool IsCloseHand(Hand hand) 120 { 121 List<Finger> listOfFingers = hand.Fingers; 122 int count = 0; 123 for (int f = 0; f < listOfFingers.Count; f++) 124 { 125 Finger finger = listOfFingers[f]; 126 if ((finger.TipPosition - hand.PalmPosition).Magnitude < 0.05f) 127 { 128 count++; 129 } 130 } 131 return (count == 4); 132 } 133 134 /// <summary> 135 /// 判断手指是否全张开 136 /// </summary> 137 /// <param name="hand"></param> 138 /// <returns></returns> 139 bool IsOpenFullHand(Hand hand) 140 { 141 return hand.GrabStrength == 0; 142 } 143 144 /// <summary> 145 /// 手滑向左边 146 /// </summary> 147 /// <param name="hand"></param> 148 /// <returns></returns> 149 protected bool IsMoveLeft(Hand hand) // 手划向左边 150 { 151 //x轴移动的速度 deltaVelocity = 0.7f 152 return hand.PalmVelocity.x < -deltaVelocity; 153 } 154 155 /// <summary> 156 /// 手滑向右边 157 /// </summary> 158 /// <param name="hand"></param> 159 /// <returns></returns> 160 protected bool IsMoveRight(Hand hand) 161 { 162 return hand.PalmVelocity.x > deltaVelocity; 163 } 164 165 /// <summary> 166 /// 手滑向上边 167 /// </summary> 168 /// <param name="hand"></param> 169 /// <returns></returns> 170 protected bool IsMoveUp(Hand hand) 171 { 172 return hand.PalmVelocity.y > deltaVelocity; 173 } 174 175 /// <summary> 176 /// 手滑向下边 177 /// </summary> 178 /// <param name="hand"></param> 179 /// <returns></returns> 180 protected bool IsMoveDown(Hand hand) 181 { 182 return hand.PalmVelocity.y < -deltaVelocity; 183 } 184 185 186 /// <summary> 187 /// 判断四指是否靠向掌心 188 /// </summary> 189 /// <param name="hand"></param> 190 /// <returns></returns> 191 bool CheckFingerCloseToHand(Hand hand) 192 { 193 List<Finger> listOfFingers = hand.Fingers; 194 int count = 0; 195 for (int f = 0; f < listOfFingers.Count; f++) 196 { 197 Finger finger = listOfFingers[f]; 198 if ((finger.TipPosition - hand.PalmPosition).Magnitude < 0.05f) 199 { 200 if (finger.Type == Finger.FingerType.TYPE_THUMB) 201 { 202 return false; 203 } 204 else 205 { 206 count++; 207 } 208 } 209 } 210 return (count == 4); 211 } 212 213 214 }
using Leap; using Leap.Unity; using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 物体跟随左手移动 /// </summary> public class LeapBehavior : MonoBehaviour { LeapProvider provider; void Start() { provider = FindObjectOfType<LeapProvider>() as LeapProvider; } void Update() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft) { transform.position = hand.PalmPosition.ToVector3() + hand.PalmNormal.ToVector3() * (transform.localScale.y * .5f + .02f); transform.rotation = hand.Basis.CalculateRotation(); } } } }
4.触碰改变颜色
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using Leap; 5 using Leap.Unity; 6 using System; 7 /// <summary> 8 /// 手指摄取颜色 9 /// </summary> 10 public class JudgeChangeColor : MonoBehaviour 11 { 12 public Color c; 13 public static Color selectedColor; 14 public bool selectable = false; 15 16 void OnTriggerStay(Collider c) 17 { 18 if (c.gameObject.transform.parent.name.Equals("index")) 19 { 20 if (this.selectable) 21 { 22 JudgeChangeColor.selectedColor = this.c; 23 this.transform.Rotate(Vector3.up); 24 return; 25 } 26 transform.gameObject.GetComponent<MeshRenderer>().material.color = JudgeChangeColor.selectedColor; 27 } 28 } 29 30 }
5.拇指和食指捏住改变缩放
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using Leap; 5 using Leap.Unity; 6 using System; 7 /// <summary> 8 /// 手指摄取颜色 9 /// </summary> 10 public class CubeInteraction : MonoBehaviour { 11 public Transform tran; 12 bool isHold = false; 13 Vector3 offset; 14 void Start() 15 { 16 17 } 18 public Transform[] bonesL; 19 public Transform[] bonesR; 20 public HandModelBase leftHand; 21 public HandModelBase rightHand; 22 23 List<HandModelBase> handModelList = new List<HandModelBase>(); 24 25 void Update() 26 { 27 //如果两个手都没有识别 清空列表 28 if (!leftHand.IsTracked) 29 { 30 if (handModelList.Contains(leftHand)) 31 { 32 handModelList.Remove(leftHand); 33 } 34 } 35 if (!rightHand.IsTracked) 36 { 37 if (handModelList.Contains(rightHand)) 38 { 39 handModelList.Remove(rightHand); 40 } 41 } 42 //鼠标移动 根据list[0]去操作,判断识别手的先后关系 43 if (leftHand != null && leftHand.IsTracked) 44 { 45 if (!handModelList.Contains(leftHand)) 46 { 47 handModelList.Add(leftHand); 48 } 49 } 50 if (rightHand != null && rightHand.IsTracked) 51 { 52 if (!handModelList.Contains(rightHand)) 53 { 54 handModelList.Add(rightHand); 55 } 56 } 57 if (handModelList.Count > 0) 58 { 59 JudgeHand(); 60 } 61 } 62 63 private void JudgeHand() 64 { 65 if (Vector3.Distance(bonesL[0].position, bonesL[1].position) < 0.02f && 66 Vector3.Distance(bonesR[0].position, bonesR[1].position) < 0.02f) 67 { 68 Debug.Log("两只手握住"); 69 float distance = Vector3.Distance(bonesL[1].position, bonesR[1].position); 70 tran.localScale = new Vector3(distance, distance, distance); 71 } 72 73 } 74 75 void OnTriggerStay(Collider c) 76 { 77 if (isHold) 78 { 79 transform.position = bonesL[1].position - offset; 80 } 81 } 82 83 }
using Leap;using System.Collections;using System.Collections.Generic;using UnityEngine;using Leap.Unity;/// <summary>/// 旋转/缩放/移动/// </summary>public class ControlAnimation : MonoBehaviour{
LeapProvider provider; public HandModelBase leftHandModel; public HandModelBase rightHandModel; private const float rotate_sensitive = 1500f; //旋转灵敏度 private const float displacement_sensitive = 0.015f; //位移灵敏度 private const float rotate_initial_value = 0f; //旋转初始位置值
/// <summary> /// 判断条件 尽量勿动 /// </summary> const float smallestVelocity = 0.1f; const float deltaVelocity = 0.000001f; const float deltaCloseFinger = 0.06f;
void Start() { provider = FindObjectOfType<LeapProvider>() as LeapProvider; }
void Update() { Scale(); Rotation(); Position(); }
/// <summary> /// 缩小 /// </summary> public void Scale() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (isOpenFullHand(hand)) { Debug.Log("大");
//Vector3 value = transform.localScale; //value += new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); //// Debug.Log(value); //transform.localScale = value; transform.Translate(Vector3.forward * Time.deltaTime * 5); } if (isCloseHand(hand)) { //Debug.Log("小"); //Vector3 value = transform.localScale; //value -= new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); //// Debug.Log(value);
//transform.localScale = value; } } }
/// <summary> /// 旋转 /// </summary> public void Rotation() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft || hand.IsRight) { Vector3 value = transform.localEulerAngles; value = new Vector3(/*hand.PalmPosition.y * rotate_sensitive + rotate_initial_value*/0, hand.PalmPosition.x * rotate_sensitive + rotate_initial_value, 0); transform.localEulerAngles = value; } else { hand.PalmPosition.y = transform.localEulerAngles.x; hand.PalmPosition.x = transform.localEulerAngles.y; } } }
/// <summary> /// 位移 /// </summary> public void Position() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft || hand.IsRight) { if (isMoveLeft(hand)) { transform.localPosition = new Vector3(hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; } if (isMoveRight(hand)) { transform.localPosition = new Vector3(-hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; } } }
}
protected bool isMoveRight(Hand hand)// 手划向右边 { Debug.Log("左滑"); return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand); }
protected bool isMoveLeft(Hand hand) // 手划向左边 { Debug.Log("右滑"); //x轴移动的速度 deltaVelocity = 0.7f isStationary (hand) 判断hand是否禁止 return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand); }
protected bool isStationary(Hand hand)// 固定不动的 { return hand.PalmVelocity.Magnitude < smallestVelocity; }
protected bool isCloseHand(Hand hand) //是否握拳 { Debug.Log("握拳"); 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); }
protected bool isOpenFullHand(Hand hand) //手掌全展开~ { Debug.Log("展开"); //Debug.Log (hand.GrabStrength + " " + hand.PalmVelocity + " " + hand.PalmVelocity.Magnitude); return hand.GrabStrength == 0; }}