"""
地形渲染器
负责渲染程序化生成的地形
"""

import numpy as np
import math
from typing import Dict, Any, List, Tuple

class TerrainRenderer:
    """
    地形渲染器
    负责渲染程序化生成的地形，包括网格生成、纹理映射、光照计算等
    """
    
    def __init__(self, plugin):
        """
        初始化地形渲染器
        
        Args:
            plugin: 程序化地形生成插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 渲染配置
        self.render_params = {
            'resolution': plugin.config.get('terrain_size', 512),
            'lod_levels': plugin.config.get('lod_levels', 5),
            'chunk_size': plugin.config.get('chunk_size', 32),
            'max_distance': 1000.0,
            'lod_distance_factor': 2.0
        }
        
        # 光照参数
        self.lighting_params = {
            'ambient_light': 0.3,
            'diffuse_light': 0.7,
            'specular_light': 0.2,
            'light_direction': [0.5, 0.5, 0.5],
            'light_color': [1.0, 1.0, 1.0]
        }
        
        # 材质参数
        self.material_params = {
            'diffuse_texture': True,
            'normal_mapping': True,
            'specular_mapping': False,
            'texture_scale': 1.0,
            'tessellation_factor': 1.0
        }
        
        # 着色器参数
        self.shader_params = {
            'vertex_shader': 'terrain_vertex.glsl',
            'fragment_shader': 'terrain_fragment.glsl',
            'geometry_shader': None,
            'tessellation_control_shader': None,
            'tessellation_evaluation_shader': None
        }
        
        # 渲染状态
        self.render_buffers = {}
        self.vertex_arrays = {}
        self.textures = {}
        self.shaders = {}
        
        # LOD管理
        self.lod_chunks = {}
        self.visible_chunks = set()
        
        # 统计信息
        self.stats = {
            'chunks_rendered': 0,
            'vertices_rendered': 0,
            'triangles_rendered': 0,
            'render_time': 0.0,
            'average_render_time': 0.0,
            'lod_switches': 0
        }
        
        print("✓ 地形渲染器已创建")
        
    def initialize(self) -> bool:
        """
        初始化地形渲染器
        
        Returns:
            是否初始化成功
        """
        try:
            # 初始化渲染资源（在实际实现中会初始化GPU资源）
            self._initialize_render_resources()
            
            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._cleanup_render_resources()
            
            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
                
            # 更新LOD
            self._update_lod()
            
            # 更新可见区块
            self._update_visible_chunks()
            
        except Exception as e:
            print(f"✗ 地形渲染器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _initialize_render_resources(self):
        """初始化渲染资源"""
        try:
            # 在实际实现中，这里会初始化GPU缓冲区、纹理、着色器等
            print("  → 初始化渲染缓冲区...")
            print("  → 初始化着色器...")
            print("  → 初始化纹理...")
            
            # 模拟创建一些基本的渲染资源
            self.render_buffers['terrain_vertices'] = []
            self.render_buffers['terrain_indices'] = []
            self.vertex_arrays['terrain_vao'] = []
            self.textures['terrain_diffuse'] = []
            self.textures['terrain_normal'] = []
            self.shaders['terrain_shader'] = []
            
        except Exception as e:
            print(f"✗ 渲染资源初始化失败: {e}")
            
    def _cleanup_render_resources(self):
        """清理渲染资源"""
        try:
            # 在实际实现中，这里会清理GPU资源
            self.render_buffers.clear()
            self.vertex_arrays.clear()
            self.textures.clear()
            self.shaders.clear()
            self.lod_chunks.clear()
            self.visible_chunks.clear()
            
        except Exception as e:
            print(f"✗ 渲染资源清理失败: {e}")
            
    def render_terrain(self, camera_position: List[float], view_matrix: np.ndarray, 
                      projection_matrix: np.ndarray) -> bool:
        """
        渲染地形
        
        Args:
            camera_position: 摄像机位置
            view_matrix: 视图矩阵
            projection_matrix: 投影矩阵
            
        Returns:
            是否渲染成功
        """
        try:
            if not self.enabled:
                print("✗ 地形渲染器未启用")
                return False
                
            import time
            render_start_time = time.time()
            
            print("✓ 开始渲染地形...")
            
            # 更新摄像机相关数据
            self._update_camera_data(camera_position, view_matrix, projection_matrix)
            
            # 准备渲染数据
            self._prepare_render_data()
            
            # 执行渲染
            self._execute_rendering()
            
            # 更新统计信息
            render_time = time.time() - render_start_time
            self.stats['render_time'] = render_time
            self.stats['chunks_rendered'] += len(self.visible_chunks)
            
            if self.stats['chunks_rendered'] > 0:
                self.stats['average_render_time'] = (
                    self.stats['average_render_time'] * (self.stats['chunks_rendered'] - 1) + render_time
                ) / self.stats['chunks_rendered']
                
            print(f"✓ 地形渲染完成，耗时: {render_time:.3f}秒")
            return True
            
        except Exception as e:
            print(f"✗ 地形渲染失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def _update_camera_data(self, camera_position: List[float], view_matrix: np.ndarray, 
                           projection_matrix: np.ndarray):
        """更新摄像机相关数据"""
        try:
            # 在实际实现中，这里会更新着色器中的摄像机参数
            pass
        except Exception as e:
            print(f"✗ 摄像机数据更新失败: {e}")
            
    def _prepare_render_data(self):
        """准备渲染数据"""
        try:
            # 在实际实现中，这里会准备顶点缓冲区、索引缓冲区等
            pass
        except Exception as e:
            print(f"✗ 渲染数据准备失败: {e}")
            
    def _execute_rendering(self):
        """执行渲染"""
        try:
            # 在实际实现中，这里会调用GPU渲染命令
            print("  → 绑定着色器程序...")
            print("  → 设置光照参数...")
            print("  → 绑定纹理...")
            print("  → 渲染可见区块...")
            
            # 模拟渲染过程
            for chunk_key in self.visible_chunks:
                print(f"    → 渲染区块 {chunk_key}")
                
        except Exception as e:
            print(f"✗ 渲染执行失败: {e}")
            
    def _update_lod(self):
        """更新LOD级别"""
        try:
            # 在实际实现中，这里会根据摄像机距离更新每个区块的LOD级别
            pass
        except Exception as e:
            print(f"✗ LOD更新失败: {e}")
            
    def _update_visible_chunks(self):
        """更新可见区块"""
        try:
            # 在实际实现中，这里会根据视锥体剔除确定可见区块
            if self.plugin.terrain_manager:
                terrain_data = self.plugin.terrain_manager.get_terrain_data()
                if terrain_data.get('is_generating', False):
                    # 如果地形正在生成，暂时不更新可见区块
                    return
                    
                # 获取可见区块列表
                visible_chunk_keys = self.plugin.terrain_manager.get_visible_chunks()
                self.visible_chunks = set(visible_chunk_keys)
                
        except Exception as e:
            print(f"✗ 可见区块更新失败: {e}")
            
    def set_render_parameters(self, params: Dict[str, Any]):
        """
        设置渲染参数
        
        Args:
            params: 渲染参数字典
        """
        self.render_params.update(params)
        print(f"✓ 渲染参数已更新: {self.render_params}")
        
    def set_lighting_parameters(self, params: Dict[str, Any]):
        """
        设置光照参数
        
        Args:
            params: 光照参数字典
        """
        self.lighting_params.update(params)
        print(f"✓ 光照参数已更新: {self.lighting_params}")
        
    def set_material_parameters(self, params: Dict[str, Any]):
        """
        设置材质参数
        
        Args:
            params: 材质参数字典
        """
        self.material_params.update(params)
        print(f"✓ 材质参数已更新: {self.material_params}")
        
    def set_shader_parameters(self, params: Dict[str, Any]):
        """
        设置着色器参数
        
        Args:
            params: 着色器参数字典
        """
        self.shader_params.update(params)
        print(f"✓ 着色器参数已更新: {self.shader_params}")
        
    def get_stats(self) -> Dict[str, Any]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def reset_stats(self):
        """重置统计信息"""
        self.stats = {
            'chunks_rendered': 0,
            'vertices_rendered': 0,
            'triangles_rendered': 0,
            'render_time': 0.0,
            'average_render_time': 0.0,
            'lod_switches': 0
        }
        print("✓ 地形渲染器统计信息已重置")
        
    def generate_terrain_mesh(self, heightmap: np.ndarray, resolution: int = None) -> Dict[str, np.ndarray]:
        """
        生成地形网格
        
        Args:
            heightmap: 高度图数据
            resolution: 网格分辨率
            
        Returns:
            包含顶点、法线、纹理坐标和索引的字典
        """
        try:
            if resolution is None:
                resolution = self.render_params['resolution']
                
            print(f"✓ 开始生成 {resolution}x{resolution} 地形网格...")
            
            # 创建网格数据
            vertices = []
            normals = []
            texcoords = []
            indices = []
            
            # 生成顶点数据
            height, width = heightmap.shape
            scale_x = 1.0 / (width - 1)
            scale_y = 1.0 / (height - 1)
            
            # 生成顶点
            for y in range(height):
                for x in range(width):
                    # 顶点位置
                    vertex_x = (x / (width - 1)) * 2.0 - 1.0  # -1 到 1
                    vertex_y = heightmap[y, x]  # 高度值
                    vertex_z = (y / (height - 1)) * 2.0 - 1.0  # -1 到 1
                    vertices.extend([vertex_x, vertex_y, vertex_z])
                    
                    # 纹理坐标
                    texcoord_u = x / (width - 1)
                    texcoord_v = 1.0 - y / (height - 1)  # 翻转V坐标
                    texcoords.extend([texcoord_u, texcoord_v])
                    
            # 计算法线
            normals = self._calculate_normals(heightmap)
            
            # 生成索引（三角形列表）
            for y in range(height - 1):
                for x in range(width - 1):
                    # 第一个三角形
                    indices.append(y * width + x)
                    indices.append(y * width + x + 1)
                    indices.append((y + 1) * width + x)
                    
                    # 第二个三角形
                    indices.append((y + 1) * width + x)
                    indices.append(y * width + x + 1)
                    indices.append((y + 1) * width + x + 1)
                    
            # 转换为numpy数组
            vertices_array = np.array(vertices, dtype=np.float32)
            normals_array = np.array(normals, dtype=np.float32)
            texcoords_array = np.array(texcoords, dtype=np.float32)
            indices_array = np.array(indices, dtype=np.uint32)
            
            # 更新统计信息
            self.stats['vertices_rendered'] = len(vertices) // 3
            self.stats['triangles_rendered'] = len(indices) // 3
            
            print(f"✓ 地形网格生成完成: {len(vertices)//3} 顶点, {len(indices)//3} 三角形")
            return {
                'vertices': vertices_array,
                'normals': normals_array,
                'texcoords': texcoords_array,
                'indices': indices_array
            }
            
        except Exception as e:
            print(f"✗ 地形网格生成失败: {e}")
            import traceback
            traceback.print_exc()
            return {
                'vertices': np.array([], dtype=np.float32),
                'normals': np.array([], dtype=np.float32),
                'texcoords': np.array([], dtype=np.float32),
                'indices': np.array([], dtype=np.uint32)
            }
            
    def _calculate_normals(self, heightmap: np.ndarray) -> List[float]:
        """
        计算法线
        
        Args:
            heightmap: 高度图数据
            
        Returns:
            法线数据列表
        """
        try:
            height, width = heightmap.shape
            normals = []
            
            for y in range(height):
                for x in range(width):
                    # 计算相邻点的高度
                    h_left = heightmap[y, max(0, x-1)]
                    h_right = heightmap[y, min(width-1, x+1)]
                    h_up = heightmap[max(0, y-1), x]
                    h_down = heightmap[min(height-1, y+1), x]
                    
                    # 计算梯度
                    dx = (h_right - h_left) * width / 2.0
                    dy = (h_down - h_up) * height / 2.0
                    dz = 2.0
                    
                    # 计算法线
                    normal = [-dx, -dy, dz]
                    norm = math.sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2])
                    if norm > 0:
                        normal = [n/norm for n in normal]
                    else:
                        normal = [0.0, 0.0, 1.0]
                        
                    normals.extend(normal)
                    
            return normals
            
        except Exception as e:
            print(f"✗ 法线计算失败: {e}")
            # 返回默认法线
            height, width = heightmap.shape
            return [0.0, 0.0, 1.0] * height * width
            
    def generate_terrain_texture(self, heightmap: np.ndarray, biome_map: np.ndarray = None, 
                               moisture_map: np.ndarray = None, temperature_map: np.ndarray = None) -> np.ndarray:
        """
        生成地形纹理
        
        Args:
            heightmap: 高度图数据
            biome_map: 生物群落图数据（可选）
            moisture_map: 湿度图数据（可选）
            temperature_map: 温度图数据（可选）
            
        Returns:
            纹理数据 (RGBA格式)
        """
        try:
            height, width = heightmap.shape
            print(f"✓ 开始生成 {width}x{height} 地形纹理...")
            
            # 创建RGBA纹理数据
            texture_data = np.zeros((height, width, 4), dtype=np.uint8)
            
            # 如果有生物群落数据，基于生物群落生成纹理
            if biome_map is not None and biome_map.shape == heightmap.shape:
                texture_data = self._generate_biome_based_texture(biome_map)
            else:
                # 基于高度生成基础纹理
                texture_data = self._generate_height_based_texture(heightmap)
                
            # 如果有湿度和温度数据，添加细节
            if moisture_map is not None and moisture_map.shape == heightmap.shape:
                texture_data = self._apply_moisture_effects(texture_data, moisture_map)
                
            if temperature_map is not None and temperature_map.shape == heightmap.shape:
                texture_data = self._apply_temperature_effects(texture_data, temperature_map)
                
            print("✓ 地形纹理生成完成")
            return texture_data
            
        except Exception as e:
            print(f"✗ 地形纹理生成失败: {e}")
            import traceback
            traceback.print_exc()
            # 返回默认纹理（蓝色）
            height, width = heightmap.shape
            return np.zeros((height, width, 4), dtype=np.uint8)
            
    def _generate_biome_based_texture(self, biome_map: np.ndarray) -> np.ndarray:
        """
        基于生物群落生成纹理
        
        Args:
            biome_map: 生物群落图数据
            
        Returns:
            纹理数据
        """
        try:
            height, width = biome_map.shape
            texture_data = np.zeros((height, width, 4), dtype=np.uint8)
            
            # 生物群落颜色映射
            biome_colors = {
                0: [0, 0, 128, 255],      # ocean - 深蓝色
                1: [255, 255, 0, 255],    # beach - 黄色
                2: [144, 238, 144, 255],  # plains - 浅绿色
                3: [34, 139, 34, 255],    # forest - 绿色
                4: [0, 100, 0, 255],      # jungle - 深绿色
                5: [255, 165, 0, 255],    # desert - 橙色
                6: [139, 137, 137, 255],  # mountain - 灰色
                7: [255, 255, 255, 255],  # snow - 白色
                8: [0, 128, 128, 255],    # taiga - 青色
                9: [173, 216, 230, 255],  # tundra - 淡蓝色
                10: [128, 128, 0, 255],   # swamp - 橄榄色
                11: [255, 215, 0, 255]    # savanna - 金色
            }
            
            # 为每个像素分配颜色
            for y in range(height):
                for x in range(width):
                    biome_id = biome_map[y, x]
                    color = biome_colors.get(biome_id, [128, 128, 128, 255])  # 默认灰色
                    texture_data[y, x] = color
                    
            return texture_data
            
        except Exception as e:
            print(f"✗ 生物群落纹理生成失败: {e}")
            height, width = biome_map.shape
            return np.zeros((height, width, 4), dtype=np.uint8)
            
    def _generate_height_based_texture(self, heightmap: np.ndarray) -> np.ndarray:
        """
        基于高度生成纹理
        
        Args:
            heightmap: 高度图数据
            
        Returns:
            纹理数据
        """
        try:
            height, width = heightmap.shape
            texture_data = np.zeros((height, width, 4), dtype=np.uint8)
            
            # 为每个像素根据高度分配颜色
            for y in range(height):
                for x in range(width):
                    height_value = heightmap[y, x]
                    
                    # 根据高度选择颜色
                    if height_value < 0.2:
                        # 水域 - 蓝色
                        r, g, b = 0, 0, int(128 + height_value * 127)
                    elif height_value < 0.3:
                        # 浅水/海滩 - 浅蓝色
                        r, g, b = int(height_value * 255), int(height_value * 255), 255
                    elif height_value < 0.5:
                        # 平原 - 绿色
                        r, g, b = 0, int(100 + height_value * 155), 0
                    elif height_value < 0.7:
                        # 丘陵 - 棕色
                        r, g, b = int(139 * height_value), int(69 * height_value), int(19 * height_value)
                    elif height_value < 0.9:
                        # 山地 - 灰色
                        r, g, b = int(100 + height_value * 155), int(100 + height_value * 155), int(100 + height_value * 155)
                    else:
                        # 雪山 - 白色
                        r, g, b = 255, 255, 255
                        
                    texture_data[y, x] = [r, g, b, 255]
                    
            return texture_data
            
        except Exception as e:
            print(f"✗ 高度纹理生成失败: {e}")
            height, width = heightmap.shape
            return np.zeros((height, width, 4), dtype=np.uint8)
            
    def _apply_moisture_effects(self, texture_data: np.ndarray, moisture_map: np.ndarray) -> np.ndarray:
        """
        应用湿度效果到纹理
        
        Args:
            texture_data: 原始纹理数据
            moisture_map: 湿度图数据
            
        Returns:
            处理后的纹理数据
        """
        try:
            processed_texture = texture_data.copy()
            height, width = moisture_map.shape
            
            # 根据湿度调整颜色
            for y in range(height):
                for x in range(width):
                    moisture_value = moisture_map[y, x]
                    
                    # 增加蓝色调表示湿润
                    if moisture_value > 0.6:
                        processed_texture[y, x, 2] = min(255, processed_texture[y, x, 2] + int(50 * moisture_value))
                        
                    # 减少红色和绿色通道表示湿润
                    if moisture_value > 0.5:
                        processed_texture[y, x, 0] = max(0, processed_texture[y, x, 0] - int(30 * moisture_value))
                        processed_texture[y, x, 1] = max(0, processed_texture[y, x, 1] - int(30 * moisture_value))
                        
            return processed_texture
            
        except Exception as e:
            print(f"✗ 湿度效果应用失败: {e}")
            return texture_data
            
    def _apply_temperature_effects(self, texture_data: np.ndarray, temperature_map: np.ndarray) -> np.ndarray:
        """
        应用温度效果到纹理
        
        Args:
            texture_data: 原始纹理数据
            temperature_map: 温度图数据
            
        Returns:
            处理后的纹理数据
        """
        try:
            processed_texture = texture_data.copy()
            height, width = temperature_map.shape
            
            # 根据温度调整颜色
            for y in range(height):
                for x in range(width):
                    temperature_value = temperature_map[y, x]
                    
                    # 增加热色调表示温暖
                    if temperature_value > 0.7:
                        processed_texture[y, x, 0] = min(255, processed_texture[y, x, 0] + int(50 * (temperature_value - 0.7) / 0.3))
                        
                    # 增加冷色调表示寒冷
                    if temperature_value < 0.3:
                        processed_texture[y, x, 2] = min(255, processed_texture[y, x, 2] + int(50 * (0.3 - temperature_value) / 0.3))
                        
            return processed_texture
            
        except Exception as e:
            print(f"✗ 温度效果应用失败: {e}")
            return texture_data
            
    def generate_normal_map(self, heightmap: np.ndarray, strength: float = 1.0) -> np.ndarray:
        """
        生成法线贴图
        
        Args:
            heightmap: 高度图数据
            strength: 法线强度
            
        Returns:
            法线贴图数据 (RGB格式)
        """
        try:
            height, width = heightmap.shape
            print(f"✓ 开始生成 {width}x{height} 法线贴图...")
            
            # 创建法线贴图数据
            normal_map = np.zeros((height, width, 3), dtype=np.uint8)
            
            # 计算每个像素的法线
            for y in range(height):
                for x in range(width):
                    # 计算相邻点的高度
                    h_left = heightmap[y, max(0, x-1)]
                    h_right = heightmap[y, min(width-1, x+1)]
                    h_up = heightmap[max(0, y-1), x]
                    h_down = heightmap[min(height-1, y+1), x]
                    
                    # 计算梯度
                    dx = (h_right - h_left) * strength
                    dy = (h_down - h_up) * strength
                    
                    # 计算法线 (转换到0-1范围再转为0-255)
                    normal_x = (dx + 1.0) * 0.5
                    normal_y = (dy + 1.0) * 0.5
                    normal_z = 1.0  # 假设主要朝向摄像机
                    normal_z = normal_z / math.sqrt(normal_x*normal_x + normal_y*normal_y + normal_z*normal_z)
                    normal_z = (normal_z + 1.0) * 0.5
                    
                    # 转换为8位值
                    normal_map[y, x] = [
                        int(normal_x * 255),
                        int(normal_y * 255),
                        int(normal_z * 255)
                    ]
                    
            print("✓ 法线贴图生成完成")
            return normal_map
            
        except Exception as e:
            print(f"✗ 法线贴图生成失败: {e}")
            import traceback
            traceback.print_exc()
            # 返回默认法线贴图（正面法线）
            height, width = heightmap.shape
            return np.full((height, width, 3), [128, 128, 255], dtype=np.uint8)
            
    def generate_splat_map(self, biome_map: np.ndarray, num_textures: int = 4) -> np.ndarray:
        """
        生成混合贴图（用于多重纹理混合）
        
        Args:
            biome_map: 生物群落图数据
            num_textures: 纹理数量
            
        Returns:
            混合贴图数据 (RGBA格式，每个通道代表一种纹理的权重)
        """
        try:
            height, width = biome_map.shape
            print(f"✓ 开始生成 {width}x{height} 混合贴图...")
            
            # 创建混合贴图数据
            splat_map = np.zeros((height, width, 4), dtype=np.uint8)
            
            # 简化的混合贴图生成
            # 在实际实现中，这里会根据生物群落类型和地形特征生成更复杂的混合
            for y in range(height):
                for x in range(width):
                    biome_id = biome_map[y, x]
                    
                    # 根据生物群落ID分配到不同的纹理通道
                    channel = biome_id % 4
                    splat_map[y, x, channel] = 255
                    
            print("✓ 混合贴图生成完成")
            return splat_map
            
        except Exception as e:
            print(f"✗ 混合贴图生成失败: {e}")
            import traceback
            traceback.print_exc()
            # 返回默认混合贴图
            height, width = biome_map.shape
            return np.zeros((height, width, 4), dtype=np.uint8)
            
    def update_chunk_mesh(self, chunk_x: int, chunk_y: int, lod_level: int, 
                         heightmap: np.ndarray) -> bool:
        """
        更新区块网格
        
        Args:
            chunk_x: 区块X坐标
            chunk_y: 区块Y坐标
            lod_level: LOD级别
            heightmap: 高度图数据
            
        Returns:
            是否更新成功
        """
        try:
            chunk_key = f"{chunk_x},{chunk_y},{lod_level}"
            
            # 生成区块网格数据
            mesh_data = self.generate_terrain_mesh(heightmap)
            
            # 存储到LOD区块中
            if chunk_key not in self.lod_chunks:
                self.lod_chunks[chunk_key] = {}
                
            self.lod_chunks[chunk_key]['mesh_data'] = mesh_data
            self.lod_chunks[chunk_key]['last_update'] = time.time()
            
            print(f"✓ 区块 [{chunk_x}, {chunk_y}] LOD {lod_level} 网格已更新")
            return True
            
        except Exception as e:
            print(f"✗ 区块网格更新失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def get_chunk_mesh(self, chunk_x: int, chunk_y: int, lod_level: int) -> Dict[str, np.ndarray]:
        """
        获取区块网格数据
        
        Args:
            chunk_x: 区块X坐标
            chunk_y: 区块Y坐标
            lod_level: LOD级别
            
        Returns:
            网格数据字典
        """
        try:
            chunk_key = f"{chunk_x},{chunk_y},{lod_level}"
            if chunk_key in self.lod_chunks:
                return self.lod_chunks[chunk_key].get('mesh_data', {})
            else:
                return {}
                
        except Exception as e:
            print(f"✗ 区块网格获取失败: {e}")
            return {}
            
    def set_lod_distances(self, distances: List[float]):
        """
        设置LOD距离
        
        Args:
            distances: LOD距离列表
        """
        self.render_params['lod_distances'] = distances
        print(f"✓ LOD距离已设置: {distances}")
        
    def get_lod_level(self, distance: float) -> int:
        """
        根据距离确定LOD级别
        
        Args:
            distance: 距离
            
        Returns:
            LOD级别
        """
        try:
            lod_distances = self.render_params.get('lod_distances', [])
            if not lod_distances:
                # 使用默认距离计算
                base_distance = 100.0
                for i in range(self.render_params['lod_levels']):
                    if distance < base_distance * (i + 1):
                        return i
                return self.render_params['lod_levels'] - 1
            else:
                # 使用自定义距离
                for i, lod_distance in enumerate(lod_distances):
                    if distance < lod_distance:
                        return i
                return len(lod_distances) - 1
                
        except Exception as e:
            print(f"✗ LOD级别计算失败: {e}")
            return 0
            
    def frustum_cull(self, camera_position: List[float], 
                    view_matrix: np.ndarray, projection_matrix: np.ndarray) -> List[Tuple[int, int]]:
        """
        视锥体剔除
        
        Args:
            camera_position: 摄像机位置
            view_matrix: 视图矩阵
            projection_matrix: 投影矩阵
            
        Returns:
            可见区块列表 [(chunk_x, chunk_y), ...]
        """
        try:
            # 在实际实现中，这里会进行复杂的视锥体剔除计算
            # 简化实现：返回所有区块
            visible_chunks = []
            
            if self.plugin.terrain_manager:
                terrain_data = self.plugin.terrain_manager.get_terrain_data()
                terrain_size = terrain_data.get('stats', {}).get('chunks_generated', 0)
                if terrain_size > 0:
                    # 模拟一些可见区块
                    for i in range(min(10, terrain_size)):
                        visible_chunks.append((i, i))
                        
            return visible_chunks
            
        except Exception as e:
            print(f"✗ 视锥体剔除失败: {e}")
            return []
            
    def occlusion_cull(self, visible_chunks: List[Tuple[int, int]]) -> List[Tuple[int, int]]:
        """
        遮挡剔除
        
        Args:
            visible_chunks: 可见区块列表
            
        Returns:
            未被遮挡的区块列表
        """
        try:
            # 在实际实现中，这里会进行遮挡剔除计算
            # 简化实现：返回所有可见区块
            return visible_chunks
            
        except Exception as e:
            print(f"✗ 遮挡剔除失败: {e}")
            return visible_chunks
            
    def generate_terrain_materials(self, biome_map: np.ndarray) -> Dict[str, Any]:
        """
        生成地形材质
        
        Args:
            biome_map: 生物群落图数据
            
        Returns:
            材质数据字典
        """
        try:
            print("✓ 开始生成地形材质...")
            
            # 在实际实现中，这里会生成多种材质纹理和属性
            materials = {
                'diffuse_textures': [],
                'normal_textures': [],
                'specular_textures': [],
                'biome_mapping': {}
            }
            
            # 为每种生物群落生成材质ID
            unique_biomes = np.unique(biome_map)
            for biome_id in unique_biomes:
                materials['biome_mapping'][biome_id] = f"material_{biome_id}"
                
            print("✓ 地形材质生成完成")
            return materials
            
        except Exception as e:
            print(f"✗ 地形材质生成失败: {e}")
            import traceback
            traceback.print_exc()
            return {}
            
    def apply_tessellation(self, vertices: np.ndarray, tessellation_factor: float) -> np.ndarray:
        """
        应用细分曲面
        
        Args:
            vertices: 顶点数据
            tessellation_factor: 细分因子
            
        Returns:
            细分后的顶点数据
        """
        try:
            # 在实际实现中，这里会使用GPU细分着色器
            # 简化实现：返回原始顶点
            print(f"✓ 应用细分曲面 (因子: {tessellation_factor})")
            return vertices
            
        except Exception as e:
            print(f"✗ 细分曲面应用失败: {e}")
            return vertices
            
    def apply_displacement_mapping(self, heightmap: np.ndarray, displacement_factor: float) -> np.ndarray:
        """
        应用置换贴图
        
        Args:
            heightmap: 高度图数据
            displacement_factor: 置换因子
            
        Returns:
            置换后的顶点数据
        """
        try:
            # 在实际实现中，这里会在细分着色器中应用置换贴图
            # 简化实现：返回处理后的高度图
            displaced_heightmap = heightmap * displacement_factor
            print(f"✓ 应用置换贴图 (因子: {displacement_factor})")
            return displaced_heightmap
            
        except Exception as e:
            print(f"✗ 置换贴图应用失败: {e}")
            return heightmap
            
    def calculate_shadow_map(self, light_direction: List[float], 
                           heightmap: np.ndarray) -> np.ndarray:
        """
        计算阴影贴图
        
        Args:
            light_direction: 光照方向
            heightmap: 高度图数据
            
        Returns:
            阴影贴图数据
        """
        try:
            height, width = heightmap.shape
            print(f"✓ 开始计算 {width}x{height} 阴影贴图...")
            
            # 创建阴影贴图数据
            shadow_map = np.ones((height, width), dtype=np.float32)
            
            # 简化的阴影计算
            light_x, light_y, light_z = light_direction
            
            # 根据光照方向计算阴影
            for y in range(height):
                for x in range(width):
                    # 简单的高度遮挡计算
                    current_height = heightmap[y, x]
                    shadow_factor = 1.0
                    
                    # 检查在光照方向上是否有更高的地形遮挡
                    step_x = int(light_x * 10)
                    step_y = int(light_y * 10)
                    
                    check_x = x + step_x
                    check_y = y + step_y
                    
                    if 0 <= check_x < width and 0 <= check_y < height:
                        check_height = heightmap[check_y, check_x]
                        if check_height > current_height:
                            shadow_factor = 0.5  # 简单的半阴影
                            
                    shadow_map[y, x] = shadow_factor
                    
            print("✓ 阴影贴图计算完成")
            return shadow_map
            
        except Exception as e:
            print(f"✗ 阴影贴图计算失败: {e}")
            import traceback
            traceback.print_exc()
            # 返回默认阴影贴图（无阴影）
            height, width = heightmap.shape
            return np.ones((height, width), dtype=np.float32)
            
    def apply_atmospheric_effects(self, color_data: np.ndarray, 
                                camera_position: List[float], 
                                sun_direction: List[float]) -> np.ndarray:
        """
        应用大气效果
        
        Args:
            color_data: 颜色数据
            camera_position: 摄像机位置
            sun_direction: 太阳方向
            
        Returns:
            处理后的颜色数据
        """
        try:
            processed_colors = color_data.copy()
            height, width = processed_colors.shape[:2]
            
            print("✓ 应用大气效果...")
            
            # 简化的雾效和光照计算
            fog_density = 0.01
            sun_r, sun_g, sun_b = sun_direction
            
            for y in range(height):
                for x in range(width):
                    # 计算到摄像机的距离（简化）
                    distance = math.sqrt((x - camera_position[0])**2 + (y - camera_position[1])**2)
                    
                    # 应用雾效
                    fog_factor = math.exp(-distance * fog_density)
                    fog_factor = max(0.0, min(1.0, fog_factor))
                    
                    # 混合雾颜色（白色）
                    processed_colors[y, x, 0] = int(processed_colors[y, x, 0] * fog_factor + 255 * (1 - fog_factor))
                    processed_colors[y, x, 1] = int(processed_colors[y, x, 1] * fog_factor + 255 * (1 - fog_factor))
                    processed_colors[y, x, 2] = int(processed_colors[y, x, 2] * fog_factor + 255 * (1 - fog_factor))
                    
            print("✓ 大气效果应用完成")
            return processed_colors
            
        except Exception as e:
            print(f"✗ 大气效果应用失败: {e}")
            return color_data
            
    def optimize_rendering(self, target_fps: float = 60.0):
        """
        优化渲染性能
        
        Args:
            target_fps: 目标帧率
        """
        try:
            print(f"✓ 开始优化渲染性能 (目标FPS: {target_fps})")
            
            # 根据目标FPS调整渲染参数
            current_fps = 1.0 / max(0.001, self.stats['average_render_time'])
            
            if current_fps < target_fps * 0.8:  # 如果FPS低于目标的80%
                # 降低渲染质量以提高性能
                self.render_params['lod_levels'] = max(1, self.render_params['lod_levels'] - 1)
                self.render_params['chunk_size'] = min(64, self.render_params['chunk_size'] * 2)
                print("  → 降低LOD级别和增加区块大小以提高性能")
                
            elif current_fps > target_fps * 1.2:  # 如果FPS高于目标的120%
                # 提高渲染质量
                self.render_params['lod_levels'] = min(10, self.render_params['lod_levels'] + 1)
                self.render_params['chunk_size'] = max(8, self.render_params['chunk_size'] // 2)
                print("  → 提高LOD级别和减小区块大小以提高质量")
                
            print("✓ 渲染性能优化完成")
            
        except Exception as e:
            print(f"✗ 渲染性能优化失败: {e}")
            
    def export_render_settings(self, filename: str) -> bool:
        """
        导出渲染设置
        
        Args:
            filename: 文件名
            
        Returns:
            是否导出成功
        """
        try:
            import json
            
            settings = {
                'render_params': self.render_params,
                'lighting_params': self.lighting_params,
                'material_params': self.material_params,
                'shader_params': self.shader_params,
                'timestamp': time.time()
            }
            
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(settings, f, ensure_ascii=False, indent=2)
                
            print(f"✓ 渲染设置已导出到: {filename}")
            return True
            
        except Exception as e:
            print(f"✗ 渲染设置导出失败: {e}")
            return False
            
    def import_render_settings(self, filename: str) -> bool:
        """
        导入渲染设置
        
        Args:
            filename: 文件名
            
        Returns:
            是否导入成功
        """
        try:
            import json
            
            with open(filename, 'r', encoding='utf-8') as f:
                settings = json.load(f)
                
            # 更新参数
            if 'render_params' in settings:
                self.render_params.update(settings['render_params'])
            if 'lighting_params' in settings:
                self.lighting_params.update(settings['lighting_params'])
            if 'material_params' in settings:
                self.material_params.update(settings['material_params'])
            if 'shader_params' in settings:
                self.shader_params.update(settings['shader_params'])
                
            print(f"✓ 渲染设置已从 {filename} 导入")
            return True
            
        except Exception as e:
            print(f"✗ 渲染设置导入失败: {e}")
            return False
            
    def get_render_capabilities(self) -> Dict[str, Any]:
        """
        获取渲染能力信息
        
        Returns:
            渲染能力信息字典
        """
        return {
            'max_texture_size': 8192,
            'max_lod_levels': 10,
            'supported_shaders': ['vertex', 'fragment', 'geometry', 'tessellation'],
            'supports_normal_mapping': True,
            'supports_displacement_mapping': True,
            'supports_tessellation': True,
            'supports_shadow_mapping': True,
            'max_anisotropy': 16.0
        }
        
    def set_render_quality(self, quality_level: str):
        """
        设置渲染质量级别
        
        Args:
            quality_level: 质量级别 ('low', 'medium', 'high', 'ultra')
        """
        quality_settings = {
            'low': {
                'lod_levels': 2,
                'chunk_size': 64,
                'normal_mapping': False,
                'tessellation_factor': 0.5
            },
            'medium': {
                'lod_levels': 4,
                'chunk_size': 32,
                'normal_mapping': True,
                'tessellation_factor': 1.0
            },
            'high': {
                'lod_levels': 6,
                'chunk_size': 16,
                'normal_mapping': True,
                'tessellation_factor': 2.0
            },
            'ultra': {
                'lod_levels': 8,
                'chunk_size': 8,
                'normal_mapping': True,
                'tessellation_factor': 4.0
            }
        }
        
        if quality_level in quality_settings:
            settings = quality_settings[quality_level]
            self.render_params['lod_levels'] = settings['lod_levels']
            self.render_params['chunk_size'] = settings['chunk_size']
            self.material_params['normal_mapping'] = settings['normal_mapping']
            self.material_params['tessellation_factor'] = settings['tessellation_factor']
            print(f"✓ 渲染质量已设置为: {quality_level}")
        else:
            print(f"✗ 无效的质量级别: {quality_level}")