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

huangapple go评论95阅读模式
英文:

Perlin Noise in Python: Noise Values Compacted, Need Help Forming Sinusoidal Pattern

问题

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

然而,我在生成的噪声值方面遇到了问题。噪声值似乎没有形成平滑的正弦波状模式,而是被压缩在一起,缺乏期望的变化。因此,最终的噪声表示没有显示我所期望的地形特征。

这是我block_perlin_noise方法的代码片段:

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

# ...其他代码

# 定义表示区块的类
class Chunk:
    def __init__(self, geometry: List[int] = (16, 16, 16), position: List[int] = (0, 0, 0),
                 rotation: List[int] = (0, 0, 0)):
        # 验证输入参数
        if not isinstance(geometry, tuple) or len(geometry) != 3 or all(value == 0 for value in geometry):
            raise TypeError("geometry必须是一个长度为3且非零值的元组。")
        if not all(isinstance(value, int) for value in position) and all(isinstance(value, int) for value in rotation):
            raise TypeError("position必须是一个包含浮点数的元组。")
        # 初始化实例变量
        self.geometry = geometry
        self.position = position
        self.rotation = rotation

    # 为区块中不同类型的方块生成Perlin噪声的方法
    def block_perlin_noise(self) -> np.ndarray:
        chunk_width, chunk_height, chunk_depth = self.geometry

        # 为区块中不同类型的方块生成噪声值,并将它们存储在单独的3D数组中
        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)
        # 初始化区块噪声数组
        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):
                    # 为洞穴生成Perlin噪声
                    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
                    ))

                    # 为陆地方块生成Perlin噪声
                    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
                    ))

                    # 为山丘生成Perlin噪声
                    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
                    ))

                    # 为山脉生成Perlin噪声
                    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
                    ))

                    # 结合不同的噪声类型得到最终的区块噪声
                    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
    # ...我之前代码的继续部分

    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]
            # 根据噪声值调整点的大小
            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噪声生成参数或我的方法,以实现地形表示中更平滑、类似正弦波的模式?

英文:

I'm currently working on a project involving Perlin noise generation in Python. I've implemented the Perlin noise generation using the noise library and generated different types of noise values (cave, land, hill, mountain) within a chunk using a combination of these noise types.

However, I'm facing an issue with the generated noise values. Instead of the noise values forming a smooth, sinusoidal pattern, they seem to be compacted and lacking the desired variation. As a result, the final noise representation doesn't display the expected terrain features I'm aiming for.

Here's a snippet of my code for the block_perlin_noise method:

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()

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

I'm aiming for a Minecraft chunk terrain-like representation with gradual variations similar to a sin wave, but the noise values are not providing that smoothness and appear to be compressed into one place.

Could anyone help me understand why my noise values are compacted and not forming the expected pattern? Are there any adjustments I can make to the Perlin noise generation parameters or my approach to achieve a smoother, sinusoidal-like pattern in my terrain representation?

答案1

得分: 1

我确保这段代码封装了使用Matplotlib在3D图中渲染块噪声的过程。当你在Chunk类的实例上调用render()方法时,它会生成噪声,创建图表,并使用Matplotlib显示出来。

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

        # 生成块噪声
        chunk_noise = self.get_block_mapping_grid()

        # 为3D图创建网格
        chunk_width, chunk_height, chunk_depth = self.geometry
        X, Y = np.meshgrid(np.arange(chunk_width), np.arange(chunk_height))

        # 创建一个3D图形
        fig = plt.figure()

        ax = fig.add_subplot(111, projection='3d')  # 使用Axes3D
        # 将块噪声作为表面绘制
        ax.plot_surface(X, Y, chunk_noise[:, :, 0, 0], cmap='terrain')

        # 设置标签和标题
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('噪声值')
        ax.set_title('块噪声')
        plt.show()
英文:

I made sure, this code segment encapsulates the rendering process of the chunk noise in a 3D plot using Matplotlib. When you call the render() method on an instance of the Chunk class, it will generate the noise, create the plot, and display it using 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()

huangapple
  • 本文由 发表于 2023年8月8日 23:42:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76861159.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定