numpy 在Python中使用Perlin噪声生成Minecraft地形

vcirk6k6  于 2023-10-19  发布在  Python
关注(0)|答案(1)|浏览(118)

我试图创建一个类似于Minecraft的地形生成系统(丘陵,山脉,草原,河流),其中地形呈现正弦曲线图案。我一直在探索柏林噪声作为实现这种效果的一种手段,但我正在努力产生预期的结果。有人能告诉我如何实现柏林噪声来生成具有这些特征的草地般蜿蜒的山丘和山谷的地形吗?

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import noise

# Parameters for terrain generation
width = 256
height = 256
depth = 256  # New parameter for the third dimension
scale = 0.05  # Adjust this for different terrain scales
octaves = 6
persistence = 0.5

# Initialize an empty 3D array to store terrain data
terrain = np.zeros((depth, height, width))

# Generate terrain using Perlin noise
for z in range(depth):
    for y in range(height):
        for x in range(width):
            value = noise.pnoise3(x * scale, y * scale, z * scale, octaves=octaves, persistence=persistence)
            terrain[z][y][x] = value

# Normalize terrain data to the range [0, 1]
terrain = (terrain - np.min(terrain)) / (np.max(terrain) - np.min(terrain))

# Create a 3D visualization of the terrain
x_coords, y_coords, z_coords = np.meshgrid(np.arange(width), np.arange(height), np.arange(depth))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_title('3D Minecraft-like Terrain with Grassland Sinusoidal Patterns')
terrain_plot = ax.scatter(x_coords, y_coords, z_coords, c=terrain, cmap='terrain', marker='.')
fig.colorbar(terrain_plot, label='Elevation')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

这里展示的是我的代码的当前状态的说明性表示。如所观察到的,柏林噪声值已经合并成立方结构,这是与非预期结果偏离的表现。

但我期待的是一个像正弦波一样的阵型。我该怎么办?

xxb16uws

xxb16uws1#

如果您希望获得每个点的高程,一个简单的方法是将其从3D问题更改为2D问题,并将每个点的值解释为高程。
范例:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import scipy.ndimage
import noise
plt.rcParams["figure.figsize"] = (20,20)

# Parameters for terrain generation
width = 256
height = 256
scale = 0.01  # Adjust this for different terrain scales
octaves = 6
persistence = 0.5

# Initialize an empty 3D array to store terrain data
terrain = np.zeros((height, width))

# Generate terrain using Perlin noise
for y in range(height):
    for x in range(width):
        value = noise.pnoise2(x * scale, y * scale, octaves=octaves, persistence=persistence)
        terrain[y][x] = value

# Create a 3D visualization of the terrain
x_coords, y_coords = np.meshgrid(np.arange(width), np.arange(height))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_title('3D Minecraft-like Terrain with Grassland Sinusoidal Patterns')
terrain_plot = ax.scatter(x_coords, y_coords, terrain, c=terrain, cmap='terrain', marker='.')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

绘图输出:

我试图复制你的例子,使它有点顺利。
如果你正在寻找一些平滑的东西,我建议使用a Gaussian filter来平滑噪音。
如果在for循环后插入以下代码:

filter_size = 3  # number of pixels per standard deviation for gaussian filter
terrain = scipy.ndimage.gaussian_filter(terrain, filter_size)

结果更平滑。这是过滤器大小为3时的样子:

较高的filter_size值会使其更平滑,较小的值会使其更粗糙。

相关问题