1319 lines
44 KiB
Python
1319 lines
44 KiB
Python
"""
|
||
噪声生成器
|
||
负责生成各种类型的程序化噪声
|
||
"""
|
||
|
||
import numpy as np
|
||
import math
|
||
from typing import Dict, Any
|
||
|
||
class NoiseGenerator:
|
||
"""
|
||
噪声生成器
|
||
负责生成各种类型的程序化噪声,包括Perlin噪声、Simplex噪声、分形噪声等
|
||
"""
|
||
|
||
def __init__(self, plugin):
|
||
"""
|
||
初始化噪声生成器
|
||
|
||
Args:
|
||
plugin: 程序化地形生成插件实例
|
||
"""
|
||
self.plugin = plugin
|
||
self.enabled = False
|
||
self.initialized = False
|
||
|
||
# 噪声配置
|
||
self.seed = plugin.config.get('seed', 12345)
|
||
|
||
# 噪声类型参数
|
||
self.noise_types = {
|
||
'perlin': {'enabled': True, 'weight': 1.0},
|
||
'simplex': {'enabled': True, 'weight': 1.0},
|
||
'value': {'enabled': True, 'weight': 0.5},
|
||
'worley': {'enabled': True, 'weight': 0.3},
|
||
'white': {'enabled': True, 'weight': 0.2}
|
||
}
|
||
|
||
# 分形噪声参数
|
||
self.fractal_params = {
|
||
'octaves': 6,
|
||
'persistence': 0.5,
|
||
'lacunarity': 2.0,
|
||
'scale': 1.0
|
||
}
|
||
|
||
# 随机数生成器
|
||
self.random_generator = None
|
||
|
||
# 预计算的梯度向量表
|
||
self.gradient_table = []
|
||
|
||
# 统计信息
|
||
self.stats = {
|
||
'noise_generated': 0,
|
||
'total_generation_time': 0.0,
|
||
'average_generation_time': 0.0
|
||
}
|
||
|
||
print("✓ 噪声生成器已创建")
|
||
|
||
def initialize(self) -> bool:
|
||
"""
|
||
初始化噪声生成器
|
||
|
||
Returns:
|
||
是否初始化成功
|
||
"""
|
||
try:
|
||
# 初始化随机数生成器
|
||
self.random_generator = np.random.RandomState(self.seed)
|
||
|
||
# 初始化梯度表
|
||
self._initialize_gradient_table()
|
||
|
||
self.initialized = True
|
||
print("✓ 噪声生成器初始化完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 噪声生成器初始化失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def enable(self) -> bool:
|
||
"""
|
||
启用噪声生成器
|
||
|
||
Returns:
|
||
是否启用成功
|
||
"""
|
||
try:
|
||
if not self.initialized:
|
||
print("✗ 噪声生成器未初始化")
|
||
return False
|
||
|
||
self.enabled = True
|
||
print("✓ 噪声生成器已启用")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 噪声生成器启用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def disable(self):
|
||
"""禁用噪声生成器"""
|
||
try:
|
||
self.enabled = False
|
||
print("✓ 噪声生成器已禁用")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 噪声生成器禁用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def finalize(self):
|
||
"""清理噪声生成器资源"""
|
||
try:
|
||
self.disable()
|
||
self.initialized = False
|
||
print("✓ 噪声生成器资源已清理")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 噪声生成器资源清理失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def update(self, dt: float):
|
||
"""
|
||
更新噪声生成器状态
|
||
|
||
Args:
|
||
dt: 时间增量
|
||
"""
|
||
# 处理更新逻辑
|
||
pass
|
||
|
||
def _initialize_gradient_table(self):
|
||
"""初始化梯度向量表"""
|
||
try:
|
||
# 创建2D梯度向量表 (Perlin噪声使用)
|
||
self.gradient_table = []
|
||
for i in range(256):
|
||
# 生成随机角度
|
||
angle = self.random_generator.uniform(0, 2 * math.pi)
|
||
# 计算梯度向量
|
||
gradient = (math.cos(angle), math.sin(angle))
|
||
self.gradient_table.append(gradient)
|
||
|
||
# 复制表以避免边界检查
|
||
self.gradient_table = self.gradient_table + self.gradient_table
|
||
|
||
except Exception as e:
|
||
print(f"✗ 梯度表初始化失败: {e}")
|
||
# 创建默认梯度表
|
||
self.gradient_table = [(1, 0), (0, 1), (-1, 0), (0, -1)] * 64
|
||
|
||
def set_seed(self, seed: int):
|
||
"""
|
||
设置随机种子
|
||
|
||
Args:
|
||
seed: 随机种子
|
||
"""
|
||
self.seed = seed
|
||
if self.random_generator is not None:
|
||
self.random_generator.seed(seed)
|
||
# 重新初始化梯度表
|
||
self._initialize_gradient_table()
|
||
print(f"✓ 噪声生成器随机种子设置为: {seed}")
|
||
|
||
def generate_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成噪声值
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 生成Perlin噪声(默认)
|
||
noise_value = self._perlin_noise(x, y, local_seed)
|
||
|
||
# 更新统计信息
|
||
self.stats['noise_generated'] += 1
|
||
|
||
return noise_value
|
||
|
||
except Exception as e:
|
||
print(f"✗ 噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def _perlin_noise(self, x: float, y: float, seed: int) -> float:
|
||
"""
|
||
生成Perlin噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子
|
||
|
||
Returns:
|
||
Perlin噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
# 确保使用正确的种子
|
||
if seed != self.seed and self.random_generator is not None:
|
||
self.random_generator.seed(seed)
|
||
|
||
# 找到包含点的单元格
|
||
x0 = int(math.floor(x)) & 255
|
||
y0 = int(math.floor(y)) & 255
|
||
x1 = (x0 + 1) & 255
|
||
y1 = (y0 + 1) & 255
|
||
|
||
# 计算单元格内的坐标
|
||
xf = x - math.floor(x)
|
||
yf = y - math.floor(y)
|
||
|
||
# 计算平滑系数
|
||
u = self._fade(xf)
|
||
v = self._fade(yf)
|
||
|
||
# 计算梯度点积
|
||
n00 = self._gradient(self.gradient_table[x0 + self.gradient_table[y0][0]], xf, yf)
|
||
n01 = self._gradient(self.gradient_table[x0 + self.gradient_table[y1][0]], xf, yf - 1)
|
||
n10 = self._gradient(self.gradient_table[x1 + self.gradient_table[y0][0]], xf - 1, yf)
|
||
n11 = self._gradient(self.gradient_table[x1 + self.gradient_table[y1][0]], xf - 1, yf - 1)
|
||
|
||
# 双线性插值
|
||
x1_result = self._lerp(n00, n10, u)
|
||
x2_result = self._lerp(n01, n11, u)
|
||
result = self._lerp(x1_result, x2_result, v)
|
||
|
||
return result
|
||
|
||
except Exception as e:
|
||
# 出错时返回简单噪声
|
||
return self._simple_noise(x, y, seed)
|
||
|
||
def _fade(self, t: float) -> float:
|
||
"""
|
||
Fade函数 (6*t^5 - 15*t^4 + 10*t^3)
|
||
|
||
Args:
|
||
t: 输入值
|
||
|
||
Returns:
|
||
平滑后的值
|
||
"""
|
||
return t * t * t * (t * (t * 6 - 15) + 10)
|
||
|
||
def _lerp(self, a: float, b: float, t: float) -> float:
|
||
"""
|
||
线性插值
|
||
|
||
Args:
|
||
a: 起始值
|
||
b: 结束值
|
||
t: 插值参数 (0-1)
|
||
|
||
Returns:
|
||
插值结果
|
||
"""
|
||
return a + t * (b - a)
|
||
|
||
def _gradient(self, hash_val: tuple, x: float, y: float) -> float:
|
||
"""
|
||
计算梯度点积
|
||
|
||
Args:
|
||
hash_val: 梯度向量
|
||
x: X偏移
|
||
y: Y偏移
|
||
|
||
Returns:
|
||
点积结果
|
||
"""
|
||
return hash_val[0] * x + hash_val[1] * y
|
||
|
||
def _simple_noise(self, x: float, y: float, seed: int) -> float:
|
||
"""
|
||
简单噪声生成(备用方案)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子
|
||
|
||
Returns:
|
||
噪声值
|
||
"""
|
||
# 使用正弦波生成伪随机噪声
|
||
value = math.sin(x * 12.9898 + y * 78.233 + seed) * 43758.5453
|
||
return (value - math.floor(value)) * 2.0 - 1.0
|
||
|
||
def generate_simplex_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成Simplex噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
Simplex噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# Simplex噪声实现
|
||
# 这里使用简化版本
|
||
value = self._simple_noise(x, y, local_seed)
|
||
return value
|
||
|
||
except Exception as e:
|
||
print(f"✗ Simplex噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_value_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成值噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
值噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 值噪声实现
|
||
# 获取整数坐标
|
||
x_int = int(math.floor(x))
|
||
y_int = int(math.floor(y))
|
||
|
||
# 获取小数部分
|
||
x_frac = x - x_int
|
||
y_frac = y - y_int
|
||
|
||
# 生成四个角的随机值
|
||
corners = []
|
||
for dy in [0, 1]:
|
||
for dx in [0, 1]:
|
||
corner_seed = ((x_int + dx) * 374761393 + (y_int + dy) * 668265263 + local_seed) & 0x7fffffff
|
||
self.random_generator.seed(corner_seed)
|
||
corners.append(self.random_generator.uniform(-1.0, 1.0))
|
||
|
||
# 双线性插值
|
||
u = self._fade(x_frac)
|
||
v = self._fade(y_frac)
|
||
|
||
top = self._lerp(corners[0], corners[1], u)
|
||
bottom = self._lerp(corners[2], corners[3], u)
|
||
result = self._lerp(top, bottom, v)
|
||
|
||
return result
|
||
|
||
except Exception as e:
|
||
print(f"✗ 值噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_worley_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成Worley噪声(细胞噪声)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
Worley噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 找到点所在的网格单元格
|
||
cell_x = int(math.floor(x))
|
||
cell_y = int(math.floor(y))
|
||
|
||
# 初始化最小距离
|
||
min_distance = float('inf')
|
||
|
||
# 检查周围的9个单元格
|
||
for dy in [-1, 0, 1]:
|
||
for dx in [-1, 0, 1]:
|
||
# 计算相邻单元格坐标
|
||
nx = cell_x + dx
|
||
ny = cell_y + dy
|
||
|
||
# 生成单元格中的特征点
|
||
feature_seed = (nx * 374761393 + ny * 668265263 + local_seed) & 0x7fffffff
|
||
self.random_generator.seed(feature_seed)
|
||
fx = nx + self.random_generator.uniform(0.0, 1.0)
|
||
fy = ny + self.random_generator.uniform(0.0, 1.0)
|
||
|
||
# 计算到特征点的距离
|
||
distance = math.sqrt((x - fx)**2 + (y - fy)**2)
|
||
min_distance = min(min_distance, distance)
|
||
|
||
# 将距离转换为噪声值 (通常限制在0-1范围内)
|
||
return min(1.0, min_distance)
|
||
|
||
except Exception as e:
|
||
print(f"✗ Worley噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_white_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成白噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
白噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 生成伪随机值
|
||
noise_seed = (int(x * 1000) * 374761393 + int(y * 1000) * 668265263 + local_seed) & 0x7fffffff
|
||
self.random_generator.seed(noise_seed)
|
||
return self.random_generator.uniform(-1.0, 1.0)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 白噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_fractal_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成分形噪声(fBm - 分数布朗运动)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
分形噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成分形噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
max_value = 0.0 # 用于归一化
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声
|
||
noise_value = self.generate_noise(x * frequency, y * frequency, local_seed + i)
|
||
total += noise_value * amplitude
|
||
|
||
# 更新最大值
|
||
max_value += amplitude
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence
|
||
|
||
# 归一化结果
|
||
if max_value > 0:
|
||
return total / max_value
|
||
else:
|
||
return total
|
||
|
||
except Exception as e:
|
||
print(f"✗ 分形噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_rigid_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成刚性噪声(用于生成山脉等地质特征)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
刚性噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成刚性噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声并转换为刚性形式
|
||
noise_value = abs(self.generate_noise(x * frequency, y * frequency, local_seed + i))
|
||
total += (1.0 - noise_value) * amplitude
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence
|
||
|
||
return min(1.0, total)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 刚性噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_turbulence_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成湍流噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
湍流噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成湍流噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声并取绝对值
|
||
noise_value = abs(self.generate_noise(x * frequency, y * frequency, local_seed + i))
|
||
total += noise_value * amplitude
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence
|
||
|
||
return min(1.0, total)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 湍流噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_combined_noise(self, x: float, y: float, seed: int = None) -> float:
|
||
"""
|
||
生成组合噪声(混合多种噪声类型)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
组合噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
total = 0.0
|
||
total_weight = 0.0
|
||
|
||
# 生成Perlin噪声
|
||
if self.noise_types['perlin']['enabled']:
|
||
weight = self.noise_types['perlin']['weight']
|
||
noise_value = self.generate_noise(x, y, local_seed)
|
||
total += noise_value * weight
|
||
total_weight += weight
|
||
|
||
# 生成Simplex噪声
|
||
if self.noise_types['simplex']['enabled']:
|
||
weight = self.noise_types['simplex']['weight']
|
||
noise_value = self.generate_simplex_noise(x, y, local_seed + 1000)
|
||
total += noise_value * weight
|
||
total_weight += weight
|
||
|
||
# 生成值噪声
|
||
if self.noise_types['value']['enabled']:
|
||
weight = self.noise_types['value']['weight']
|
||
noise_value = self.generate_value_noise(x, y, local_seed + 2000)
|
||
total += noise_value * weight
|
||
total_weight += weight
|
||
|
||
# 生成Worley噪声
|
||
if self.noise_types['worley']['enabled']:
|
||
weight = self.noise_types['worley']['weight']
|
||
noise_value = self.generate_worley_noise(x, y, local_seed + 3000)
|
||
# Worley噪声范围是0-1,需要转换为-1到1
|
||
noise_value = noise_value * 2.0 - 1.0
|
||
total += noise_value * weight
|
||
total_weight += weight
|
||
|
||
# 生成白噪声
|
||
if self.noise_types['white']['enabled']:
|
||
weight = self.noise_types['white']['weight']
|
||
noise_value = self.generate_white_noise(x, y, local_seed + 4000)
|
||
total += noise_value * weight
|
||
total_weight += weight
|
||
|
||
# 归一化结果
|
||
if total_weight > 0:
|
||
return total / total_weight
|
||
else:
|
||
return 0.0
|
||
|
||
except Exception as e:
|
||
print(f"✗ 组合噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def set_noise_type_enabled(self, noise_type: str, enabled: bool):
|
||
"""
|
||
设置噪声类型是否启用
|
||
|
||
Args:
|
||
noise_type: 噪声类型
|
||
enabled: 是否启用
|
||
"""
|
||
if noise_type in self.noise_types:
|
||
self.noise_types[noise_type]['enabled'] = enabled
|
||
print(f"✓ 噪声类型 '{noise_type}' 已{'启用' if enabled else '禁用'}")
|
||
else:
|
||
print(f"✗ 无效的噪声类型: {noise_type}")
|
||
|
||
def set_noise_type_weight(self, noise_type: str, weight: float):
|
||
"""
|
||
设置噪声类型权重
|
||
|
||
Args:
|
||
noise_type: 噪声类型
|
||
weight: 权重值
|
||
"""
|
||
if noise_type in self.noise_types:
|
||
self.noise_types[noise_type]['weight'] = max(0.0, weight)
|
||
print(f"✓ 噪声类型 '{noise_type}' 权重设置为: {weight}")
|
||
else:
|
||
print(f"✗ 无效的噪声类型: {noise_type}")
|
||
|
||
def set_fractal_parameters(self, octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None):
|
||
"""
|
||
设置分形噪声参数
|
||
|
||
Args:
|
||
octaves: 八度数
|
||
persistence: 持久性
|
||
lacunarity: 间隙性
|
||
scale: 缩放
|
||
"""
|
||
if octaves is not None:
|
||
self.fractal_params['octaves'] = max(1, octaves)
|
||
if persistence is not None:
|
||
self.fractal_params['persistence'] = max(0.0, min(1.0, persistence))
|
||
if lacunarity is not None:
|
||
self.fractal_params['lacunarity'] = max(1.0, lacunarity)
|
||
if scale is not None:
|
||
self.fractal_params['scale'] = max(0.01, scale)
|
||
|
||
print(f"✓ 分形噪声参数已更新: {self.fractal_params}")
|
||
|
||
def get_stats(self) -> Dict[str, Any]:
|
||
"""
|
||
获取统计信息
|
||
|
||
Returns:
|
||
统计信息字典
|
||
"""
|
||
# 更新平均生成时间
|
||
if self.stats['noise_generated'] > 0:
|
||
self.stats['average_generation_time'] = self.stats['total_generation_time'] / self.stats['noise_generated']
|
||
return self.stats.copy()
|
||
|
||
def reset_stats(self):
|
||
"""重置统计信息"""
|
||
self.stats = {
|
||
'noise_generated': 0,
|
||
'total_generation_time': 0.0,
|
||
'average_generation_time': 0.0
|
||
}
|
||
print("✓ 噪声生成器统计信息已重置")
|
||
|
||
def generate_anisotropic_noise(self, x: float, y: float, direction: float,
|
||
anisotropy: float, seed: int = None) -> float:
|
||
"""
|
||
生成各向异性噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
direction: 主要方向(弧度)
|
||
anisotropy: 各向异性程度(0-1)
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
各向异性噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 计算各向异性变换
|
||
cos_dir = math.cos(direction)
|
||
sin_dir = math.sin(direction)
|
||
|
||
# 应用各向异性变换
|
||
x_aniso = x * (cos_dir * cos_dir + sin_dir * sin_dir * (1 - anisotropy))
|
||
y_aniso = y * (sin_dir * sin_dir + cos_dir * cos_dir * (1 - anisotropy))
|
||
|
||
# 生成噪声
|
||
return self.generate_noise(x_aniso, y_aniso, local_seed)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 各向异性噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_billow_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成云朵状噪声(Billow噪声)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
Billow噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成Billow噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声并转换为Billow形式
|
||
noise_value = abs(self.generate_noise(x * frequency, y * frequency, local_seed + i)) * 2.0 - 1.0
|
||
noise_value = noise_value * noise_value # 平方以增强对比度
|
||
total += noise_value * amplitude
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence
|
||
|
||
# 转换到0-1范围
|
||
return min(1.0, max(0.0, total * 0.5 + 0.5))
|
||
|
||
except Exception as e:
|
||
print(f"✗ Billow噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_voronoi_noise(self, x: float, y: float, seed: int = None,
|
||
distance_metric: str = 'euclidean') -> float:
|
||
"""
|
||
生成Voronoi噪声(另一种细胞噪声)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
distance_metric: 距离度量方式 ('euclidean', 'manhattan', 'chebyshev')
|
||
|
||
Returns:
|
||
Voronoi噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 找到点所在的网格单元格
|
||
cell_x = int(math.floor(x))
|
||
cell_y = int(math.floor(y))
|
||
|
||
# 初始化最近和次近距离
|
||
closest_distance = float('inf')
|
||
second_closest_distance = float('inf')
|
||
|
||
# 检查周围的9个单元格
|
||
for dy in [-1, 0, 1]:
|
||
for dx in [-1, 0, 1]:
|
||
# 计算相邻单元格坐标
|
||
nx = cell_x + dx
|
||
ny = cell_y + dy
|
||
|
||
# 生成单元格中的特征点
|
||
feature_seed = (nx * 374761393 + ny * 668265263 + local_seed) & 0x7fffffff
|
||
self.random_generator.seed(feature_seed)
|
||
fx = nx + self.random_generator.uniform(0.0, 1.0)
|
||
fy = ny + self.random_generator.uniform(0.0, 1.0)
|
||
|
||
# 计算到特征点的距离
|
||
if distance_metric == 'euclidean':
|
||
distance = math.sqrt((x - fx)**2 + (y - fy)**2)
|
||
elif distance_metric == 'manhattan':
|
||
distance = abs(x - fx) + abs(y - fy)
|
||
elif distance_metric == 'chebyshev':
|
||
distance = max(abs(x - fx), abs(y - fy))
|
||
else:
|
||
distance = math.sqrt((x - fx)**2 + (y - fy)**2)
|
||
|
||
# 更新最近和次近距离
|
||
if distance < closest_distance:
|
||
second_closest_distance = closest_distance
|
||
closest_distance = distance
|
||
elif distance < second_closest_distance:
|
||
second_closest_distance = distance
|
||
|
||
# 返回次近和最近距离的差值
|
||
difference = second_closest_distance - closest_distance
|
||
return max(0.0, min(1.0, difference))
|
||
|
||
except Exception as e:
|
||
print(f"✗ Voronoi噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_cylindrical_noise(self, x: float, y: float, z: float, seed: int = None) -> float:
|
||
"""
|
||
生成圆柱形噪声(3D噪声投影到2D)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
z: Z坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
圆柱形噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 将2D坐标转换为圆柱坐标
|
||
angle = math.atan2(y, x)
|
||
radius = math.sqrt(x*x + y*y)
|
||
|
||
# 生成3D噪声
|
||
return self.generate_noise(angle, radius, local_seed + int(z * 1000))
|
||
|
||
except Exception as e:
|
||
print(f"✗ 圆柱形噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_spherical_noise(self, x: float, y: float, z: float, seed: int = None) -> float:
|
||
"""
|
||
生成球形噪声(3D噪声投影到2D)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
z: Z坐标
|
||
seed: 随机种子(可选)
|
||
|
||
Returns:
|
||
球形噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 将笛卡尔坐标转换为球坐标
|
||
radius = math.sqrt(x*x + y*y + z*z)
|
||
if radius == 0:
|
||
return 0.0
|
||
|
||
theta = math.acos(z / radius) # 极角
|
||
phi = math.atan2(y, x) # 方位角
|
||
|
||
# 生成噪声
|
||
return self.generate_noise(theta, phi, local_seed + int(radius * 1000))
|
||
|
||
except Exception as e:
|
||
print(f"✗ 球形噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_domain_warping_noise(self, x: float, y: float, seed: int = None,
|
||
warp_strength: float = 1.0) -> float:
|
||
"""
|
||
生成域变形噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
warp_strength: 变形强度
|
||
|
||
Returns:
|
||
域变形噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 生成变形向量
|
||
warp_x = self.generate_noise(x, y, local_seed + 10000) * warp_strength
|
||
warp_y = self.generate_noise(x, y, local_seed + 20000) * warp_strength
|
||
|
||
# 应用变形并生成噪声
|
||
return self.generate_noise(x + warp_x, y + warp_y, local_seed)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 域变形噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_swiss_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成Swiss噪声(用于生成山脉等地质特征)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
Swiss噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成Swiss噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声
|
||
noise_value = self.generate_noise(x * frequency, y * frequency, local_seed + i)
|
||
# Swiss噪声使用噪声值的绝对值并反转
|
||
swiss_value = 1.0 - abs(noise_value)
|
||
total += swiss_value * amplitude
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence * swiss_value # Swiss噪声的关键:振幅根据值调整
|
||
|
||
return min(1.0, max(0.0, total))
|
||
|
||
except Exception as e:
|
||
print(f"✗ Swiss噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_jordan_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None) -> float:
|
||
"""
|
||
生成Jordan噪声(用于生成更自然的地形)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
|
||
Returns:
|
||
Jordan噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成Jordan噪声
|
||
total = 0.0
|
||
frequency = scale
|
||
amplitude = 1.0
|
||
gain = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声
|
||
noise_value = self.generate_noise(x * frequency, y * frequency, local_seed + i)
|
||
total += noise_value * amplitude * gain
|
||
|
||
# Jordan噪声的关键:增益根据前一层的值调整
|
||
gain = 0.9 * (1.0 - abs(noise_value))
|
||
|
||
# 更新频率和振幅
|
||
frequency *= lacunarity
|
||
amplitude *= persistence
|
||
|
||
return max(-1.0, min(1.0, total))
|
||
|
||
except Exception as e:
|
||
print(f"✗ Jordan噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_ridged_multifractal_noise(self, x: float, y: float, seed: int = None,
|
||
octaves: int = None, persistence: float = None,
|
||
lacunarity: float = None, scale: float = None,
|
||
offset: float = 1.0, gain: float = 2.0) -> float:
|
||
"""
|
||
生成脊状多分形噪声
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
octaves: 八度数(可选)
|
||
persistence: 持久性(可选)
|
||
lacunarity: 间隙性(可选)
|
||
scale: 缩放(可选)
|
||
offset: 偏移值
|
||
gain: 增益值
|
||
|
||
Returns:
|
||
脊状多分形噪声值 (0.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定参数或默认参数
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
if octaves is None:
|
||
octaves = self.fractal_params['octaves']
|
||
if persistence is None:
|
||
persistence = self.fractal_params['persistence']
|
||
if lacunarity is None:
|
||
lacunarity = self.fractal_params['lacunarity']
|
||
if scale is None:
|
||
scale = self.fractal_params['scale']
|
||
|
||
# 生成脊状多分形噪声
|
||
result = 0.0
|
||
frequency = scale
|
||
weight = 1.0
|
||
|
||
for i in range(octaves):
|
||
# 生成当前层噪声
|
||
noise_value = self.generate_noise(x * frequency, y * frequency, local_seed + i)
|
||
# 转换为脊状
|
||
noise_value = offset - abs(noise_value)
|
||
noise_value *= noise_value # 平方以增强脊状效果
|
||
|
||
# 应用权重
|
||
result += noise_value * weight
|
||
|
||
# 更新权重
|
||
weight = noise_value * gain
|
||
weight = max(0.0, min(1.0, weight))
|
||
|
||
# 更新频率
|
||
frequency *= lacunarity
|
||
|
||
return min(1.0, max(0.0, result))
|
||
|
||
except Exception as e:
|
||
print(f"✗ 脊状多分形噪声生成失败: {e}")
|
||
return 0.0
|
||
|
||
def generate_gabor_noise(self, x: float, y: float, seed: int = None,
|
||
frequency: float = 1.0, bandwidth: float = 1.0,
|
||
impulse_variance: float = 1.0) -> float:
|
||
"""
|
||
生成Gabor噪声(滤波型噪声)
|
||
|
||
Args:
|
||
x: X坐标
|
||
y: Y坐标
|
||
seed: 随机种子(可选)
|
||
frequency: 频率
|
||
bandwidth: 带宽
|
||
impulse_variance: 脉冲方差
|
||
|
||
Returns:
|
||
Gabor噪声值 (-1.0 到 1.0)
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return 0.0
|
||
|
||
# 使用指定种子或默认种子
|
||
if seed is not None:
|
||
local_seed = seed
|
||
else:
|
||
local_seed = self.seed
|
||
|
||
# 简化的Gabor噪声实现
|
||
# 实际实现会更复杂,这里提供一个近似版本
|
||
|
||
# 生成随机相位和方向
|
||
phase_seed = int(x * 1000 + y * 1000 + local_seed) & 0x7fffffff
|
||
self.random_generator.seed(phase_seed)
|
||
phase = self.random_generator.uniform(0, 2 * math.pi)
|
||
orientation = self.random_generator.uniform(0, 2 * math.pi)
|
||
|
||
# 计算方向向量
|
||
cos_orient = math.cos(orientation)
|
||
sin_orient = math.sin(orientation)
|
||
|
||
# 投影到方向向量上
|
||
projected_x = x * cos_orient + y * sin_orient
|
||
projected_y = -x * sin_orient + y * cos_orient
|
||
|
||
# 生成Gabor函数响应
|
||
envelope = math.exp(-(projected_x**2 + projected_y**2) / (2 * impulse_variance))
|
||
wave = math.cos(2 * math.pi * frequency * projected_x + phase)
|
||
|
||
return envelope * wave
|
||
|
||
except Exception as e:
|
||
print(f"✗ Gabor噪声生成失败: {e}")
|
||
return 0.0 |