使用Kinect2作为Oculus游戏应用的输入设备
注: 文章写于2015年8月, 眼下VR游戏Demo已经完结, 所以把上一次预研的一些经验分享出来, 希望对大家有所帮助
背景
初接触Oculus时, 从网上下载了一大堆的Demo来体验, 可是, 操作体验大都比較差, 特别是FPS类. 这也让我们意识到, 对于VR游戏, 最大的挑战还不是显示方式的变化, 而是交互方式. 在一个沉浸式的环境中, 最自然的交互就是最完美的方式. 当中主要的需求, 就是能够使用双手跟VR中的虚拟环境进行交互. 这么一来, 首先键鼠或手柄就被排除掉了, 我们仅仅好针对市面上的一些输入设备, 挨个进行评估实验:
- Wiimote: 仅仅能检測运动和方向, 无法准确定位双手的位置
- Leap Motion: 粘在Oculus上能够模拟出双手, 可是识别范围太小, 骨骼的稳定性比較差, 严重影响体验
- Razer Hydra: 能够获取双手的空间位置和旋转, 加上两个手柄上的按键也能触发一些状态切换, 算是看起来还不错的方案. 缺点是位置偏差比較大, 可能是磁场受干扰的问题
- RealSense: 相似LeapMotion, 可是精度比較低, 导致识别出的骨骼位置抖动严重, 无法用于双手的骨骼映射
试来试去, 好像眼下市面上除了高成本的动作捕捉设备, 还没有比較完美的VR输入设备能够用. 最后, 把目光转向了旁边XboxOne开发机配的Kinect2.
因为我们组去年进行了XboxOne体感游戏的研发, 积累了一些Kinect2体感操作的经验, 就把Kinect2连接到了PC上, 看看能不能把体感操作与Oculus的VR显示结合到一起.
需求分析
前面也提到了, 尽量达到接近自然的交互方式, 那就须要实现这几个关键点:
- 能够在虚拟世界中显示出双手, 最好能有肢体躯干
- 虚拟空间中的双手位置与现实空间中跟头部的相对位置(包含旋转)保持一致
- 能够使用双手对虚拟世界中的物体产生影响
- 能够识别一些简单的手势, 如抓, 推, 拉, 按, 摸等等
那Kinect2提供的数据或者功能有哪些呢?
- 30帧/s的Color/Depth/BodyIndex/IR数据
- 身体骨骼位置和朝向(比較不稳定, 会抖动)
- 双手的三种状态识别, 正好相应 石头 剪刀 布(误识别率较高)
- 其他诸如语音之类的功能临时用不上
像LeapMotion那样每根手指单独识别是做不到了, 退而求其次, 仅仅能在交互设计上就去规避过小元素, 使用整个手掌做为交互
双手的骨骼位置能够为我们提供双手的空间定位, 而三种状态能够參考我们在XboxOne体感游戏中的UI交互经验, 把抓住拖动之类的手势利用起来
实现细节
双手肢体的绘制
因为Kinect API已经提供了人体骨骼的变换信息, 那自然而然的我们就想在游戏中绑定到一个蒙皮模型上
终于我们也在UE4中实现了, 可是体验下来很不惬意, 为什么呢?
- Kinect中获取的骨骼变换信息会频繁抖动, 假设不进行处理, 会像抽风一样
- 假设对骨骼变换数据进行稳定性的过滤处理, 会添加响应延迟, 导致虚拟肢体的动作比实际总是慢半拍
- 不同体形的的人的映射到同一模型的效果会有问题, 比方想象一下一个身材高大的人在Oculus中看到自己胳膊变短了是什么感觉. 这会影响基于直觉和经验的空间位置推断
那还有什么别的方法去实现双手肢体的绘制吗? 在使用KinectStudio调试时, 发现3D视图下的深度呈现比較有意思:
事实上这就是深度数据(DepthBuffer)映射到3D空间里的离散的点, 这里我把这样的表示方式称之为 “点云(PointCloud)”
于是突发奇想, 在虚拟空间使用点云表现自己的躯体, 双手手指的动作也能够精确地映射过去. 那么, 这可行吗?
- 延迟: 因为DepthBuffer是硬件採集的原始数据, 是没有经过处理的, 不存在中间的数据处理时间(延迟), 所以在响应速度上肯定是很理想的, 能够控制在70ms左右(Kinect2硬件固定60ms)
- 数据量: DepthBuffer的分辨率是512x424, 也就是须要映射到21万多个顶点, 虽说有点多, 但也在可接受范围内, 实在不行能够隔行取点, 以终于效果需求为准
- UE4点云渲染: 每帧依据DepthBuffer计算出相应的VertexBuffer, 构建DynamicMesh进行绘制, PrimitiveType使用PointList
然后再依据BodyIndex数据剔除掉周围环境和其他人的点, 就完美的把自己映射到UE4的3D场景中了. 下图加了个简单的材质, 顶点法线使用地形中经常使用的SlopeBased方法计算
点云坐标系对齐
有了点云的躯体了, 怎么把它 “装”在虚拟世界中的头以下呢?
因为Kinect, Oculus, UE4相当于是三个不同的坐标系, 假设要把点云映射到Oculus视角下身体的位置, 须要一些坐标映射和转换.
- UE4已经默认集成了Oculus的支持, 所以这两个坐标系的处理不用我们担心了, 默认Oculus头戴显示器的坐标就是UE4摄像机的位置加上PostionTracking的Offset
- 而Oculus头戴显示器的位置来源于Oculus DK2中带的CameraSensor, 这才是Oculus虚拟坐标的基准点, 仅仅只是UE4做了变换, 把Oculus初始位置映射到了摄像机的位置上
- Kinect中的DepthBuffer映射成顶点后, 全都是CameraSpacePoint, 即Kinect设备本身就是原点. 须要注意的是, Kinect坐标与UE4坐标须要做一下转换, 相应关系为 UE4Vector = FVector(-V.Z * 100, V.X * 100, V.Y * 100)
那找到Oculus和Kinect坐标系中分别固定不动的基准点后, 把它们进行对齐, 两边的坐标系不就能够重合了?
方法很easy, 把Kinect和Oculus的CameraSensor”合体”:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
游戏中能够通过CameraComponent位置和Oculus的CameraOrigin计算出Sensor的世界坐标, 然后把点云对齐到这个位置就可以, 通过一个能够保存配置的Offset进行偏移校正
交互设计
整个交互灵感事实上来源于钢铁侠电影里的全息投影的交互片段, 我们的目标就是把这样的科幻片中经常出现的镜头变成现实
以全息投影的感觉做为美术风格的指导方向, 结合我们日常接触最多的功能, 我们实现了5种交互控件:
图片查看器: 仅仅有一个翻页操作
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
视频播放器, 能够操作播放/暂停, 放大后有电影院看电影的感觉, 这也是眼下VR视频应用比較经常使用的方式
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
网页浏览器: 我们集成了CEF, 相当于内嵌了一个chrome, 支持HTML5的游戏. 以下的视频中我们选择了一个H5的猜单词小游戏, 支持网页上的点击操作
打飞机小游戏: 这个是使用体感操作的, 尽管是一个2D平面的游戏, 可是爆炸后的碎片会落到地板上, 视觉效果还不错
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
模型查看器: 主要是用于演示在3D空间怎么用双手比較直观地观察一个三维物体, 能够说这才是VR交互的亮点所在, 你能够从各个角度和随意大小去观察一个物体的每一个细节
每一个控件我们还做了统一的Tooltips的弹出动画提示, 这样的3D空间的信息显示也是AR应用场景中比較常见的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
为了更好地展示每一个控件的功能, 我们把整个全息交互场景分成了前后两”层”
- 远景: 仅仅能同一时候存在一个控件, 能够抓住进行拖动和缩放操作, 并进行每一个控件特定的功能操作, 如网页的点击, 小游戏的手势移动等等.
- 近景: 摆放各个功能控件, 相当于任务栏图标, 能够通过手势把它”扔”到远景的那一层上去, 相当于窗体最大化/Active状态
对远景的控件进行操作时, 双手各加了一根闪电特效, 如同释放魔法一样, 在远处控件上模拟出相似iPad的操作体验
PS: 为了不正确第一人称的VR显示产生干扰, 已经把点云的头”砍”掉了
近景的交互是基于双手的”Touch”操作, 通过Kinect获取双手骨骼位置, 挂了两个碰撞体用于检測与控件之间的Overlap状态
效果展示
点击播放视频(略)
优化
基于VertexBuffer的点云因为要进行顶点坐标计算, 十分消耗CPU, 为了节省时间, 能够把顶点计算转移到GPU, 使用静态VertexBuffer+动态VertexTexture进行Mesh的构建, 而同一时候带来的优点是点云不再限于Point渲染, 能够做成Particle的样子
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
总结
在做VR技术预研的过程中, 我们也发现三大VR设备(Oculus, Steam VR, PS VR)的公布的操作设备已经趋于一致: 双持控制器, 每一个控制器都能够获取位置和旋转, 而且带有传统的button和摇杆. 这尽管不是最自然的交互方式, 可是也是眼下在成本和功能之间的一种平衡, 兴许的VR游戏开发, 操作上就能够基于这些设备做统一的设计.
有了这个VR交互Demo的成功经验, 我们把这样的交互方式也带入了正在开发的一个VR游戏Demo, 在Oculus Touch没上市之前, 这是眼下我们能在VR中实现的比較好的操作体验. 个人以为, 仅仅是显示方式的变化并不能带来游戏性上的太大变化, 双手控制器才干够让VR游戏玩法产生很多其他创意, 从根本上推动产生新的游戏类型和全新体验.
使用Kinect2作为Oculus游戏应用的输入设备的更多相关文章
- Unity开发Oculus游戏
1.下载Oculus对应自己操作系统的SKD&RunTime 下载地址 我这里是window系统,下载的是0.6.0.0版本的 2.安装RunTime,电脑右下角状态栏会出现一个小眼睛表示安装 ...
- OCulus Rift 游戏开发六原则
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/46685477 作者:car ...
- 转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架
高层游戏引擎——基于OGRE所实现的高层游戏引擎框架 这是意念自己的毕业论文,在一个具体的实践之中,意念主要负责的是物件和GUI之外的其他游戏系统.意念才学疏陋,望众位前辈不吝赐教.由于代码质量不高. ...
- 剖析虚幻渲染体系(15)- XR专题
目录 15.1 本篇概述 15.1.1 本篇内容 15.1.2 XR概念 15.1.2.1 VR 15.1.2.2 AR 15.1.2.3 MR 15.1.2.4 XR 15.1.3 XR综述 15. ...
- 开启cocos2dx 3.0的Console功能
下面内容用于自己知识的备忘,想看具体内容,请參照例如以下地址. 原英文文地址: http://discuss.cocos2d-x.org/t/cocos3-0-tutorial-console-tut ...
- Linux触摸驱动分析
测试平台 宿主机平台:Ubuntu 12.04.4 LTS 目标机:Easy-ARM IMX283 目标机内核:Linux 2.6.35.3 触摸屏基础知识 一.结构 上图是电阻触摸屏的一个侧面剖视图 ...
- Oculus Store游戏下载默认路径修改方法
最近在测试一款VR游戏,所以在硬件设备上选择了HTC Vive和Oculus两款眼镜.相对而言,HTC安装比较人性化:支持自定义安装路径,而且可在界面更改应用程序下载位置,如图所示: 这下替我节省了不 ...
- VR就是下一个浪潮_2016 (GMGC) 全球移动游戏大会观后感
"VR就是下一个浪潮" --2016 (GMGC) 全球移动游戏大会观后感 早在2014年参会Unity举办的一年一度的金立方盛典大会,就初次体验了VR头盔设备,于是印象深刻 ...
- Unity User Group 北京站图文报道:《Unity3D VR游戏与应用开发》
很高兴,能有机会回报Unity技术社区:我和雨松MOMO担任UUG北京站的负责人, 组织Unity技术交流和分享活动. 本次北京UUG活动场地–微软大厦 成功的UUG离不开默默无闻的付出:提前2小时到 ...
随机推荐
- (转)Ant使用例子
文章来自:http://www.blogjava.net/feng0801/archive/2014/07/29/416297.html Ant是一个Apache基金会下的跨平台的构件工具,它可以实现 ...
- spring in action学习笔记十五:配置DispatcherServlet和ContextLoaderListener的几种方式。
在spring in action中论述了:DispatcherServlet和ContextLoaderListener的关系,简言之就是DispatcherServlet是用于加载web层的组件的 ...
- 关于#include <bits/stdc++.h>
经常看人写#include <bits/stdc++.h>却不知道是干啥的? #include<bits/stdc++.h>包含了目前c++所包含的所有头文件 对比: #inc ...
- PHP持久进程
在有些业务需求中,一个业务逻辑会涉及很多其他模块,这时可以把不需要返回的数据,扔到后台异步处理(比如注册时邮件验证,发邮件这个过程就可以扔到后台处理). 这个时候可以在后台起一个PHP进程,轮循处理业 ...
- GitHub上README写法暨markdown语法解读
原文: GitHub上README写法暨markdown语法解读 自从开始玩GitHub以来,就 越来越 感觉它有爱.最近对它的 README.md 文件颇为感兴趣.便写下这贴,帮助更多的还不会编写R ...
- mysql服务性能优化—my.cnf_my.ini配置说明详解(16G内存)
这配置已经优化的不错了,如果你的mysql没有什么特殊情况的话,可以直接使用该配置参数 MYSQL服务器my.cnf配置文档详解硬件:内存16G [client]port = 3306socket = ...
- 培训补坑(day3:网络流&最小割)
继续补坑.. 第三天主要是网络流 首先我们先了解一下网络流的最基本的算法:dinic 这个算法的主要做法就是这样的: 在建好的网络流的图上从源点开始向汇点跑一遍BFS,然后如果一条边的流量不为0,那么 ...
- 神奇的幻方(NOIP2015)(真·纯模拟)
原题传送门 这是道SB模拟题,NOIP--难度 直接贴代码 #include<iostream> #include<cstdio> using namespace std; , ...
- 多线程之:竞态条件&临界区
竞态条件指:当一个对象或者一个不同步的共享状态,被两个或者两个以上的线程修改时,对访问顺序敏感,则会产生竞态条件. 临界区指:导致竞态条件发生的代码区. 如:increase块为临界区 public ...
- flask框架基本使用(2)(响应与重定向)
#转载请留言联系 flask 框架基本使用(1):https://www.cnblogs.com/chichung/p/9756935.html 1. flask 自定义返回状态码与响应头 from ...