Leap Motion 之 准备工作
来源:互联网 发布:腾讯代理吃鸡优化 编辑:程序博客网 时间:2024/06/10 14:32
【仅用于个人复习使用,顺序较乱】
一、环境搭建
1、unity(5.0以上版本)
2、LeapMotion SDK(https://developer.leapmotion.com/get-started/)
压缩包(几百MB)下载下来解压安装就okay~
3、Core Asset For Unity(https://developer.leapmotion.com/unity/)
这个只有1.9MB,一个很小的unityPackage~
二、连接测试
1、基本连接
http://jingyan.baidu.com/article/c843ea0bb19a3d77931e4af7.html
右键leap motion控制器可以打开visualizer,按v键可以切换模式。显示橙色则需要清除leap motion上的污迹。(启动会一直闪绿色,只需稍等片刻即可)
如果提示leap service未启动,点击电脑-管理-服务-leap service,右键选择启动即可。
2、Visualizer的使用
http://blog.csdn.net/guoming0000/article/details/9566563
不知道为什么很多命令按了并没有用O>o
三、LeapMotion&Unity
(PS:如果Unity中无法new新的工程,重新登录账号即可,不要问我是怎么知道的O.O)
Core Asset中只有Capsule Hand和Debug Hand,可以从官网下载Hand Module来获得其他的Hand Model,例如Rigged Hand。
四、Core Asset
1、Plugins文件夹
插件?不是很清楚。。。
2、Leap Motion文件夹
这个文件夹是CoreAsset的核心内容。
Gizmos:传感器的贴图
Materials:材质
Models:手的模型
Resources:自定义的Shander,用于Materials中的材质
Textures:一些贴图。。。
OK,以上这些都不重要,属于花里胡哨,下面才是重点。
Editor:一些Editor脚本。
Prefab:预制件,比如HandController。拖入Hierarchy中即可直接使用。
Scripts:一些脚本,例如LeapHandController,后面会具体分析。
Scenes:提供的demo场景,有AR、VR、Desktop。我们这里以Desktop为例。双击进入该场景。
该场景的层次结构如图所示:
HandModels就是双手的模型在hierarchy中生成的对象,LeapHandController就是双手的控制器。需要将HandModels中的Graphics Hands(用来渲染的mesh)和Physics Hands(碰撞器和刚体)传入LeapHandController中,LeapHandController才可以正常work。
LeapHandController对象包含三个脚本:LeapHandController.cs、LeapServiceProvider.cs、HandPool.cs。以下是对这些脚本的解释,当然这对正常使用影响不大,你也可以选择直接跳过这部分。
(1)LeapHandController.cs
直接看注释就好,比较详细~
using UnityEngine;using System.Collections;using System.Collections.Generic;using Leap;//名字空间namespace Leap.Unity { /** * LeapHandController uses a Factory to create and update HandRepresentations based on Frame's received from a Provider */ public class LeapHandController : MonoBehaviour { protected LeapProvider provider; protected HandFactory factory; protected Dictionary<int, HandRepresentation> graphicsReps = new Dictionary<int, HandRepresentation>(); protected Dictionary<int, HandRepresentation> physicsReps = new Dictionary<int, HandRepresentation>(); // Reference distance from thumb base to pinky base in mm. // 也就是拇指到小指在unity中代表的距离 protected const float GIZMO_SCALE = 5.0f; // 这个是内部变量,为了封装的考虑,在下面使用C#中的get和set方法。由于是protected,所以在Inspector面板中不会显示,添加[SerilizeField]将其序列化,可以强制显示在面板上。 protected bool graphicsEnabled = true; protected bool physicsEnabled = true; // get和set方法,主要是权限控制,以及在赋值或读值的时候加入代码检验。带有get/set方法的变量不会显示在Inspector面板中。主要是用在脚本中,暴露给其他类调用来修改相应的变量。如果在Inspector面板修改,则需要Editor去手动关联。当然unity5.0之后的版本可以通过SetProperty来自动实现这一功能。 //关于get/set以及Editor,可以参考这个链接:http://www.cnblogs.com/lixiang-share/p/4658132.html。 public bool GraphicsEnabled { get { return graphicsEnabled; } set { graphicsEnabled = value; } } public bool PhysicsEnabled { get { return physicsEnabled; } set { physicsEnabled = value; } } /** Draws the Leap Motion gizmo when in the Unity editor. */ //所谓的Gizmos,也就是在Scene窗口中显示的小玩意儿,在Scene窗口顶栏可以设置显示的Gizmos种类。而在Game窗口中就不在显示了。 void OnDrawGizmos() { Gizmos.matrix = Matrix4x4.Scale(GIZMO_SCALE * Vector3.one); //这就是Gizmos文件夹的那张贴图 Gizmos.DrawIcon(transform.position, "leap_motion.png"); } protected virtual void OnEnable() { //LeapProvider和HandFactory是Scripts文件夹下两个抽象类,requireComponent<T>是这个脚本中自定义的一个函数,相当于GetComponent,只不过如果没有Component的话会写log。 //其实拿到的就是LeapServiceProvider和HandPool。这两个对象就是那两个抽象类的实现类。 provider = requireComponent<LeapProvider>(); factory = requireComponent<HandFactory>(); provider.OnUpdateFrame += OnUpdateFrame; provider.OnFixedFrame += OnFixedFrame; } protected virtual void OnDisable() { provider.OnUpdateFrame -= OnUpdateFrame; provider.OnFixedFrame -= OnFixedFrame; } /** Updates the graphics HandRepresentations. */ protected virtual void OnUpdateFrame(Frame frame) { if (frame != null && graphicsEnabled) { UpdateHandRepresentations(graphicsReps, ModelType.Graphics, frame); } } /** Updates the physics HandRepresentations. */ protected virtual void OnFixedFrame(Frame frame) { if (frame != null && physicsEnabled) { UpdateHandRepresentations(physicsReps, ModelType.Physics, frame); } } /** * Updates HandRepresentations based in the specified HandRepresentation Dictionary. * Active HandRepresentation instances are updated if the hand they represent is still * present in the Provider's CurrentFrame; otherwise, the HandRepresentation is removed. If new * Leap Hand objects are present in the Leap HandRepresentation Dictionary, new HandRepresentations are * created and added to the dictionary. * @param all_hand_reps = A dictionary of Leap Hand ID's with a paired HandRepresentation * @param modelType Filters for a type of hand model, for example, physics or graphics hands. * @param frame The Leap Frame containing Leap Hand data for each currently tracked hand */ protected virtual void UpdateHandRepresentations(Dictionary<int, HandRepresentation> all_hand_reps, ModelType modelType, Frame frame) { //Frame应该是LeapMotion自己定义的类,猜测可能是将LeapMotion捕捉到的一帧画面进行解析之后,用来保存信息的类。比如这里的frame.Hands.Count就是指这帧画面中的手的数量。 for (int i = 0; i < frame.Hands.Count; i++) { var curHand = frame.Hands[i]; HandRepresentation rep; //如果有就直接get value,如果没有则add一个新的pair if (!all_hand_reps.TryGetValue(curHand.Id, out rep)) { rep = factory.MakeHandRepresentation(curHand, modelType); if (rep != null) { all_hand_reps.Add(curHand.Id, rep); } } //这里会将HandRepresentation的IsMarked置为true,也就是说每一帧画面中active的rep都会被标记。 if (rep != null) { rep.IsMarked = true; rep.UpdateRepresentation(curHand); rep.LastUpdatedTime = (int)frame.Timestamp; } } /** Mark-and-sweep to finish unused HandRepresentations */ //遍历Dictionary,如果发现未被标记的rep,则他一定不是active的,则直接remove掉。 HandRepresentation toBeDeleted = null; for (var it = all_hand_reps.GetEnumerator(); it.MoveNext();) { var r = it.Current; if (r.Value != null) { if (r.Value.IsMarked) { r.Value.IsMarked = false; } else { /** Initialize toBeDeleted with a value to be deleted */ //Debug.Log("Finishing"); toBeDeleted = r.Value; } } } /**Inform the representation that we will no longer be giving it any hand updates * because the corresponding hand has gone away */ if (toBeDeleted != null) { all_hand_reps.Remove(toBeDeleted.HandID); toBeDeleted.Finish(); } } private T requireComponent<T>() where T : Component { T component = GetComponent<T>(); if (component == null) { string componentName = typeof(T).Name; Debug.LogError("LeapHandController could not find a " + componentName + " and has been disabled. Make sure there is a " + componentName + " on the same gameObject."); enabled = false; } return component; } }}
总的来说,就是LeapMotion实时的捕捉每帧的画面。拿到某帧画面后,通过解析将信息保存在Frame当中。
Frame当中的Hands实际上就是Hand类型的List。
当前手部信息(例如finger的位置啊)保存在Hand中,通过Factory产生HandRepresentation并保存在Dictionary中。
每次Update()时,对Dictionary中的active的HandRepresentation调用UpdateRepresentation()函数,其实就是更新HandRepresentation中的Hand属性,也就是更新了场景中的HandModel。
(由于更细节或者更底层的东西还没有看过,所以目前提及的并不一定全都正确,先note一下~)
(2)LeapServiceProvider和HandPool
(代码较长,暂时没看~大致上前者是负责提供frame,而后者是负责将frame的Hand给封装成HandRepresentation)
- Leap Motion 之 准备工作
- Leap Motion 之 Base Class
- leap motion
- Leap Motion
- Leap Motion
- Leap Motion 之 官方SDK代码分析
- Leap Motion自带Sample之详解_Win/C++版本
- Leap Motion自带Sample之详解_Win/C++版本
- Leap Motion自带Sample之详解_Win/C++版本
- Leap Motion自带Sample之详解_Win/C++版本
- LEAP MOTION与MYO
- Leap Motion概述
- Leap Motion架构
- Leap Motion触摸仿真
- Leap Motion架构
- leap motion 系统简介
- Leap Motion架构
- Leap Motion 入门简介
- Hadoop的测试例子WordCount(含效果图)
- ORACLE 函数大全
- 机器学习之-回归树-具体怎么实现及应用
- JAVA知识点总结04
- Java_ftp_file upload and download
- Leap Motion 之 准备工作
- JAVA 获取项目路径
- BZOJ1004 Cards (burnside dp 扩展欧几里德)
- Oracle
- App Store 审核指南
- Mysql_基本操作命令
- Delphi产生任务栏图标【TNotifyIconData】
- 常见用户关心问题
- Linux下Redis服务器安装配置