多次将 Perlin 噪声应用于平面/球体

Applying Perlin noise to plane multiple times/ sphere

我对 Perlin 噪声和一般 pv.sample_function 有一些疑问。

  1. 你会如何将 Perlin 噪声应用于球体?我想要一个有点变形的球体。
  2. 你能多次对一个网格 (sphere/plane) 应用 Perlin 噪声吗?我想要一架飞机,上面有一些粗糙的 'waves' 和高细节噪声(因此有大波浪和小波浪)。
  3. 频率中的第三个参数到底是做什么的?在尝试了一些值之后,我没有注意到它是如何影响噪音的。

这是我想应用于一个平面的两种不同的 frequencies/Perlin 噪声。此外,它显示了他们分别创建的平面。

def smooth_and_plot(sampled : pv.core.grid.UniformGrid):
    mesh = sampled.warp_by_scalar('scalars')
    mesh = mesh.extract_surface()

    # clean and smooth a little to reduce perlin noise artifacts
    mesh = mesh.smooth(n_iter=100, inplace=True, relaxation_factor=0.07)
    mesh.plot()


def gravel_plane():
    freq = [180, 180, 50]
    noise = pv.perlin_noise(0.2, freq, (0, 0, 0))
    sampled = pv.sample_function(noise,
                                 bounds=(-10, 2, -10, 10, -10, 10),
                                 dim=(500, 500, 1))

    smooth_and_plot(sampled)


def bumpy_plane():
    freq = [0.5, 0.7, 0]
    noise = pv.perlin_noise(0.5, freq, (-10, -10, -10))
    sampled = pv.sample_function(noise,
                                 bounds=(-10, 2, -10, 10, -10, 10),
                                 dim=(500, 500, 1))

    smooth_and_plot(sampled)

出于教学原因,让我以相反的顺序回答您的问题。

  1. What exactly does the third parameter in the frequency do? After playing around with some values I haven't noticed how it affected the noise.

您没有看到效果,因为您查看的是二维样本,并更改​​了沿第三轴的行为。这三个频率分别指定噪声沿 x、y 和 z 轴的粒度。换句话说,生成的隐函数是三个变量的标量函数。只是你的采样把维度降到了2。

当涉及到空间量时,频率可能是一个令人惊讶的量,但它的工作方式与时间相同。时间频率高表示振荡周期短,时间频率低表示振荡周期长。高空间频率意味着短波长,低空间频率意味着长波长。具体来说,波长和频率成反比。

因此,当您开始沿 z 轴切片时,您将看到第三个频率的效果:

import pyvista as pv

freq = [0.5, 0.5, 2]
noise = pv.perlin_noise(0.5, freq, (0, 0, 0))
noise_cube = pv.sample_function(noise,
                                bounds=(-10, 10, -10, 10, -10, 10),
                                dim=(200, 200, 200))
noise_cube.slice_orthogonal(-9, -9, -9).plot()

如你所见,xy平面中的斑点是圆形的,因为两个平面内频率相等。但是在两个垂直平面上,斑点都被拉长了:它们在 z 方向上更平坦。这是因为沿 z 轴的频率大四倍,导致波长小四倍。这将导致随机斑点具有大致 4:1 纵横比。

  1. Can you apply Perlin noise to a mesh (sphere/plane) multiple times? I would like to have a plane with some rough 'waves' and high detailed noise on top of them (thus having big waves with little waves in them).

您的代码片段中发生的所有事情是在预定义的矩形网格上对函数进行采样,并将结果值作为标量存储在网格上。如果你想叠加两个函数,你所要做的就是将两个这样的函数调用的标量相加。这会有些浪费,因为您要生成相同的网格两次(并丢弃其中一份副本),但从开发的角度来看,这是最不费力的解决方案:

def bumpy_gravel_plane():
    bounds = (-10, 2, -10, 10, -10, 10)
    dim = (500, 500, 1)

    freq = [180, 180, 50]
    noise = pv.perlin_noise(0.2, freq, (0, 0, 0))
    sampled_gravel = pv.sample_function(noise, bounds=bounds, dim=dim)

    freq = [0.5, 0.7, 0]
    noise = pv.perlin_noise(0.5, freq, (-10, -10, -10))
    sampled_bumps = pv.sample_function(noise, bounds=bounds, dim=dim)

    sampled = sampled_gravel
    sampled['scalars'] += sampled_bumps['scalars']

    smooth_and_plot(sampled)

  1. How would you go about applying Perlin noise to a sphere? I would like to have a little bit disformed sphere.

生成 2d 纹理并将其应用到球体的常用解决方案在这里不起作用,因为噪声不是周期性的,因此您不能像那样轻易关闭它。但仔细想想,生成的 Perlin 噪声是一个 3d 函数。您可以直接在您的球体上对这个 3d 函数进行采样!

有一个小问题:我认为仅使用 pyvista 无法做到这一点。我们必须稍微弄脏我们的手,我的意思是使用裸露的 vtk 方法(即噪音的 EvaluateFunction())。生成您的球体,然后在其点上查询您选择的噪声函数。如果您希望结果看起来对称,则必须沿所有三个笛卡尔轴设置相同的频率:

def bumpy_sphere(R=10):
    freq = [0.5, 0.5, 0.5]
    noise = pv.perlin_noise(0.5, freq, (0, 0, 0))
    sampled = pv.Sphere(radius=R, phi_resolution=100, theta_resolution=100)
    # query the noise at each point manually
    sampled['scalars'] = [noise.EvaluateFunction(point) for point in sampled.points]

    smooth_and_plot(sampled)