4

I'm trying to start my own Leap Motion project on the Mac, but I'm having some problems.

I'd like to use Objective-C for this project, and I have read that there is a Leap Motion library for this language. However, I'm not sure how to integrate Leap Motion controls using this library into a Mac application.

Something similar was asked here, only they were asking using the Python Leap Motion library.

How can you add Leap Motion controls to an Objective-C Mac application?

4

2 回答 2

17

我最近这样做了,所以我可以提供用于将 Leap Motion 控件添加到 Mac 应用程序的步骤。事实上,如果你想要一个例子,我的 Leap-enabled Molecules 应用程序的源代码可以在 GitHub 上找到。构建它所需要的只是 Leap SDK。

Leap Motion Objective-C 标头基本上是其底层 C++ API 的包装器,但您无需关心这一点,因为您只能通过 Objective-C 访问它。

要将库添加到您的项目中,请首先在系统中的某个位置安装 Leap SDK。从那里,添加对项目中Leap.hLeapMath.hLeapObjectiveC.hLeapObjectiveC.mm文件的引用。将libLeap.dylib库添加到您的链接库。

为了避免在 beta 期间出现编译器和链接器错误(可能已经解决),我需要转到我的构建设置C++ Standard Library并将libstdc++.

您需要确保 Leap 库与您的应用程序捆绑在一起,因此请确保在构建阶段将其复制到捆绑的框架中。我还需要使用以下运行脚本构建阶段来确保其内部路径设置正确(同样,不确定现在是否需要这样做):

echo TARGET_BUILD_DIR=${TARGET_BUILD_DIR}
echo TARGET_NAME=${TARGET_NAME}
cd "${TARGET_BUILD_DIR}/${TARGET_NAME}.app/Contents/MacOS"
ls -la
# then remap the loader path
install_name_tool -change @loader_path/libLeap.dylib @executable_path/../Resources/libLeap.dylib "${TARGET_NAME}"

设置时的最后一个注意事项是,如果您对 Mac 应用程序进行沙盒处理,则需要启用传出网络连接授权,否则应用程序将无法连接到 Mac 上运行的 Leap Motion 服务器应用程序。

完成所有设置后,您就可以开始从 Leap Motion Controller 获取输入。中央 LeapController 对象将为 Leap Motion 事件提供委托回调。您可以使用如下代码进行设置:

controller = [[LeapController alloc] init];
[controller addListener:self];

你的委托需要满足 LeapListener 协议,它有一堆可选的回调方法:

// Controller object has initialized
- (void)onInit:(NSNotification *)notification
// Controller has connected
- (void)onConnect:(NSNotification *)notification;
// Controller has disconnected
- (void)onDisconnect:(NSNotification *)notification;
// Exiting your LeapController object
- (void)onExit:(NSNotification *)notification;
// New frame data has arrived from the controller
- (void)onFrame:(NSNotification *)notification;

连接和断开回调是显而易见的,尽管您会注意到一件事是在 Xcode 中调试您的应用程序时永远不会触发断开回调。当你断开 Leap Motion 控制器时,你需要在调试器之外运行你的应用程序来触发它。

您将在回调中花费大部分时间-onFrame:,因为这是您获取定位更新的地方。您可以从中获取 LeapController 作为通知对象,并且可以使用以下命令提取当前帧数据:

LeapController *aController = (LeapController *)[notification object];
LeapFrame *frame = [aController frame:0];

LeapFrame 包含 Leap 观察到的所有场景数据,包括手和手指的位置以及它们的整体缩放。LeapFrame 上的-hands方法为您提供了所有检测到的 LeapHand 对象的数组。反过来,您可以从 LeapHand 的-fingers方法中获取每个 LeapFinger。您还可以提取手的palmPositionpalmNormal和整体direction

方向以 LeapVectors 的形式提供,它们是围绕 3-D 向量的包装对象。您可以从中提取 X、Y 和 Z 分量,或执行向量操作或在其他 LeapVector 之间进行比较。

在 Molecules 中,我通过读取相对于屏幕的进出或从左到右的运动来调整分子结构的比例和方向。我通过比较从一帧到下一帧的张开手的位置来做到这一点。我存储上一帧,然后在现在和上次我们看到这只手使用时进行比较

LeapVector *handTranslation = [firstHand translation:previousLeapFrame];

您还可以比较手的帧或帧中的所有对象作为一组的比例、旋转等。从我在上面的代码中获得的帧到帧的平移,我可以提取单独的 X、Y 和 Z 分量来旋转我的模型以响应 X 和 Y 平移并基于 Z 进行缩放。

我在我的应用程序中使用了总定位,但是通过跟踪单个指尖显然可以做得更好。在您的应用程序启动并在设备上运行后,我建议您通读 Objective-C 端的 Leap SDK 头文件,以了解您还可以看到哪些其他功能。此外,请尝试不同的交互模式,因为您可能会对在 3-D 空间中哪些工作做得好和不好做感到惊讶。

于 2013-07-30T02:19:24.027 回答
1

@Brad Larson 的回答几乎涵盖了所有内容,因此请参阅它以获取更多详细信息。但是,他的回答显示了如何使用使用 NSNotifications 工作的 LeapListener 协议。

如果您不喜欢 NSNotificationCenter :p,或者不关心您的更新发生在哪个线程上,这里有一个如何使用LeapDelegate.

@interface MyClass () < LeapDelegate >
@property (strong, nonatomic) LeapController *controller;
@end



- (void)startLeapMotion
{
    if (!_controller) {
        _controller = [[LeapController alloc] initWithDelegate:self];
//
//    Could also be...
//
//    [_controller addDelegate:self];
//    [_controller removeDelegate];
    }
}


- (void)onInit:(LeapController *)controller
{
    NSLog(@"Init");
}

- (void)onConnect:(LeapController *)controller
{
    NSLog(@"Connect");

//    Some settings that came bundled with the Leap sample project. Use if needed
//
//    [controller setPolicyFlags:LEAP_POLICY_DEFAULT];
//    [controller enableGesture:LEAP_GESTURE_TYPE_CIRCLE enable:YES];
//    [controller enableGesture:LEAP_GESTURE_TYPE_KEY_TAP enable:YES];
//    [controller enableGesture:LEAP_GESTURE_TYPE_SCREEN_TAP enable:YES];
//    [controller enableGesture:LEAP_GESTURE_TYPE_SWIPE enable:YES];
}

- (void)onFocusGained:(LeapController *)controller
{
    NSLog(@"Focus Gained");
}

- (void)onFrame:(LeapController *)controller
{
// Write awesome code here!!!
    NSLog(@"Frame");
}

- (void)onFocusLost:(LeapController *)controller
{
    NSLog(@"Focus Lost");
}

- (void)onDisconnect:(LeapController *)controller
{
    NSLog(@"Disconnected");
}

- (void)onExit:(LeapController *)controller
{
    NSLog(@"Exited");
}
于 2013-08-09T17:17:06.890 回答