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

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

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

问题

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

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

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

  1. import numpy as np
  2. import noise
  3. from typing import List, Dict
  4. # ...其他代码
  5. # 定义表示区块的类
  6. class Chunk:
  7. def __init__(self, geometry: List[int] = (16, 16, 16), position: List[int] = (0, 0, 0),
  8. rotation: List[int] = (0, 0, 0)):
  9. # 验证输入参数
  10. if not isinstance(geometry, tuple) or len(geometry) != 3 or all(value == 0 for value in geometry):
  11. raise TypeError("geometry必须是一个长度为3且非零值的元组。")
  12. if not all(isinstance(value, int) for value in position) and all(isinstance(value, int) for value in rotation):
  13. raise TypeError("position必须是一个包含浮点数的元组。")
  14. # 初始化实例变量
  15. self.geometry = geometry
  16. self.position = position
  17. self.rotation = rotation
  18. # 为区块中不同类型的方块生成Perlin噪声的方法
  19. def block_perlin_noise(self) -> np.ndarray:
  20. chunk_width, chunk_height, chunk_depth = self.geometry
  21. # 为区块中不同类型的方块生成噪声值,并将它们存储在单独的3D数组中
  22. cave_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  23. land_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  24. hill_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  25. mountain_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  26. # 初始化区块噪声数组
  27. chunk_noise = np.zeros((chunk_width, chunk_height, chunk_depth, 3), dtype=int)
  28. for x in range(chunk_width):
  29. for y in range(chunk_height):
  30. for z in range(chunk_depth):
  31. # 为洞穴生成Perlin噪声
  32. cave_noise[x, y, z] = int(noise.pnoise3(
  33. (x + self.position[0]) / chunk_width,
  34. (y + self.position[1]) / chunk_height,
  35. (z + self.position[2]) / chunk_depth,
  36. octaves=2,
  37. persistence=0.8,
  38. lacunarity=1.2,
  39. repeatx=chunk_width,
  40. repeaty=chunk_height,
  41. repeatz=chunk_depth,
  42. base=1
  43. ))
  44. # 为陆地方块生成Perlin噪声
  45. land_noise[x, y, z] = int(noise.pnoise3(
  46. (x + self.position[0]) / chunk_width,
  47. (y + self.position[1]) / chunk_height,
  48. (z + self.position[2]) / chunk_depth,
  49. octaves=4,
  50. persistence=0.5,
  51. lacunarity=1.0,
  52. repeatx=chunk_width,
  53. repeaty=chunk_height,
  54. repeatz=chunk_depth,
  55. base=0
  56. ))
  57. # 为山丘生成Perlin噪声
  58. hill_noise[x, y, z] = int(noise.pnoise3(
  59. (x + self.position[0]) / chunk_width,
  60. (y + self.position[1]) / chunk_height,
  61. (z + self.position[2]) / chunk_depth,
  62. octaves=6,
  63. persistence=0.5,
  64. lacunarity=1.5,
  65. repeatx=chunk_width,
  66. repeaty=chunk_height,
  67. repeatz=chunk_depth,
  68. base=1
  69. ))
  70. # 为山脉生成Perlin噪声
  71. mountain_noise[x, y, z] = int(noise.pnoise3(
  72. (x + self.position[0]) / chunk_width,
  73. (y + self.position[1]) / chunk_height,
  74. (z + self.position[2]) / chunk_depth,
  75. octaves=8,
  76. persistence=0.5,
  77. lacunarity=2.0,
  78. repeatx=chunk_width,
  79. repeaty=chunk_height,
  80. repeatz=chunk_depth,
  81. base=1
  82. ))
  83. # 结合不同的噪声类型得到最终的区块噪声
  84. chunk_noise[x, y, z] = np.sum([
  85. cave_noise[x, y, z],
  86. land_noise[x, y, z],
  87. hill_noise[x, y, z],
  88. mountain_noise[x, y, z]
  89. ])
  90. return chunk_noise
  1. # ...我之前代码的继续部分
  2. def render(self):
  3. figure = plt.figure()
  4. axes = figure.add_subplot(111, projection='3d')
  5. chunk_noise = self.block_perlin_noise()
  6. for x, y, z in np.ndindex(*self.geometry):
  7. block_x_value, block_y_value, block_z_value = chunk_noise[x, y, z]
  8. # 根据噪声值调整点的大小
  9. axes.scatter(x + self.position[0], y + self.position[1], z + self.position[2], marker='o', s=5)
  10. axes.set_xlabel('X')
  11. axes.set_ylabel('Y')
  12. axes.set_zlabel('Z')
  13. 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:

  1. import numpy as np
  2. import noise
  3. from typing import List, Dict
  4. # ... unsolicited code
  5. # Define a class to represent a Chunk
  6. class Chunk:
  7. def __init__(self, geometry: List[int] = (16, 16, 16), position: List[int] = (0, 0, 0),
  8. rotation: List[int] = (0, 0, 0)):
  9. # Validate the input parameters
  10. if not isinstance(geometry, tuple) or len(geometry) != 3 or all(value == 0 for value in geometry):
  11. raise TypeError("geometry must be a tuple of length 3 with non-zero values.")
  12. if not all(isinstance(value, int) for value in position) and all(isinstance(value, int) for value in rotation):
  13. raise TypeError("position must be a tuple of floats.")
  14. # Initialize instance variables
  15. self.geometry = geometry
  16. self.position = position
  17. self.rotation = rotation
  18. # Method to generate Perlin noise for different types of blocks in the chunk
  19. def block_perlin_noise(self) -> np.ndarray:
  20. chunk_width, chunk_height, chunk_depth = self.geometry
  21. # Generate noise values for different types of blocks in the chunk
  22. # and store them in separate 3D arrays
  23. cave_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  24. land_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  25. hill_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  26. mountain_noise = np.zeros((chunk_width, chunk_height, chunk_depth), dtype=int)
  27. # Initialize the chunk noise array
  28. chunk_noise = np.zeros((chunk_width, chunk_height, chunk_depth, 3), dtype=int)
  29. for x in range(chunk_width):
  30. for y in range(chunk_height):
  31. for z in range(chunk_depth):
  32. # Generate Perlin noise for caves
  33. cave_noise[x, y, z] = int(noise.pnoise3(
  34. (x + self.position[0]) / chunk_width,
  35. (y + self.position[1]) / chunk_height,
  36. (z + self.position[2]) / chunk_depth,
  37. octaves=2,
  38. persistence=0.8,
  39. lacunarity=1.2,
  40. repeatx=chunk_width,
  41. repeaty=chunk_height,
  42. repeatz=chunk_depth,
  43. base=1
  44. ))
  45. # Generate Perlin noise for land blocks
  46. land_noise[x, y, z] = int(noise.pnoise3(
  47. (x + self.position[0]) / chunk_width,
  48. (y + self.position[1]) / chunk_height,
  49. (z + self.position[2]) / chunk_depth,
  50. octaves=4,
  51. persistence=0.5,
  52. lacunarity=1.0,
  53. repeatx=chunk_width,
  54. repeaty=chunk_height,
  55. repeatz=chunk_depth,
  56. base=0
  57. ))
  58. # Generate Perlin noise for hills
  59. hill_noise[x, y, z] = int(noise.pnoise3(
  60. (x + self.position[0]) / chunk_width,
  61. (y + self.position[1]) / chunk_height,
  62. (z + self.position[2]) / chunk_depth,
  63. octaves=6,
  64. persistence=0.5,
  65. lacunarity=1.5,
  66. repeatx=chunk_width,
  67. repeaty=chunk_height,
  68. repeatz=chunk_depth,
  69. base=1
  70. ))
  71. # Generate Perlin noise for mountains
  72. mountain_noise[x, y, z] = int(noise.pnoise3(
  73. (x + self.position[0]) / chunk_width,
  74. (y + self.position[1]) / chunk_height,
  75. (z + self.position[2]) / chunk_depth,
  76. octaves=8,
  77. persistence=0.5,
  78. lacunarity=2.0,
  79. repeatx=chunk_width,
  80. repeaty=chunk_height,
  81. repeatz=chunk_depth,
  82. base=1
  83. ))
  84. # Combine different noise types to get the final chunk noise
  85. chunk_noise[x, y, z] = np.sum([
  86. cave_noise[x, y, z],
  87. land_noise[x, y, z],
  88. hill_noise[x, y, z],
  89. mountain_noise[x, y, z]
  90. ])
  91. return chunk_noise
  1. # ... continuation of my previous code
  2. def render(self):
  3. figure = plt.figure()
  4. axes = figure.add_subplot(111, projection='3d')
  5. chunk_noise = self.block_perlin_noise()
  6. for x, y, z in np.ndindex(*self.geometry):
  7. block_x_value, block_y_value, block_z_value = chunk_noise[x, y, z]
  8. # You can adjust the size of the points based on the noise values
  9. axes.scatter(x + self.position[0], y + self.position[1], z + self.position[2], marker='o', s=5)
  10. axes.set_xlabel('X')
  11. axes.set_ylabel('Y')
  12. axes.set_zlabel('Z')
  13. 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显示出来。

  1. def render(self):
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. # 生成块噪声
  5. chunk_noise = self.get_block_mapping_grid()
  6. # 为3D图创建网格
  7. chunk_width, chunk_height, chunk_depth = self.geometry
  8. X, Y = np.meshgrid(np.arange(chunk_width), np.arange(chunk_height))
  9. # 创建一个3D图形
  10. fig = plt.figure()
  11. ax = fig.add_subplot(111, projection='3d') # 使用Axes3D
  12. # 将块噪声作为表面绘制
  13. ax.plot_surface(X, Y, chunk_noise[:, :, 0, 0], cmap='terrain')
  14. # 设置标签和标题
  15. ax.set_xlabel('X')
  16. ax.set_ylabel('Y')
  17. ax.set_zlabel('噪声值')
  18. ax.set_title('块噪声')
  19. 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.

  1. def render(self):
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. # Generate chunk noise
  5. chunk_noise = self.get_block_mapping_grid()
  6. # Create a meshgrid for the 3D plot
  7. chunk_width, chunk_height, chunk_depth = self.geometry
  8. X, Y = np.meshgrid(np.arange(chunk_width), np.arange(chunk_height))
  9. # Create a 3D figure
  10. fig = plt.figure()
  11. ax = fig.add_subplot(111, projection='3d') # Use Axes3D
  12. # Plot the chunk noise as a surface
  13. ax.plot_surface(X, Y, chunk_noise[:, :, 0, 0], cmap='terrain')
  14. # Set labels and title
  15. ax.set_xlabel('X')
  16. ax.set_ylabel('Y')
  17. ax.set_zlabel('Noise Value')
  18. ax.set_title('Chunk Noise')
  19. 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:

确定