Leap Motion触摸仿真

Leap Motion翻译系列文章http://52coding.com/leap-motion-official-doc-translation

触摸仿真

Leap Motion的API提供了在你的应用中可以进行仿真的信息。触摸信息是通过尖端类提供的。

概述

Leap 定义了一个自适应的触摸平面,你可以将它与你应用中的二维元素美妙的结合在一起。这个平面粗糙的旋转到与x-y平面平行,但是根据用户的手指和手的位置动态调整。但用户的手或者工具从前方到达平面,Leap会报告尖端物体是接近还是触碰到这个虚拟的平面。API通过2个值汇报与平面相关的信息:触摸平面地带和到触摸平面的距离。

上图:虚拟触摸平面

 

触摸地带是识别Leap Motion软件是否把尖端当作悬浮在触摸平面,是穿透触摸平面还是相对于屏幕较远(或者指向错误的方向)。地带包含“悬浮”、“触摸”和“无”。触摸地带的转换根据触摸距离变换有一定滞后。这个滞后用于避免突然和反复的变换。如果你在应用中使用这个触摸交互,你可能不需要经常考虑地带。

 

只有当尖端在悬浮和触摸地带,触摸距离才是有效的。这个距离是归一到[-1,+1]的数值。当一个尖端物体第一次进入悬浮地带,此时触摸距离为+1,而当距离不断减少到0,意味着尖端物体接近触摸平面。但尖端物体穿入平面,距离变为0。因为尖端物体继续往触摸地带推进,距离不断靠近但不会超过-1(永远趋向于-1)。

 

你可以使用地带数值,根据悬浮还是触摸来决定何时更新界面元素。你还可以使用距离,根据是否靠近平面进一步改变界面元素[一个粗,一个细]。例如,当手指在控制体上并且在悬浮地带,你可以让控制体高亮显示,并且依据用户到底多接近控制体的距离,改变光标形态。


作为触摸仿真API的一部分,Leap Motion为尖端物体,提供了一个额外的相对于标准坐标的稳定坐标。Leap Motion软件使用自适应滤波器来稳定这个位置,可以平滑和降低运动,最终使得它在屏幕上小区域内(例如按钮和链接)更容易地与用户交互。但运动缓慢是平滑效果也越强,这样用户可以调整距离并且更容易的触碰到特定的点[这个效果很赞,和人们在现实世界操作一样]。

获取触摸地带

触摸地带通过尖端类的touchZone属性描述。这些地带都是使用枚举类型标识的,一共有下面三个状态:

#NONE --- 尖端距离触摸屏幕太远,大于考虑它触摸的距离。又或者它指向反方向的用户(也就是物体默认在用户正面前,用户手指着自己是一种不合适的操作)

#HOVERING --- 尖端物体的顶端已经到达悬浮地带,但不被认为触摸。

#TOUCHING --- 尖端到达了虚拟平面内。

下面的代码片段说明如何取回最前面手指的地带标识:

    Leap::Frame frame = leap.frame();
    Leap::Pointable pointable = frame.pointables().frontmost();
    Leap::Pointable::Zone zone = pointable.touchZone();

获取触摸距离

触摸距离是通过尖端类的touchDistance属性描述的。这个距离范围是+1到-1,对应了手指移向和穿过虚拟触摸平面。这个距离没有物理意义,但却是Leap Motion软件认为的到底有多靠近触碰。

 

下面的代码段说明如何取出最前端手指的触摸距离:

    Leap::Frame frame = leap.frame();
    Leap::Pointable pointable = frame.pointables().frontmost();
    float distance = pointable.touchDistance();

获取尖端的稳定坐标

稳定坐标是尖端类的stabilizedTipPosition属性描述的。这个位置根据标准Leap Motion坐标系统参照得出的,但是具有一个上下文相关大量数据的滤波器,所以很稳定。

下面的代码片段描述了如何得到最前端手指的稳定位置:

    Leap::Frame frame = leap.frame();
    Leap::Pointable pointable = frame.pointables().frontmost();
    Leap::Vector stabilizedPosition = pointable.stabilizedTipPosition();

从Leap Motion坐标系转换到应用坐标系

但使用触摸仿真时,你必须把Leap Motion的坐标空间转化到应用的屏幕空间。为了使得这个操作更简单,Leap Motion的API提供了一个交互箱子类[交互盒子类](IneractionBox)。这个交互箱子类描述Leap Motion视野中的线性物体运动。这个类提供了一个把物体范围中的坐标归一化到[0,1]范围内。你可以归一化一个距离,并且根据应用尺寸,把结果坐标进行缩放,来获取一个在应用中的坐标。

 

例如,如果你在客户区域中有个具有windowWidth和windowHeight两个度量的窗口,你可以使用以下代码,取得在窗口中触摸点的二维像素坐标:

    Leap::Frame frame = leap.frame();
    Leap::Finger finger = frame.fingers().frontmost();
    Leap::Vector stabilizedPosition = finger.stabilizedTipPosition();

    Leap::InteractionBox iBox = leap.frame().interactionBox();
    Leap::Vector normalizedPosition = iBox.normalizePoint(stabilizedPosition);
    float x = normalizedPosition.x * windowWidth;
    float y = windowHeight - normalizedPosition.y * windowHeight;

触点例子

下面的例子使用触摸仿真的API,来显示所有在应用窗口下,检测到的尖端物体。这个例子使用了触摸地带来设置点的颜色,使用触摸距离来设置alpha数值。使用了交互盒子类爸稳定的顶点位置被映射到应用窗口中。

上图:触摸点例子

#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "Leap.h"
#include "LeapMath.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class TouchPointsApp : public AppNative {
  public:
        void setup();
        void draw();
  private:
    int windowWidth = 800;
    int windowHeight = 800;
    Leap::Controller leap;
};

void TouchPointsApp::setup()
{
    this->setWindowSize(windowWidth, windowHeight);
    this->setFrameRate(120);
    gl::enableAlphaBlending();
}

void TouchPointsApp::draw()
{
        gl::clear( Color( .97, .93, .79 ) );
    Leap::PointableList pointables = leap.frame().pointables();
    Leap::InteractionBox iBox = leap.frame().interactionBox();

    for( int p = 0; p < pointables.count(); p++ )
    {
        Leap::Pointable pointable = pointables[p];
        Leap::Vector normalizedPosition = iBox.normalizePoint(pointable.stabilizedTipPosition());
        float x = normalizedPosition.x * windowWidth;
        float y = windowHeight - normalizedPosition.y * windowHeight;

        if(pointable.touchDistance() > 0 && pointable.touchZone() != Leap::Pointable::Zone::ZONE_NONE)
        {
            gl::color(0, 1, 0, 1 - pointable.touchDistance());
        }
        else if(pointable.touchDistance() <= 0)
        {
            gl::color(1, 0, 0, -pointable.touchDistance());
        }
        else
        {
            gl::color(0, 0, 1, .05);
        }

        gl::drawSolidCircle(Vec2f(x,y), 40);
    }
}

CINDER_APP_NATIVE( TouchPointsApp, RendererGl )

这个例子使用了Cinder库来创建用于绘画的应用窗口。[例子这么简单,怎么玩运行啊]

你可能感兴趣的:(Leap Motion触摸仿真)