【问题标题】:Marching Cubes, voxels, need a bit of suggestionsMarching Cubes,体素,需要一些建议
【发布时间】:2012-02-02 17:08:29
【问题描述】:

我正在尝试构建一个适当的可破坏地形,仅用于研究目的。 好吧,一切都很顺利,但分辨率还不够让我满意。 我看过很多人们如何实现 MC 算法的例子,但其中大部分, 据我了解,使用函数对最终网格进行三角剖分,这不是 适合我。

我将尝试简要解释一下我是如何构建我的地形的,也许有人 你们中的一些人会给我建议如何改进或提高最终地形的分辨率。

1) 预先计算 MC 三角形。

我在每个案例(0-255)的 MC 查找表中运行简单循环并计算三角形 愤怒:[0,0,0] - [1,1,1]。 这里没有问题。

2) 地形

我有地形类,它存储我的体素。 一般来说,它看起来像这样:

int size = 32;//Size of each axis.
unsigned char *voxels = new unsigned char[(size * size * size)/8];

因此,每个轴的长度为 32 个单位,但是,我存储每个位的体素信息。 意思是如果位打开(1),有东西,应该有东西。

我有几个功能:

TurnOn(x,y,z);
TurnOff(x,y,z);

打开或关闭体素位置。 (有助于处理位)。

一旦分配了地形,我就会运行 perlin 噪声,并打开或关闭位。

我的地形类还有一个功能,从 x,y,z 位置提取 Marching Cubes 案例编号 (0-255):

unsigned char GetCaseNumber(x,y,z);

通过确定该体素的邻居是打开还是关闭。 这里没有问题。

3) 渲染部分

我正在循环每个轴,提取案例编号,然后按案例获取预先计算的三角形, 转换为 x,y,z 坐标,并绘制这些三角形。 这里没有问题。

所以结果如下所示:

但如您所见,在任何单个位置,分辨率都无法与例如以下内容相比:
(来源:angelfire.com

我在 MC 示例中看到人们正在使用一种叫做“iso values”的东西,我不明白。 任何关于如何改进我的工作的建议,或者什么是 iso 值,以及如何在统一网格中实现它都会非常可爱。

【问题讨论】:

  • 分辨率在我看来是一样的,只是样本不像你的那样锁定在网格上。
  • 我认为您的意思是“等距表面”。这个想法是采用一些标量场函数,例如一个球体r(x,y,z) = sqrt(x**2 + y**2 + z**2) 并测试某个阈值以确定该位置是否在定义的阈值之内或之外。在您的 MC 实现中,您将使用 r(x,y,z) > t 的结果而不是体素填充位。

标签: c++ math opengl terrain marching-cubes


【解决方案1】:

问题是你的体素是一个二进制掩码(只是打开或关闭)。

这对于“默认”行进立方体算法非常有用,但它确实意味着您的网格中会出现锐利的边缘。

平滑示例可能是从平滑标量数据生成的。

想象一下,如果您的数据在 0 和 1.0 之间平稳变化,并且您将阈值设置为 0.5。现在,在检测到给定立方体的配置后,您可以查看生成的所有顶点。

假设您在两个体素之间的边上有一个顶点,一个值为 0.4,另一个值为 0.7。然后,您将顶点移动到在 0.4 和 0.7 之间插值时恰好得到 0.5(阈值)的位置。所以它会更接近 0.4 顶点。

这样,每个顶点都恰好位于插值 iso 曲面上,您将生成更平滑的三角形。

但它确实要求您的输入体素是标量的(并且变化平滑)。如果您的体素是双层的(均为 0 或 1),这将产生与您之前得到的相同的三角形。

另一个想法(不是您问题的答案,但可能有用):

为了在没有数学正确性的情况下获得更平滑的渲染,计算每个顶点的平均法线向量,并为连接到它的每个三角形使用该法线可能是值得的。这将隐藏锋利的边缘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-16
    相关资源
    最近更新 更多