gpt4 book ai didi

c++ - 为什么这个噪声函数不处理否定参数?

转载 作者:太空宇宙 更新时间:2023-11-04 06:50:11 25 4
gpt4 key购买 nike

我有改编自 "Improved" Perlin noise 的代码

double improved_noise (double x, double y, double z)
{
// Calculate the "unit cube" that the point asked will be located in
// The left bound is ( |_x_|,|_y_|,|_z_| ) and the right bound is that
// plus 1. Next we calculate the location (from 0.0 to 1.0) in that
// cube. We also fade the location to smooth the result.

int xi = (int)x & 255;
int yi = (int)y & 255;
int zi = (int)z & 255;

double xf = x - (int) x;
double yf = y - (int) y;
double zf = z - (int) z;

double u = fade (xf);
double v = fade (yf);
double w = fade (zf);

int aaa, aba, aab, abb, baa, bba, bab, bbb;
auto & p = permutation;

aaa = p[p[p[ xi ] + yi ] + zi ];
aba = p[p[p[ xi ] + inc(yi)] + zi ];
aab = p[p[p[ xi ] + yi ] + inc(zi)];
abb = p[p[p[ xi ] + inc(yi)] + inc(zi)];
baa = p[p[p[inc(xi)] + yi ] + zi ];
bba = p[p[p[inc(xi)] + inc(yi)] + zi ];
bab = p[p[p[inc(xi)] + yi ] + inc(zi)];
bbb = p[p[p[inc(xi)] + inc(yi)] + inc(zi)];

double x1, x2, y1, y2;

// The gradient function calculates the dot product between a
// pseudorandom gradient vector and the vector from the input
// coordinate to the 8 surrounding points in its unit cube.

// This is all then lerped together as a sort of weighted average
// based on the faded (u,v,w) values we made earlier.

x1 = lerp (
grad (aaa, xf , yf , zf),
grad (baa, xf-1, yf , zf),
u);

x2 = lerp (
grad (aba, xf , yf-1, zf),
grad (bba, xf-1, yf-1, zf),
u);

y1 = lerp (x1, x2, v);

x1 = lerp (
grad (aab, xf , yf , zf-1),
grad (bab, xf-1, yf , zf-1),
u);

x2 = lerp (
grad (abb, xf , yf-1, zf-1),
grad (bbb, xf-1, yf-1, zf-1),
u);

y2 = lerp (x1, x2, v);

return (lerp (y1, y2, w) + 1) / 2;
}

我想要一个方向上的周期性噪声,所以我将该方向包裹在一个额外维度的圆上,这样调用它

 improved_noise (sin(x*2*M_PI), cos(x*2*M_PI), y))

我得到了奇怪的结果(大和/或负数)。一些实验表明,当 improved_noise 的参数为负数时会发生这种情况。

为什么这个函数不能很好地处理负值,并且可以很容易地对其进行调整,以便完整的数字行是一个有效的参数吗?

最佳答案

improved_noise 不是为处理负输入而设计的。

其中的一条评论说:

The left bound is ( |_x_|,|_y_|,|_z_| )…

The |…| notation suggests the absolute value is intended. However, the code computes:

int xi = (int)x & 255;

在常见的 C 实现中(使用二进制补码),这有效地计算了 x 模 256 的整数部分的余数。例如,如果 x 是 −3.25,它的整数部分是 - 3,这会将 xi 设置为 253(即 −3+256)。

这有两个问题。首先,253不是-3的绝对值,所以这段代码与注释不符。其次,它采用包含点的单位立方体的“右”边界(具有较大值的边界),而评论和正值的行为表明其意图是设置 xiyizi 到“左”边界(值较小的那个)。

从那里继续,代码设置 double xf = x - (int) x;。对于非负值,这将生成 x 的小数部分。例如,如果 x 为 3.25,则 xf 将为 .25。但是,对于负值和先前的 & 255 操作,这会误入歧途。对于 x = −3.25,它计算出 −3.25 − 253 = −256.25。但该代码可能仅用于在单位立方体内插值,对于从 0 到 1 的小数部分。无论用于执行插值的函数可能都不支持 −256.25。

从本质上讲,此代码从未设计为支持负值,修复它需要从它应该如何运行的首要原则重新设计它。

original code you point to更好:

int X = (int)Math.floor(x) & 255

x -= Math.floor(x);

前者正确使用 floor 找到“左”边界,而不管 x 是否为负。然后它应用 & 255 到那个。假设二进制补码,这将在周期性平铺中提供正确的坐标。 (假设二进制补码不是纯粹可移植的,应该记录或避免。)

然后它通过减去 xfloor 而不是减去 & 255 的结果来正确找到分数。例如,对于 x = −3.25,这将产生整数坐标 −4 和小数 .75。

修改 improved_noise 以类似方式工作可能会有所帮助。您可以尝试:

int xi = (int) floor(x) & 255;
int yi = (int) floor(y) & 255;
int zi = (int) floor(z) & 255;

double xf = x - floor(x);
double yf = y - floor(y);
double zf = z - floor(z);

你用 C++ 和 C 标记了这个问题。在 C++ 中,最好使用 std::floor 而不是 floor,并且可能还有其他问题C++ 和 C 的区别。

关于c++ - 为什么这个噪声函数不处理否定参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52668947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com