""" 地形优化和LOD系统 提供完整的地形优化功能,包括LOD控制、碰撞优化、渲染优化和性能监控 """ from panda3d.core import BitMask32, GeoMipTerrain import time import psutil import gc class TerrainOptimization: """ 地形优化和LOD系统类 提供完整的地形优化功能 """ def __init__(self, world): self.world = world self.lod_enabled = True self.lod_threshold = 50.0 self.min_block_size = 16 self.max_block_size = 64 self.auto_lod_enabled = True self.performance_monitoring = True self.last_optimization_time = 0 def enable_lod(self, enabled=True): """ 启用或禁用LOD """ self.lod_enabled = enabled print(f"LOD系统已{'启用' if enabled else '禁用'}") def set_lod_threshold(self, threshold): """ 设置LOD阈值 """ self.lod_threshold = max(1.0, min(1000.0, float(threshold))) print(f"LOD阈值设置为: {self.lod_threshold}") def set_auto_lod(self, enabled=True): """ 启用或禁用自动LOD调整 """ self.auto_lod_enabled = enabled print(f"自动LOD调整已{'启用' if enabled else '禁用'}") def update_terrain_lod(self, terrain_info): """ 更新单个地形的LOD """ if not self.lod_enabled: return try: if terrain_info in self.world.terrain_manager.terrains: terrain = terrain_info['terrain'] if hasattr(terrain, 'setNearFarThreshold'): # 设置LOD阈值 near_threshold = self.lod_threshold far_threshold = self.lod_threshold * 2 terrain.setNearFarThreshold(near_threshold, far_threshold) # 如果启用自动LOD,根据距离动态调整 if self.auto_lod_enabled: distance = self._calculate_terrain_distance(terrain_info) if distance > 200: # 远距离时使用更大的块 block_size = min(self.max_block_size, int(distance / 10)) else: # 近距离时使用更小的块 block_size = max(self.min_block_size, int(64 - distance / 5)) self.set_terrain_block_size(terrain_info, block_size) except Exception as e: print(f"更新地形LOD时出错: {e}") def update_all_terrains_lod(self): """ 更新所有地形的LOD """ if not self.lod_enabled: return if hasattr(self.world, 'terrain_manager'): for terrain_info in self.world.terrain_manager.terrains: self.update_terrain_lod(terrain_info) def optimize_terrain_collision(self, terrain_info): """ 优化地形碰撞体 """ try: terrain_node = terrain_info['node'] if terrain_node: # 清除现有的碰撞体 for child in terrain_node.getChildren(): if child.getName().startswith("terrain_collision_"): child.removeNode() # 设置地形节点的碰撞掩码 terrain_node.setCollideMask(BitMask32.bit(2)) # 为地形的所有子节点也设置碰撞掩码 for child in terrain_node.getChildren(): child.setCollideMask(BitMask32.bit(2)) # 如果地形很大,可以考虑创建简化的碰撞网格 if self._should_simplify_collision(terrain_info): self._create_simplified_collision(terrain_info) print("地形碰撞体已优化") return True except Exception as e: print(f"优化地形碰撞体时出错: {e}") return False def _should_simplify_collision(self, terrain_info): """ 判断是否需要简化碰撞体 """ try: heightfield = terrain_info.get('heightfield') if heightfield: width = heightfield.getXSize() height = heightfield.getYSize() # 如果地形分辨率很高,考虑简化碰撞 return width > 256 or height > 256 return False except: return False def _create_simplified_collision(self, terrain_info): """ 创建简化的碰撞体 """ print("创建简化的地形碰撞体") # 这里可以实现创建低分辨率碰撞网格的逻辑 def optimize_terrain_rendering(self, terrain_info): """ 优化地形渲染 """ try: terrain_node = terrain_info['node'] if terrain_node: # 如果使用RenderPipeline,应用优化效果 if hasattr(self.world, 'render_pipeline'): try: # 根据距离选择不同的效果 distance = self._calculate_terrain_distance(terrain_info) if distance > 100: # 远距离使用简化效果 effect_file = "effects/terrain_far.yaml" else: # 近距离使用高质量效果 effect_file = "effects/terrain_near.yaml" self.world.render_pipeline.set_effect( terrain_node, effect_file, { "normal_mapping": distance < 50, # 近距离启用法线贴图 "parallax_mapping": distance < 30, # 很近距离启用视差贴图 "lod_rendering": self.lod_enabled, "distance": distance }, 15 # 排序值 ) print(f"应用优化的地形渲染效果: {effect_file}") except Exception as e: print(f"应用优化渲染效果失败: {e}") # 设置渲染优先级 terrain_node.setBin("background", 0) terrain_node.setDepthWrite(True) return True except Exception as e: print(f"优化地形渲染时出错: {e}") return False def get_terrain_performance_stats(self, terrain_info): """ 获取地形性能统计信息 """ stats = { 'lod_enabled': self.lod_enabled, 'lod_threshold': self.lod_threshold, 'vertices': 0, 'triangles': 0, 'memory_usage': 0, 'block_size': 32, 'distance': 0 } try: terrain = terrain_info['terrain'] if terrain: # 获取地形几何信息 if hasattr(terrain, 'getRoot'): root_node = terrain.getRoot() if root_node: # 估算顶点和三角形数量 heightfield = terrain_info.get('heightfield') if heightfield: width = heightfield.getXSize() height = heightfield.getYSize() stats['vertices'] = width * height stats['triangles'] = (width - 1) * (height - 1) * 2 # 获取块大小 if hasattr(terrain, 'getBlockSize'): stats['block_size'] = terrain.getBlockSize() # 计算距离 stats['distance'] = self._calculate_terrain_distance(terrain_info) except Exception as e: print(f"获取地形性能统计时出错: {e}") return stats def auto_optimize_terrains(self): """ 自动优化所有地形 """ if not hasattr(self.world, 'terrain_manager'): return # 检查是否需要优化(避免过于频繁的优化) current_time = time.time() if current_time - self.last_optimization_time < 1.0: # 至少间隔1秒 return self.last_optimization_time = current_time optimized_count = 0 for terrain_info in self.world.terrain_manager.terrains: # 优化碰撞体 if self.optimize_terrain_collision(terrain_info): optimized_count += 1 # 优化渲染 if self.optimize_terrain_rendering(terrain_info): optimized_count += 1 # 更新LOD self.update_terrain_lod(terrain_info) # 更新所有地形的LOD self.update_all_terrains_lod() # 执行垃圾回收 if optimized_count > 0: gc.collect() print(f"自动优化完成,优化了 {optimized_count} 个项目") def set_terrain_block_size(self, terrain_info, block_size): """ 设置地形块大小(影响LOD效果) """ try: # 限制块大小范围 block_size = max(self.min_block_size, min(self.max_block_size, int(block_size))) terrain = terrain_info['terrain'] if hasattr(terrain, 'setBlockSize'): terrain.setBlockSize(block_size) print(f"地形块大小设置为: {block_size}") return True except Exception as e: print(f"设置地形块大小时出错: {e}") return False return False def set_block_size_range(self, min_size, max_size): """ 设置块大小范围 """ self.min_block_size = max(8, min(128, int(min_size))) self.max_block_size = max(8, min(128, int(max_size))) print(f"地形块大小范围设置为: {self.min_block_size} - {self.max_block_size}") def _calculate_terrain_distance(self, terrain_info): """ 计算地形到相机的距离 """ try: terrain_node = terrain_info['node'] if terrain_node and hasattr(self.world, 'cam'): terrain_pos = terrain_node.getPos() camera_pos = self.world.cam.getPos() distance = (terrain_pos - camera_pos).length() return distance return 50.0 # 默认距离 except: return 50.0 def enable_performance_monitoring(self, enabled=True): """ 启用或禁用性能监控 """ self.performance_monitoring = enabled print(f"性能监控已{'启用' if enabled else '禁用'}") def get_system_performance_stats(self): """ 获取系统性能统计信息 """ try: # 获取内存使用情况 process = psutil.Process() memory_info = process.memory_info() # 获取CPU使用率 cpu_percent = process.cpu_percent() return { 'memory_rss': memory_info.rss, 'memory_vms': memory_info.vms, 'cpu_percent': cpu_percent, 'terrain_count': len(self.world.terrain_manager.terrains) if hasattr(self.world, 'terrain_manager') else 0 } except Exception as e: print(f"获取系统性能统计时出错: {e}") return {} def optimize_memory_usage(self): """ 优化内存使用 """ try: # 执行垃圾回收 collected = gc.collect() print(f"执行垃圾回收,清理了 {collected} 个对象") # 优化纹理内存使用 if hasattr(self.world, 'texture_cache'): self.world.texture_cache.clear_unused() return True except Exception as e: print(f"优化内存使用时出错: {e}") return False def set_render_distance(self, distance): """ 设置渲染距离 """ try: if hasattr(self.world, 'camLens'): self.world.camLens.setNearFar(0.1, float(distance)) print(f"渲染距离设置为: {distance}") return True except Exception as e: print(f"设置渲染距离时出错: {e}") return False return False def enable_frustum_culling(self, enabled=True): """ 启用或禁用视锥体剔除 """ try: if hasattr(self.world, 'terrain_manager'): for terrain_info in self.world.terrain_manager.terrains: terrain_node = terrain_info['node'] if terrain_node: if enabled: terrain_node.setAttrib(CullFaceAttrib.makePanda()) else: terrain_node.clearAttrib(CullFaceAttrib.getClassType()) print(f"视锥体剔除已{'启用' if enabled else '禁用'}") return True except Exception as e: print(f"设置视锥体剔除时出错: {e}") return False return False