体感“神器” Leapmotion 使用小结
“神器”之所以要打引号,是因为这个形容词放在几年前,是当之无愧的。但现在的体感设备层出不穷,相比之下。它的技术和体验早已不新鲜。
Leapmotion 早在 2013 年正式上市,却始终没有成为一款大众的产品。这里介绍它,是因为对创意编程而言,是个非常好的拓展工具,练习工具。相比鼠标,键盘,可以带来更新的交互体验。激发灵感的同时,能帮助你更好地理解三维空间。
Leapmotion 是什么?
Leapmotion 和 Kinect 一样,都可以归类为体感设备。前者于 13 年上市,后者是微软在 09 年推出的产品。
体感设备说得直白一点,就是传感器。像温度计测温度,湿度计测湿度。只是体感设备测量的东西不一样而已。无论 Leapmotion 还是 Kinect,它们最终会把测量到的信息传到电脑,这样就可以与程序产生各种交互。
测什么?
Leapmotion 的强项是用来识别手势。网上宣称的数据精度可达 0.01 mm。理论上支持识别多个手掌。但实际使用时,只有在单手或双手的情况下,效果才最稳定。
( Leapmotion 及其使用场景 )
而 Kinect 主要用于做骨架识别,人脸识别,以及简单的手势识别。能识别多人,适合捕捉更大范围的运动,如手臂的挥动等。
( Kinect 1 代 )
( Kinect 2 代 )
Leapmotion 的优势
相比 Kinect ,Leapmotion 有如下优点
小巧便携
灵敏,精度高
偏向“桌面”操作
32g 的重量,可以让你可以和笔记本一起,随时随地带到身上。连接也仅要一根数据线,十分轻便。
可以做什么
玩游戏
对于一般的用户,这可能是它最有吸引力的地方。Leapmotion 的官网有一个应用商店。() 你可以从中下载到各种免费或付费的应用和游戏,而且大部分能同时支持 mac 和 pc。
这里推荐一个富有禅意的游戏,可以用手指来捏造型。有点像玩软陶,它能充分展现 leapmotion 的特性。
控制电脑
除了游戏之外,leapmotion 可以作为一个“鼠标替代器”。通过 Mudra Mouse 等应用,就能将它用于浏览网页,文档,播放切换音乐等。另外,比较有趣的是插件 Ethereal,它能让你在 Photoshop 中使用 leapmotion,由此在空中作画。
以上功能看似酷炫,但并不实用,不要妄想把它当作可以提高效率的生产工具
开发游戏、应用
在官网的 appstore 上架的应用数量非常少,不到 300 个。如果你是会编程的 geek 玩家,那福利就来了。若不满足现有内容,可以自己动手,丰衣足食。
官方文档(
Leapmotion 能使用各种语言和平台进行开发。如网站开发常用的 Js,游戏开发中常用的游戏引擎 Unity 、Unreal。当然,最重要的是还支持两种创意编程工具, Processing 和 Openframeworks.
他们两者都有相关的 leapmotion 插件,使用方法都是相通的。下面会基于 Openframeworks 并结合插件 ofxLeapmotion2 进行展开。
开发准备工作
下载插件 ofxLeapmotion2
首先可以到如下地址下载插件,作者是 genekogan。
()
下载后将整个文件夹放到 OF 的 addon 目录中,并把末尾的“-master ”去掉。
接着把 Leapmotion 通过数据线连接到电脑,并且平放到屏幕前方。
这时打开并运行插件中提供的 example,就能直接使用,从中可以预览识别效果。
现在,你能看到 leapmotion 在 OF 中跑起来是什么样子的
理解插件 ofxLeapmotion2
人们之所以会写各种各样的插件(addons),最终目的都是为了偷懒。把相对底层的代码封装起来,以此简化流程,提高效率。
ofxLeapmotion2 是一个专门在 OF 中使用的插件,使用它我们就无需阅读官方的 API 文档,快速上手开发。
下载任何一个插件,第一步就是要读懂它。不清除是作者们大多比较懒,还是认为例子已经足够简单,无需解释。其实大部分下载下来的范例都不会很细致地交代每句代码的含义。这时就需要你自行解读。
这里提供一些读代码的思路,不仅限于理解插件。
寻根溯源
一般顺序最好先从头文件 ofApp.h 开始,看看声明中用到了哪些插件中特有的数据类型。在这里就是 ofxLeapMotion 和 ofxLeapMotionSimpleHand。根据命名,以及后面的用法,就能大致猜出功能
区分功能块
既然有这些数据类型,自然会声明并使用相应的对象。上一步相当于找到了几个主干,往下看就要到源文件 ofApp.cpp 中观察它们是怎么延伸出枝叶的。
对象的许多功能和 OF 程序的主结构是很像的,互相呼应。有的用于初始化,有的用于更新,有的用于获取数据,处理数据。由于每个部分是由若干行代码组成的,数量或多或少。因而更更整体地看待它,很多细节无需彻底搞懂,只要确定对应的功能即可。可以把代码当作积木,头脑中要有体块意识
分块理解,逐个击破
若不能完全理解,可以先从一个对象,一个主干开始往下看。逐步梳理。当不确定函数的作用时,可以多使用注释符做排除。对于变量和参数则可以多使用 cout,从控制台上观察数据。等到理解了局部,再转战到其他部分,问题也就迎刃而解
从结果推测功能
在插件提供的例子中,可以看到手掌,但仔细观察会发现。其实并不存在一个绘制手掌的函数。所有的手指关节,都是由最基本的球体和直线组成的,用到了我们熟知的 ofDrawSphere 和 ofDrawLine 函数。由此可以推断,这些函数的参数部分填写的就是关节的顶点。我们之后也能调用它,来做各种各样的东西
ofxLeapmotion2 常用函数具体含义
根据上面思路,结合作者的注释。下面选一些关键概念进行说明
1.在 ofApp.h 中可以看到这样一句声明
vector <ofxLeapMotionSimpleHand> simpleHands;
里面就用到了一个很重要的类 ofxLeapMotionSimpleHand。这句代码的作用是声明了一个 vector 对象 simpleHands,它用于储存手掌关节的顶点信息。通过
simpleHands.size(),则可以获取当前识别手掌的数量。
2.update() 函数中的 setMappingX,setMappingY,setMappingZ。作用是将识别到的物理坐标,映射到程序中的空间坐标。前两个参数一般不用调整。若想修改手掌的显示比例可以修改后两个参数
3.for 循环中的 f 从 0 到 4,会影响 simpleHands[i].fingers[ fingerTypes[f]] 获取的坐标,分别对应拇指,食指,中指,无名指,小指。而每根手指,分别有四个节点。从顶部的指尖到根部,在程序中分别命名为 tip,dip,pip,mcp
根据相应的索引,我们就能在 simpleHands 对象中,调取所需的顶点坐标。假如我们希望在所有手掌的食指指尖上,绘制一个正方体。就可以在 draw 中加入如下代码。
“fingerTypes[1]”代表食指,“.tip” 代表指尖关节。
值得注意的是,它必须要写在上面的 for 循环中。而不能将下面的代码直接写在 draw 之内,否则会报错。
ofDrawBox(simpleHands[0].fingers[ fingerTypes[1] ].tip,100)
这是因为当手掌不在设备上方时,simpleHands 会为“空”,也就是数量为 0。所以通过任何下标来调取数据都会出错。除非施加一个判断条件
if(simpleHands.size() > 0){
ofSetColor(255);
ofDrawBox(simpleHands[0].fingers[ fingerTypes[1] ].tip,100);
}
这样就会使得识别的第一个手掌的食指位置,出现一个正方体
常规计算
要用 Leapmotion 开发交互程序,仅仅知道节点坐标是不够的。我们还要对它进行各种运算
记录运动轨迹
可通过创建 vector
计算运动速度
与二维情况下的计算方式是一致的,通过前后两帧坐标的位置差,就可得出速度。但需要将储存上一帧点坐标的变量赋值,写在 draw 函数的末尾。lastPos 代表上一坐标,newPos 代表当前坐标,speed 为该点运行速度
...
speed = newPos - lastPos;
lastPos = newPos;
...
计算手指的伸出距离
在某些应用中,我们需要了解每根手指离掌心的距离。这时可以创建一个 vector
数据更新部分:
绘图部分:
ofSetColor(255);
for(int i = 0;i < handDist.size();i++){
ofDrawRectangle(100 * i - 200, 0, 50, handDist[i]);
}
运行效果:
如果你想开发一个猜拳游戏,那么只要比较各个手指之间的距离,就能知道是剪刀,还是石头布了
拾取,触碰判断
原理相当的简单,通过计算两点间的距离做判断。由于理论上手指节点的坐标是不可能完全重叠的,所以需要设定一个距离阀值。当两点间距离小于此值,则表示为拾取或触碰。假如要识别击掌动作,就可以计算两掌的 handPos 距离。
OF 中的计算距离可使用函数 distance.
dist = A.distance(B); // A,B 表示点坐标
Leapmotion 练习
结合上面的计算技巧,就足以满足大多数的创作需求。下面是使用结合 leapmotion 做的一些实验,文末会附带下载链接
练习01: 3D 画板
思路:
创建一个名为 brushPos 的 vector
对象,用于储存点坐标 设定一个名为 brushDist 的 float 变量,用于设置录入的最小间距。当前后两点坐标小于 brushDist,才在 brushPos 中 push_back 顶点。以此保证轨迹均匀
绘制部分,使用 sin 函数控制球体的大小变化
可通过方向键控制球体大小,并切换光照模式
绘图部分代码:
ofBeginShape();
for(int i = 0;i < brushPos.size();i++){
ofSetColor(ofColor::fromHsb(i * 30 % 255,255,255));
ofCurveVertex(brushPos.size[i]);
ofSetSphereResolution(12);
ofFill();
ofDrawSphere(brushPos.size[i],sphereR * sin(ofGetFrameNum()/10.0 + i * 0.2));
}
ofNoFill();
ofEndShape();
练习02: 3D 钢琴
演示视频:
https://v.qq.com/txp/iframe/player.html?vid=x0343q4b2j7&width=500&height=375&auto=0
思路:
可参考文章中里面的音乐钢琴部分 ( 写给设计师的 OF 编程指南10-媒体加载与事件 ),与二维版是一致的,区别只是将绘制图形绘制到三维空间中
推荐结合插件 ofxAudioUnit,可以使用系统的内置音色,免去寻找音频素材
练习03: 宇宙粒子
演示视频:
https://v.qq.com/txp/iframe/player.html?vid=u0343xamyhy&width=500&height=375&auto=0
思路:
这里使用了常规的粒子系统
食指指尖有一个朝向判断,通过对指尖的第一关节(tip)和第二关节(dip)的 y 坐标进行相减。就能根据正负值来了解指尖是朝上或是朝下
指尖朝上时,释放粒子,开始绘制。朝下时,停止绘制
练习04: 传送门
近期的《 Doctor Strange 》,视觉方面非常出彩。参考里面传送门,尝试用 leapmotion 实现了一个简单的交互程序。用食指来画传送门。
演示视频:
https://v.qq.com/txp/iframe/player.html?vid=s0343hbcbry&width=500&height=375&auto=0
思路:
为了让轨迹更靠近圆形。所以对坐标进行了约束,手指只能影响关键点的角度
总结
有关 leapmotion 的介绍就到此结束了。如果你正在学习创意编程。个人非常推荐这一工具。它能突破二维屏幕的限制,在空间作画。有了它,即使不购买昂贵的VR硬件。也能直观地体验在虚拟空间中创作的快感。所以若想 cosplay 一下造物主,不妨考虑入手一个
下载链接
以上实例的下载地址:
若过期可点击左下方的阅读原文