繁体   English   中英

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

[英]How do I generate random points in 3D space?

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

根据我的理解,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);
}

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

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

就像是

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);
}

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

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

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

由于对独特种子的要求变得非常繁琐,您还可以通过将体积分成较小的体积来获得可重复的结果,每个体积由N点组成,并且整个块共享相同的独特种子,即i th的随机值element是具有块种子的随机生成器的第i运行。

这将使独特种子的需求减少N倍,但是将平均检索操作增加因子(N-1)/ 2。

不久之前,我已经尝试了几个<random>发行版, 这里有一些代码显示~graphical~output (注释是葡萄牙语,但代码很简单)。

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

采取与Kahler上面的优秀答案略有不同的方法,我想知道你是否只是寻找一种改变数字空间的方法。

在这种情况下,可以说在一维数字空间中存在随机数。 即。 可以使用0向上和向下的整数值。

随机生成的32位整数必须介于0和4294967295之间,即。 你有4294967296个可能的唯一数字。 但是,如果您“消耗”该随机数,例如二维空间(如我们所说的“网格”),那么您的网格大小将是4294967296的第二个根,即65536.意味着您有65536个65536个可能的“时隙”可以随机为0或1(但随机数分布将完全匹配该网格)。

如果您在3D空间中使用随机整数,则面向4294967296的第3个根,即大约1625.即。 网格大小约为1625x1625x1625个插槽(也可以说是“单元”)。

正如你在这里看到的那样,1625并不多,其含义是这样的:如果你碰巧使用32位浮点数来维持一个空间用于XYZ位置(也许是一个太空游戏?你没有提到),那么你解决了这个空间使用96位 - 甚至更糟糕的是,如果使用双精度寻址,则使用192位 - 而在仅32位空间中生成随机数。 这意味着在数值空间之间的映射中将存在重复或粗糙(“坏粒度”)。 很难准确预测你将如何体验这一点。 但是,您只有1625个可能的x位置。

(尽管如此,可以将随机数从1维空间改为3维。实际上很简单。生成数字,抓住它的布尔表示(二进制,比特)。然后简单地取前11位和从那些构造一个整数;将它用于position.x。然后对接下来的11位做同样的事情并用于position.y.z位置只得到10位......嗯 - 哦,好吧:-)。)

使用种子与此无关。 种子使随机生成可重复,并且Kahlers描述仍然完全可能。

现在来看潜在的问题:

  • 如果你将这些东西“隔离”为blob(使用内部3D-postion寻址,从中继承种子),那么就会担心你的随机生成会从blob 重复到blob。 所有斑点都会得到相同的外观。

  • 另一方面,如果你为种子使用全局的巨大坐标寻址,那么你可能会在各个blob中的随机数中得到差的粒度(例如,沿着一个方向只有1625个可能的位置,种类)。

很难说,但你最终可能会得到视觉上不满意的结果。 我建议不要在时间生成一个随机数,而是3,每个方向一个。 您仍然可以确定它是否是命中(您的“阈值”) - 但只是使用单个随机数的三元组处理检查并使用您的世界(全球)定位系统为每个单独的种子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM