EG/plugins/user/procedural_terrain_generation/noise/noise_generator.py
2025-12-12 16:16:15 +08:00

1319 lines
45 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
噪声生成器
负责生成各种类型的程序化噪声
"""
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