""" 生态系统可视化器 负责提供植被和生态系统的可视化表示 """ 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}")