一. 安装
1. 打开官网:https://developer.leapmotion.com/get-started
2. 先要下载和安装LeapMotion的驱动程序
注:我买的是二代Leap Motion,所以在Win10下 不支持V2 Desktop的开发驱动,选择左面的。(注意是开发驱动,而非App应用)
我下载的最新版本是3.1.2,解压后如下图。
运行EXE文件,根据提示安装驱动,实际上这将安装了一个驻留程序在系统托盘中,并且生成一个自动启动的系统服务Leap Service,在控制面板中可查看它,当遇到Leap Motion不工作,或者托盘中图标显示黑色时,可检查一下这个服务是否正常。
如果系统托盘出的 Leap Motion 体感控制器图标为黑色,说明 Leap Service 服务并未运行,我们还需要手动启动服务,以支持 Leap Motion 体感控制器的使用。
步骤:
1.单击开始菜单,在“搜索程序和文件”输入框中键入“services.msc”,回车。
2.在服务控制台中,点选“Leap Service”服务,点击“启动”按钮,启动该服务。
3.系统托盘处的 Leap Motion 体感控制器图标变为绿色,说明服务启动成功。
驱动程序与LeapService通讯,读取硬件层面3D摄像头跟踪的手势数据,上层类的应用(如Unity,虚幻4,Java等)则与驱动程序(C++写成)通讯。
安装成功后,能看到LeapMotion两个摄像头和中间LED灯都正常亮起,表明处于工作状态,这时可用自动安装的Leap App Home应用来测试一下,通过它还可下载一些官方的例子。
3. 下载准备好各类Unity包
到https://developer.leapmotion.com/unity下载所需的包。
其中CoreAssert是核心包,其他都是封装好的各类功能包,在实战篇中会介绍。
二. 基本概念
1. 坐标系统
Unity使用左手坐标,LeapMotion使用右手坐标(所以,Z轴是相反的)。
Unity以米为单位,LeapMotion使用毫米。LeapMotion配备的Plugin脚本内部对坐标系统进行了转化,即将单位和坐标转化为Unity的标准。
注意:在Unity中,一定要从LeapServiceProvider中获得Frame对象,否则在帧中的数据(TrackingData)将还使用Leap的坐标系统。LeapServiceProvider解析了Scaling,Rotation,Translation的变换.
2. 手势跟踪
LeapMotion使用了光学传感器和红外光组件。传感器的FOV为150度。顶部0.03~0.06米为有效的跟踪范围。
最佳的工作环境是可产生清晰的、高对比度对象轮廓的光照环境。
HMD模式下(头盔绑定的模式 ),跟踪算法被优化成对不同的视角下识别手势(大概的意思可能是,你头盔多动动,识别得更好一些),比放在桌面固定不动要更好一些。
3. 手(Hand Assert)
(1)表示方法
在预制件目录下,分成图形(图元)和物理两组脚本和预制件,可以用其中各一来组合表示手。这一处一定要理解,官方的Unity包里给了一些场景例子,可以研习一下。
从概念上手被区分成Graphic和Physic两种组件构成,前一即是图元,主要是呈现手的外观,后一主要表现手的物理特性(如刚体、碰撞)。
也可以没有物理组件,这样就不能产生物理特征了。
(2)创建手的方法
有几种创建手的方法:
(3)一个例子
下图是一个典型的手的例子,一个HandController下挂4个子对象,分别是图元左右手,物理左右手。
三. 创建你自己的手Prefab
注:跟着官方例子创建一个手,可能并不是很实用,但有助于理解手的预制件和原理组成。
你可以创建类似于已提供的Unity包里的手预制件,用你自己的图形来表示手,同时定制自己的手的行为(基于已提供好的代码)。
我们要创建的这种手称为“离散手预制件Discrete Hand Prefabs”,意思是手上每个部位都是单独的Game Object,都有其单独的位置和方向信息。在Core assert 包里,机器人的手即是这样的“离散预制件”。下面介绍了通过使用Unity自带的几何体(圆柱、圆)来创建Prefab。
首先,我们需要创建一个手指的Prefab,并且使用它来创建手Prefab。
1. 创建一个场景.
2. 新建一个空对象,命名KnobbyFinger
3. 创建骨头
1) 新建一个空对象到KnobbyFinger下,命名Metacarpal (掌骨)
2) 新建一个Cylinder到Metacarpal,命名Tube.在创建你自己的手时,将此Cylinder替换为你自己的图形对象(或Obejct)
3) 移除碰撞体组件,否则RigidHand碰撞体将会与它反弹。
4) 设置X Rotation为90。
(最好设置成Top视野来观察)
5) 将Tube X、Z的Scale设置成0.003(3毫米)。之所以这样设置,是因为要使用带皮肤的骨头,真实的手指要更胖一些。
6) 设置Tube Y的Scale为0.034(34毫米)。这个决定了手指的长度。
尺寸必须使用真实世界的,转化为米。Y的长度应为68mm的一半,这是因为Cylinder是2个单位高。所以我们要Scale缩减50%。.
7) 复制Metacarpal,命名Proximal,Tube的 Y-Scale设置为0.02
8) 再复制Metacarpal,命名Intermediate,Tube的Y-Scale设置为0.01。
9) 再次复制Metacarpal,命名Distal,Tube的Y-Scale为0.007。
4. 创建关节
记住:你不必都需要骨头和关节
1) 新建空对象到KnobbyFinger,取名MetacarpophalangealJoint(掌指关节)。
2) 新建一个圆到关节,取名Knob.
3) 移除碰撞体。
4) 将Knob所有的Scale设置成0.01(1厘米).
5) 复制MetacarpophalangealJoint更名为ProximalinterphalangealJoint.
6) 复制MetacarpophalangealJoint更名为DistalinterphalangealJoint.
6. 增加SkeletalFinger 脚本组件到KnobbyFinger
7. 拖动每个关节和骨头到脚本中的相应变量处。
具体如下:
Bones:
o 0 -Metacarpal
o 1 - Proximal
o 2 -Intermediate
o 3 - Distal
Joints:
o 0 - MetacarpohalangealJoint
o 1 -ProximalinterphalangealJoint
o 2 -DistalphalangealJoint
8. 将KonbbyFinger做成预制件。
(创建好手指Prefab后)
1. 创建空对象,取名KnobbyHand.
2. 增加SkeletalHand 脚本到 KnobbyHand.
3. 脚本变量Handedness设置成“Either.” (如果你的手是不对称的,设置成 “Right” or “Left”.)
4. 拖动5个KnobbyFinger Prefab到手中,命名为:Thumb, Index, Middle, Ring, and Pinky.
5. 对于每个手指,设置Finger类型为相对应的类型(SkelatalFinger脚本组件中)。
6. 拖动手指到KnobbyHand 的SkeletalHand 脚本中相应的Fingers变量上.
Finger element order:
o 0 - Thumb
o 1 - Index
o 2 - Middle
o 3 - Ring
o 4 - Pinky
7. 拇指是特殊的,没有Metacarpal. 因此,编辑Thumb,在bone数组中移除bone( element 0 ) . 删除Metacarpal子对象.
8. 增加手掌Add the palm:
如果没有图形元素,你可以在KnobbyHand的SkeletalHand脚本变量Palm,wrist,forearm先留为空白。手掌也可通过RigidHand来表示,如果你不使用palm,你可以修改RigidHand的副本,但要移除rigid body和collider。
1) 增加一个空对象到KnobbyHand.取名Palm.
2) 增加一个Cylinder到 Palm.取名 Disc.
3) 移除Collider.
4) 设置Disc的 scale为 (.085, .0015, .085)..
5) 拖动Palm到SkeletalHand脚本的Palm变量中
9. 增加手腕:
1) 增加一个空对象到KnobbyHand,取名Wrist.
2) 增加一个圆到Wrist.取名 Ball.
3) 移除Collider.
4) 设置Ball的 scale为(.03, .03, .03).
5) 拖动Wrist到SkeletalHand脚本WristJoint变量中.
10. 增加胳膊
1) 增加一个空对象Arm.
2) 增加一个Cylinder:Rod.
3) 移除Collider.
4) 设置Rod的x rotation为: 90.
5) 设置Rod的scale为:(.02, .12, .02).
6) 拖动 Arm到SkeletalHand脚本的Forearm
12. 将KnobbyHand创建为prefab.
KnobbyHand的结构应为下图所示:
1. 新建一个LeapHandController prefab到场景中,以便交互区域是在摄影机的FOV内。
2. 设置如下层次结构
3. 在LeapHandController的HandPool中设置:
4. 运行关卡,观察你的手
如果RigidHand组件在Scene窗口中可见,但抖动或反弹,确保你移除图元手部位的所有碰撞体。
如果手指重叠或者移动在一个手指的控制下,检查手指SkeletalFinger 脚本的手指类型设置。
如果你的手混杂成一大团的乱糟糟样子,那是每个子元的Scale设置的太大了,记得Unity的单位是1米,一个典型的手宽度是8.5厘米(或者表示成Unity transform的Scale是0.085)。如果想使手更大一些(在游戏里看),增大LeapHandController的Scale.
三.Unity 主要类介绍
1. Leap.Unity 命名空间下的类
此命名空间下的类负责与Unity的GameObject或组件交互,获取跟踪数据。
· LeapServiceProvider –
访问跟踪(手势轨迹)数据和图形,并与LeapController对象通信,转换轨迹数据为Unity的制式;同时将右手坐标转化为左手坐标。
· IHandModel,HandModel,或继承于它们的 类(如CapsuleHand)–
所有的手都基于这些接口和类,如果你创建自己的手,你必须实现IHandModel 或继承HandModel.
· LeapHandController –
负责与手的图元以及物理对象进行交互。
2. Leap命名空间leap Leap
Leap空间中的类定义了LeapMotion所跟踪的具体内容。
· Frame
帧是某个时间点的数据集合,一个帧包含了Hand对象。
· Hand
一个Hand手对象表示了一个跟踪的手,一个手总是包含5个手指以及相关属性如:Direction,PalmPosition,和Basis(orientation).
· Finger
一个Finger手指对象表示了追踪的手指。一个手指包含四个骨头。
· Bone
Bone骨头对象表示手指的一段,并包含位置、大小和方位数据。
· Arm
Arm胳膊对象是特殊的Bone,其实是跟踪了前臂。.
Leap命名空间下的脚本不是仅专属于Unity的,也可被任何C#程序调用。但在Unity中使用这些类有一些重要的区别:你必须从LeapProvider中获得Frame对象,而不是从Controller对象。LeapProvider将Leap Motion的坐标空间转为Unity的。如果你直接从Controller中获得帧,那么你必须自己处理这些转化。
LeapMotion和UnityAPI为向量和空间变换定义了各自的类,你可以从Leap Motion的类转为Unity等价的类,如下例所示。
Vector3 unityVector = leapVector.ToVector3();
Quaternion unityRotation = leapMatrix.Rotation();
Vector3 unityTranslation = leapMatrix.origin.ToVector3();
Vector3 unityScale = new Vector3(leapMatrix.xBasis.Magnitude,leapMatrix.yBasis.Magnitude,leapMatrix.zBasis.Magnitude);