LeapMotion控制

关于leapMotion控制的部分代码,如下

 

 

第一部分:LeapManager,用来初始化leapMotion

using UnityEngine;
using System.Collections;
using Leap;

public class LeapManager : MonoBehaviour {
	public Camera _mainCam; //Not required to be set. Defaults to camera tagged "MainCamera".

	public static float _forwardFingerContraint = 0.7f; // Min result of dot product between finger direction and hand direction to determine if finger is facing forward.

	private static Controller _leapController = new Controller();  //实例化控制器
	private static Frame _currentFrame = Frame.Invalid; // 实例化帧
	private static bool _pointerAvailible = false; //判断指示器是否实例化
	private Vector2 _pointerPositionScreen = new Vector3(0,0);  //指示器屏幕坐标(由指示器世界坐标转换而来)
	private Vector3 _pointerPositionWorld = new Vector3(0,0,0);//指示器世界坐标
	private Vector3 _pointerPositionScreenToWorld = new Vector3(0,0,0);//指示器屏幕转世界坐标(由指示器屏幕坐标+z轴转换而来)
	private float _screenToWorldDistance = 10.0f;//  屏幕转世界坐标时的z轴设置

	//Accessors
	/*
	 * A direct reference to the Controller for accessing the LeapMotion data yourself rather than going through the helper.
	 */
	public Controller leapController{ //获得实例化的控制器
		get { return _leapController; }
	}
	
	/*
	 * The most recent frame of data from the LeapMotion controller.
	 */
	public Frame currentFrame  // 获得LeapMotion每一帧
	{
		get { return _currentFrame; }
	}
	
	/*
	 * Is there a pointing finger currently tracked in the scene.
	 */
	public bool pointerAvailible {//指示器是否实例化(如果手实例化了,指示器也就同时实例化)
		get{ return _pointerAvailible; }
	}
	
	/*
	 * The currently tracked (if any) pointing finger in screen space.
	 */
	public Vector2 pointerPositionScreen { //指示器在屏幕坐标
		get { return _pointerAvailible ? _pointerPositionScreen : Vector2.zero; }
	}
	
	/*
	 * The currently tracked (if any) pointing finger in world space.
	 */
	public Vector3 pointerPositionWorld {//指示器在世界坐标
		get { return _pointerAvailible ? _pointerPositionWorld : Vector3.zero; }
	}

	/*
	 * The screen position of the currently tracked (if any) pointing finger projected into world space
	 * at a distance of [screenToWorldDistance].
	 */
	public Vector3 pointerPositionScreenToWorld {  // 指示器在屏幕坐标转世界坐标
		get { return _pointerPositionScreenToWorld; }
	}

	/*
	 * The projection distance for the pointerPositionScreenToWorld calculation. 
	 * Default Value is 10.0f
	 */
	public float screenToWorldDistance {  //屏幕到世界的距离,z轴
		get { return _screenToWorldDistance; }
		set { _screenToWorldDistance = value; }
	}

	//Public Static Functions

	/*
	 * Returns the most likely finger to be pointing on the given hand. 
	 * Returns Finger.Invalid if no such finger exists.
	 */
	public static Finger pointingFigner(Hand hand)//寻找手指中z轴位置最小的手指
	{
		Finger forwardFinger = Finger.Invalid;//手指是否实例化
		ArrayList forwardFingers = forwardFacingFingers(hand);
		
		if(forwardFingers.Count > 0)
		{
			
			float minZ = float.MaxValue;//float最大值
			
			foreach(Finger finger in forwardFingers)
			{
				if(finger.TipPosition.z < minZ)
				{
					minZ = finger.TipPosition.z;
					forwardFinger = finger;
				}
			}
		}
		
		return forwardFinger;
	}

	/*
	 * Returns a list of fingers whose position is in front 
	 * of the hand (relative to the hand direction). 
	 * 
	 * This is most useful in trying to lower the chances 
	 * of detecting a thumb (though not a perfect method).
	 */
	public static ArrayList forwardFacingFingers(Hand hand)  //将点乘大于某一值时,手指放入集合类中,返回一个集合类
	{
		ArrayList forwardFingers = new ArrayList();
		
		foreach(Finger finger in hand.Fingers)
		{
			if(isForwardRelativeToHand(finger, hand)) { forwardFingers.Add(finger); }
		}
		
		return forwardFingers;
	}

	/*
	 * Returns whether or not the given hand is open.
	 */
	public static bool isHandOpen(Hand hand)  //如果手指张开大于2个,判断为手掌张开
	{
		return hand.Fingers.Count > 2;
	}

	public static bool isForwardRelativeToHand(Pointable item, Hand hand)//参数为(一、手指或工具,二、Pointable,手)点乘,如果是垂直的返回0,相同方向的返回1,相反方向的返回-1
	{
		return Vector3.Dot((item.TipPosition.ToUnity() - hand.PalmPosition.ToUnity()).normalized, hand.Direction.ToUnity()) > _forwardFingerContraint;//手指的方向和设备到手掌单位方向的点乘
	}
	
	// Unity Monobehavior Defenitions

	/*
	 * If the _mainCam isn't overridden, 
	 * find the camera with the "MainCamera" tag.
	 */
	void Start () {
		if(_mainCam == null)
		{
			_mainCam = (GameObject.FindGameObjectWithTag("MainCamera") as GameObject).GetComponent(typeof(Camera)) as Camera;
		}
		Debug.Log(_mainCam);
	}
	
	/*
	 * Set the pointer world and screen positions each frame.
	 */
	void Update () {
		_currentFrame = _leapController.Frame();

		Hand primeHand = frontmostHand();

		Finger primeFinger = Finger.Invalid;

		if(primeHand.IsValid)
		{
			primeFinger = pointingFigner(primeHand);

			if(primeFinger.IsValid) 
			{ 
				_pointerAvailible = true; 

				_pointerPositionWorld = primeFinger.TipPosition.ToUnityTranslated();//获得世界坐标
				//TODO: Needs Improvement: Doesn't work if camera is not looking at world origin.
				_pointerPositionScreen = _mainCam.WorldToScreenPoint(_pointerPositionWorld);//世界坐标转屏幕坐标
				_pointerPositionScreenToWorld = _mainCam.ScreenToWorldPoint(new Vector3(pointerPositionScreen.x, //屏幕坐标转世界坐标
				                                                                        pointerPositionScreen.y,
				                                                                        _screenToWorldDistance));
			}
			else
			{ 
				_pointerAvailible = false; 
			}
		}
	}

	//Public Instance Methods

	/*
	 * Get the screen coordinates of all the tracked fingers 
	 * on the given hand.
	 */
	public Vector2[] getScreenFingerPositions(Hand hand)//获得手指在屏幕上的坐标
	{
		Vector2[] retArr = new Vector2[hand.Fingers.Count];

		for(int i=0;i



第二部分:LeapMotion数据转换,转换为Unity的数据

using UnityEngine;
using System.Collections;
using Leap;

namespace Leap
{
	//Extension to the unity vector class. Provides automatic scaling into unity scene space.
	//Leap coordinates are in cm, so the .02f scaling factor means 1cm of hand motion = .02m scene motion
	public static class LeapExtensions
	{
		public static Vector3 InputScale = new Vector3(0.04f, 0.04f, 0.04f);
		public static Vector3 InputOffset = new Vector3(0,-8,0);
		
		//For Directions
		public static Vector3 ToUnity(this Vector lv)//转unity坐标
		{
			return FlippedZ(lv);
		}
		//For Acceleration/Velocity
		public static Vector3 ToUnityScaled(this Vector lv)//转unity坐标,比例可视化调节
		{
			return Scaled(FlippedZ( lv ));
		}
		//For Positions
		public static Vector3 ToUnityTranslated(this Vector lv)//转unity坐标,偏移调节
		{
			return Offset(Scaled(FlippedZ( lv )));
		}
		
		private static Vector3 FlippedZ( Vector v ) { return new Vector3( v.x, v.y, -v.z ); }
		private static Vector3 Scaled( Vector3 v ) { return new Vector3( v.x * InputScale.x,
																		 v.y * InputScale.y,
																		 v.z * InputScale.z ); }
		private static Vector3 Offset( Vector3 v ) { return v + InputOffset; }
	}
}


第三部分:leapMotion控制,通过获取到的数据进行控制模型

using UnityEngine;
using System.Collections;
using Leap;
/// 
/// LeapMotion连接正常下模式进行模型切换和动画切换的脚本
/// 
public class LeapCtrl : MonoBehaviour {

	//实例化FindObj单例类,用来需找需要的对象
	private SingleFindObj _mySingleInLeap;
	//初始化LeapMotion的脚本
	private LeapManager _myLeapManage;
	//从LeapManage获取的靠前的手
	private Hand _myHandInLeap;
	//当前帧
	private Frame _newFrame;
	//之前第15帧
	private Frame _preFrame;
	//当前手
	private Hand _newHand;
	//之前第15帧手
	private Hand _preHand;

	//手移动距离切换模型
	private int _distanceHandMove = 100;
	//模型旋转速度
	private int _speedModelRotation = 10;
	//模型比例控制速度
	private int _speedModeScale = 10;

	//表示是否在进行切换模型
	private bool _isMoveUp;
	//表示是否画圈手势切换动画
	private bool _isGestureMoveUp;

	/// 
	/// RotationTransform函数变量
	/// 
	//是否正在旋转
	private bool _isRotation;
	//模型旋转的临时变量
	private Vector3 _rotationThis;
	private Vector _newHandPosition;

	/// 
	/// ScaleTransform函数变量
	///  
	//在改变比例大小情况下,表示禁止移动和旋转
	private bool _forbidMoveAndRotation;
	//是否正在改变比例
	private bool _isScale;
	//改变比例的临时变量
	private Vector3 _scaleThis;
	private double _distanceFigner;

	void Start () 
	{
		_mySingleInLeap = SingleFindObj.GetInstance();
		_myLeapManage = GameObject.Find("LeapManager").GetComponent();

		//获取leap下速度和距离
		SingleXmlRead _myXmlRead = SingleXmlRead.GetInstance();
		try
		{
			if(_myXmlRead._distanceHandMove.Length >0 )
			{
				_distanceHandMove = int.Parse(_myXmlRead._distanceHandMove[0]);
			}
		}
		catch{_distanceHandMove = 100;}

		try
		{
			if(_myXmlRead._speedScale.Length >0)
			{
				_speedModeScale = int.Parse( _myXmlRead._speedScale[0]);
			}
		}
		catch{_speedModeScale = 10 ;}

		try
		{
			if(_myXmlRead._speedRotation.Length>0)
			{
				_speedModelRotation = int.Parse( _myXmlRead._speedRotation[0]);
			}
		}
		catch{_speedModelRotation = 10;}
	}

	void Update () 
	{
		if(_mySingleInLeap._childModelInSingle != null )
		{
			HandProperties();//获取手属性

			if(!_mySingleInLeap._isAndroidWork)//如果没有Android控制
			{
				if( _myHandInLeap.IsValid)//如果手实例化
				{
					_mySingleInLeap._isLeapWork = true;
				
					if(!_forbidMoveAndRotation)
					{
						ModelMoveUp();
						GestureModelMoveUp();
						RotationTransform();
					}

					ScaleTransform();
				}
				else//没有检测到手
				{
					EndLeapCtrl();
				}
			}
			else//Android手机接入控制
			{
				EndLeapCtrl();
			}
		}
	}
	//结束LeapMotion控制
	void EndLeapCtrl()
	{
		_mySingleInLeap._isLeapWork = false;
		
		StopCoroutine("WaitMoveUp");
		StopCoroutine("WaitGesturemodelMoveUp");
		_isMoveUp = false;
		_isRotation = false;
		_isScale = false;
		_isGestureMoveUp = false;
		_forbidMoveAndRotation = false;
	}

	//开始时,获取手属性
	void HandProperties()
	{
		_myHandInLeap = _myLeapManage.frontmostHand();
		
		_newFrame = _myLeapManage.currentFrame;
		_preFrame = _myLeapManage.preFrame;
		
		_newHand = _newFrame.Hand(_myHandInLeap.Id);
		_preHand = _preFrame.Hand(_myHandInLeap.Id);

	}
	//模型切换的条件判断
	void ModelMoveUp()
	{
		if(_preHand.PalmPosition.y !=0 )
		{
			if(_newHand.PalmPosition.y - _preHand.PalmPosition.y > _distanceHandMove)
			{
				if(!_isMoveUp)
				{
					StartCoroutine( "WaitMoveUp");

					//调用_modelMoveCore类中的切换模型
					_mySingleInLeap._modelMoveCore.MoveUpCore();
				}
			}
		}
	}
	IEnumerator WaitMoveUp()
	{
		_isMoveUp = true;
		yield return new WaitForSeconds(.5f);
		_isMoveUp = false;
	}
	//动画切换的条件判断
	void GestureModelMoveUp()
	{
		GestureList _gesture = _newFrame.Gestures();
		for(int i = 0;i<_gesture.Count;i++)
		{
			switch(_gesture[i].Type)
			{
				case Gesture.GestureType.TYPECIRCLE:
					if(!_isGestureMoveUp)
					{
						StartCoroutine( "WaitGesturemodelMoveUp");
						CircleGesture _circleGesture = new CircleGesture(_gesture[i]);
						if(_circleGesture.Pointable.Direction.AngleTo(_circleGesture.Normal)<= System.Math.PI/2)
						{
							//调用_modelMoveCore类中的切换模型
							//_mySingleInLeap._modelMoveCore.MoveUpCore();
							//调用_modelMoveCore类中的切换动画
							_mySingleInLeap._modelMoveCore.AnimatorSwitchoverCore();
						}
						else if(_circleGesture.Pointable.Direction.AngleTo(_circleGesture.Normal)> System.Math.PI/2)
						{
							_mySingleInLeap._modelMoveCore.AnimatorSwitchoverCoreBack();
						}
					}
					break;

				default:break;
			}
		} //自带画圈TypeCircle手势
	}
	IEnumerator WaitGesturemodelMoveUp()
	{
		_isGestureMoveUp = true;
		yield return new WaitForSeconds(1f);
		_isGestureMoveUp = false;
	}

	//控制模型旋转
	void RotationTransform()
	{
		if(_newHand.Fingers.Count <3)
		{
			if(!_isRotation)
			{
				_newHandPosition = _newHand.PalmPosition;
				_rotationThis = transform.localRotation.eulerAngles;
				_isRotation = true;	
			}
			transform.localRotation = Quaternion.Slerp(transform.localRotation,Quaternion.Euler(0,_rotationThis.y +(_newHand.PalmPosition.x-_newHandPosition.x),0),Time.deltaTime * _speedModelRotation);		
		}
		else 
		{
			_isRotation = false;
		}
	}

	//控制模型比例大小
	void ScaleTransform()
	{
		if(_myLeapManage.IsDoubleHand()&& LeapManager.isHandOpen(_newHand))//两只手
		{
			_forbidMoveAndRotation = true;

			Finger[] _myFinger = _myLeapManage.DoubleFinger();
			if(!_isScale)
			{
				_distanceFigner = ReturnPlus(_myFinger[0].TipPosition.x - _myFinger[1].TipPosition.x)/200.0;//缩小1000倍
				_scaleThis = transform.localScale;
				_isScale = true;
			}
			float _dis = (float) (ReturnPlus(_myFinger[0].TipPosition.x - _myFinger[1].TipPosition.x)/200.0 - _distanceFigner);//缩小1000倍

			Vector3 _newScale = new Vector3( _scaleThis.x + _dis, _scaleThis.y + _dis, _scaleThis.y + _dis);
			if(_newScale.x < 0)
			{
				_newScale = new Vector3(0,0,0);
			}
	
			transform.localScale = Vector3.Slerp( transform.localScale,_newScale,Time.deltaTime *_speedModeScale );
		}
		else
		{
			_isScale = false;
			_forbidMoveAndRotation = false;
		}
	}
	double ReturnPlus(double _value)//返回正值
	{
		if(_value <0 )
			_value = -_value;
		return _value;
	}
}




你可能感兴趣的:(Unity)