EG/plugins/user/vegetation_ecosystem/visualization/eco_visualizer.py
2025-12-12 16:16:15 +08:00

690 lines
23 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 time
from typing import Dict, Any, List, Optional
import math
import random
class EcoVisualizer:
"""
生态系统可视化器
负责提供植被和生态系统的可视化表示,包括渲染、着色和特效
"""
def __init__(self, plugin):
"""
初始化生态系统可视化器
Args:
plugin: 植被和生态系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 渲染配置
self.render_config = {
'render_distance': 100.0, # 渲染距离
'lod_levels': 5, # LOD级别数
'max_instances': 5000, # 最大实例数
'billboard_threshold': 50.0, # 公告牌阈值
'fade_distance': 80.0, # 淡出距离
'render_vegetation': True, # 渲染植被
'render_animals': True, # 渲染动物
'render_effects': True # 渲染特效
}
# 着色配置
self.shading_config = {
'use_dynamic_lighting': True, # 使用动态光照
'shadow_quality': 'medium', # 阴影质量
'wind_effect': 0.5, # 风效强度
'seasonal_tint': True, # 季节色调
'health_based_color': True, # 基于健康的颜色
'specular_intensity': 0.3 # 镜面反射强度
}
# 特效配置
self.effect_config = {
'particle_effects': True, # 粒子特效
'bloom_effect': True, # 泛光效果
'depth_of_field': False, # 景深效果
'motion_blur': False, # 运动模糊
'color_grading': 'natural', # 色彩分级
'fog_effect': True # 雾效
}
# LOD系统
self.lod_system = {
'levels': [
{'distance': 0, 'detail': 'high', 'polygon_count': 1000},
{'distance': 20, 'detail': 'medium', 'polygon_count': 500},
{'distance': 40, 'detail': 'low', 'polygon_count': 200},
{'distance': 60, 'detail': 'very_low', 'polygon_count': 50},
{'distance': 80, 'detail': 'billboard', 'polygon_count': 1}
],
'transition_smoothness': 0.5 # LOD过渡平滑度
}
# 颜色方案
self.color_schemes = {
'vegetation': {
'healthy': (0.2, 0.8, 0.2), # 健康绿色
'stressed': (0.8, 0.8, 0.2), # 压力黄色
'dying': (0.8, 0.2, 0.2), # 濒死红色
'dormant': (0.5, 0.5, 0.5) # 休眠灰色
},
'seasons': {
'spring': (1.0, 1.0, 0.8), # 春季色调
'summer': (1.0, 0.9, 0.7), # 夏季色调
'autumn': (1.0, 0.7, 0.5), # 秋季色调
'winter': (0.8, 0.8, 1.0) # 冬季色调
}
}
# 相机配置
self.camera_config = {
'position': (0, 0, 0),
'rotation': (0, 0, 0),
'fov': 60.0,
'near_clip': 0.1,
'far_clip': 1000.0
}
# 可视化统计
self.visualization_stats = {
'rendered_instances': 0,
'draw_calls': 0,
'render_time': 0.0,
'lod_transitions': 0,
'effects_applied': 0
}
# 缓存系统
self.render_cache = {}
self.cache_config = {
'max_cache_size': 100,
'cache_timeout': 300 # 5分钟
}
print("✓ 生态系统可视化器已创建")
def initialize(self) -> bool:
"""
初始化生态系统可视化器
Returns:
是否初始化成功
"""
try:
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.render_cache.clear()
self.initialized = False
print("✓ 生态系统可视化器资源已清理")
except Exception as e:
print(f"✗ 生态系统可视化器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新可视化器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 更新相机位置
self._update_camera(dt)
# 更新LOD系统
self._update_lod_system(dt)
# 更新特效
self._update_effects(dt)
# 清理缓存
self._cleanup_cache()
except Exception as e:
print(f"✗ 生态系统可视化器更新失败: {e}")
import traceback
traceback.print_exc()
def _update_camera(self, dt: float):
"""更新相机状态"""
try:
# 在实际实现中,这里会根据用户输入或脚本更新相机位置
pass
except Exception as e:
print(f"✗ 相机更新失败: {e}")
def _update_lod_system(self, dt: float):
"""更新LOD系统"""
try:
# 在实际实现中这里会根据相机距离更新LOD级别
pass
except Exception as e:
print(f"✗ LOD系统更新失败: {e}")
def _update_effects(self, dt: float):
"""更新特效系统"""
try:
# 在实际实现中,这里会更新各种视觉特效
pass
except Exception as e:
print(f"✗ 特效系统更新失败: {e}")
def _cleanup_cache(self):
"""清理渲染缓存"""
try:
current_time = time.time()
expired_keys = []
for key, (timestamp, _) in self.render_cache.items():
if current_time - timestamp > self.cache_config['cache_timeout']:
expired_keys.append(key)
for key in expired_keys:
del self.render_cache[key]
except Exception as e:
print(f"✗ 缓存清理失败: {e}")
def render_vegetation(self):
"""渲染植被"""
try:
if not self.enabled or not self.render_config['render_vegetation']:
return
if not self.plugin.vegetation_manager:
return
# 获取所有植被实例
instances = self.plugin.vegetation_manager.get_all_vegetation_instances()
rendered_count = 0
for instance_id, instance in instances.items():
if not instance['alive']:
continue
if rendered_count >= self.render_config['max_instances']:
break
# 计算LOD级别
lod_level = self._calculate_lod_level(instance['position'])
# 获取植被类型信息
veg_type = instance['type']
veg_info = self.plugin.vegetation_manager.get_vegetation_info(veg_type)
if not veg_info:
continue
# 计算颜色
color = self._calculate_vegetation_color(instance, veg_info)
# 应用季节色调
if self.shading_config['seasonal_tint'] and self.plugin.seasonal_effects:
seasonal_color = self.plugin.seasonal_effects.get_vegetation_change_factor('leaf_color')
if isinstance(seasonal_color, tuple) and len(seasonal_color) == 3:
color = tuple(color[i] * seasonal_color[i] for i in range(3))
# 应用风效
wind_effect = self.shading_config['wind_effect']
# 在实际实现中这里会调用渲染API进行渲染
rendered_count += 1
self.visualization_stats['rendered_instances'] = rendered_count
self.visualization_stats['draw_calls'] += rendered_count
except Exception as e:
print(f"✗ 植被渲染失败: {e}")
def _calculate_lod_level(self, position: tuple) -> int:
"""
计算LOD级别
Args:
position: 位置坐标
Returns:
LOD级别索引
"""
try:
camera_pos = self.camera_config['position']
distance = math.sqrt(
(position[0] - camera_pos[0])**2 +
(position[1] - camera_pos[1])**2 +
(position[2] - camera_pos[2])**2
)
# 根据距离选择LOD级别
for i, level in enumerate(self.lod_system['levels']):
if distance <= level['distance']:
return min(i, len(self.lod_system['levels']) - 1)
return len(self.lod_system['levels']) - 1
except Exception as e:
print(f"✗ LOD级别计算失败: {e}")
return 0
def _calculate_vegetation_color(self, instance: Dict[str, Any], veg_info: Dict[str, Any]) -> tuple:
"""
计算植被颜色
Args:
instance: 植被实例
veg_info: 植被信息
Returns:
RGB颜色元组
"""
try:
base_color = veg_info.get('color', (0.2, 0.8, 0.2))
# 基于健康度调整颜色
if self.shading_config['health_based_color']:
health = instance['health']
if health > 0.7:
color = self.color_schemes['vegetation']['healthy']
elif health > 0.3:
color = self.color_schemes['vegetation']['stressed']
elif health > 0.1:
color = self.color_schemes['vegetation']['dying']
else:
color = self.color_schemes['vegetation']['dormant']
# 混合基础颜色和健康颜色
color = tuple((base_color[i] + color[i]) / 2 for i in range(3))
else:
color = base_color
return color
except Exception as e:
print(f"✗ 植被颜色计算失败: {e}")
return (0.2, 0.8, 0.2)
def render_animals(self):
"""渲染动物"""
try:
if not self.enabled or not self.render_config['render_animals']:
return
if not self.plugin.animal_simulator:
return
# 获取所有动物实例
instances = self.plugin.animal_simulator.get_all_animal_instances()
for instance_id, instance in instances.items():
if not instance['alive']:
continue
# 获取动物种类信息
species = instance['species']
species_info = self.plugin.animal_simulator.get_animal_info(species)
if not species_info:
continue
# 计算LOD级别
lod_level = self._calculate_lod_level(instance['position'])
# 在实际实现中这里会调用渲染API进行渲染
self.visualization_stats['draw_calls'] += len(instances)
except Exception as e:
print(f"✗ 动物渲染失败: {e}")
def render_ecosystem_effects(self):
"""渲染生态系统特效"""
try:
if not self.enabled or not self.render_config['render_effects']:
return
# 在实际实现中,这里会渲染各种生态系统特效
# 如花粉飘散、落叶、动物足迹等
self.visualization_stats['effects_applied'] += 1
except Exception as e:
print(f"✗ 生态系统特效渲染失败: {e}")
def set_render_config(self, config: Dict[str, Any]):
"""
设置渲染配置
Args:
config: 渲染配置字典
"""
try:
self.render_config.update(config)
print(f"✓ 渲染配置已更新: {self.render_config}")
except Exception as e:
print(f"✗ 渲染配置更新失败: {e}")
def get_render_config(self) -> Dict[str, Any]:
"""
获取渲染配置
Returns:
渲染配置字典
"""
return self.render_config.copy()
def set_shading_config(self, config: Dict[str, Any]):
"""
设置着色配置
Args:
config: 着色配置字典
"""
try:
self.shading_config.update(config)
print(f"✓ 着色配置已更新: {self.shading_config}")
except Exception as e:
print(f"✗ 着色配置更新失败: {e}")
def get_shading_config(self) -> Dict[str, Any]:
"""
获取着色配置
Returns:
着色配置字典
"""
return self.shading_config.copy()
def set_effect_config(self, config: Dict[str, Any]):
"""
设置特效配置
Args:
config: 特效配置字典
"""
try:
self.effect_config.update(config)
print(f"✓ 特效配置已更新: {self.effect_config}")
except Exception as e:
print(f"✗ 特效配置更新失败: {e}")
def get_effect_config(self) -> Dict[str, Any]:
"""
获取特效配置
Returns:
特效配置字典
"""
return self.effect_config.copy()
def set_camera_config(self, config: Dict[str, Any]):
"""
设置相机配置
Args:
config: 相机配置字典
"""
try:
self.camera_config.update(config)
print(f"✓ 相机配置已更新: {self.camera_config}")
except Exception as e:
print(f"✗ 相机配置更新失败: {e}")
def get_camera_config(self) -> Dict[str, Any]:
"""
获取相机配置
Returns:
相机配置字典
"""
return self.camera_config.copy()
def get_lod_system(self) -> Dict[str, Any]:
"""
获取LOD系统配置
Returns:
LOD系统配置字典
"""
return self.lod_system.copy()
def set_lod_level(self, level: int, distance: float, detail: str, polygon_count: int):
"""
设置LOD级别
Args:
level: LOD级别索引
distance: 距离阈值
detail: 细节级别
polygon_count: 多边形数量
"""
try:
if 0 <= level < len(self.lod_system['levels']):
self.lod_system['levels'][level] = {
'distance': distance,
'detail': detail,
'polygon_count': polygon_count
}
print(f"✓ LOD级别 {level} 已更新")
else:
print(f"✗ 无效的LOD级别: {level}")
except Exception as e:
print(f"✗ LOD级别设置失败: {e}")
def get_color_schemes(self) -> Dict[str, Dict[str, tuple]]:
"""
获取颜色方案
Returns:
颜色方案字典
"""
return self.color_schemes.copy()
def set_color_scheme(self, category: str, scheme_name: str, color: tuple):
"""
设置颜色方案
Args:
category: 颜色类别
scheme_name: 方案名称
color: RGB颜色元组
"""
try:
if category in self.color_schemes:
self.color_schemes[category][scheme_name] = color
print(f"✓ 颜色方案已更新: {category}.{scheme_name}")
else:
print(f"✗ 无效的颜色类别: {category}")
except Exception as e:
print(f"✗ 颜色方案设置失败: {e}")
def get_visualization_stats(self) -> Dict[str, Any]:
"""
获取可视化统计信息
Returns:
统计信息字典
"""
return self.visualization_stats.copy()
def reset_visualization_stats(self):
"""重置可视化统计信息"""
try:
self.visualization_stats = {
'rendered_instances': 0,
'draw_calls': 0,
'render_time': 0.0,
'lod_transitions': 0,
'effects_applied': 0
}
print("✓ 可视化统计信息已重置")
except Exception as e:
print(f"✗ 可视化统计信息重置失败: {e}")
def clear_render_cache(self):
"""清空渲染缓存"""
try:
self.render_cache.clear()
print("✓ 渲染缓存已清空")
except Exception as e:
print(f"✗ 渲染缓存清空失败: {e}")
def get_cache_info(self) -> Dict[str, Any]:
"""
获取缓存信息
Returns:
缓存信息字典
"""
try:
return {
'cache_size': len(self.render_cache),
'max_size': self.cache_config['max_cache_size'],
'timeout': self.cache_config['cache_timeout']
}
except Exception as e:
print(f"✗ 缓存信息获取失败: {e}")
return {}
def set_cache_config(self, config: Dict[str, Any]):
"""
设置缓存配置
Args:
config: 缓存配置字典
"""
try:
self.cache_config.update(config)
print(f"✓ 缓存配置已更新: {self.cache_config}")
except Exception as e:
print(f"✗ 缓存配置更新失败: {e}")
def capture_screenshot(self, filename: str = None) -> str:
"""
截取屏幕截图
Args:
filename: 文件名如果为None则自动生成
Returns:
截图文件路径
"""
try:
if filename is None:
timestamp = int(time.time())
filename = f"ecosystem_screenshot_{timestamp}.png"
# 在实际实现中这里会调用渲染API截取屏幕
print(f"✓ 屏幕截图已保存: {filename}")
return filename
except Exception as e:
print(f"✗ 屏幕截图失败: {e}")
return ""
def render_heightmap(self) -> bool:
"""
渲染高度图
Returns:
是否渲染成功
"""
try:
# 在实际实现中,这里会渲染地形高度图
print("✓ 高度图渲染完成")
return True
except Exception as e:
print(f"✗ 高度图渲染失败: {e}")
return False
def render_vegetation_density_map(self) -> bool:
"""
渲染植被密度图
Returns:
是否渲染成功
"""
try:
# 在实际实现中,这里会渲染植被密度图
print("✓ 植被密度图渲染完成")
return True
except Exception as e:
print(f"✗ 植被密度图渲染失败: {e}")
return False
def toggle_wireframe_mode(self):
"""切换线框模式"""
try:
# 在实际实现中,这里会切换渲染模式
print("✓ 线框模式已切换")
except Exception as e:
print(f"✗ 线框模式切换失败: {e}")
def toggle_debug_info(self):
"""切换调试信息显示"""
try:
# 在实际实现中,这里会切换调试信息显示
print("✓ 调试信息显示已切换")
except Exception as e:
print(f"✗ 调试信息显示切换失败: {e}")