如何存储体素数据

How do you store voxel data?

本文关键字:数据 存储体      更新时间:2023-10-16

我一直在网上寻找,使用体素数据的能力给我留下了深刻印象,尤其是在地形构建和操纵方面。问题是,在我访问的任何网站上,体素都没有得到明确的解释,也没有得到如何使用/实现它们的解释。我只发现体素是体积数据。请提供更完整的答案;什么是体积数据。这似乎是一个简单的问题,但我仍然不确定。

此外,您将如何实现体素数据?(我的目标是将其实现到一个c++程序中。)你会使用哪种数据类型来存储体素数据,使我能够在运行时尽快修改内容。我在网上查了一下,找不到任何解释如何存储数据的东西。对象、数组等的列表。。。

如何使用体素?

编辑:由于我刚开始使用体素,我可能会从使用它只对简单对象建模开始,但最终我会使用它来渲染地形和世界对象。

本质上,体素是像素("体积像素")的三维扩展,它们确实可以用于表示体积数据。

什么是体积数据

从数学上讲,体积数据可以看作是一个三维函数F(x,y,z)。在许多应用中,该函数是标量函数,即,它在空间中的每个点(x,y,z)都有一个标量值。例如,在医学应用中,这可能是某些组织的密度。为了以数字方式表示这一点,一种常见的方法是简单地对数据进行切片:想象(X,Y)平面中的图像,并移动z值以获得多个图像。如果切片彼此靠近,图像可以以视频序列显示,例如在用于MRI扫描的wiki页面上可以看到(https://upload.wikimedia.org/wikipedia/commons/transcoded/4/44/Structural_MRI_animation.ogv/Structural_MRI_animation.ogv.360p.webm)。正如您所看到的,空间中的每个点都有一个标量值,该值表示为灰度。

代替切片或视频,还可以使用体素来表示该数据。现在,我们不再将2D平面划分为规则的像素网格,而是将3D区域划分为规则网格的体素。同样,可以为每个体素提供标量值。然而,可视化这并不是微不足道的:虽然我们可以只给像素一个灰度值,但这对体素不起作用(我们只能看到盒子本身的颜色,而不能看到盒子内部的颜色)。事实上,这个问题是由我们生活在一个3D世界中的事实引起的:我们可以从第三维度观看2D图像并完全观察它;但我们无法观察3D体素空间并完全观察它,因为我们没有第四维度可供观察(除非你将时间计算为第四维度,即创建视频)。

因此,我们只能查看部分数据。如上所述,一种方法是制作切片。另一种方法是观察所谓的"等参曲面":我们在三维空间中创建每个点都具有相同标量值的曲面。对于医学扫描,这允许从体积数据中提取例如大脑部分(不仅作为切片,而且作为3D模型)。

最后,请注意曲面(网格、地形…)不是体积的,它们是弯曲、扭曲、拉伸和变形的二维形状,以嵌入三维空间。理想情况下,它们表示体积对象的边界,但不一定(例如,地形数据可能不是闭合网格)。使用体积数据表示曲面的一种方法是确保曲面再次是某个函数的等参曲面。例如:F(x,y,z)=x^2+y^2+z^2-R^2可以表示半径为R、以原点为中心的球体。对于球体的所有点(x',y',z'),F(x'、y'、z')=0。甚至,对于球体内的点,F<0,对于球体之外的点,F>0。

"构造"这种函数的一种方法是创建距离图,即创建体积数据,使每个点F(x,y,z)指示到曲面的距离。当然,曲面是距离为0的所有点的集合(因此,值为0的等参曲面与上面的球体一样)。

如何实施

正如其他人所说,这确实取决于用法。本质上,数据可以在3D矩阵中给出。然而,这是一个巨大的!如果你想将分辨率提高一倍,你需要8倍的存储空间,所以一般来说,这不是一个有效的解决方案。这将适用于较小的示例,但不能很好地扩展。

八叉树结构是最常见的存储结构。存在许多八叉树的实现和优化,因此请查看哪些内容可以(重新)使用。正如Andreas Kahler所指出的,稀疏体素八叉树是最近的一种方法。

八叉树允许更容易地导航到相邻单元格、父单元格、子单元格。。。(我现在假设八叉树(或2D中的四叉树)的概念是已知的?)然而,如果许多叶细胞位于最精细的分辨率,这种数据结构将带来巨大的开销!那么,这比3D阵列更好吗?这在一定程度上取决于您要使用的体积数据以及要执行的操作。

如果数据用于表示曲面,八叉树通常会更好:如前所述,曲面并不是真正的体积曲面,因此不需要许多体素来具有相关数据(因此:"稀疏"八叉树)。参考距离图,唯一相关的数据是值为0的点。其他点也可以有任何值,但这些都无关紧要(在某些情况下,仍然考虑符号,以表示"内部"answers"外部",但如果只需要表面,则不需要值本身)。

如何使用

如果通过"使用",你想知道如何渲染它们,那么你可以看看"行进立方体"及其优化。MC将根据体积数据创建一个三角形网格,以任何经典方式进行渲染。您也可以查看体积渲染来渲染"3D采样数据集"(即体素),而不是转换为三角形(https://en.wikipedia.org/wiki/Volume_rendering)。我不得不承认,我对体积渲染不太熟悉,所以我现在只把它放在wiki链接上。

体素只是3D像素,即3D空间规则地细分为块。

你是如何使用它们的?这真的取决于你想做什么。光线投射地形游戏引擎?医学体积渲染器?完全不同的东西?

普通3D阵列可能是最适合您的,但它占用大量内存。正如BWG所指出的,八叉树是另一种流行的替代方法。搜索稀疏体素八叉树以获取更新的方法。

在90年代和00年代的流行用法中,"体素"可能意味着一些不同的东西,这可能是你发现很难找到一致信息的原因之一。在技术成像文献中,它指的是3D体积元素。然而,通常情况下,它被用来描述更明确地称为高细节光线投射引擎的东西(与《末日》或《德军总部》中的低细节光线投射发动机相反)。Flipcode档案中有一个流行的多部分教程。还可以看看Jacco的这份简报。

你可以在那里找到许多旧的演示,它们应该在模拟下运行。它们有利于启发和剖析,但往往会使用大量的汇编代码。

你应该仔细考虑你想用你的引擎支持什么:赛车、飞行、3D物体、行星等,因为这些限制可能会改变你的引擎的实现。通常,本身没有数据结构,但地形高度场在程序上由函数表示。否则,可以使用图像作为高度场。为了提高性能,在向屏幕渲染时,请考虑细节级别,换句话说,渲染元素将占用多少实际像素。这将决定您对高度场进行了多少采样。一旦你做了一些工作,你可以考虑如何在时间和屏幕空间上混合像素,使它们看起来更好,同时尽可能少地渲染。