〔Part 1〕Oculus Medium移动工具的开发日记

发表于2018-01-13
评论0 1.8k浏览
本文来自Oculus的David Farrel
  Oculus Medium是一款专为Touch设计的沉浸式VR体验,你可以在VR环境之中雕刻,建模,绘制和创建有形对象。Oculus最近添加了Move Tool,它允许用户抓拿,移动和重新设置雕刻作品的一部分。“Move Tool”是Medium“Summer of Move”(1.2版本)更新的主要功能之一,这也是Medium用户长期以来的反馈要求。

Move Tool是VR中的一个强大工具,因为它支持用户同时转换和旋转3D对象。对于这样的更改,以往的非VR应用程序需要用户通过鼠标和键盘进行单独的操作,而既麻烦,又不直观,并且通常局限于2D平面(如屏幕空间或垂直于平面)。

在过去一年中,Oculus对Move Tool创建了三个版本的原型。前两个原型因各种原因而被放弃,我们将文章后面进行讨论。工具的第三个版本,也是最后一个版本(当前版本)使用了一种更强大的雕刻数据处理方式。在这篇文章中,我将介绍如何使用Touch控制器创建位移字段;我们是如何将位移字段应用于3D对象;并讨论我们创建的三个原型。在以后的文章中,我们将仔细研究Medium是如何将三角网格转换为有向距离字段(signed distance field,SDF),以及这将如何为其他类型的雕刻操作提供帮助。

1. 6自由度输入

Touch控制器为每只手提供了高度准确的6自由度(DOF)输入。6DOF意味着你可以用手控制三维平移和旋转。这与平面屏幕所支持2DOF鼠标完全不同。你可以直接在3D环境中思考,无需再把鼠标的运动映射至3D空间,而且雕塑的调整只能通过平移和旋转来完成。

与其他2D程序的类似工具相比,这是Move Tool与众不同的功能之一。在使用Medium的时候,我们很容易就会理所当然地认为,我们可以简单通过移动手部来指定一个位置和方向。回顾使用鼠标操作平板应用程序的时候,鼠标的2DOF限制了你对变换的表达。与之相比,Medium等VR应用为用户提供了一个直接的方式来进行同时转换和旋转3D对象。

一种解释6DOF输入的方法是,定义一个变换矩阵。通过用手部控制变换矩阵,我们可以轻松操作3D对象。Move Tool使用来自Touch控制器的输入来创建一对变换矩阵:定义移动效果的起始变换矩阵;定义雕刻最终位置和方向的结束变换矩阵。这一对矩阵将输入至产生位移字段的变形函数中。

以下是起始变换矩阵和结束变换矩阵的形象化展示:

2. 位移字段

Move Tool的三个原型版本都采用了可应用于雕刻的位移字段概念。位移字段定义字段中每一个点的一个矢量,而这个字段可用于移位(变形)嵌入其中的对象。这是把Touch控制器的手部姿势转换为可应用于3D对象的操作的一种直接方式。

当你第一次按下扳机键时,我们会捕捉当前变换矩阵,并将其作为变形的开始。当你移动手部时,我们会捕获第二个变换矩阵,并将其作为变形的终点。当你释放扳机键时,我们会应用变形网格(在此之前,我们会向用户显示变形结果的快速效果预览图)。在按下扳机键时,另一只手仍然可以抓拿雕刻和操作雕刻的位置,但Move Tool会保持在同一位置。这种双手操作往往比单手操作更容易。从数学的角度来看,当你第一次按下扳机键时,我们会设置StartTransformMatrix;当你释放扳机键时,我们则设置NewTransformMatrix。我们同时允许用户控制适用于工具的目标球面大小,以及一个球面内层,而其中一切都以100%位移(如果点位于其间,我们则平滑地插入影响)。考虑到这一切,我们可以使用这个公式来创建一个位移矢量:

displacement(p) = p + falloff * (NewTransformMatrix * inv(StartTransformMatrix) * p – p)

其中

p = a 3D point,
falloff = smoothstep(outerradius, innerradius, distance(p – StartTransformMatrix.translation), smoothstep() is the same as HLSL/GLSL’s smoothstep()

这个函数创建了一个我们将应用于雕刻的位移字段。

下面是位移字段的样式。视频演示了转换,旋转。打漩和缩放。其他位移字段同样可以使用,例如,我们正在考虑如何将这个应用于拧捏/膨胀工具。

3. Medium的曲面呈现

在解释Move Tool三个原型的开发之前,我将介绍Medium是如何代表雕刻数据的部分信息。

Medium用隐式曲面定义3D对象(雕刻)。曲面存储为像素三维网格中的有向距离字段(SDF)。SDF包含一系列可以区分三角网格的有用属性,例如加,减和相交这样的CSG操作。另外,SDF从来不会自相交,你总是能清楚确定一个点是位于内部还是外部。另一方面,三角网格是存储曲面的显式方法。当你想要转换或移置一个点时,它们的效果十分显著,但它们可以自相交并且存在其他数值问题。CGS操作难以作用域三角网格。

距离值的3D数组很快就会变得很大。为了管理这个数据集,我们只存储距离曲面的距离值。这个区域被称为水平集的“narrow band(窄带)”。Medium的narrow band宽度是2,这意味着它会固定[-2.0 .. +2.0]范围以外的任何距离值。Medium会稀疏地存储距离数据:它将3D数组划分为8x8x8的数据块,只有包含对象实体部分的区块才存储在散列表中。

左边是一个雕刻;右边是SDF一部分的形象化呈现。narrow band是靠近曲面的浅蓝色区域。

左边是不带曲面的SDF。蓝色在曲面之外,橙色则位于里面。右边是包含有向距离数字的的近景图。注意数据是如何固定在narrow band上。

4. 第一代Move Tool原型

Move Tool的第一个版本采用了水平集方法(level set),通过位移字段来平移SDF。在水平集平移这种技术中,一个简单的偏微分方程式会描述运动通过一个速度字段。由于这个方程式重复应用于SDF数据的3D网格,曲面将会移动。

我们是根据一个欧拉模型模拟来实施水平集平移。这从一个指向距离字段开始,通过将平移偏微分方程应用至字段来进行模拟,并且重新初始化字段以赋予其距离值。为了实现Move Tool,我们使用位移字段来平移雕刻曲面。

这个版本在大部分情况下否符合我们的预期,但有两个问题导致我们不满意最终的结果:随着时间的推移,细节出现了丢失,而且性能成本也很高。造成细节损失是原因是,通过网格上的距离​​样本来估算曲面时会导致一定的舍入误差。当网格采样点之间存在高频细节时,细节将会丢失。这种误差将随着模拟的每一步而不断累积(这被称为数值耗散)。平移技术的第二个问题是高性能成本。模拟的步长必须受到限制,从而确保曲面的每步移动不会超过一个网格点。因此,一次移动需要数百个模拟步骤。

即使这种平移方法对Move Tool而言效果不佳,但对其他工具来说,这是一种有用的技术,因为它可以自动处理拓扑变化。我们将其应用于Medium的Swirl Tool中。这同样出现了数值耗散的问题,但由于旋转可以迅速混合所有一切,所以细节的损失不是一个大问题。但对Move Tool来说,细节保存十分重要。当你移动手臂和手部时,你不会希望手指将由于数字耗散而消散于无。

由于细节损失和性能问题,我们决定不发布此版本的工具。

Move Tool版本1.0,即便是简单的雕刻都会造成细节损失。

5. 第二代Move Tool原型

Move Tool的第二个版本是由软件工程师Aaron Lieberman所编写,工作原理如下:

  1. 按下扳机键,将SDF数据的当前状态复制到一侧。

  2. 当用户移动Touch控制器时,我们可以想象该工具是一个胶囊。在胶囊中的每个网格点处,通过移动变形的反转(找到其原始距离值)来转换该点,从而对缓存的SDF进行采样。与Move Tool的第一个版本相比,该版本在你移动工具时可以保留大量的细节。然而,这种方法仍然存在一定的问题。

第一个问题是,你只能对一个指向距离字段进行刚体变换。只有平移和旋转才能保留指向距离字段所保持的欧氏距离。当位移字段伸展距离数据时(应用非均匀尺度),结果值将不再是距离。这打破了Medium关于指向距离字段属性的众多假设。我们考虑在结果字段上运行指向距离字段重新初始化,但重新初始化SDF往往会略微影响对象的细节,而这是我们试图避免发生的事情。另外在某些情况下,距离太不正确,甚至是重新初始化也无济于事。第二个问题是,这个版本同样存在性能问题。随着你移动工具,在你看到雕刻出现在新位置之前,你需要等待一小会。延迟的原因是,我们每次移动Touch控制器时都会对曲面进行网格重构。

我们决定放弃这种方法,因为距离字段并不正确,因为Move Tool2.0的性能无法提供抓取和操纵雕刻的逼真感觉。

Move Tool2.0。我们寻找了一番才找到一个关于这个版本的视频,而视频实际上使其看上去效果不错。然而,你可以发现它在性能上遇到的挑战,这个雕刻跟Medium的初始球体一样大小。

6. 第三代Move Tool原型(最终版本)

在今年年初,Medium的设计负责人Lydia Choy和我重新讨论了Move Tool的问题,我们通过集思广益的方式来实施我们感到满意的事情。我们研究了其他基于三角形的3D内容创作应用,并参考了其中的移动工具和抓取笔刷。这种工具主要是移置三角网格的顶点。我们感到遗憾的是,这在三角网格上实现类似的操作十分简单,但对指向距离字段呈现而言则十分困难。

在进一步思考之后,我们提出了一个当时听起来非正统的方案,但最终取得了很好的结果。假如我们不直接使用SDK,而是使用三角网格,变形这个网格,然后再将其转换回SDK,这样又如何呢?Medium已经存在三角网格:我们不断使用Transvoxel来从等效曲面提取三角网格(一种Marching Cubes算法的变体)。这是GPU用于渲染的网格(我们也可以使用Raymarching的方法,但我们使用三角形是出于一系列与性能有关的原因)。

我们预计从三角网格到SDF的转换需要一定的时间进行计算,而且我们不确定速度有多快。所以我们决定分两个阶段实现新的移动工具:第一阶段将通过替换GPU顶点着色器中的顶点来显示移动的预览;第二阶段将是更长的转换过程。这遵循了我们其他一些工具的设计流程,比如像“Increase Resolution(增加分辨率)”那样的冗长图层操作,其中我们在操作完成时会显示Windows沙漏或OSX旋转指针的等价物。

Lydia开发了第一阶段,修改了雕刻顶点着色器代码。在我们感到满意后,我们发现变形三角网格的效果很好。即使在我们的默认分辨率级别下,你也可以执行移动,同时不会看到因镶嵌不足而造成的伪影。 Transvoxel生成的网格(以及大多数Marching Cubes风格的算法)具备两个可以使其适应这种变形风格的属性。这是一个非常密集的网格,曲面上均匀分布一系列的点(顶点)。此外,网格总是双面曲形(严密),我们在把三角网格转换回SDF时充分利用了这一点。

下面,你将可以看到Move Tool的两个阶段。在第一个阶段,用户使用Touch控制器来调整乌龟头部的位置,亦即操作雕刻。在第二阶段,我们将计算新的SDF数据。当操作的时间多于1秒时,我们将展示Medium的动画标志,提示用户系统正在处理之中,但我们仍然是在VR帧率下进行渲染。

6. 下一步?

由于“Summer of Move”更新已经发布,Move Tool在Medium社区取得了积极的反馈:

“我非常喜欢Move Tool!定义和调整3D形状变得非常简单。”

“喜欢Move Tool!只需一个手势即可为我的小动物增加一点点龇牙低吼。”

“不仅去除了移动工具的不足,同时使其成为了我所见过的最佳移动工具。”

在未来的文章中,我将详细解析我们是如何将三角网格转换回SDF,这种方法如何作用于其他工具,以及我们如何在实现这一切的同时仍然能够维持VR帧率。

https://yivian.com/news/39833.html

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引