如何在3D空间中生成随机点?

kul*_*lin 5 c++ random 3d

我遇到的最大问题是我没有词汇来描述我的意思,所以如果没有其他的话,一些帮助将非常感激.

根据我的理解,Perlin噪声可以为3D空间中的某个点提供随机值,此外,任何附近的点都将具有相似的值.我在一个程序中工作,当随机值超过某个阈值时,生成漂浮在空间中的3D斑点.这很有效,因为我可以选择任何一点,而不必担心之前计算的点数,确定它的值(如果我想要的话可​​以对blob生成进行处理).

我现在想做类似的事情,除非我想在随机值超过某个阈值时更改blob上该点的颜色.然而,我希望这是随机的,与其邻居无关(与Perlin噪声不同).

我想要用什么样的算法来实现这个目标?

关键标准:

  1. 该函数将3D矢量作为参数.
  2. 这些值在点到点上完全不相关.
  3. 订单检查点不会影响功能的结果.
  4. 如果向其传递相同的点,则该函数返回相同的结果.

结果

所以我决定采用类似于Kahler的答案的方法进行一些非常小的调整.我不想使用重复实例化所使用的所有重定向和操作,甚至只是重复播种随机数生成器.我最终复制了UE4 RandomStream类中使用的随机数生成器,使其符合我的需要.我确定这个发电机不是他们自己的,因为使用的数字似乎出现在其他地方,但那是我发现它的地方.

float WhiteNoise::GetNoise3D(const FVector& vector) const
{
    int32 s1 = seed;
    int32 s2 = ((s1 + FMath::TruncToInt(vector.X)) * 196314165) + 907633515;
    int32 s3 = ((s2 + FMath::TruncToInt(vector.Y)) * 196314165) + 907633515;
    int32 s4 = ((s3 + FMath::TruncToInt(vector.Z)) * 196314165) + 907633515;

    const float tmp = 1.0f;

    float result;

    *(int32*)&result = (*(int32*)&tmp & 0xff800000) | (s4 & 0x007fffff);

     return FMath::Fractional(result);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码有一些明显的问题.一个是数字不是很随机,另一个是截断导致粒度问题.在我的情况下,这两个都是完全可以接受的,所以这个工作得相当好.

Kah*_*ler 2

如果每次传入相同的参数时函数都返回相同的数字,则它不是随机函数。要获得明显随机的模式而不保存每个点的确切结果,您可以使用种子依赖于位置的随机生成器。

就像是

value_t get_value(coord_t x, coord_t  y, coord_t z)
{
    seed_t seed = some_equation(x,y,z);
    return generate_random_with_seed(seed);
}
Run Code Online (Sandbox Code Playgroud)

C++ 现在有了这个<random>库,你必须调整方程才能得到满意的结果。每次种子重复时,它们都会重复,每次调用都有明显的随机模式。一种可能的种子生成器是将所有可能的离散可能性分布在种子类型上,因为相等的种子意味着相等的结果。

(因此 256x256x256 网格可以使用种子(x*256*256 + y*256 + z)

该策略实际上将有序集映射到明显无序集。输出将与种子上的随机生成器操作的位置相关。

由于对独特种子的要求可能变得相当麻烦,您还可以通过将体积分割为较小的体积来获得可重复的结果,每个较小的体积由 - 点组成,并且整个块共享相同的唯一种子,第 - 元素N的随机值为使用块种子运行随机生成器的第 - 次ii

这会将唯一种子的需求减少 N 倍,但将平均检索操作增加 (N-1)/2 倍。

不久前,我尝试了几个发行<random>版,这里有一些显示〜图形〜输出的代码(注释是葡萄牙语,但代码很简单)。

您可能需要一个均匀随机变量作为阈值, 这里是对uniform_int_distribution的在线参考