使用(4D?)噪声为 UV 球体制作动画

Animate an UV sphere with (4D?) noise

我正在使用 libnoise 的 C# 端口和 XNA(我知道它已经死了)来生成行星。

libnoise中有一个function接收球面顶点坐标(经纬度)和returns一个随机值(从-1到1)

因此,使用该值,我可以更改球体表面每个顶点的高度(高度),创建一些高度,模拟行星表面(我不是简单地在周围包裹纹理球体,我实际上是从头开始创建每个顶点)。

我所拥有的示例:

现在我想为球体设置动画,like this

但事实是,libnoise 仅适用于 3D 噪声。 "planet" 函数将纬度和经度映射到立方体的 XYZ 坐标。

而且我相信,要像我想要的那样为球体设置动画,我需要一个额外的坐标作为 "time" 维度。我对吗?或者是否可以使用 libnoise 提供的功能来做到这一点?

OBS:正如我提到的,我使用的是 UV 球体,而不是 icosphere 或球形立方体。

编辑:这是 libnoise 用来将 lat/long 映射到 XYZ 的算法:

public double GetValue(double latitude, double longitude) {           

    double x=0, y=0, z=0;

    double PI = 3.1415926535897932385;
    double DEG_TO_RAD = PI / 180.0;

    double r = System.Math.Cos(DEG_TO_RAD * lat);

    x = r * System.Math.Cos(DEG_TO_RAD * lon);
    y = System.Math.Sin(DEG_TO_RAD * lat);
    z = r * System.Math.Sin(DEG_TO_RAD * lon);

    return GetNoiseValueAt(x, y, z);

}

一个n维的噪声函数有n个独立的输入(i0, i1, ..., in-1, in) & returns 一个值v,因此3D噪声足以生成随时间变化的高度图。在您的情况下,输入是经度、纬度和时间,输出是高度偏移。

简单的通用算法是:

at each time step (t){
  for each vertex (v) on a sphere centered on some point (c){
    calculate the longitude & latitude
    get the scalar noise value (n) for the longitude, latitude & time
    calculate the new vertex position (p) as follows p = ((v-c)n)+c
  }
}

注意:这假设您不是 replacing/modifiying 原始顶点值。您可以保存它们的副本(使用更少的计算,但更多的内存)或根据与 c 的距离重新计算它们(使用更少的内存,但更多的计算)。此外,您可能会通过计算 2 个(或更多)较大的时间步长并进行插值以获得中间帧来获得更流畅的动画。

据我所知,此解决方案适用于 UV 球体、棱角球体或球形立方体。

好的,我想我做到了。

我刚刚将时间参数添加到映射的 XYZ 坐标中。

使用相同的纬度和经度但将时间增加 0.01d 给了我一个不错的结果。

这是我的代码:

public double GetValue(double latitude, double longitude, double time) {           

    double x=0, y=0, z=0;

    double PI = 3.1415926535897932385;
    double DEG_TO_RAD = PI / 180.0;

    double r = System.Math.Cos(DEG_TO_RAD * lat);

    x = r * System.Math.Cos(DEG_TO_RAD * lon);
    y = System.Math.Sin(DEG_TO_RAD * lat);
    z = r * System.Math.Sin(DEG_TO_RAD * lon);

    return GetNoiseValueAt(x + time, y + time, z + time);

}

如果有人有更好的解决方案请分享!

抱歉回答晚了,但我在网上其他地方找不到满意的答案,所以我写这篇文章是为了以后遇到这个问题的人。

对我有用的是使用多个 3d perlin 噪声源,并将它们组合成 1 个噪声源。将时间添加到 xyz 坐标只会产生非常明显的地形在 (-1,-1,-1) 方向上移动的效果。 平均超过 4 个不相关的噪声源确实会稍微改变噪声特性,因此您可能需要根据您的用例调整一些因素。 这个解决方案仍然不完美,但我没有看到任何视觉伪影。

代码是 C++ libnoise,但它应该同样可以很好地翻译成其他语言。

noise::module::Perlin perlin_noise[4];

float get_height(ofVec3f p, float time) {
    p*=2;
    time /= 10 ;
    return (perlin_noise[0].GetValue(p.x, p.y, p.z) +
            perlin_noise[1].GetValue(p.x, p.y, time) +
            perlin_noise[2].GetValue(p.x, time, p.z) +
            perlin_noise[3].GetValue(time, p.y, p.z))/2;
}

理想情况下,对于单个 3d 噪声源,您想将 x、y、z 坐标与 t 的单调函数相乘,以便它探索噪声源的不断扩展的球面,但我没有我还没有想出数学..

编辑:我使用的框架 (openframeworks) 内置了 4d perlin 噪声函数 ofSignedNoise(glm::vec4)