Marching Cube问题

6
我正在使用C++和Opengl编写程序来实现Marching Cube。然而,我目前最好的参考资料只有http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/中提供的C代码。在网上,提供的代码都是用C语言编写的。我的问题在于我不理解triTable和edgeTable以及它们之间的关系。请问有人能帮我解释一下或指导我如何将算法转换为代码吗?
1个回答

12
这些表格用于找出如何镶嵌表面:
第一个表格给出了插值所需的边缘。 第二个表格告诉你如何进行细分,也就是说,你需要在立方体内制作哪些三角形。
举个例子: 假设顶点1和2都在等值线以下,那么cubeindex应该为3。 整个交汇处应该看起来像楔形。
如果仔细想一下,你需要在边缘上插值: 0和9,以及2和10。 如果你把这些输入到一个位域中,每个位对应“边界是否相交?”,你最终会得到类似于这样的结果:
10 9 8 7 6 5 4 3 2 1 边缘 1 1 0 0 0 0 1 0 1 0 是否相交?
不是吗?
这正是二进制下edgeTable[3]的值;) 0x30A = 1100001010
现在你可以编写一个函数,在这些边缘上进行线性插值,以适应你的等值面。 这些点将成为你在此单元格内的表面。
但如何细分这个单元格/表面呢?
如果你查看triTable [3],你会发现自己露出了微笑的脸:)
在评论中表示困惑后,附加说明:;-)
Marching Cubes是做什么的: 想象一下,你有一个黑暗的房间,里面只有一个点光源。 它是标量强度值的体积光强场的中心。 你可以到达点(x,y,z)并测量那里的强度,例如3坎德拉。
现在,您想要渲染通过所有具有特定光强度的点的表面。 您可以想象这个等值面看起来像点光源周围的球体。这就是我们希望Marching cubes能够提供的。
现在,在房间中运行并标记每个具有大致等值的点作为顶点将是算法上非常复杂的,并且会导致巨大数量的顶点。然后我们必须以某种方式细分它们。
所以:首先,Marching cubes将整个体积划分为相等大小的立方体。 如果基础数据具有某种基础离散性,则使用其倍数。我不会讨论另一种情况,因为那是罕见的。 例如,我们将具有1mm密度的网格放入2mx5mx5m的房间中。
我们使用5mmx5mmx5mm的立方体。运行它们应该更便宜。
你现在可以想象一下,一些立方体的边缘与等值面相交。 这些是有趣的。此代码识别它们:
cubeindex = 0; if (grid.val[0]
如果cubeindex保持为零,则此特定的立方体未被等值面相交。 如果cubeindex> 0,则现在您知道等值面通过此立方体 并且您想要渲染其中的等值面片段。
请在脑海中想象一下。查看http://en.wikipedia.org/wiki/Marching_cubes以获取相交立方体的示例。
您可以轻松获得的顶点是立方体边缘上的顶点。只需在两个角点之间进行线性插值,以找到等值面的位置并在那里放置一个顶点。但是哪些边相交?这就是edgeTable[cubeindex]中的信息。那是带有所有if语句的大块代码,将插值点作为xyz点的顶点存储在vertlist[]数组中。此部分如下所示:
获取位域= edgeTable[cubeindex]
如果在位域中标记了边缘1(位域中设置了位1)
   vertlist [0] = 插值点,在边缘1的某个地方
...等等。
现在您有一个充满顶点的数组,但是如何将它们连接到三角形?这是tritable提供的信息。
其余部分基本上就是我上面解释的内容。
如果仍然有问题,请具体说明给您带来麻烦的代码部分。

2
如果那个笑容不想出现,想一想你会如何把三角形放进去,然后将其与triTable中的提议进行比较。 玩得开心!;-) - AndreasT
嘿,谢谢,AndreasT 实际上我有点迷失了。就你所知,我对算法一无所知。 我现在有点理解triTable是如何工作的,但我仍然不明白edgeTable是如何工作的以及如何确定使用哪个表面。 - noob88
不知何故,这里的代码格式化无法正常工作。 代码片段被截断了 :( 。但是如果你和源网站进行比较,应该是可以管理的。 - AndreasT
顺便问一下,“grid.val[0]”和“isolevel”在“grid.val[0]<isolevel”中分别代表什么值?‘grid’是一个运算符吗? - noob88
好答案!解释得也很好。 - Nathan Fellman

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