Oculus开发实战:为《First Steps》实现60Hz手部追踪
高频手部追踪
(映维网 2021年05月06日)Oculus日前发布了全新的追踪模式:高频手部追踪(High Frequency Hand Tracking)。据介绍,手部追踪的频率将会从30Hz增加至60Hz,而且这一模式能够实现更好的手势检测和更低的延迟。在下面这篇博文中,团队介绍了如何在《First Steps》中实现所述功能。下面是映维网的具体整理:
最初的《First Steps》包括与对象交互,在靶场射击和与机器人共舞等内容,并旨在向Quest新人介绍虚拟现实、Touch控制器,以及六自由度无线束缚体验的魅力。
由于它依赖于以手为中心的交互和近场对象操纵机制,我们将手部追踪(用双手代替Touch控制器的能力)纳入至到《First Steps》,以这种方式探索手部追踪集成的潜力,以及向现有应用添加“真实双手”的挑战。
我们对所述项目设定了初步的目标,包括:
- 以一种接近于原始意图的简单方法中来加入手部追踪
- 不添加、删除或显著重新设计体验的任何环节
- 确保应用程序与原始应用程序一样具有高性能
- 不增加新的交互
- 能够在任何时候在双手和控制器之间切换
- 双手在两种模式下的工作方式没有太大变化
- 在两种模式下,双手的大小和视觉风格应该相同
对于这一点,我们认为双手应该符合下面的准则:
- 手从不隐藏
- 每个对象只有一个手势
- 仅当手闭合时实现手和手指碰撞
- 离开camera视图时手不会丢失对象
1. Hands API提供了什么?
Hands AP提供的是:不使用控制器的情况下在VR中呈现用户完整手部关节表示所需的信息。这包括:
- 手的位置和方向
- 手指的位置和方向
- 追踪置信度(高或低)
- 手的尺寸(即大小)
- 捏合(手指+拇指)力度信息
- UI光线投射的指针姿态
- 打开通用菜单或应用定义菜单的系统手势
2. 我们在集成时需要解决什么问题?
2.1 更新手部rig
最初的《First Steps》使用了一个基于Oculus Avatars库的旧款手部模型和rig。为了利用手部追踪,我们必须更新手部模型和使用新的rig。
2.2 手势
当握持不同的对象时,《First Steps》使用静态手势来表示双手。相关asset源于动画团队的手动创作。我们一开始尝试自动重定asset,但最初的重定目标并没有补偿空间切换rig和降级的手部视觉。为了更新姿态资源并令它们看起来和原始的一样好,我们重新编写了新版rig的所有资源。
新版hand rig等比例于玩家的实际手部尺寸。我们曾担心当用户的手部明显小于或大于原始模型时,手势看起来会非常糟糕,但结果证明效果很好。
当玩家在游戏中拾起或握持一个对象时,我们使用静态手势。我们进行了修改,允许部分手指在特定情况下独立于静态姿势移动:例如,当持枪时,玩家的手锁定为静态姿势,但食指除外,食指保持追踪。这样就可以准确地表示“扣动扳机”运动。
为新版hand rig创造姿势的整个过程花了大约一个月。
如果我们要从零开始一个项目,我们会从最初就使用标准的手部追踪rig。
2.2 玩家输入
为了在控制器追踪的双手和camera追踪的双手之间动态切换,我们将玩家输入抽象到一个接口中,然后编写控制器追踪实现和camera追踪实现。这允许玩家可以在体验中的任何时候拿起或放下控制器,而游戏将自动在控制器追踪双手或camera追踪双手之间切换。
3. 我们建立了什么样的通用系统?
3.1 抓取
抓取和放下是几乎所有虚拟现实体验的核心。对于手部追踪,有许多可能的方法来实现抓取和放下。
对于这个项目,我们希望“抓取”跟最初的《First Steps》类似。在最初的版本里面,玩家通过扣动扳机键来尝试抓取。当发生这种情况时,引擎会检查手部碰撞器是否与对象的抓取碰撞器重叠。如果为正,则会发生抓取。
我们决定在玩家抓取时使用手部触碰对象的触觉反馈。这意味着当出现下列情况时我们认为玩家尝试抓取:
- 拇指和任何手指之间执行捏合,或者拳头闭合。
- 手和对象的碰撞触发重叠。
3.2检测闭合的手
现在API只告诉我们“拇指和每个手指之间的捏合”,我们必须自己分析以确定一只闭合的手。我们开发的系统将玩家的手指位置与闭合的参考手进行比较。我们检查每个手指的关节旋转,以确定拳头何时闭合或打开。为了防止意外释放,闭合手和张开手的阈值不同。我们需要先用手指抓取对象,然后用手指抬起一些对象,比如枪和飞艇控制器。我们开发了一个这样的系统:如果手闭合,我们可以把分析中的任何手指掩膜。
我们希望在未来将这项研究带到API。
3.3抓取移动对象
我们发现抓住运动中的对象很难。为了解决这个问题,在对象运动时,我们沿着它的速度方向增加可抓取碰撞。顺着它将在一秒钟内移动的距离,我们将对象的碰撞沿轨迹向前和向后延伸。这使得投掷和抓住运动对象更加容易。
3.4抓取音频
音频可以增强沉浸感,提高玩家抓取和放下对象时的信心。在没有抓取音频的情况下,我们发现用户会出现更多错误的抓取尝试。对象的抓取特定音效可以帮助用户知道他们何时成功抓取了一个对象。另外,我们在用户放开一个对象时添加了一个释放下坠的声音。
3.5释放
我们首先将释放实现为抓取的逆操作,这导致了许多错误的释放。通过实验,我们添加了以下规则来放置任何对象:
- 只有在置信度“高”时才释放
- 只有在玩家连续75毫秒不捏合/抓取的情况下才能释放
- 恢复追踪后,等待15毫秒,然后再进行释放测试
- “释放”和“抓取”的阈值不同
3.6投掷
我们发现用手部追踪投掷对象非常困难。当投掷对象时,玩家倾向于快速地移动手部,并且移动范围很广。这会导致手部经常离开头显的追踪范围。
为了改进这一点,我们构建了一个根据数据构建投掷向量的系统,所述数据包括玩家最后已知的优势手位置、速度和注视方向。这改进了投掷交互,但我们可以进一步迭代这个系统。
3.7缓冲手部变换
缓冲变换组件的调试可视化
我们提出了一个可以在固定时间内(目前为1秒)保留所有手部变换和速度的缓冲区的系统。这比我们需要的数据要多得多,但至少保留一秒钟的数据以供调试非常有用。
这种变换有两个用途:
- 确定我们是否有足够的数据在玩家手部打开时构建一个投掷向量。
- 在构建投掷向量以说明手部追踪延迟时,我们能够在时间上后退。我们现在后退大约40毫秒,相当于3帧。
3.8 构建投掷向量
当我们检测到玩家执行投掷动作时,我们为这个投掷构建一个向量,然后将这个向量作为一个速度应用到投出对象。目前我们有三种方法:
- 高置信度投掷:当高置信度变换缓冲区中有好的数据时(我们当前检查前80ms的每帧是否有连续的数据),我们只需使用40ms前的变换缓冲区速度。这会产生好的投掷。
- 低置信度投掷:如果高置信度变换缓冲区中没有足够的数据,我们将使用类似的方法,但这次将从所有变换缓冲区获取数据。如果所述缓冲区报告的速度大于某个阈值(当前为50cm/s),且在头部正向(180度以内),则使用所述数据生成一个投掷矢量。这不太稳定,但通常能够提供好的结果。
- 极低置信度追踪:当两个缓冲区都没有足够的数据来提供投掷向量时,我们使用不同的方法。这经常发生在快速过肩投掷的时候。在这种情况下,我们将投掷向量构建为其他两个向量的加权平均值:1.从手最近离开追踪边界的点到手当前位置的归一化向量;2.玩家的归一化头部正向。
目前,我们加权这两个向量,第一个60%和第二个40%。这提供了投掷的方向。使用第一个矢量(追踪丢失点到当前手部位置)的幅值乘以某个系数(当前为0.4)来进行计算。这提供了一种在执行特定姿势时感觉良好的投掷,例如过肩投掷。
3.9 克服没有水平速度的掉落
我们遇到的一个问题是,用户投掷一个对象,但对象在掉落至地面时没有水平速度。这通常是因为在释放投掷后,对象会“粘”在玩家的手上几秒钟(手指的自我遮挡阻止了快速检测释放手势)。我们尝试通过两种方式缓解这一问题:
第一个问题:
在执行投掷动作时,我们会降低抓取轴的释放阈值,以便更容易释放对象。投掷运动检测使用一系列的启发式算法:
- 手移动的速度有多快。
- 手的运动有多少是在头部正向。
- 手距离头部正向有多远。
- 手离头有多远。
这种方法优化了发生在玩家正向的投掷。我们发现这种降低阈值的方法不是非常有效;当手指被遮挡时,我们得到的追踪数据很少。
第二个问题
当释放一个对象时,比较从最后一秒开始的一系列投掷向量(使用前面描述的方法进行构建),并选择最好的一个。“最佳”投掷向量的选择使用与(1.)中描述的类似启发式算法,但对较新的向量添加了额外的正权重。这对于减少以前发生的“无水平速度掉落”非常有效。对于所述方法,偶尔的投掷会“粘”在手上几帧,然后朝着投掷方向飞出,但这比以前的行为更可取,因为它们会简单地掉到地板上面。
4. 手部追踪精度降低
在对手部追踪进行初始集成后,我们发现在某些情况下(如光线不足和手部遮挡),手部的位置和方向精度会迅速下降。这种质量损失相当普遍,而且对游戏体验极为不利。
4.1 算法
考虑到这种情况,经过一定的实验后我们提出了一个滤波系统。它由以下步骤组成:
第一步:静止凝冻
当数据与上一帧没有明显变化时,只需保持上一帧的变换。
第二步:抖动平滑
接下来,如果新数据非常接近前一帧,则应用平滑曲线。如果手部变换自上一帧以来只改变很小,则小比例从上一帧插值。这确实会增加延迟(我们正在努力避免),但由于它只应用于小的改动,所以似乎不会对体验产生负面影响。
第三步:数据质量
追踪系统报告置信度信息(“低”或“高”)以及手部变换信息。当数据具有高置信度时,它通常是准确的(任何不精确的情况都由抖动平滑处理)。也就是说,当数据的置信度较低时,数据往往依然是准确的。
为了确定数据是高质量还是低质量,我们遵循以下算法:
1.如果追踪系统显示手的位置无效,我们将数据标记为低质量。
2.如果追踪系统显示追踪置信度为好,我们将数据标记为高质量。
3.否则,我们将根据下面启发式算法将数据标记为高质量或低质量:
3.1 此帧中的手部位移在最大距离范围内。
3.2 此帧中的手部速度在最大速度范围内。
3.3 此帧中的加速度在最大加速度范围内。
3.4 此帧中的角速度在最大速度范围内。
3.5有了所有这些启发式算法,我们可以找到能够准确分类大多数低质量情况的设置,而且不会出现太多的检测错误。
第四步:外推
我们一开始尝试平滑插值低质量的数据,使它看起来相对一致。然而,这比错误的数据更令人沮丧。
相反,我们只是从上一次可用的高质量数据推断手的运动。高质量的速度和角速度整合以继续手的运动。对于低质量数据的每一帧,向高质量速度应用阻尼标量,以便在一行中有多个低质量帧时使手减速到停止。
第五步:插值
前面的步骤效果很好,但当手从外推转到高质量数据时,会出现明显的(和分散注意力的)“断裂感”。为了消除这种情况,我们只需从外推插值到高质量数据。
这可以十分之一秒内完成。尽管这确实增加了在这段时间内的延迟,但你不会感觉到更多的延迟。这是因为每一帧都是向最新数据插值,所以即使你移动双手,它都会向你的双手插值。
4.2 手指抖动
对于手指,我们使用与手相似的方法来滤波数据,但仅使用角速度作为启发式算法。手部追踪API只公开每个手指(而不是每个骨骼)的置信度,所以我们在手指骨骼使用所述置信度数据。
这里最重要的是平滑。手的骨头有抖动,即使是高置信度的数据。
4.3 调试菜单
我们添加了一个调试菜单,用户可以在运行游戏时用“系统手势”进行调用。这使我们能够启用和禁用诸如手部变换滤波和投掷辅助等功能,从而允许对其进行快速A/B测试。
5. 什么交互效果最好?
5.1 纸飞机
纸飞机是一个有趣的投掷情况。尽管依然存在投掷对象时的一些缺点(有时候,投掷姿态和实际投掷之间存在延迟),但我们发现,玩家常常做出的投掷姿态相当契合头显的追踪边界。
飞机的飞行轨迹已经在脚本中进行了模拟。如果我们没有足够的数据来产生一个非常真实的投掷弧,缺点就不那么明显。
5.2 双手持枪
双手持枪是最好的惊喜之一。它们的效果从一开始就比单手持枪要好得多。自动开火的扳机键十分可靠,而且瞄准精度更高。
我们很幸运,因为这种枪械已经设计成可以绕过控制器追踪的限制。例如,所述模型的设计是为了防止玩家利用枪的瞄准器,因为这可能会导致Quest对Touch控制器执行的内向外追踪触失败。这种设计同时为camera提供了一个很好的视角。大多数玩家把枪举在胸前,这是看到所有手指和避免自我遮挡的最佳位置。只使用平移而不使用旋转来进行瞄准,可以弥补只用一只手平移和旋转时出现的任何追踪不一致。
这里的经验是,在设计交互,确保玩家将双手放到前面,而且高度和距离都适合追踪。
5.3 物理
我们发现按钮和系绳球都很好用。这里的关键是让对象按预期响应。按钮是一个动态动画,当你按下并释放时,它会对运动作出一对一的响应。如你所料,系绳球是通过物理进行响应。如果在触碰按钮或系绳球时播放一个固定的动画,临场感就会消失。
当玩家的手臂完全伸展时,按钮和系绳球都有限制,所以会自动阻挡或快速移动。这两种情况都可以通过对象放置得到缓解。
6. 我们是如何优化性能的?
我们能够利用一些新工具和功能来提高应用的性能。我们使用分析工具来识别和修复性能问题,包括Renderdoc for Oculus。
- 关闭遮挡剔除:我们发现的一个主要问题是遮挡剔除启用,这降低了应用程序的性能。禁用这种遮挡剔除可以显著提高帧速率。
- 启用front-to-back rendering:另一个主要的优化是启用front-to-back rendering。这对Quest 2的高分辨率显示器特别有影响(即使启用了注视点渲染)。在Unreal Engine中,可以通过将以下设置添加到DefaultEngine.ini来启用所述功能:
[/Script/Engine.renderSettings] r.Mobile.MeshSortingMethod=1
- 启用延迟锁定/相位同步:我们在项目中启用了相位同步和延迟锁定。所述功能将应用程序的显示延迟从大约40毫秒平均减少到大约35毫秒。一开始在集成所述功能时,我们看到平均帧速率每秒下降了几帧。当我们将应用优化成无需关闭相位同步和延迟锁定就能以稳定的90帧/秒的速度运行时,重新启用它们并没有导致性能下降。
- 使用高频手部追踪:在开发初期,我们尝试了一种新的选择以提高追踪摄像头的速度。启用高频追踪后,应用程序可用的CPU和GPU资源将减少。这意味着团队必须花费额外的时间来优化应用程序,以便在较低的时钟速度下以全帧速率运行。
对于我们的团队来说,感知延迟、手势识别和追踪质量的改善显而易见。我们发现高频手部追踪和稳定的90fps相结合可以提供最佳的体验,值得CPU/GPU方面的折衷。