我试图在Mac上启动自己的Leap Motion项目,但我遇到了一些问题。
我想在这个项目中使用Objective-C,我已经读过这个语言有一个Leap Motion库。但是,我不确定如何将使用此库的Leap Motion控件集成到Mac应用程序中。
类似的问题here,只是他们要求使用Python Leap Motion库。
如何将Leap Motion控件添加到Objective-C Mac应用程序?
答案 0 :(得分:17)
我最近这样做了,所以我可以提供用于将Leap Motion控件添加到Mac应用程序的步骤。事实上,如果你想要一个例子,我的Leap-enabled Molecules应用程序的源代码是available on GitHub。构建它所需要的就是Leap SDK。
Leap Motion Objective-C标头基本上是围绕其底层C ++ API的包装器,但您不需要关心它,因为您只能通过Objective-C访问它。
要将库添加到项目中,请先在系统中的某处安装Leap SDK。从那里,添加对项目中Leap.h
,LeapMath.h
,LeapObjectiveC.h
和LeapObjectiveC.mm
文件的引用。将libLeap.dylib
库添加到链接库中。
为了避免在测试期间(可能已经解决)编译器和链接器错误,我需要转到我的构建设置并将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控制器获取输入。中心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对象的数组。反过来,您可以从-fingers
方法获取LeapHinger的每个LeapFinger。您还可以提取手的palmPosition
,palmNormal
和整体direction
。
方向以LeapVectors形式提供,它是围绕三维向量的包装对象。您可以从中提取X,Y和Z分量,或者在其他LeapVectors之间执行矢量操作或比较。
在分子中,我通过读取相对于屏幕的进出或从左到右的运动来调整分子结构的比例和方向。我通过比较一只手从一帧到下一帧的张开手的位置来做到这一点。我存储了前一帧,然后在现在和我们最后一次使用
看到这只手之间进行比较LeapVector *handTranslation = [firstHand translation:previousLeapFrame];
您还可以将手的帧或帧中的所有对象之间的比例,旋转等作为一组进行比较。从我在上面的代码中获得的帧到帧的平移,我可以提取单独的X,Y和Z分量来旋转我的模型以响应X和Y的平移和基于Z的缩放。
我对我的应用程序使用粗略定位,但通过跟踪个人指尖显然可以更精细。在您的应用程序启动并运行该设备之后,我建议您阅读Objective-C端的Leap SDK头文件,以了解向您展示的其他功能。此外,尝试不同的交互模式,因为您可能会惊讶于在3D空间中哪些有效且无效。
答案 1 :(得分: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");
}