【问题标题】:Animate an UV sphere with (4D?) noise使用(4D?)噪声为 UV 球体设置动画
【发布时间】:2016-03-10 05:16:14
【问题描述】:

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

libnoise 中有一个function,它接收球面中顶点的坐标(纬度和经度)并返回一个随机值(从-1 到1)。

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

我所拥有的一个例子:

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

但问题是,libnoise 仅适用于 3D 噪声。 “行星”函数将纬度和经度映射到立方体的 XYZ 坐标。

而且我相信,要像我想要的那样为球体设置动画,我需要一个额外的坐标,作为“时间”维度。我对吗?或者是否可以使用 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);

}

【问题讨论】:

  • 澄清一下:您只需要随时间变化的高度图,还是需要仅用高度图无法描述的带有拱门、洞穴等的地形?
  • 此时,只是随时间变化的高度图。只要 x/y 映射到 lat/long。

标签: c# perlin-noise procedural-generation


【解决方案1】:

一个n维噪声函数有n个独立的输入(i0, i1, ..., in-1, i n) & 返回值 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
  }
}

注意:这假设您没有替换/修改原始顶点值。您可以保存它们的副本(使用更少的计算,但更多的内存)或根据与 c 的距离重新计算它们(使用更少的内存,但更多的计算)。此外,您可以通过计算 2 个(或更多)更大的时间步长并通过插值获得中间帧来获得更平滑的动画。

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

【讨论】:

  • 然后我想我不能用 libnoise 做到这一点,我用 libnoise 用来将纬度/经度映射到 XYZ 的代码编辑了我的问题。我可以从中理解的是,它们直接从“立方体”中获取值,因此边界可以无缝连接。第三个“时间”参数适合该函数的哪个位置?
  • 大概,时间会结束,这样动画就会以无缝的方式循环。
【解决方案2】:

好吧,我想我做到了。

我刚刚将时间参数添加到映射的 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);

}

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

【讨论】:

    【解决方案3】:

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

    对我有用的是使用多个 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)有一个内置于ofSignedNoise(glm::vec4)的4d perlin噪声函数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多