6

我目前正在编写一个程序来使用 C++ 和 Opengl 实现 Marching Cube。

但是,我最好的参考仅来自http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/

在网络上,提供的代码是用 C 编写的。
我的问题是我不了解 triTable 和 edgeTable
以及它们之间的关系。

谁能帮助我解释或指导我将算法转换为代码?

4

1 回答 1

12

这些表用于找出如何细分曲面:

第一个表为您提供了插值所需的边。第二个表格为您提供了镶嵌的方式,即您必须在立方体内制作哪些三角形。

一个小例子:

假设,顶点 1 和 2 低于 iso 水平,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 能够为我们提供的。

现在遍历房间中的所有点并将每个点标记为具有大致 iso 值的顶点,这在算法上将非常复杂,并且会导致大量顶点。然后我们必须以某种方式进行镶嵌。

所以:First Marching cubes 将整个体积分割成相同大小的立方体。如果基础数据具有某种基础离散性,则使用其倍数。我不会讨论另一种情况,因为这种情况很少见。比如我们把一个密度为 1mm 的网格放到一个 2mx5mx5m 的房间里

我们使用 5mmx5mmx5mm 的立方体。穿过它们应该便宜得多。

您现在可以想象,一些立方体的边缘与等值面相交。这些是有趣的。此代码标识它们:

立方体索引 = 0;
   如果 (grid.val[0]

如果 cubeindex 保持为零,则此特定立方体不会与等值面相交。如果 cubeindex > 0,您现在知道等值面穿过这个立方体,并且您想要渲染它内部的等值面。

请在你的脑海中想象一下。有关相交立方体的示例,请参见 http://en.wikipedia.org/wiki/Marching_cubes

您可以轻松获得的顶点是立方体边缘的顶点。只需在 2 个角点之间进行线性插值即可找到等值的位置并将顶点放在那里。但是哪些边相交???也就是 edgeTable[cubeindex] 中的信息。这是包含所有 if 的一大段代码,它将插值点作为顶点存储在 xyz 点数组中:vertlist[]。这篇文章如下:

获取位域 = edgeTable[cubeindex]
 如果在位域中标记边缘 1(位域中的位 1 设置为 1)
    vertlist[0] = 插值点,位于边 1 的某处
... 等等。

您现在有一个充满顶点的数组,但是如何将它们连接到三角形?这是 tritable 提供的信息。

其余的几乎就是我上面解释的内容。

那么如果仍然存在问题,请具体说明给您带来麻烦的代码。

于 2009-04-22T11:18:17.013 回答