Potree:大规模点云渲染

Potree:大规模点云渲染

  • 前言
  • 数据结构
    • Octree(八叉树)
    • Modifiable Nested Octree
    • Potree's Octree Structure
      • Poisson-Disk Subsampling
      • Potree 构建算法
      • Potree 索引文件分割
  • 总结
  • 参考资料

前言

Potree 是基于 WebGL 的开源大规模点云渲染器,其由维也纳工业大学计算机图形与算法研究中心(Institute of Computer Graphics and Algorithms, TU Wien)开发。官网点击这里:Potree。
根据相关论文以及展示的介绍,其支持 Billion 级别点云数据的渲染,一个复杂场景渲染示例如下图所示:

点云数据中本身仅仅包含多个点数据,对于较小规模的点云数据,只需要依次使用面或者点等方式将其全部渲染出来。但是面对较大数据量的点云,就需要考虑许多随之而来的问题:

  • 内存限制:以基于 V8 引擎为例,32 位机器可使用内存约为 0.7 GB,64 位机器可使用内存约为 1.4 GB。而渲染完整的 1 Billion 无 RGB 信息的点云数据就需要超过 22 GB 的内存进行存储(对于 JavaScript 仅有 double 数据,其计算为每个点需要 XYZ 三个点,即存储每个点需要 3 × 8 个 Byte 的内存,1 Billion 点云约为 22.35 GB)。因此,必须将点云数据进行分割,从而按需渲染以减少内存使用量;
  • 实时渲染需求:对于点云渲染的应用场景,往往并不仅仅只需要输出渲染后的可视化结果,而是需要满足基于点云渲染后的具体应用需求,例如游戏或者标注工具等。这对于点云渲染带来了实时性的需求,因此必须对巨大规模的点云数据采取一定的处理以减少 CPU 以及 GPU 的计算压力;
  • 网络传输速度:B/S 架构下由于点云资源需要通过网络进行传输,如果直接传输完整的点云数据,则在渲染计算开始前,用户需要花费大量的等待时间。这一点对于用户体验而言也同样是必须解决的痛点。

以上所述的问题需要对于点云渲染的各个阶段采取一定的措施,包括:数据预处理、数据加载、渲染计算等,但是归根结底,其本质就在于给出高效的点云数据结构

数据结构

在正式介绍 Potree 的数据结构之前,首先对于铺垫产生的这一数据结构的前述研究进行一个简单的介绍。
与大多数技术发展相类似,Potree 也并不是从石头缝里头蹦出来的,其数据结构的提出受到了之前多项研究的启发(来自同个实验室之前论文的启发, 包括 Nested Octree 和 Modifiable Nested Octree )。

Octree(八叉树)

八叉树是三维空间中最简单的树形数据结构,其每个节点中包含 8 个内部节点,将节点所在空间分割为 8 个子空间,依次递归表示不同粒度的三维空间数据。

Potree:大规模点云渲染_第1张图片
来自 wiki

由于八叉树中包含不同层级的空间数据,因此其可以应用于不同细节层次(随着离观察者距离增加而降低)的三维渲染的过程中。八叉树是最为基础的数据结构,后续将介绍的一些数据结构事实上是对于八叉树的优化或者拓展。

Modifiable Nested Octree

(再往前追溯还应当继续讨论讨论 SPT 和 MOSPT 等等,但是我懒
可修改的嵌套八叉树(以下简称 MNO)由 Claus Scheiblauer 在其 PhD 论文《Interactions with Gigantic PointCloud》中提出,其实际上是基于细节等级(Level of detail, LOD)对于输入点云的下采样。低等级的节点占据更大的体素以及更稀疏的下采样样本点云,随着节点层级的升高,其点云的稠密程度增加。同时,输入点云中所有的点仅被一个节点所包含,也即是意味着构建的 MNO 中不存在重复点以及遗漏点。
下图显示了一个全填满的嵌套二叉树(嵌套八叉树 Nested Octree 的简单版本)的实例,其由索引以及每个索引节点存放的二叉树所构成,大致的数据结构一窥便知。
Potree:大规模点云渲染_第2张图片
嵌套八叉树用于点云的渲染时效率较高,但是由于其存在依赖,导致对其进行点的编辑效率较低。这主要是由于每次执行点的删除或者增添的过程中都需要对内部八叉树进行重新的构建,同时,其层级结构也需要重新进行序列化。
为了提升点修改操作的执行效率,MNO 提出了利用网格替代嵌套八叉树中的内部八叉树(Inner Octree)。其变更如下图所示:
Potree:大规模点云渲染_第3张图片
MNO 使用的三维网格被划分为 128^3 个单元。通过原始点云构建 MNO 结构时,点首先被添加到根节点中,并占据其所对应的单元。同时,为了保证新的子节点中包含了足够数量的点,每个网格还设置了一个阈值,用于存储多余的点,当点遇到已被占据的单元并且多余点不超出阈值时,其将被暂放入一个等待数组中,直到等待数组中存放了足够的点并构建出子节点网格。通过这一阈值就可以避免某些子网格中包含点数量过少造成不必要的开销。

Potree’s Octree Structure

Potree 所采用的数据结构基于 MNO 进行部分修改,其主要的构建算法与 MNO类似,但是针对于其应用于实际场景渲染中存在的潜在问题进行具体的优化,其主要为两点:

  • MNO 不保证网格单元间点的间隔: MNO 仅仅保证每个点落入其所属的单元中,但是相邻单元间的间隔距离可能很短,这会对下采样样本的质量造成影响;
  • MNO 将层级结构索引保存在单一文件中:当处理的点云过于庞大时,其所生成的索引文件大小也将膨胀,例如 AHN2 的点云中包含 640 billion 个点,处理后具有 13 层八叉树以及 38 million 个文件,仅仅是索引文件就超过 190 MB。

Poisson-Disk Subsampling

在 MNO 的构建过程中,当点落入到某个单元所在空间时,其立即占据该单元,并且后续落在同个单元的点将被放入暂存数组或者放入其子节点的网格单元中。使用其他更优的采样方法可以提升这一下采样样本的质量,例如 grid center、Poisson-disk、Morton-sorted nth 等。其二维的采样样本结果如下图所示,在这里不进行具体展开。
Potree:大规模点云渲染_第4张图片
Potree 中采用了 Poisson-disk 下采样方法,其保证了每个点与其他点的最小间距。Poisson-disk 的实现可以应用很多算法,例如 dart throwing 算法等。其基本思路就是在每次添加点时检查其与其他点的距离,若小于间隔则进行抛弃。
为了加速间隔计算过程,Potree 同样将节点划分为多个单元,从而只需要对同个单元以及相邻单元进行计算。同时,较小的单元大小会增大内存的开销,而较大的单元大小则无法起到加速计算的效果,在具体实现中需要对其进行实验取舍。

Potree 构建算法

Potree 数据结构的构建过程为:

  1. 输入点云中每个点依次被放入根节点中;
  2. 点落入某个节点中,如果该节点中其他点没有保持最小距离则落入子节点中(由于随着节点层级的升高其所占空间会减小,因此每高一层级,该节点的最小间距减半);
  3. 与 MNO 相类似,落入叶节点(其下不包含节点)中的点并不会立即构建内部节点,而是先被存放在叶节点中,直到点的数量达到阈值;
  4. 为了降低构建过程中的内存使用量,每处理 10 million 的点则会将当前的数据写入硬盘中,后续若需要则重新读回。

以上是 Potree 的构建过程,其算法流程相对较为简白。

Potree 索引文件分割

构建完成 Potree 数据结构后,用户端需要层级索引文件来寻找需要加载并渲染的节点。层级索引文件较大会导致客户端初始载入时间过长。下图显示了 Potree 中将 MNO 的单一索引文件分割为多个子索引文件,每个子索引文件根据 hierarchyStepSize 包含对应深度的索引。
Potree:大规模点云渲染_第5张图片
通过对索引文件的分割,可以对索引文件实现按需加载从而使得客户端更快完成渲染。

总结

虽然根据 Markus Schuetz 的学位论文将 Potree 相关原理揉碎来看还是挺清晰简白的,但是其最终实现的效果的确很 fancy,即使在性能相对较差的计算机上也能够完成大量点云渲染的工作。
同时,值得一提的是,虽然 Potree 项目早在 2014 年就开始了开发工作,但是截止到 2018 年,其实现中居然还包含了 ES8 的 async/await 语法,开发过程中想必经历了非常痛苦的重构工作吧。
除却本文中着重介绍的 Potree 数据结构,在渲染过程中,Potree 也进行了一些较小的优化工作,其并不是本文重点,在此不表。如果还有精力的话,后续(有生之年)会继续对本文中提到的其他论文进行介绍。
不过看起来 Potree 团队似乎仅仅只是做一个应用,没有将其提供给其他开发者做二次开发的打算。除去几篇论文,Potree 官网等各处没有提供相关实现文档,同时在 Potree 的左边工具栏的实现中似乎也对 div 的 id 进行了硬编码实现。这样一来,二次开发使用的 API 基本靠翻源码和猜,终究令人心累。

参考资料

  1. Potree - github
  2. Potree: Rendering Large Point Clouds in Web Browsers, Schuetz
  3. Interactions with Gigantic Point Clouds, Scheiblauer
  4. Instant Points, Wimmer, Scheiblauer

你可能感兴趣的:(前端杂物筐,图形学)