Python 中的 Perlin 噪声:噪声值压缩,需要帮助形成正弦模式

问题描述 投票:0回答:1

我目前正在研究一个涉及 Python 中 Perlin 噪声生成的项目。我使用噪声库实现了 Perlin 噪声生成,并使用这些噪声类型的组合在块内生成了不同类型的噪声值(洞穴、陆地、山丘、山脉)。

但是,我面临着生成的噪声值的问题。噪声值没有形成平滑的正弦模式,而是看起来很紧凑并且缺乏所需的变化。因此,最终的噪声表示没有显示我想要的预期地形特征。

这是我的

block_perlin_noise
方法的代码片段:

import numpy as np
import noise
from typing import List, Dict

# ... unsolicited code

# Define a class to represent a Chunk
class Chunk:
    def __init__(self, geometry: List[int] = (16, 16, 16), position: List[int] = (0, 0, 0),
                 rotation: List[int] = (0, 0, 0)):
        # Validate the input parameters
        if not isinstance(geometry, tuple) or len(geometry) != 3 or all(value == 0 for value in geometry):
            raise TypeError("geometry must be a tuple of length 3 with non-zero values.")
        if not all(isinstance(value, int) for value in position) and all(isinstance(value, int) for value in rotation):
            raise TypeError("position must be a tuple of floats.")
        # Initialize instance variables
        self.geometry = geometry
        self.position = position
        self.rotation = rotation

    # Method to generate Perlin noise for different types of blocks in the chunk
    def block_perlin_noise(self) -> np.ndarray:
        chunk_width, chunk_height, chunk_depth = self.geometry

        # Generate noise values for different types of blocks in the chunk
        # and store them in separate 3D arrays
        cave_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
        land_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
        hill_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
        mountain_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
        # Initialize the chunk noise array
        chunk_noise = np.zeros((chunk_width, chunk_height, chunk_depth, 3), dtype=int)

        for x in range(chunk_width):
            for y in range(chunk_height):
                for z in range(chunk_depth):
                    # Generate Perlin noise for caves
                    cave_noise[x, y, z] = int(noise.pnoise3(
                        (x + self.position[0]) / chunk_width,
                        (y + self.position[1]) / chunk_height,
                        (z + self.position[2]) / chunk_depth,
                        octaves=2,
                        persistence=0.8,
                        lacunarity=1.2,
                        repeatx=chunk_width,
                        repeaty=chunk_height,
                        repeatz=chunk_depth,
                        base=1
                    ))

                    # Generate Perlin noise for land blocks
                    land_noise[x, y, z] = int(noise.pnoise3(
                        (x + self.position[0]) / chunk_width,
                        (y + self.position[1]) / chunk_height,
                        (z + self.position[2]) / chunk_depth,
                        octaves=4,
                        persistence=0.5,
                        lacunarity=1.0,
                        repeatx=chunk_width,
                        repeaty=chunk_height,
                        repeatz=chunk_depth,
                        base=0
                    ))

                    # Generate Perlin noise for hills
                    hill_noise[x, y, z] = int(noise.pnoise3(
                        (x + self.position[0]) / chunk_width,
                        (y + self.position[1]) / chunk_height,
                        (z + self.position[2]) / chunk_depth,
                        octaves=6,
                        persistence=0.5,
                        lacunarity=1.5,
                        repeatx=chunk_width,
                        repeaty=chunk_height,
                        repeatz=chunk_depth,
                        base=1
                    ))

                    # Generate Perlin noise for mountains
                    mountain_noise[x, y, z] = int(noise.pnoise3(
                        (x + self.position[0]) / chunk_width,
                        (y + self.position[1]) / chunk_height,
                        (z + self.position[2]) / chunk_depth,
                        octaves=8,
                        persistence=0.5,
                        lacunarity=2.0,
                        repeatx=chunk_width,
                        repeaty=chunk_height,
                        repeatz=chunk_depth,
                        base=1
                    ))

                    # Combine different noise types to get the final chunk noise
                    chunk_noise[x, y, z] = np.sum([
                        cave_noise[x, y, z],
                        land_noise[x, y, z],
                        hill_noise[x, y, z],
                        mountain_noise[x, y, z]
                    ])

        return chunk_noise
    # ... continuation of my previous code

    def render(self):
        figure = plt.figure()
        axes = figure.add_subplot(111, projection='3d')

        chunk_noise = self.block_perlin_noise()
        for x, y, z in np.ndindex(*self.geometry):
            block_x_value, block_y_value, block_z_value = chunk_noise[x, y, z]
            # You can adjust the size of the points based on the noise values
            axes.scatter(x + self.position[0], y + self.position[1], z + self.position[2], marker='o', s=5)

        axes.set_xlabel('X')
        axes.set_ylabel('Y')
        axes.set_zlabel('Z')
        plt.show()

我的目标是一种类似于 Minecraft 块地形的表示,具有类似于正弦波的渐变,但噪声值无法提供那种平滑度,并且似乎被压缩到一个地方。

任何人都可以帮助我理解为什么我的噪声值被压缩并且没有形成预期的模式吗?我可以对 Perlin 噪声生成参数或我的方法进行任何调整,以在地形表示中实现更平滑、类似正弦的模式吗?

python matplotlib perlin-noise
1个回答
0
投票

我确定,此代码段使用 Matplotlib 封装了 3D 图中块噪声的渲染过程。当您在

render()
类的实例上调用
Chunk
方法时,它将生成噪声、创建绘图并使用 Matplotlib 显示它。

    def render(self):
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import Axes3D

        # Generate chunk noise
        chunk_noise = self.get_block_mapping_grid()

        # Create a meshgrid for the 3D plot
        chunk_width, chunk_height, chunk_depth = self.geometry
        X, Y = np.meshgrid(np.arange(chunk_width), np.arange(chunk_height))

        # Create a 3D figure
        fig = plt.figure()

        ax = fig.add_subplot(111, projection='3d')  # Use Axes3D
        # Plot the chunk noise as a surface
        ax.plot_surface(X, Y, chunk_noise[:, :, 0, 0], cmap='terrain')

        # Set labels and title
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Noise Value')
        ax.set_title('Chunk Noise')
        plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.