关于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
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;
}
}