〔Part 2〕Oculus Medium移动工具的开发日记
文章相关引用及参考:oculus
本文来自Oculus的David Farrell
(映维网 2017年12月29日) Oculus Medium是一款专为Touch设计的沉浸式VR体验,你可以在VR环境之中雕刻,建模,绘制和创建有形对象。Oculus最近添加了Move Tool,它允许用户抓拿,移动和重新设置雕刻作品的一部分。“Move Tool”是Medium“Summer of Move”(1.2版本)更新的主要功能之一,这也是Medium用户长期以来的反馈要求。
延伸阅读:〔Part 1〕Oculus Medium移动工具的开发日记
在先前的文章中,我们探讨了Move Tool的开发过程,以及部分行之有效和无效的方向。在本文中,我们将指向距离字段和三角网格将如何为曲面呈现带来帮助,Medium如何将三角网格转换成指向距离字段,以及可以应用于其他雕刻操作的部分方法。
1. 两种互补的曲面呈现
在Medium中,雕刻操作支持指向距离字段。自Medium的早期版本以来,渲染器都在使用通过Transvoxel算法生成的三角网格。Transvoxel是一种类似于Marching Cubes的技术,能够创建多个可以无缝拼接在一起的细节层次三角形网格。GPU将渲染这种三角网格,而不是渲染SDF的隐式曲面。
在开发Move Tool的时候,我们探索了如何将三角网格转换回指向距离字段呈现。我们惊喜地发现,三角网格到SDF的转换质量比我们预期要高。虽然这是一个有损失的转换,但在实践中,用户在Medium中无法感知数据的损失。
我们意识到能够选择SDF或网格呈现进行雕刻操作是一项强大的技术。每个呈现都有其优点和缺点,而彼此之间可以相辅相成
1)指向距离字段(SDF):
优点:
- 布尔CSG操作简单而强大
- 曲面永远是严密的,永远不会自相交
- 点明确位于曲面之内或曲面之外
- 拓扑修改十分容易
缺点:
- 难以用常规方法移动曲面
2)三角网格:
优点:
- 计算机图形学中最常见的呈现形式
- 网格的顶点十分容易移动
缺点:
- 难以实现稳定的布尔CSG操作
- 很难检测和修复自相交表面
在完成Move Tool后,我们发现我们可以使用任意一种曲面呈现方法,并彼此进行转换。这是一种强大的技术,我们不仅将其用于Move Tool,同时会应用于其他雕刻操作。
左边是显示为线框三角网格的雕刻;右边则是代表同一雕刻的指向距离字段
2. 从三角网格到SDF
为了将三角网格转换为SDF,Medium假设输入三角网格为双面曲形。Transvoxel生成的所有网格都是如此,因为指向距离字段表示的曲面始终为双面曲形。这个假设可以很容易确定一个给定点是位于网格内部还是网格外部。
转换通过以下步骤完成:
1) 光栅化网格,将其变成 逐个像素的片段列表
对于任何严密双面曲形网格,你可以从该点出发的任意方向投射光线,并计算光线穿过的曲面数量来确定点是位于曲面内部还是曲面外部。如果穿过的数量为偶数,则该点位于曲面之外,如果数量为奇数,则该点位于曲面之内。由于光线可以往任意方向投射,所以我们把X轴的光栅化应用至到YZ平面上,而不是使用光线追踪来查找曲面。光栅化和光线追踪有许多共同之处,但在这种情况下,光栅化意味着我们可以避免构建像光线追踪所需的加速结构。
在光栅化过程中,我们创建了逐个像素的片段列表,并记录片段是来自前向还是后向三角形。每个光栅化片段都记录在逐个像素列表中;这里没有深度缓冲区测试来拒绝片段。这些列表会在下一步中使用。
这是光栅化的片段。浅绿色片段为前向,深绿色片段则是后向:
2) 通过配对前向和后向的片段来生成内部区域的span
在光栅化所有三角形后,我们迭代了每个像素的片段列表。我们按照深度坐标对每个列表中的片段进行排序,配对相应的前向片段和后向片段。这些配对表示对象的内部区域,并存储为spans(片段配对的起始和结束X坐标。有了这些信息,我们就能知道输出指向距离字段中任意点的指向。
以下是spans的渲染图(洋红色):
3)在边界框中,和每个三角性周围生成未指向距离
Medium将其数据存储在一个窄带水平集中,其中窄带宽度为每个方向2 voxel。由于我们只关心窄带数据,因此网格到SDF的转换代码将围绕每一个三角形形成一个边界框,并且令边界框膨胀,使其包含窄带。在边界框中的每个网格点处,我们找到了从该网格点到该三角形的指向距离。如果这个三角形是最接近网格点的那一个(如果距离小于当前值),我们更新网格点的距离值。
这些距离值存储在8×8×8 voxel的区块中。我们不需要窄带以外的距离值,所以这些区块将稀疏地进行存储以节省内存。利用这些信息,我们知道输出指向距离字段中任意点的指向距离。
3. 将它们整合在一起
一旦这些步骤完成,我们就得到了我们所需要的指向距离字段的所有信息。对于3D网格中的任何点,我们使用步骤2的结果来查看一个span是否覆盖了该点,因此是否出现一个正数或负数指向。从步骤3的结果中,我们知道该点的距离大小。结合两者,我们将知道该点的指向距离。
从指向距离字段 → 三角网格 → 变形三角网格 → 回到指向距离字段
4. MOVE TOOL之外
除了Move Tool之外,使用两个互补的曲面呈现同样能为其他雕刻操作中带来帮助。
4.1 改变分辨率
Medium 1.0有一种方法来提高雕刻层的分辨率,但没有办法降低分辨率。这是因为我们最多只能将距离值存储为一个窄带的距离。当提高分辨率时,点会被缩放,使得彼此间更加靠近,而它们能够保持在窄带之内。但在降低分辨率的时候,点就会更加远离彼此。如果它们被缩放至窄带之外,它们的距离值被限制在窄带的最大值,而这实际上没有任何意义。
我们意识到,通过采用SDF的三角网格,缩放网格,然后将其转换回SDF,我们能够支持Decrease Resolution(降低分辨率)的操作。这样做的效果很好,我们重新实施了原来的Increase Resolution(提高分辨率),以此来做同样的事情,只需缩放一个不同的值即可。这甚至可以用于包含非均匀比例的分辨率更改。
三个Increase Resolution操作之后的三个Dncrease Resolution操作
4.2 Copy To Clay
另一个有用的雕刻操作是Copy To Clay。该操作将导入由Medium创建的3D三角网格,并将其转换为可雕刻的SDF数据。这是三角网格到SDF代码的简单方法,需要注意的是,上面描述的网格到SDF技术假定三角网格为双曲面。对于在Medium以外创建的网格,这并非都是如此。所以为了能够支持任意网格,Copy To Clay代码对网格进行了三次光栅化,并在三个不同方向上创建了span:沿X轴向下,沿Y轴向下,沿Z轴向下。对于每一个点,我们根据三个方向上的span进行表决。一致的两个(理想情况下是三个)span将用于决定该点是否位于对象内部。这不是一个完美的解决方案,但确实解决了许多有问题的网格。
左边是在Medium之外创建的网格的线框视图;右边是导入至Medium中的相同网格,并复制到黏土。
4.3 细节层次
当我们实施Decrease Resolution的时候,我们注意到的第一件事情是,先进行Increase Resolution再进行Dncrease Resolution操作能够实现非常好的细节层次网格。细节会逐渐消失在雕刻的每个更小的版本中。我们意识到,通过以较低分辨率SDF重新扫描雕刻的三角网格来生成细节层次网格非常容易和快速。我们正在研究这个功能,以便在Medium主屏和网页中快速生成用于缩略图查看的小型预览网格。 Medium从1.1更新开始就能够提取和导出网格物体,但通过这种方法来产生细节层次要比Medium的边折叠抽取器更快。
原来的高分辨率
更低分辨率的LOD网格
然而,通过这种方法来生成LOD网格存在两个问题:首先,这种LOD方案导致细节的统一损失,而更传统的边折叠抽取器能够保持更精细的细节。Medium的抽取器使用二次误差度量来指导边折叠,这会保留网格中的特征,但需要更多时间进行计算。其次,对网格进行下降采样会导致混叠,从而导致LOD网格缺失几何。一个简单的例子是,当网格一部分介于网格采样点之间的时候。尽管这些点的距离值是正确的,但它们都带有一个正指向(亦即它们位于雕刻曲面之外),而且等效曲面提取算法不会在这些样本之间放置三角形。
左边,高分辨率网格之上的原始曲面;中间,低分辨率网格之上的相同曲面;右边,通过低分辨率网格进行等效曲面提取后的曲面。请注意最右边的图像是如何丢失位于网格点之间的曲面部分
5. 最后
总之,能够充分利用我们数据集的两种呈现方式,并在数据集之间快速转换的做法非常有用。这率先应用到了Move Tool,而你可以看到它是如何帮助我们解决了其他问题。我们正在继续研究新的和有趣的方式,通过利用这一点来加速现有的操作,并为操作雕刻带来新的方法。
在下一篇文章中,我们将探讨Meidum是如何异步执行Move Tool和其他雕刻操作,从而确保应用能够维持VR帧率。