你如何存储体素数据?

3

我一直在网上寻找信息,对于使用体素数据进行地形建模和操作的能力印象深刻。问题是,在我访问的任何网站上都没有清楚地解释体素或如何使用/实现它们。我发现的只有体素是体积数据。请提供一个更完整的答案; 什么是体积数据?这似乎是一个简单的问题,但我仍然不确定。

此外,您会如何实现体素数据?(我打算将其实现到一个C ++程序中。)您将使用什么数据类型来存储体素数据,以便使我能够尽可能快地在运行时修改内容。我在网上查找了一些东西,但找不到任何解释如何存储数据的内容。列表对象、数组等...

如何使用体素?

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


为了简单起见:使用3D数组。为了提高性能:我认为使用八叉树 - BWG
3个回答

6
实质上,体素是像素的三维扩展(“体积像素”),它们确实可以用于表示体积数据。
什么是体积数据
从数学上讲,体积数据可以看作是三维函数F(x,y,z)。在许多应用中,此函数是标量函数,即每个空间点(x,y,z)都有一个标量值。例如,在医疗应用中,这可以是某些组织的密度。为了在数字上表示这一点,一种常见的方法是简单地制作数据的切片:想象一下在(X,Y)平面中的图像,并将z值移动到具有一定数量的图像。如果切片彼此接近,则可以将图像显示为视频序列,例如在MRI扫描的维基页面上所见(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空间中创建表面,使得每个点具有相同的标量值。对于医学扫描,这允许从体积数据中提取例如脑部(不仅作为切片,而是作为3D模型)。
最后,需要注意的是,表面(网格、地形等)不是体积形状,它们是2D形状弯曲、扭曲、拉伸和变形以嵌入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的点。其他点也可以具有任何值,但这些值并不重要(在某些情况下,仍然考虑符号,以表示“内部”和“外部”,但仅需要表面时不需要该值本身)。
如何使用
如果您想知道“使用”是指如何呈现它们,那么您可以查看“ marching cubes”及其优化。MC将从体积数据创建一个三角形网格,以任何经典方式呈现。除了转换为三角形之外,您还可以查看体积渲染,以将“ 3D采样数据集”(即体素)呈现为这样( https://en.wikipedia.org/wiki/Volume_rendering)。我必须承认我对体积渲染不太熟悉,所以现在就只留下维基链接了。

工作中的MRI扫描链接:https://upload.wikimedia.org/wikipedia/commons/4/44/Structural_MRI_animation.ogv - NanBlanc

2

体素就是三维像素,即将三维空间规则地分成块。

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

对于您来说,纯3D数组可能是最好的选择,但它需要大量内存。正如BWF所指出的,八叉树是另一种流行的替代方案。搜索稀疏体素八叉树以获取更近期的方法。


0
在 90 年代和 00 年代的流行用法中,“体素”可能意味着不同的事情,这也是你一直发现很难找到一致信息的原因之一。在技术成像文献中,它表示三维体积元素。然而,它常用于描述相对更清晰地称为高细节光线投射引擎(而非 Doom 或 Wolfenstein 中的低细节光线投射引擎)。一个受欢迎的多部分教程位于 Flipcode archives。还可以查看Jacco 的这篇简短文章
有许多旧演示版本可以在仿真器中找到。它们很适合作为灵感来源和解剖学习材料,但往往使用大量汇编代码。

你应该仔细考虑你的引擎要支持什么:赛车、飞行、3D对象、星球等,因为这些限制会改变你的引擎的实现。通常情况下,并没有一个数据结构,但地形高度场是通过函数进行程序表示的。否则,你可以使用图像作为高度场。为了提高性能,在渲染到屏幕时,要考虑细节级别,也就是渲染元素所占用的实际像素数量。这将决定你对高度场进行多少采样。一旦你有了可行的方案,你可以考虑如何在时间和屏幕空间内混合像素,使它们看起来更好,同时尽可能少地进行渲染。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接