将柏林噪波多次应用于平面/球体

2024-06-02 06:52:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些关于柏林噪声和pv.sample_函数的问题

  1. 如何将柏林噪声应用于球体?我想要一个有点变形的球体
  2. 可以多次将柏林噪波应用于网格(球体/平面)吗?我想要一架飞机,上面有一些粗糙的“波浪”和高细节的噪音(因此有大浪,里面有小浪)
  3. 频率中的第三个参数具体做什么?在使用了一些值之后,我没有注意到它是如何影响噪声的

这是两种不同的频率/柏林噪声,我想应用于一个平面。此外,它还显示了它们各自创建的平面

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)

Tags: andsampleplotdef噪声平面频率smooth
1条回答
网友
1楼 · 发布于 2024-06-02 06:52:18

出于教学上的原因,让我以相反的顺序回答你们的问题

  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.

您没有看到效果,因为您正在查看2d样本,并沿第三个轴更改行为。这三个频率分别指定沿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()

Three orthogonal slices of Perlin noise, showing smaller wavelength along z

如您所见,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)

screenshot of grid with large-scale bumps and short-scale granular texture

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

通常生成2d纹理并将其应用于球体的解决方案在这里不起作用,因为噪波不是周期性的,因此您无法像那样轻松地将其关闭。但是如果你仔细想想,产生的柏林噪声是一个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)

Sphere with Perlin noisy surface warping and scalars

相关问题 更多 >