在VR/AR环境中搭建物体是很神奇的。想象一下, 无重力情况下去组装汽车发动机, 搭建灵活的虚拟工作区, 或用无限块砖头建造虚拟的城堡。在VR/AR的很多场景中都需要移动、组装虚拟对象, 特别是在教育、企业和工业培训中——更不用说桌面和实时策略游戏了。
在最新的交互实验中,我们探索了如何让搭建、堆叠类交互变得顺畅、稳定、有效响应,以及如何在保持完整物理模拟的细微差别和丰富性的同时, 快速准确地放置、堆叠和装配虚拟物体。
挑战
使用裸手操作符合物理定律的虚拟对象是一项极其复杂的任务。这是我们开发Leap Motion交互引擎的初衷之一, 目的是让用户在抓取和释放虚拟物体的过程中感觉自然、真实。
然而, 精确的旋转、放置和堆叠有物理属性的物体需要被巧妙地感知。堆叠就是一个很好的例子。
在 VR 中堆叠不应该让人感觉像在拆弹。
在现实世界中堆叠物体时, 我们可以通过触觉来感知塔的稳定性。把一块物体放到塔上时, 我们能感觉到物体是何时何地碰触到了塔结构的。在那一瞬间,是可以实际感受到阻力的。
在 VR 中解决这些问题最简单的方法是禁用物理,仅是简单地移动对象。这可以成功消除意外动作(比如碰撞、推)带来的影响。
当禁用重力和惯性时, 我们可以随意组装物体。不过这看起来还是怪怪的!
然而, 这个解决方案远非理想, 因为精确的旋转、放置和对准仍然是一个挑战。此外, 对虚拟对象禁用物理会使得体验的吸引力大打折扣。VR/AR 先天具有仿造丰富现实的能力, 而且只有当你使用自己双手时才会将这能力完全释放。
供差遣的脚手架
最佳的 VR/AR 交互通常需要将现实世界的灵感与媒介的独特可能性相结合。在现实世界中,如何能更容易地组装东西呢? 我们想到了用标尺来对齐,和脚手架——在建筑工程中辅助材料搭建的临时结构。
网格是平面3D 应用程序的一个常见特征。在 VR中, 我们看到早期的例子Google Blocks就很好的运用了这一元素。
然而, 我们并不建议将整个世界放在网格中, 而是建议将网格作为可分散的立体工具。这将是一个临时的,可调整大小的三维网格,来帮助你装配虚拟对象——你可以把它想成是一个听候差遣的脚手架!当物体被放置到网格中时, 它们就会被一个物理弹簧捕捉到相应位置, 并在整个交互过程中保持物理模拟。一旦用户完成组装, 他们就可以停用网格来释放弹簧并让对象返回到无约束的物理模拟中。
要创建这样一个脚手架系统, 我们需要构建两个组件: (1) 一个可供差遣、可调整大小的3D 网格, (2) 一个可供装配对象的示例集。
生成一个3D 网格
在需要“脚手架”交互的周围生成一个视觉网格是简单而直接的。但是, 由于我们希望能够动态地改变脚手架的尺寸, 我们可能需要为脚手架做多个网格部署 。为了优化, 我们创建了一个自定义的 GPU Instancing 着色器来呈现我们脚手架网格中的点。这种对相同对象的重复渲染很适合放到 GPU上——它有助于节省 CPU 周期和保持高帧率。
在开发的早期阶段, 可以对点进行颜色编码。由于网格能随时被调整大小, 颜色有助于识别我们正在破坏和重新创建的内容, 同时了解我们的点是否有序。(当然这也很漂亮, 我们喜欢彩虹的东西)
基于着色器的网格悬停反馈
让VR环境中让尽可能多的事物能对我们的动作有所反馈,一直以来都是我们工作的努力方向,因为这能够让 VR 这样神奇的媒介变得更有存在感、更有魔力。另外,VR 缺乏我们在现实世界中所依赖的许多深度线索, 虚拟物体的反馈也可以帮助我们了解自己身体不同部位在VR中的相对位置。
在这一想法驱动下, 我们在做完一个立方体网格后再度发散。由于我们使用了自定义着色器来呈现网格点, 所以我们可以为着色器添加功能, 以帮助用户更好地了解他们手的位置和深度—— 当你的手靠近时, 我们的网格点就会变大发光,使反馈更明显, 用户更方便使用。
创造能与脚手架互动的立方体,和他们的“思想”
要想创建一个可以放置在网格中(并对齐)的物体,首先要添加 InteractionBehaviour 组件到我们的立方体模型中。与Leap Motion交互引擎相结合, 它可以解决重要的任务——让这个物体可被抓取。为了是立方体能与网格交互, 我们创建并添加了另一个 Monobehaviour 组件(可以叫它 ScaffoldBehaviour)。这种Behavior能尽可能多地处理立方体特定的逻辑, 使得网格保持简单易用。
与网格本身一样, 我们已经学会了思考我们交互的作用以及交互本身。我们设计了交互逻辑,来创建和控制立方体的“思想”, 这样你就可以很容易地知道当你释放它时, 立方体会跑去哪里:
使用Leap Motion交互引擎把手(Handles)工具调整网格大小
用户通过建立把手来抓取和拖动,可以调整脚手架大小以适应特定区域。我们创建了带有交互引擎行为的球形把手, 来限制它们在控制轴上的移动。这样, 如果用户在脚手架中放置立方体, 并拖动把手使网格变小, 这个立方块就会被丢弃。反之, 如果拖动把手让网格变大, 这些已放置在网格点上的立方体, 会迅速就位!
Widget部件的阶段、状态和形状
现在, 我们有了一个可调整大小的3D 网格, 而且能够显示对象的目标位置, 是时候将此功能捆绑到一个部件中。我们希望能够使用多个脚手架,而且能释放一个脚手架部件, 使它可以自动移到最近的表面, 自动对齐, 并自动着陆。为了管理此高级功能带来的所有状态更改, 我们创建了一个脚手架分类, 以置顶并控制其他分类。
为了这个功能, 我们有一个具有四个状态的简单状态机(state machine):
- 已锚定: 所有脚手架的功能都将被隐藏, 除了可被抓取的图标。
- 保持: 将显示脚手架的网格和把手。我们运行逻辑来寻找合适的平面
- 着陆: 当脚手架被放走时, 它将动画至与最近的表面对齐。
- 部署中: 这是脚手架网格及其把手的主要活动状态.
部署前的锚定阶段是网格的完全收缩状态。 它可连接到浮动的手菜单插槽,或放置在环境中的某个位置, 可以随时拾取。在这种状态下, 我们将小部件缩小到3D 图标, 仅有三个彩色球体和一个较大的白色锚球。
一旦你拿起图标小部件, 我们就进入到保持/放置状态。图标成为完整的功能小部件, 其红色, 绿色和蓝色轴把手显现出来。在握住它的时候, 我们从小部件中投出射线来寻找合适的放置面。旋转小部件可以让你瞄准射线。
在位置命中时, 我们将显示与目标表面对齐的展开的小部件。当指向一个可行的表面时, 松开小部件, 就可将小部件动画到其目标位置, 然后自动展开坐标轴, 生成3D 脚手架。
部署好的小部件需要一些功能: 通过推或抓取轴把手来调整每个轴的长短,拾取整个脚手架并将其放置在其他位置的方法, 以及停用/重新激活脚手架的方法。
小部件本身的形状经历了几次迭代, 我们从卷尺和其他手持式建筑辅助工具,以及一些软件中汲取灵感,最后打磨出了红、绿、蓝三个轴把手用来直接交互, 白色的锚,以及白色结构来暗指方向。
你可以左右推动、抓取、拉动彩色的轴把手:
抓住较大的白色锚,可以拾起、移动整个小部件和脚手架。这会暂时让小部件返回到保持/放置状态, 并投射新的可行目标位置。
按一下开关, 三个轴可以收回,整个脚手架停用:
终于我们到了有趣的环节——装配物体,完了再拆卸他们!网格单元的大小是可定义的,我们把它设置成双手便于操作的大小——大于乐高积木, 小于砖块。我们建了一些简单的形状模型, 并创建了一个小的倾斜环境来安装和拆卸组件。现在尝试下快速而准确地装配。
当你的手接近一个形状时, 它的颜色会轻微变亮, 越接近越亮。当你选择它时, 它会变亮,让你清楚地知道它被 “抓住” 了:
当你手拿着一个形状物体进入网格, 会出现另一个浅白的形状, 显示最接近的可行位置和旋转方案。这个时候释放形状,他就会移动到浅白形状的位置。如果形状物体与被占据的空间相交, 显色的形状会变成红色。这时释放的话,形状物体就会直接从手上掉下来。
一旦一个物体被拉到了网格里, 它们的角上会出现凹槽动画,营造一种他们被安在脚手架上的感觉:
最后也可能最重要的一环, 就是调整整个互动的物理感。举个例子, 下面是我们将一个物体安在脚手架后禁用物理时它的样子。
缺少了和物体对象的互动,会给用户空洞和不满意的感觉。一会儿碰的上,一会儿碰不上的交互规则切换使得体验的连贯性被打破。如果我们添加些弹簧,保持物体的交互连贯性后会发生什么呢?
是不是好多了!现在网格更像是一个结构化的力场, 将物体牵在它的位置上。但这时需要注意, 因为物体间也可以相互碰撞,所以当我们干扰整个结构时, 这些物体也可能会互相干扰, 因为它们的弹簧正试图将它们推回到原位。
幸运的是, 在 VR 中我们可以简单地使用分层功能使安在网格中的物体只能和手,而不能和其他物体碰撞。
这样整个交互过程中既兼顾物理属性, 也不会因为碰撞混乱而牺牲速度或精确度。现在是堆积木表演时间啦!
您对VR/AR中的堆叠和装配有何看法?您希望在哪些应用程序中使用这个功能?在评论中让我们知道!如果您想尝试下Demo, 请访问下周的Leap Motion博客 。我们将分享这个演示以及详尽说明它是怎么做出来的。
图片版权: Leap Motion, CanStock, Medium, Google, Sunghoon Jung, Epic Games
An abridged version of this post was originally published on RoadtoVR. An English version is also available.