UnityLeapMotion流程记录

突然接到一个LeapMotion的项目,回想起上次做LeapMotion还是在几年前,但是当时没有去记录,所以这次就相当于是重新走了一遍流程。很苦恼,赶紧记录下来。防止之后忘记。这次的需求还是比较简单的,用手滑动控制图片序列播放。

准备

  • Unity版本2021.3.19f1c1
  • LeapMotion一台

开始接入

Downloads – Page Array – Ultraleap

首先来到官网下载LeapMotion的必备组件

选择对应的设备,我这台设备是比较旧的。

无脑安装

安装好后还需要来到github页面下载unity-leapmotion的插件

https://github.com/ultraleap/UnityPlugin

然后导入到unity工程中

导入后找到Capsule Hands场景就是官方的示例

针对需求查看了官网文档。有两种想法:

  1. 通过XRXRI and XRHands Integration - Ultraleap documentation

去用手滑动UI。

  1. 获取手部追踪数据,用程序去判断,得到值,然后去改变视频的帧。

最终选择了第二种方法,觉得第二种比较简单。

创建HandControl.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;using Leap;
using Leap.Unity;public class HandControl : MonoBehaviour
{public static bool Gesture_left = false;public static bool Gesture_right = false;public static bool Gesture_up = false;public static bool Gesture_down = false;public static bool Gesture_zoom = false;public static float movePOs = 0.0f;private LeapProvider mProvider;private Frame mFrame;private Hand mHand;public ImageSwitcher imageSwitcher;private Vector3 leftPosition;private Vector3 rightPosition;public static float zoom = 1.0f;[Tooltip("Velocity (m/s) of Palm ")]public float smallestVelocity = 1.45f;//手掌移动的最小速度[Tooltip("Velocity (m/s) of Single Direction ")][Range(0, 1)]public float deltaVelocity = 1.0f;//单方向上手掌移动的速度// Use this for initializationvoid Start(){mProvider = FindObjectOfType<LeapProvider>() as LeapProvider;}// Update is called once per framevoid Update(){mFrame = mProvider.CurrentFrame;//获取当前帧//获得手的个数//print ("hand num are " + mFrame.Hands.Count);if (mFrame.Hands.Count > 0){if (mFrame.Hands.Count == 2)zoom = CalcuateDistance(mFrame);if (mFrame.Hands.Count == 1)LRUDGestures(mFrame, ref movePOs);}}float CalcuateDistance(Frame mFrame){Gesture_zoom = true;Gesture_left = false;Gesture_right = false;float distance = 0f;//print ("Two hands");foreach (var itemHands in mFrame.Hands){if (itemHands.IsLeft){leftPosition = itemHands.PalmPosition;//print ("leftPosition" + leftPosition);}if (itemHands.IsRight){rightPosition = itemHands.PalmPosition;//print ("rightPosition" + rightPosition);}}if (leftPosition != Vector3.zero && rightPosition != Vector3.zero){Vector3 leftPos = new Vector3(leftPosition.x, leftPosition.y, leftPosition.z);Vector3 rightPos = new Vector3(rightPosition.x, rightPosition.y, rightPosition.z);distance = 10 * Vector3.Distance(leftPos, rightPos);//print("distance" + distance);}if (distance != 0)return distance;elsereturn distance = 1;}void LRUDGestures(Frame mFrame, ref float movePOs){Gesture_zoom = false;foreach (var item in mFrame.Hands){int numFinger = item.Fingers.Count;//print ("item is  " + numFinger);//print("hand are " + isOpenFullHand (item));// print ("isOpenFullHands is  " + isOpenFullHands(item));if (item.GrabStrength == 1){}else if (item.GrabStrength == 0){//print ("num is 5, open your hand");//print("PalmVelocity" + item.PalmVelocity);//print("PalmPosition" + item.PalmPosition);movePOs = item.PalmPosition.x;if (isMoveLeft(item)){Gesture_left = true;Gesture_right = false;//print("move left");}else if (isMoveRight(item)){Gesture_left = false;Gesture_right = true;//print("move Right");}else if (isMoveUp(item)){Gesture_left = false;Gesture_right = false;print("move Up");imageSwitcher.PreviousImage();}else if (isMoveDown(item)){Gesture_left = false;Gesture_right = false;print("move Down");imageSwitcher.NextImage();}else if (isMoveForward(item)){Gesture_left = false;Gesture_right = false;print("move Forward");imageSwitcher.PreviousImage();}else if (isMoveBack(item)){Gesture_left = false;Gesture_right = false;print("move back");imageSwitcher.NextImage();}}}}private bool isStone(Hand hand){//print ("hand.GrabAngle" + hand.GrabAngle);return hand.GrabStrength > 2.0f;}//是否抓取public bool isGrabHand(Hand hand){return hand.GrabStrength > 0.8f;        //抓取力 }//hand move four directionpublic bool isMoveRight(Hand hand){return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand);}// 手划向右边public bool isMoveLeft(Hand hand){//print (hand.PalmVelocity.x );return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand);}//手向上 public bool isMoveUp(Hand hand){//print ("hand.PalmVelocity.y" + hand.PalmVelocity.y);return hand.PalmVelocity.y > deltaVelocity && !isStationary(hand);}//手向下  public bool isMoveDown(Hand hand){return hand.PalmVelocity.y < -deltaVelocity && !isStationary(hand);}//手向前public bool isMoveForward(Hand hand){//print (hand.PalmVelocity.z);return hand.PalmVelocity.z > deltaVelocity && !isStationary(hand);}//手向后 public bool isMoveBack(Hand hand){return hand.PalmVelocity.z < -deltaVelocity && !isStationary(hand);}//固定不动的public bool isStationary(Hand hand){return hand.PalmVelocity.magnitude < smallestVelocity;      //Vector3.Magnitude返回向量的长度}}

创建ImageSwitcher.cs脚本

using UnityEngine;
using UnityEngine.UI; // 引入UI命名空间public class ImageSwitcher : MonoBehaviour
{public Image displayImage; // 用于显示图片的Image组件public Sprite[] images; // 存储所有图片的数组private int currentImageIndex = 0; // 当前显示的图片索引void Start(){// 初始化时显示第一张图片if (images.Length > 0){displayImage.sprite = images[currentImageIndex];}}// 切换到下一张图片public void NextImage(){if (images.Length > 0){currentImageIndex = (currentImageIndex + 1) % images.Length; // 使用模运算确保索引循环displayImage.sprite = images[currentImageIndex];}}// 切换到上一张图片public void PreviousImage(){if (images.Length > 0){currentImageIndex = (currentImageIndex - 1 + images.Length) % images.Length; // 使用模运算确保索引循环displayImage.sprite = images[currentImageIndex];}}
}

将两个脚本挂载在场景中并赋值

image switcher中的images将准备好的序列帧拖入

创建Canvas和Image。将image拖入image Switcher中

最终场景是这样的结构。使用的场景是官方的Capsule Hands。

成功运行。这个项目比较简单,开发的时候也没有遇到坑,在此记录下防止后面忘了流程。

官方文档

Get started with our plugins for XR developers - Ultraleap documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/845694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Visual Studio2022中同一个项目里写作业,有多个cpp文件会报错

为了省事&#xff0c;在同一个项目里写很多个题目&#xff0c;结果只有一个cpp文件时没出错&#xff0c;写了2个cpp文件再想运行时就出错了&#xff1b; 将不相关的cpp文件移出去 在源文件中对其点击右键&#xff0c;找到“从项目中排除”&#xff1b; 结果如图&#xff0c;剩…

深度学习21天 —— 卷积神经网络(CNN):识别验证码( 第12天)

目录 一、前期准备 1.1 标签数字化 1.2 加载数据 1.3 配置数据 二、其他 2.1 损失函数 categorical_crossentropy 2.2 plt.legend(loc ) 2.3 history.history 活动地址&#xff1a;CSDN21天学习挑战赛 学习&#xff1a;深度学习100例-卷积神经网络&#xff08;CNN&…

通过 SFP 接口实现千兆光纤以太网通信2

Tri Mode Ethernet MAC IP 核结构 时钟网络 IP 核内部时钟网络结构如下图所示。其中&#xff0c;tx_mac_aclk 为 AXI-Stream 发送接口的同步时钟&#xff0c; rx_mac_aclk 为 AXI-Stream 接收接口的同步时钟。由于在设计中没有使用 MDIO 接口&#xff0c;所以不存在时钟信号 …

二人订单共享结束制:终身受益的新模式

在当今快速发展的互联网时代&#xff0c;一个创新的商业模式总能引起广泛关注。其中&#xff0c;“二人订单共享结束制”以其独特的魅力&#xff0c;吸引了众多消费者和创业者的目光。这一模式不仅为消费者带来了实惠&#xff0c;更为创业者提供了一个全新的平台。 只需购买一…

【C++集群聊天服务器(一)】|Linux平台资源受限下boost库和muduo网络库源码编译安装

本人使用的服务器是2G2核 ubuntu22.04 前置工作 muduo库源码github仓库地址&#xff1a; muduo WIndows和Linux平台的boost源码包下载(zip是Windows版&#xff0c;tar.gz是Linux版&#xff0c;你也可以去boost官网下载最新版本) Boost C Libraries 由于muduo网络库是基于boo…

基于java的CRM客户关系管理系统(二)

目录 第二章 相关技术介绍 2.1 后台介绍 2.1.1 B/S平台模式 2.1.2 MVC 2.1.3 Spring 2.1.4 Hibernate 2.1.5 Struts 2.2 前端介绍 2.2.1 JSP网页技术 2.3 开发工具 2.4 本章小结 前面内容请移步 基于java的CRM客户关系管理系统&#xff08;二&#xff09; 资源…

网络原理-TCP/IP --传输层(UDP)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 目录 端口号UDP协议 端口号 我们在学习套接字的时候,涉及到两个概念:IP地址和端口号 IP地址是用来确定主机,这是网络层提供的概念 而端口号就是用来确定主机上的应用程序,就是传输层的概念的…

CANDela studio新建和编辑服务

服务定义和编辑只能够在CDDT里面进行&#xff0c;思路分为三步&#xff1a; 1、Protocol Services里面添加服务&#xff0c;定义服务的格式、请求和正负响应。 2、根据服务的功能归类到Diagnostic Class Tenplates 3、Variant里面的Supported Diagnostic Classes勾选 然后我…

【2023百度之星初赛】跑步,夏日漫步,糖果促销,第五维度,公园,新材料,星际航行,蛋糕划分

目录 题目&#xff1a;跑步 思路&#xff1a; 题目&#xff1a;夏日漫步 思路&#xff1a; 题目&#xff1a;糖果促销 思路&#xff1a; 题目&#xff1a;第五维度 思路&#xff1a; 题目&#xff1a;公园 思路&#xff1a; 新材料 思路&#xff1a; 星际航行 思路…

Ubuntu基础使用

快捷键&#xff1a; 命令行打开快捷方式&#xff1a;Ctrl Alt T Ctrl l 清屏 截屏&#xff1a; LinuxOS命令&#xff1a; 显示当前工作目录所有内容&#xff1a;ls &#xff08;-a -l、-lh&#xff09; -a 输入全部内容&#xff08;包括隐藏文件&#xff09; -l 竖向展示…

CompassArena 司南大模型测评--代码编写

测试角度 要说测试模型&#xff0c;对咱们程序员来说&#xff0c;那自然是写代码的能力强不强比较重要了。那么下面我们以 leetcode 中的一道表面上是困难题的题目来考考各家大模型&#xff0c;看看哪个才应该是咱们日常写程序的帮手。 部分模型回答 问题部分如下截图&#…

Linux前奏-预热版本

一、操作系统概述 1.1 了解操作系统的作用 我们所熟知的计算机&#xff0c;也就是电脑&#xff0c;就是由硬件和软件来组成的 硬件&#xff1a;计算机系统中由电子机械&#xff0c;和各种光电元件等组成的各种物理装置的总称 软件是什么呢&#xff1f; 软件&#xff1a;用…

调查问卷和考试系统SurveyKing

什么是 SurveyKing &#xff1f; SurveyKing 是功能更强大的调查问卷、考试系统&#xff0c;很多功能体验超过问卷网、问卷星。支持在线考试/调查问卷/公开查询/题库刷题/投票。 软件特性 &#x1f947; 支持 20 多种题型&#xff0c;如填空、选择、下拉、级联、矩阵、分页、签…

QiuDN:新手友好的公益CDN

在数字化的今天&#xff0c;网站的速度将直接影响着用户体验和搜索引擎排名&#xff0c;因此&#xff0c;作为一名网站管理员&#xff0c;我一直在寻找能够提升网站速度的解决方案。在一次偶然的机会中&#xff0c;我了解到了QiuDN&#xff0c;一个公益性质的CDN。听创始人称丘…

Vue3-Ref Reactive toRef toRefs对比学习

响应式数据&#xff1a; Ref 作用&#xff1a;定义响应式变量。 语法&#xff1a;let xxx ref(初始值)(里面可以是任何规定内类型、数组等)。 返回值&#xff1a;一个RefImpl的实例对象&#xff0c;简称ref对象或ref&#xff0c;ref对象的value属性是响应式的。 注意点&am…

使用Python库Matplotlib绘制常用图表类型

使用Python库Matplotlib绘图 一、Matplotlib绘图参数设置1.1 设置分辨率和画布大小1.2 保存图片并设置边缘留白为紧凑型1.3 设置坐标轴标签1.4 画直线设置线宽和颜色1.5 画子图1.5.1 通过figure的add_subplot()画子图1.5.2 通过plt的subplots画子图 二、使用Matplotlib中scatte…

深入解析芯片背后的技术:揭开半导体产业的神秘面纱

引言&#xff1a; 在这个数字化、信息化的时代&#xff0c;芯片已经成为了现代科技发展的重要基石。从智能手机、电脑到汽车、物联网设备&#xff0c;芯片无处不在。然而&#xff0c;对于大多数人来说&#xff0c;芯片背后的技术仍然是一个神秘而遥不可及的领域。本文将深入解…

【Linux-阻塞,非阻塞,异步】

Linux-阻塞&#xff0c;非阻塞&#xff0c;异步 ■ Linux-阻塞-非阻塞 IO-异步■ Linux-阻塞IO■ 阻塞IO简介■ open■ 等待队列■ 示例一&#xff1a;APP阻塞IO读取进入睡眠后-等待队列唤醒进程■■ ■ Linux-非阻塞IO■ 非阻塞IO简介■ open■ 轮询■ 1、select 函数■ 2、po…

python-双胞胎字符串

[问题描述]&#xff1a;给定两个字符串s和t&#xff0c;每次可以任意交换s的奇数位和偶数位的字符&#xff0c;即奇数位的字符可以与任意其它奇数位的字符交换&#xff0c;偶数位的字符同样也可以与任意偶数位的字符的字符交换&#xff0c;问能否在有限的次数的交换下使s变为t?…

智能售货机加盟新契机

加盟智能售货机业务&#xff0c;尤其是在当前技术迭代迅速与市场需求高涨的背景下&#xff0c;正成为众多创业者积极探索的领域。以重庆臻奶惠为代表的企业&#xff0c;正利用其在智能科技与支付资讯的深厚底蕴&#xff0c;为有意涉足该行业的加盟者铺设了一条既稳健又具前瞻性…