你如何存储体素数据?

时间:2015-01-07 03:19:50

标签: c++ voxel

我一直在网上看,我对使用体素数据的能力印象深刻,特别是对于地形构建和操作。问题是在我访问的任何网站或如何使用/实施它们时,体素永远不会被清楚地解释。我发现所有体素都是体积数据。请提供更完整的答案;什么是体积数据。这似乎是一个简单的问题,但我仍然不确定。

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

你如何使用体素?

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

3 个答案:

答案 0 :(得分:1)

体素只有3d像素,即3d空间有规律地细分为块。

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

普通的3d数组可能是最适合您的,但它是内存密集型的。正如BWG所指出的那样,octtree是另一种流行的选择。搜索稀疏体素八分之一以获得更新的方法。

答案 1 :(得分:0)

在90年代和00年代的流行用法中,“体素”可能意味着有些不同,这可能是您发现很难找到一致信息的一个原因。在技​​术成像文献中,它意味着3D体积元素。尽管如此,它常常被用来描述更加明确的高细节光线投射引擎(与Doom或Wolfenstein中的低细节光线投射引擎相对)。一个受欢迎的多部分教程存在于Flipcode archives中。另请查看this brief one by Jacco

你可以找到许多应该在仿真下运行的旧演示。它们有助于灵感和解剖,但往往会使用大量的汇编代码。

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

答案 2 :(得分:0)

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

什么是体积数据

在数学上,体积数据可以看作是三维函数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)。如您所见,空间中的每个点都有一个标量值,表示为灰度。

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

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

最后,请注意曲面(网格,地形,......)不是体积的,它们是2D形状弯曲,扭曲,拉伸和变形以嵌入3D空间。理想情况下,它们代表体积对象的边界,但不一定(例如,地形数据可能不是闭合网格)。使用体积数据表示曲面的一种方法是确保曲面再次成为某些函数的等值面。作为示例:F(x,y,z)= x ^ 2 + y ^ 2 + z ^ 2-R ^ 2可以表示具有半径R的球体,其以原点为中心。对于球体的所有点(x&#39;,y&#39;,z&#39;),F(x&#39;,y&#39;,z&#39;)= 0.更多,对于内部的点球,F < 0,对于球体外的点,F> 0。 0

构建&#34;的方法。这样的功能是通过创建距离图,即创建体积数据,使得每个点F(x,y,z)指示到表面的距离。当然,表面是距离为0的所有点的集合(因此,同样地,值为0的等值面也与上面的球体一样)。

如何实施

正如其他人所说,这确实取决于用法。实质上,数据可以在3D矩阵中给出。但是,这是巨大!如果您希望分辨率加倍,则需要8倍的存储空间,因此通常这不是一个有效的解决方案。这适用于较小的示例,但不能很好地扩展。

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

八分之一允许更容易导航到相邻单元格,父单元格,子单元格......(我现在假设八叉树(或2D中的四叉树)的概念已知?)但是,如果有许多叶子单元位于最好的分辨率,这个数据结构将带来巨大的开销!因此,这比3D阵列更好:它在某种程度上取决于您想要使用的体积数据,以及您想要执行的操作。

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

如何使用

如果通过&#34;使用&#34;,你想知道如何渲染它们,那么你可以看看&#34;行进立方体&#34;及其优化。 MC将根据体积数据创建三角形网格,以任何经典方式呈现。您还可以查看体绘制以呈现&#34; 3D采样数据集,而不是转换为三角形。 (即体素)本身(https://en.wikipedia.org/wiki/Volume_rendering)。我不得不承认我对体积渲染并不熟悉,所以我现在只将其留在wiki-link上。