1558 lines
62 KiB
Python
1558 lines
62 KiB
Python
"""
|
||
地形天气和环境系统
|
||
提供完整的天气模拟、环境效果、光照控制、动态天空等功能
|
||
"""
|
||
|
||
from panda3d.core import NodePath, Vec3, Point3, Vec4, LVector3f
|
||
from panda3d.core import AmbientLight, DirectionalLight, PointLight, Spotlight
|
||
from panda3d.core import Fog, Shader, ShaderAttrib, PerspectiveLens
|
||
from panda3d.core import Texture, TextureStage, CardMaker
|
||
from panda3d.core import PNMImage, Filename, ClockObject
|
||
from panda3d.core import deg2Rad, rad2Deg
|
||
import math
|
||
import random
|
||
import json
|
||
import os
|
||
from collections import deque
|
||
|
||
class EnvironmentSystem:
|
||
"""
|
||
地形天气和环境系统类
|
||
提供完整的天气模拟、环境效果、光照控制、动态天空等功能
|
||
"""
|
||
|
||
def __init__(self, world):
|
||
self.world = world
|
||
self.weather_conditions = {} # 存储天气条件
|
||
self.environment_effects = {} # 存储环境效果
|
||
self.lighting_system = {} # 存储光照系统
|
||
self.particle_systems = [] # 存储粒子系统
|
||
self.weather_enabled = True
|
||
self.current_weather = 'sunny'
|
||
self.time_of_day = 12.0 # 24小时制
|
||
self.current_season = 'summer'
|
||
self.weather_transition = None # 天气过渡状态
|
||
self.sky_dome = None # 天空穹顶
|
||
self.cloud_layer = None # 云层
|
||
self.wind_vector = Vec3(1, 0, 0) # 风向量
|
||
self.wind_strength = 0.1 # 风力强度
|
||
|
||
# 性能监控
|
||
self.performance_stats = {
|
||
'last_update_time': 0.0,
|
||
'update_count': 0,
|
||
'avg_update_time': 0.0
|
||
}
|
||
|
||
# 初始化环境系统
|
||
self._init_environment_system()
|
||
|
||
def _init_environment_system(self):
|
||
"""
|
||
初始化环境系统
|
||
"""
|
||
try:
|
||
# 定义默认天气条件
|
||
self._define_default_weather()
|
||
|
||
# 初始化光照系统
|
||
self._init_lighting_system()
|
||
|
||
# 初始化环境效果
|
||
self._init_environment_effects()
|
||
|
||
# 创建动态天空
|
||
self.create_dynamic_sky('dome')
|
||
|
||
print("环境系统初始化完成")
|
||
|
||
except Exception as e:
|
||
print(f"初始化环境系统时出错: {e}")
|
||
|
||
def _define_default_weather(self):
|
||
"""
|
||
定义默认天气条件(增强版)
|
||
"""
|
||
self.weather_conditions = {
|
||
'sunny': {
|
||
'name': '晴天',
|
||
'ambient_light': (0.3, 0.3, 0.3, 1.0),
|
||
'directional_light': (0.8, 0.8, 0.8, 1.0),
|
||
'light_color_temp': 5500, # 色温(K)
|
||
'fog_color': (0.5, 0.5, 0.5, 1.0),
|
||
'fog_density': 0.0,
|
||
'particle_effects': [],
|
||
'wind_strength': 0.1,
|
||
'temperature': 25.0,
|
||
'humidity': 30.0,
|
||
'visibility': 20000.0, # 能见度(米)
|
||
'cloud_coverage': 0.1, # 云覆盖率
|
||
'precipitation': 0.0, # 降水量
|
||
'sky_tint': (1.0, 1.0, 1.0, 1.0), # 天空着色
|
||
'sun_intensity': 1.0,
|
||
'moon_intensity': 0.0
|
||
},
|
||
'cloudy': {
|
||
'name': '多云',
|
||
'ambient_light': (0.2, 0.2, 0.2, 1.0),
|
||
'directional_light': (0.5, 0.5, 0.5, 1.0),
|
||
'light_color_temp': 4500,
|
||
'fog_color': (0.7, 0.7, 0.7, 1.0),
|
||
'fog_density': 0.001,
|
||
'particle_effects': ['clouds'],
|
||
'wind_strength': 0.3,
|
||
'temperature': 20.0,
|
||
'humidity': 60.0,
|
||
'visibility': 5000.0,
|
||
'cloud_coverage': 0.7,
|
||
'precipitation': 0.0,
|
||
'sky_tint': (0.8, 0.8, 0.8, 1.0),
|
||
'sun_intensity': 0.6,
|
||
'moon_intensity': 0.1
|
||
},
|
||
'rainy': {
|
||
'name': '雨天',
|
||
'ambient_light': (0.1, 0.1, 0.1, 1.0),
|
||
'directional_light': (0.3, 0.3, 0.3, 1.0),
|
||
'light_color_temp': 6500,
|
||
'fog_color': (0.8, 0.8, 0.8, 1.0),
|
||
'fog_density': 0.002,
|
||
'particle_effects': ['rain', 'clouds'],
|
||
'wind_strength': 0.5,
|
||
'temperature': 15.0,
|
||
'humidity': 90.0,
|
||
'visibility': 1000.0,
|
||
'cloud_coverage': 0.9,
|
||
'precipitation': 5.0,
|
||
'sky_tint': (0.7, 0.7, 0.7, 1.0),
|
||
'sun_intensity': 0.3,
|
||
'moon_intensity': 0.2
|
||
},
|
||
'stormy': {
|
||
'name': '暴风雨',
|
||
'ambient_light': (0.05, 0.05, 0.05, 1.0),
|
||
'directional_light': (0.2, 0.2, 0.2, 1.0),
|
||
'light_color_temp': 7000,
|
||
'fog_color': (0.9, 0.9, 0.9, 1.0),
|
||
'fog_density': 0.003,
|
||
'particle_effects': ['rain', 'lightning', 'clouds'],
|
||
'wind_strength': 1.0,
|
||
'temperature': 10.0,
|
||
'humidity': 95.0,
|
||
'visibility': 500.0,
|
||
'cloud_coverage': 1.0,
|
||
'precipitation': 20.0,
|
||
'sky_tint': (0.5, 0.5, 0.5, 1.0),
|
||
'sun_intensity': 0.1,
|
||
'moon_intensity': 0.3
|
||
},
|
||
'snowy': {
|
||
'name': '雪天',
|
||
'ambient_light': (0.2, 0.2, 0.2, 1.0),
|
||
'directional_light': (0.4, 0.4, 0.4, 1.0),
|
||
'light_color_temp': 5000,
|
||
'fog_color': (0.9, 0.9, 0.9, 1.0),
|
||
'fog_density': 0.001,
|
||
'particle_effects': ['snow', 'clouds'],
|
||
'wind_strength': 0.4,
|
||
'temperature': -5.0,
|
||
'humidity': 80.0,
|
||
'visibility': 2000.0,
|
||
'cloud_coverage': 0.8,
|
||
'precipitation': 3.0,
|
||
'sky_tint': (0.9, 0.9, 1.0, 1.0),
|
||
'sun_intensity': 0.4,
|
||
'moon_intensity': 0.4
|
||
},
|
||
'foggy': {
|
||
'name': '雾天',
|
||
'ambient_light': (0.15, 0.15, 0.15, 1.0),
|
||
'directional_light': (0.2, 0.2, 0.2, 1.0),
|
||
'light_color_temp': 3000,
|
||
'fog_color': (0.95, 0.95, 0.95, 1.0),
|
||
'fog_density': 0.005,
|
||
'particle_effects': ['mist'],
|
||
'wind_strength': 0.2,
|
||
'temperature': 12.0,
|
||
'humidity': 98.0,
|
||
'visibility': 200.0,
|
||
'cloud_coverage': 0.3,
|
||
'precipitation': 0.1,
|
||
'sky_tint': (0.9, 0.9, 0.9, 1.0),
|
||
'sun_intensity': 0.2,
|
||
'moon_intensity': 0.1
|
||
}
|
||
}
|
||
|
||
def _init_lighting_system(self):
|
||
"""
|
||
初始化光照系统(增强版)
|
||
"""
|
||
try:
|
||
# 创建环境光
|
||
ambient_light = AmbientLight('ambient_light')
|
||
ambient_light.setColor(Vec4(0.3, 0.3, 0.3, 1.0))
|
||
self.ambient_light_np = self.world.render.attachNewNode(ambient_light)
|
||
self.world.render.setLight(self.ambient_light_np)
|
||
|
||
# 创建方向光(太阳光)
|
||
directional_light = DirectionalLight('directional_light')
|
||
directional_light.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
|
||
directional_light.setShadowCaster(True, 2048, 2048)
|
||
directional_light.setCameraMask(0x00000001) # 设置相机掩码
|
||
self.directional_light_np = self.world.render.attachNewNode(directional_light)
|
||
self.directional_light_np.setHpr(45, -45, 0)
|
||
self.world.render.setLight(self.directional_light_np)
|
||
|
||
# 创建月光
|
||
moon_light = DirectionalLight('moon_light')
|
||
moon_light.setColor(Vec4(0.1, 0.1, 0.2, 1.0))
|
||
self.moon_light_np = self.world.render.attachNewNode(moon_light)
|
||
self.moon_light_np.setHpr(225, -30, 0)
|
||
# 初始时禁用月光
|
||
self.world.render.clearLight(self.moon_light_np)
|
||
|
||
# 保存光照节点
|
||
self.lighting_system = {
|
||
'ambient': {
|
||
'node': ambient_light,
|
||
'nodepath': self.ambient_light_np
|
||
},
|
||
'directional': {
|
||
'node': directional_light,
|
||
'nodepath': self.directional_light_np
|
||
},
|
||
'moon': {
|
||
'node': moon_light,
|
||
'nodepath': self.moon_light_np,
|
||
'enabled': False
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print(f"初始化光照系统时出错: {e}")
|
||
|
||
def _init_environment_effects(self):
|
||
"""
|
||
初始化环境效果(增强版)
|
||
"""
|
||
try:
|
||
# 初始化雾效
|
||
self.fog = Fog('environment_fog')
|
||
self.fog.setColor(0.5, 0.5, 0.5, 1.0)
|
||
self.fog.setExpDensity(0.0)
|
||
self.world.render.setFog(self.fog)
|
||
|
||
# 初始化风效
|
||
self.wind_vector = Vec3(1, 0, 0)
|
||
self.wind_strength = 0.1
|
||
|
||
# 初始化粒子系统容器
|
||
self.particle_containers = {
|
||
'rain': [],
|
||
'snow': [],
|
||
'clouds': [],
|
||
'lightning': [],
|
||
'mist': []
|
||
}
|
||
|
||
except Exception as e:
|
||
print(f"初始化环境效果时出错: {e}")
|
||
|
||
def set_weather(self, weather_type, transition_time=5.0):
|
||
"""
|
||
设置天气(增强版)
|
||
"""
|
||
try:
|
||
if weather_type not in self.weather_conditions:
|
||
print(f"未知的天气类型: {weather_type}")
|
||
return False
|
||
|
||
# 如果已经有过渡效果,取消它
|
||
if self.weather_transition:
|
||
self.weather_transition = None
|
||
|
||
# 如果需要平滑过渡
|
||
if transition_time > 0 and self.current_weather != weather_type:
|
||
self.weather_transition = {
|
||
'from': self.current_weather,
|
||
'to': weather_type,
|
||
'start_time': self.world.globalClock.getFrameTime(),
|
||
'duration': transition_time,
|
||
'progress': 0.0
|
||
}
|
||
print(f"开始天气过渡: {self.current_weather} -> {weather_type}")
|
||
else:
|
||
# 直接切换天气
|
||
self._apply_weather_immediately(weather_type)
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"设置天气时出错: {e}")
|
||
return False
|
||
|
||
def _apply_weather_immediately(self, weather_type):
|
||
"""
|
||
立即应用天气
|
||
"""
|
||
try:
|
||
weather = self.weather_conditions[weather_type]
|
||
self.current_weather = weather_type
|
||
|
||
# 更新环境光
|
||
if 'ambient' in self.lighting_system:
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(*weather['ambient_light']))
|
||
|
||
# 更新方向光
|
||
if 'directional' in self.lighting_system:
|
||
light_node = self.lighting_system['directional']['node']
|
||
light_node.setColor(Vec4(*weather['directional_light']))
|
||
|
||
# 更新雾效
|
||
fog_color = weather['fog_color']
|
||
self.fog.setColor(fog_color[0], fog_color[1], fog_color[2], fog_color[3])
|
||
self.fog.setExpDensity(weather['fog_density'])
|
||
|
||
# 更新风效
|
||
self.wind_strength = weather['wind_strength']
|
||
|
||
# 更新粒子效果
|
||
self._update_particle_effects(weather['particle_effects'])
|
||
|
||
# 应用天气着色器
|
||
self._apply_weather_shader(weather_type)
|
||
|
||
# 更新天空
|
||
self._update_sky_for_weather(weather_type)
|
||
|
||
print(f"设置天气为: {weather['name']}")
|
||
|
||
except Exception as e:
|
||
print(f"立即应用天气时出错: {e}")
|
||
|
||
def _update_particle_effects(self, effects_list):
|
||
"""
|
||
更新粒子效果(增强版)
|
||
"""
|
||
try:
|
||
# 清除现有粒子效果
|
||
self._clear_particle_effects()
|
||
|
||
# 创建新的粒子效果
|
||
for effect in effects_list:
|
||
if effect == 'rain':
|
||
self._create_rain_effect()
|
||
elif effect == 'snow':
|
||
self._create_snow_effect()
|
||
elif effect == 'clouds':
|
||
self._create_cloud_effect()
|
||
elif effect == 'lightning':
|
||
self._create_lightning_effect()
|
||
elif effect == 'mist':
|
||
self._create_mist_effect()
|
||
|
||
except Exception as e:
|
||
print(f"更新粒子效果时出错: {e}")
|
||
|
||
def _clear_particle_effects(self):
|
||
"""
|
||
清除粒子效果(增强版)
|
||
"""
|
||
try:
|
||
# 移除所有粒子系统节点
|
||
for effect_type, particles in self.particle_containers.items():
|
||
for particle in particles:
|
||
if particle['node'] and not particle['node'].isEmpty():
|
||
particle['node'].removeNode()
|
||
self.particle_containers[effect_type] = []
|
||
|
||
# 清空旧的粒子系统列表
|
||
self.particle_systems = []
|
||
|
||
except Exception as e:
|
||
print(f"清除粒子效果时出错: {e}")
|
||
|
||
def _create_rain_effect(self):
|
||
"""
|
||
创建雨天效果(增强版)
|
||
"""
|
||
try:
|
||
# 创建雨滴粒子系统
|
||
rain_particles = []
|
||
|
||
# 创建多个雨滴发射器以提高性能
|
||
for i in range(5):
|
||
# 创建雨滴节点
|
||
cm = CardMaker(f'rain_drop_{i}')
|
||
cm.setFrame(-0.01, 0.01, -0.1, 0.1)
|
||
rain_node = self.world.render.attachNewNode(cm.generate())
|
||
rain_node.setBin("fixed", 40) # 确保在最上层
|
||
rain_node.setDepthWrite(False)
|
||
rain_node.setDepthTest(False)
|
||
|
||
# 设置雨滴纹理(简化版本)
|
||
# 实际项目中应该加载真实的雨滴纹理
|
||
rain_node.setColor(0.5, 0.5, 1.0, 0.7)
|
||
|
||
# 创建粒子信息
|
||
particle_info = {
|
||
'type': 'rain',
|
||
'node': rain_node,
|
||
'position': Vec3(random.uniform(-50, 50), random.uniform(-50, 50), 20),
|
||
'velocity': Vec3(random.uniform(-1, 1), random.uniform(-1, 1), -20.0),
|
||
'lifetime': random.uniform(1.0, 3.0),
|
||
'age': 0.0,
|
||
'emitter_id': i
|
||
}
|
||
|
||
rain_node.setPos(particle_info['position'])
|
||
rain_particles.append(particle_info)
|
||
|
||
self.particle_containers['rain'].extend(rain_particles)
|
||
self.particle_systems.extend(rain_particles)
|
||
|
||
print("创建雨天效果")
|
||
return rain_particles
|
||
|
||
except Exception as e:
|
||
print(f"创建雨天效果时出错: {e}")
|
||
return []
|
||
|
||
def _create_snow_effect(self):
|
||
"""
|
||
创建雪天效果(增强版)
|
||
"""
|
||
try:
|
||
# 创建雪花粒子系统
|
||
snow_particles = []
|
||
|
||
# 创建多个雪花发射器
|
||
for i in range(8):
|
||
# 创建雪花节点
|
||
cm = CardMaker(f'snow_flake_{i}')
|
||
size = random.uniform(0.05, 0.15)
|
||
cm.setFrame(-size, size, -size, size)
|
||
snow_node = self.world.render.attachNewNode(cm.generate())
|
||
snow_node.setBin("fixed", 35)
|
||
snow_node.setDepthWrite(False)
|
||
snow_node.setDepthTest(False)
|
||
|
||
# 设置雪花颜色
|
||
snow_node.setColor(1.0, 1.0, 1.0, 0.8)
|
||
|
||
# 创建粒子信息
|
||
particle_info = {
|
||
'type': 'snow',
|
||
'node': snow_node,
|
||
'position': Vec3(random.uniform(-100, 100), random.uniform(-100, 100), 30),
|
||
'velocity': Vec3(random.uniform(-2, 2), random.uniform(-2, 2), random.uniform(-5, -2)),
|
||
'lifetime': random.uniform(5.0, 10.0),
|
||
'age': 0.0,
|
||
'rotation_speed': random.uniform(-10, 10),
|
||
'emitter_id': i
|
||
}
|
||
|
||
snow_node.setPos(particle_info['position'])
|
||
snow_particles.append(particle_info)
|
||
|
||
self.particle_containers['snow'].extend(snow_particles)
|
||
self.particle_systems.extend(snow_particles)
|
||
|
||
print("创建雪天效果")
|
||
return snow_particles
|
||
|
||
except Exception as e:
|
||
print(f"创建雪天效果时出错: {e}")
|
||
return []
|
||
|
||
def _create_cloud_effect(self):
|
||
"""
|
||
创建云效果(增强版)
|
||
"""
|
||
try:
|
||
# 创建云朵粒子系统
|
||
cloud_particles = []
|
||
|
||
# 创建多个云朵
|
||
for i in range(10):
|
||
# 创建云朵节点
|
||
cm = CardMaker(f'cloud_{i}')
|
||
size = random.uniform(10, 30)
|
||
cm.setFrame(-size, size, -size/2, size/2)
|
||
cloud_node = self.world.render.attachNewNode(cm.generate())
|
||
cloud_node.setBin("fixed", 30)
|
||
cloud_node.setDepthWrite(False)
|
||
cloud_node.setDepthTest(False)
|
||
|
||
# 设置云朵颜色和透明度
|
||
cloud_node.setColor(1.0, 1.0, 1.0, random.uniform(0.3, 0.7))
|
||
|
||
# 创建粒子信息
|
||
particle_info = {
|
||
'type': 'clouds',
|
||
'node': cloud_node,
|
||
'position': Vec3(random.uniform(-200, 200), random.uniform(-200, 200), random.uniform(50, 80)),
|
||
'velocity': Vec3(random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5), 0),
|
||
'lifetime': float('inf'), # 永久存在
|
||
'age': 0.0,
|
||
'scale': size,
|
||
'emitter_id': i
|
||
}
|
||
|
||
cloud_node.setPos(particle_info['position'])
|
||
cloud_particles.append(particle_info)
|
||
|
||
self.particle_containers['clouds'].extend(cloud_particles)
|
||
self.particle_systems.extend(cloud_particles)
|
||
|
||
print("创建云效果")
|
||
return cloud_particles
|
||
|
||
except Exception as e:
|
||
print(f"创建云效果时出错: {e}")
|
||
return []
|
||
|
||
def _create_lightning_effect(self):
|
||
"""
|
||
创建闪电效果(增强版)
|
||
"""
|
||
try:
|
||
# 创建闪电效果
|
||
lightning_effects = []
|
||
|
||
# 创建闪电节点
|
||
cm = CardMaker('lightning')
|
||
cm.setFrame(-100, 100, -100, 100)
|
||
lightning_node = self.world.render.attachNewNode(cm.generate())
|
||
lightning_node.setBin("fixed", 50)
|
||
lightning_node.setDepthWrite(False)
|
||
lightning_node.setDepthTest(False)
|
||
|
||
# 设置初始不可见
|
||
lightning_node.hide()
|
||
|
||
# 创建闪电信息
|
||
lightning_info = {
|
||
'type': 'lightning',
|
||
'node': lightning_node,
|
||
'position': Vec3(0, 0, 100),
|
||
'lifetime': 0.1, # 闪电持续时间很短
|
||
'age': 0.0,
|
||
'next_strike_time': random.uniform(5, 15), # 下次闪电时间
|
||
'intensity': 2.0
|
||
}
|
||
|
||
lightning_node.setPos(lightning_info['position'])
|
||
lightning_effects.append(lightning_info)
|
||
|
||
self.particle_containers['lightning'].extend(lightning_effects)
|
||
self.particle_systems.extend(lightning_effects)
|
||
|
||
print("创建闪电效果")
|
||
return lightning_effects
|
||
|
||
except Exception as e:
|
||
print(f"创建闪电效果时出错: {e}")
|
||
return []
|
||
|
||
def _create_mist_effect(self):
|
||
"""
|
||
创建雾气效果(增强版)
|
||
"""
|
||
try:
|
||
# 创建雾气粒子系统
|
||
mist_particles = []
|
||
|
||
# 创建多个雾气发射器
|
||
for i in range(3):
|
||
# 创建雾气节点
|
||
cm = CardMaker(f'mist_{i}')
|
||
size = random.uniform(20, 50)
|
||
cm.setFrame(-size, size, -size/2, size/2)
|
||
mist_node = self.world.render.attachNewNode(cm.generate())
|
||
mist_node.setBin("fixed", 25)
|
||
mist_node.setDepthWrite(False)
|
||
mist_node.setDepthTest(False)
|
||
|
||
# 设置雾气颜色
|
||
mist_node.setColor(0.9, 0.9, 0.9, random.uniform(0.2, 0.4))
|
||
|
||
# 创建粒子信息
|
||
particle_info = {
|
||
'type': 'mist',
|
||
'node': mist_node,
|
||
'position': Vec3(random.uniform(-100, 100), random.uniform(-100, 100), random.uniform(0, 5)),
|
||
'velocity': Vec3(random.uniform(-0.2, 0.2), random.uniform(-0.2, 0.2), 0),
|
||
'lifetime': float('inf'),
|
||
'age': 0.0,
|
||
'scale': size,
|
||
'emitter_id': i
|
||
}
|
||
|
||
mist_node.setPos(particle_info['position'])
|
||
mist_particles.append(particle_info)
|
||
|
||
self.particle_containers['mist'].extend(mist_particles)
|
||
self.particle_systems.extend(mist_particles)
|
||
|
||
print("创建雾气效果")
|
||
return mist_particles
|
||
|
||
except Exception as e:
|
||
print(f"创建雾气效果时出错: {e}")
|
||
return []
|
||
|
||
def _apply_weather_shader(self, weather_type):
|
||
"""
|
||
应用天气着色器(增强版)
|
||
"""
|
||
try:
|
||
# 如果使用RenderPipeline,应用天气效果
|
||
if hasattr(self.world, 'render_pipeline'):
|
||
try:
|
||
# 根据天气类型选择着色器
|
||
if weather_type == 'rainy':
|
||
effect_file = "effects/rain_weather.yaml"
|
||
elif weather_type == 'stormy':
|
||
effect_file = "effects/storm_weather.yaml"
|
||
elif weather_type == 'snowy':
|
||
effect_file = "effects/snow_weather.yaml"
|
||
elif weather_type == 'foggy':
|
||
effect_file = "effects/fog_weather.yaml"
|
||
else:
|
||
effect_file = "effects/default_weather.yaml"
|
||
|
||
self.world.render_pipeline.set_effect(
|
||
self.world.render,
|
||
effect_file,
|
||
{
|
||
"weather_type": weather_type,
|
||
"wind_strength": self.wind_strength,
|
||
"fog_density": self.weather_conditions[weather_type]['fog_density'],
|
||
"time_of_day": self.time_of_day
|
||
},
|
||
5 # 排序值
|
||
)
|
||
|
||
except Exception as e:
|
||
print(f"应用天气着色器失败: {e}")
|
||
|
||
except Exception as e:
|
||
print(f"应用天气着色器时出错: {e}")
|
||
|
||
def update_environment(self, time_delta):
|
||
"""
|
||
更新环境系统(增强版)
|
||
"""
|
||
try:
|
||
if not self.weather_enabled:
|
||
return
|
||
|
||
# 性能监控开始
|
||
start_time = self.world.globalClock.getRealTime()
|
||
|
||
# 更新天气过渡
|
||
self._update_weather_transition(time_delta)
|
||
|
||
# 更新粒子效果
|
||
self._update_particles(time_delta)
|
||
|
||
# 更新风效
|
||
self._update_wind(time_delta)
|
||
|
||
# 更新光照
|
||
self._update_lighting(time_delta)
|
||
|
||
# 更新天空
|
||
self._update_sky(time_delta)
|
||
|
||
# 更新性能统计
|
||
end_time = self.world.globalClock.getRealTime()
|
||
update_time = end_time - start_time
|
||
self.performance_stats['last_update_time'] = update_time
|
||
self.performance_stats['update_count'] += 1
|
||
|
||
# 计算平均更新时间
|
||
if self.performance_stats['update_count'] > 1:
|
||
alpha = 0.1
|
||
self.performance_stats['avg_update_time'] = (
|
||
alpha * update_time +
|
||
(1 - alpha) * self.performance_stats['avg_update_time']
|
||
)
|
||
else:
|
||
self.performance_stats['avg_update_time'] = update_time
|
||
|
||
except Exception as e:
|
||
print(f"更新环境系统时出错: {e}")
|
||
|
||
def _update_weather_transition(self, time_delta):
|
||
"""
|
||
更新天气过渡效果
|
||
"""
|
||
try:
|
||
if not self.weather_transition:
|
||
return
|
||
|
||
# 更新过渡进度
|
||
current_time = self.world.globalClock.getFrameTime()
|
||
elapsed = current_time - self.weather_transition['start_time']
|
||
progress = min(1.0, elapsed / self.weather_transition['duration'])
|
||
|
||
self.weather_transition['progress'] = progress
|
||
|
||
# 获取起始和目标天气
|
||
from_weather = self.weather_conditions[self.weather_transition['from']]
|
||
to_weather = self.weather_conditions[self.weather_transition['to']]
|
||
|
||
# 插值计算当前天气参数
|
||
if progress >= 1.0:
|
||
# 过渡完成,应用最终天气
|
||
self._apply_weather_immediately(self.weather_transition['to'])
|
||
self.weather_transition = None
|
||
else:
|
||
# 过渡中,插值计算参数
|
||
self._interpolate_weather_parameters(from_weather, to_weather, progress)
|
||
|
||
except Exception as e:
|
||
print(f"更新天气过渡时出错: {e}")
|
||
|
||
def _interpolate_weather_parameters(self, from_weather, to_weather, progress):
|
||
"""
|
||
插值计算天气参数
|
||
"""
|
||
try:
|
||
# 线性插值函数
|
||
def lerp(a, b, t):
|
||
if isinstance(a, (list, tuple)) and len(a) == len(b):
|
||
return [a[i] + (b[i] - a[i]) * t for i in range(len(a))]
|
||
return a + (b - a) * t
|
||
|
||
# 插值环境光
|
||
if 'ambient' in self.lighting_system:
|
||
ambient_from = from_weather['ambient_light']
|
||
ambient_to = to_weather['ambient_light']
|
||
ambient_current = lerp(ambient_from, ambient_to, progress)
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(*ambient_current))
|
||
|
||
# 插值方向光
|
||
if 'directional' in self.lighting_system:
|
||
directional_from = from_weather['directional_light']
|
||
directional_to = to_weather['directional_light']
|
||
directional_current = lerp(directional_from, directional_to, progress)
|
||
light_node = self.lighting_system['directional']['node']
|
||
light_node.setColor(Vec4(*directional_current))
|
||
|
||
# 插值雾效
|
||
fog_from = from_weather['fog_color']
|
||
fog_to = to_weather['fog_color']
|
||
fog_color_current = lerp(fog_from, fog_to, progress)
|
||
self.fog.setColor(fog_color_current[0], fog_color_current[1], fog_color_current[2], fog_color_current[3])
|
||
|
||
fog_density_from = from_weather['fog_density']
|
||
fog_density_to = to_weather['fog_density']
|
||
fog_density_current = lerp(fog_density_from, fog_density_to, progress)
|
||
self.fog.setExpDensity(fog_density_current)
|
||
|
||
# 插值风力
|
||
wind_from = from_weather['wind_strength']
|
||
wind_to = to_weather['wind_strength']
|
||
self.wind_strength = lerp(wind_from, wind_to, progress)
|
||
|
||
except Exception as e:
|
||
print(f"插值天气参数时出错: {e}")
|
||
|
||
def _update_particles(self, time_delta):
|
||
"""
|
||
更新粒子效果(增强版)
|
||
"""
|
||
try:
|
||
current_time = self.world.globalClock.getFrameTime()
|
||
|
||
# 更新所有粒子系统
|
||
for particle in self.particle_systems[:]: # 使用切片复制
|
||
# 更新粒子年龄
|
||
particle['age'] += time_delta
|
||
|
||
# 检查生命周期
|
||
if particle['lifetime'] != float('inf') and particle['age'] > particle['lifetime']:
|
||
# 移除过期粒子
|
||
if particle['node'] and not particle['node'].isEmpty():
|
||
particle['node'].removeNode()
|
||
if particle in self.particle_systems:
|
||
self.particle_systems.remove(particle)
|
||
continue
|
||
|
||
# 根据粒子类型更新
|
||
if particle['type'] == 'rain':
|
||
self._update_rain_particle(particle, time_delta, current_time)
|
||
elif particle['type'] == 'snow':
|
||
self._update_snow_particle(particle, time_delta, current_time)
|
||
elif particle['type'] == 'clouds':
|
||
self._update_cloud_particle(particle, time_delta, current_time)
|
||
elif particle['type'] == 'lightning':
|
||
self._update_lightning_particle(particle, time_delta, current_time)
|
||
elif particle['type'] == 'mist':
|
||
self._update_mist_particle(particle, time_delta, current_time)
|
||
|
||
except Exception as e:
|
||
print(f"更新粒子效果时出错: {e}")
|
||
|
||
def _update_rain_particle(self, particle, time_delta, current_time):
|
||
"""
|
||
更新雨滴粒子
|
||
"""
|
||
try:
|
||
# 更新位置
|
||
particle['position'] += particle['velocity'] * time_delta
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 如果雨滴落到地面以下,重置位置
|
||
if particle['position'].getZ() < 0:
|
||
particle['position'].setZ(20) # 重置到高处
|
||
particle['position'].setX(random.uniform(-50, 50))
|
||
particle['position'].setY(random.uniform(-50, 50))
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
except Exception as e:
|
||
print(f"更新雨滴粒子时出错: {e}")
|
||
|
||
def _update_snow_particle(self, particle, time_delta, current_time):
|
||
"""
|
||
更新雪花粒子
|
||
"""
|
||
try:
|
||
# 更新位置
|
||
particle['position'] += particle['velocity'] * time_delta
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 添加摆动效果
|
||
sway = math.sin(current_time * 2 + particle['emitter_id']) * 0.5
|
||
particle['position'].setX(particle['position'].getX() + sway * time_delta)
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 更新旋转
|
||
particle['node'].setHpr(particle['node'].getHpr() + Vec3(0, 0, particle['rotation_speed'] * time_delta))
|
||
|
||
# 如果雪花落到地面以下,重置位置
|
||
if particle['position'].getZ() < 0:
|
||
particle['position'].setZ(30) # 重置到高处
|
||
particle['position'].setX(random.uniform(-100, 100))
|
||
particle['position'].setY(random.uniform(-100, 100))
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
except Exception as e:
|
||
print(f"更新雪花粒子时出错: {e}")
|
||
|
||
def _update_cloud_particle(self, particle, time_delta, current_time):
|
||
"""
|
||
更新云朵粒子
|
||
"""
|
||
try:
|
||
# 更新位置
|
||
particle['position'] += particle['velocity'] * time_delta
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 添加缓慢变化效果
|
||
if random.random() < 0.01: # 1%概率改变速度
|
||
particle['velocity'] = Vec3(
|
||
random.uniform(-0.5, 0.5),
|
||
random.uniform(-0.5, 0.5),
|
||
0
|
||
)
|
||
|
||
# 如果云朵移出范围,重置位置
|
||
if (abs(particle['position'].getX()) > 300 or
|
||
abs(particle['position'].getY()) > 300):
|
||
particle['position'].setX(random.uniform(-200, 200))
|
||
particle['position'].setY(random.uniform(-200, 200))
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
except Exception as e:
|
||
print(f"更新云朵粒子时出错: {e}")
|
||
|
||
def _update_lightning_particle(self, particle, time_delta, current_time):
|
||
"""
|
||
更新闪电粒子
|
||
"""
|
||
try:
|
||
# 更新计时器
|
||
particle['next_strike_time'] -= time_delta
|
||
|
||
# 检查是否触发闪电
|
||
if particle['next_strike_time'] <= 0:
|
||
# 显示闪电
|
||
particle['node'].show()
|
||
particle['age'] = 0 # 重置年龄
|
||
|
||
# 随机改变闪电位置
|
||
particle['position'] = Vec3(
|
||
random.uniform(-100, 100),
|
||
random.uniform(-100, 100),
|
||
100
|
||
)
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 设置下次闪电时间
|
||
particle['next_strike_time'] = random.uniform(5, 15)
|
||
|
||
# 增强环境光模拟闪电光照
|
||
if 'ambient' in self.lighting_system:
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
|
||
else:
|
||
# 检查是否需要隐藏闪电
|
||
if particle['age'] > particle['lifetime']:
|
||
particle['node'].hide()
|
||
# 恢复正常环境光
|
||
current_weather = self.weather_conditions[self.current_weather]
|
||
if 'ambient' in self.lighting_system:
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(*current_weather['ambient_light']))
|
||
|
||
except Exception as e:
|
||
print(f"更新闪电粒子时出错: {e}")
|
||
|
||
def _update_mist_particle(self, particle, time_delta, current_time):
|
||
"""
|
||
更新雾气粒子
|
||
"""
|
||
try:
|
||
# 更新位置
|
||
particle['position'] += particle['velocity'] * time_delta
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
# 缓慢改变透明度
|
||
alpha = particle['node'].getColor().getW()
|
||
alpha += random.uniform(-0.01, 0.01)
|
||
alpha = max(0.1, min(0.5, alpha)) # 限制在合理范围内
|
||
particle['node'].setColor(
|
||
particle['node'].getColor().getX(),
|
||
particle['node'].getColor().getY(),
|
||
particle['node'].getColor().getZ(),
|
||
alpha
|
||
)
|
||
|
||
# 如果雾气移出范围,重置位置
|
||
if (abs(particle['position'].getX()) > 200 or
|
||
abs(particle['position'].getY()) > 200):
|
||
particle['position'].setX(random.uniform(-100, 100))
|
||
particle['position'].setY(random.uniform(-100, 100))
|
||
particle['node'].setPos(particle['position'])
|
||
|
||
except Exception as e:
|
||
print(f"更新雾气粒子时出错: {e}")
|
||
|
||
def _update_wind(self, time_delta):
|
||
"""
|
||
更新风效(增强版)
|
||
"""
|
||
try:
|
||
# 可以实现风向和风力的变化
|
||
# 例如随机改变风向或模拟阵风
|
||
current_weather = self.weather_conditions[self.current_weather]
|
||
|
||
# 模拟阵风效果
|
||
gust_factor = 1.0 + math.sin(self.world.globalClock.getFrameTime() * 0.5) * 0.3
|
||
self.wind_vector = Vec3(
|
||
math.cos(self.world.globalClock.getFrameTime() * 0.1) * gust_factor,
|
||
math.sin(self.world.globalClock.getFrameTime() * 0.1) * gust_factor,
|
||
0
|
||
) * current_weather['wind_strength']
|
||
|
||
except Exception as e:
|
||
print(f"更新风效时出错: {e}")
|
||
|
||
def _update_lighting(self, time_delta):
|
||
"""
|
||
更新光照(增强版)
|
||
"""
|
||
try:
|
||
# 更新时间
|
||
self.time_of_day += time_delta / 3600.0 # 假设1秒对应1小时
|
||
if self.time_of_day >= 24.0:
|
||
self.time_of_day -= 24.0
|
||
|
||
# 根据时间调整太阳和月亮位置
|
||
self._update_celestial_positions()
|
||
|
||
# 根据时间调整光照颜色
|
||
self._update_lighting_colors()
|
||
|
||
except Exception as e:
|
||
print(f"更新光照时出错: {e}")
|
||
|
||
def _update_celestial_positions(self):
|
||
"""
|
||
更新天体位置
|
||
"""
|
||
try:
|
||
# 计算太阳位置(简化模型)
|
||
sun_angle = self.time_of_day / 24.0 * 360.0
|
||
sun_elevation = math.sin(deg2Rad(sun_angle)) * 60.0 # 最大仰角60度
|
||
|
||
if hasattr(self, 'directional_light_np'):
|
||
self.directional_light_np.setHpr(sun_angle, -sun_elevation, 0)
|
||
|
||
# 计算月亮位置(与太阳相差180度)
|
||
moon_angle = (sun_angle + 180.0) % 360.0
|
||
moon_elevation = math.sin(deg2Rad(moon_angle)) * 50.0
|
||
|
||
if hasattr(self, 'moon_light_np'):
|
||
self.moon_light_np.setHpr(moon_angle, -moon_elevation, 0)
|
||
|
||
# 根据太阳高度控制月亮显示
|
||
if sun_elevation < -10.0: # 太阳在地平线以下10度时显示月亮
|
||
if not self.lighting_system['moon']['enabled']:
|
||
self.world.render.setLight(self.moon_light_np)
|
||
self.lighting_system['moon']['enabled'] = True
|
||
else:
|
||
if self.lighting_system['moon']['enabled']:
|
||
self.world.render.clearLight(self.moon_light_np)
|
||
self.lighting_system['moon']['enabled'] = False
|
||
|
||
except Exception as e:
|
||
print(f"更新天体位置时出错: {e}")
|
||
|
||
def _update_lighting_colors(self):
|
||
"""
|
||
更新光照颜色
|
||
"""
|
||
try:
|
||
# 根据太阳高度调整光照颜色
|
||
sun_elevation = math.sin(deg2Rad(self.time_of_day / 24.0 * 360.0)) * 60.0
|
||
|
||
# 计算日照因子
|
||
day_factor = max(0.0, min(1.0, (sun_elevation + 10.0) / 70.0)) # 从-10度到60度
|
||
|
||
# 获取当前天气
|
||
current_weather = self.weather_conditions[self.current_weather]
|
||
|
||
# 插值计算光照颜色
|
||
if 'directional' in self.lighting_system:
|
||
day_color = current_weather['directional_light']
|
||
night_color = (0.1, 0.1, 0.2, 1.0) # 月光颜色
|
||
light_color = [
|
||
day_color[i] * day_factor + night_color[i] * (1.0 - day_factor)
|
||
for i in range(4)
|
||
]
|
||
light_node = self.lighting_system['directional']['node']
|
||
light_node.setColor(Vec4(*light_color))
|
||
|
||
# 更新环境光
|
||
if 'ambient' in self.lighting_system:
|
||
day_ambient = current_weather['ambient_light']
|
||
night_ambient = (0.05, 0.05, 0.1, 1.0)
|
||
ambient_color = [
|
||
day_ambient[i] * day_factor + night_ambient[i] * (1.0 - day_factor)
|
||
for i in range(4)
|
||
]
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(*ambient_color))
|
||
|
||
except Exception as e:
|
||
print(f"更新光照颜色时出错: {e}")
|
||
|
||
def _update_sky(self, time_delta):
|
||
"""
|
||
更新天空(增强版)
|
||
"""
|
||
try:
|
||
# 更新天空颜色
|
||
self._update_sky_color()
|
||
|
||
# 更新云层
|
||
self._update_cloud_layer(time_delta)
|
||
|
||
except Exception as e:
|
||
print(f"更新天空时出错: {e}")
|
||
|
||
def _update_sky_color(self):
|
||
"""
|
||
更新天空颜色
|
||
"""
|
||
try:
|
||
# 根据时间、天气和季节调整天空颜色
|
||
current_weather = self.weather_conditions[self.current_weather]
|
||
sky_tint = current_weather['sky_tint']
|
||
|
||
# 根据太阳高度调整天空颜色
|
||
sun_elevation = math.sin(deg2Rad(self.time_of_day / 24.0 * 360.0)) * 60.0
|
||
day_factor = max(0.0, min(1.0, (sun_elevation + 10.0) / 70.0))
|
||
|
||
# 计算天空颜色
|
||
day_sky = (0.4, 0.6, 1.0, 1.0) # 白天天空蓝
|
||
night_sky = (0.05, 0.05, 0.1, 1.0) # 夜晚天空暗
|
||
|
||
sky_color = [
|
||
(day_sky[i] * sky_tint[i] * day_factor + night_sky[i] * (1.0 - day_factor))
|
||
* current_weather['sun_intensity']
|
||
for i in range(4)
|
||
]
|
||
|
||
# 应用天空颜色到天空穹顶
|
||
if self.sky_dome:
|
||
self.sky_dome.setColor(Vec4(*sky_color))
|
||
|
||
except Exception as e:
|
||
print(f"更新天空颜色时出错: {e}")
|
||
|
||
def _update_cloud_layer(self, time_delta):
|
||
"""
|
||
更新云层
|
||
"""
|
||
# 云层更新已在粒子系统中处理
|
||
pass
|
||
|
||
def _update_sky_for_weather(self, weather_type):
|
||
"""
|
||
根据天气更新天空
|
||
"""
|
||
try:
|
||
if self.sky_dome:
|
||
current_weather = self.weather_conditions[weather_type]
|
||
# 可以根据天气调整天空穹顶的纹理或颜色
|
||
pass
|
||
|
||
except Exception as e:
|
||
print(f"根据天气更新天空时出错: {e}")
|
||
|
||
def set_time_of_day(self, hour, minute=0):
|
||
"""
|
||
设置一天中的时间(增强版)
|
||
"""
|
||
try:
|
||
self.time_of_day = hour + minute / 60.0
|
||
|
||
# 立即更新光照和天空
|
||
self._update_celestial_positions()
|
||
self._update_lighting_colors()
|
||
self._update_sky_color()
|
||
|
||
print(f"设置时间为: {hour:02d}:{minute:02d}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"设置时间时出错: {e}")
|
||
return False
|
||
|
||
def set_season(self, season):
|
||
"""
|
||
设置季节(增强版)
|
||
"""
|
||
try:
|
||
seasons = {
|
||
'spring': {'temperature': 15.0, 'vegetation_color': (0.3, 0.7, 0.3, 1.0)},
|
||
'summer': {'temperature': 25.0, 'vegetation_color': (0.2, 0.8, 0.2, 1.0)},
|
||
'autumn': {'temperature': 10.0, 'vegetation_color': (0.8, 0.5, 0.2, 1.0)},
|
||
'winter': {'temperature': -5.0, 'vegetation_color': (0.6, 0.6, 0.8, 1.0)}
|
||
}
|
||
|
||
if season in seasons:
|
||
self.current_season = season
|
||
season_data = seasons[season]
|
||
print(f"设置季节为: {season}")
|
||
return season_data
|
||
|
||
except Exception as e:
|
||
print(f"设置季节时出错: {e}")
|
||
return None
|
||
|
||
def create_dynamic_sky(self, sky_type='dome'):
|
||
"""
|
||
创建动态天空(增强版)
|
||
"""
|
||
try:
|
||
# 移除现有的天空
|
||
if self.sky_dome and not self.sky_dome.isEmpty():
|
||
self.sky_dome.removeNode()
|
||
|
||
# 创建天空穹顶
|
||
if sky_type == 'dome':
|
||
self._create_sky_dome()
|
||
elif sky_type == 'box':
|
||
self._create_sky_box()
|
||
elif sky_type == 'procedural':
|
||
self._create_procedural_sky()
|
||
|
||
print(f"创建动态天空: {sky_type}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"创建动态天空时出错: {e}")
|
||
return False
|
||
|
||
def _create_sky_dome(self):
|
||
"""
|
||
创建天空穹顶(增强版)
|
||
"""
|
||
try:
|
||
# 创建天空穹顶几何体
|
||
from panda3d.core import GeomVertexFormat, GeomVertexData, GeomVertexWriter
|
||
from panda3d.core import GeomTriangles, Geom, GeomNode
|
||
|
||
# 创建顶点数据
|
||
vformat = GeomVertexFormat.getV3c4()
|
||
vdata = GeomVertexData('sky_dome', vformat, Geom.UHStatic)
|
||
|
||
# 添加顶点
|
||
vertex = GeomVertexWriter(vdata, 'vertex')
|
||
color = GeomVertexWriter(vdata, 'color')
|
||
|
||
# 创建半球形穹顶
|
||
radius = 1000.0
|
||
segments = 32
|
||
rings = 16
|
||
|
||
vertices = []
|
||
indices = []
|
||
|
||
# 生成顶点
|
||
for r in range(rings + 1):
|
||
for s in range(segments + 1):
|
||
# 球面坐标
|
||
theta = math.pi * r / rings # 从0到π
|
||
phi = 2 * math.pi * s / segments # 从0到2π
|
||
|
||
x = radius * math.sin(theta) * math.cos(phi)
|
||
y = radius * math.sin(theta) * math.sin(phi)
|
||
z = radius * math.cos(theta)
|
||
|
||
vertices.append((x, y, z))
|
||
|
||
# 生成索引
|
||
for r in range(rings):
|
||
for s in range(segments):
|
||
# 计算四个顶点的索引
|
||
i1 = r * (segments + 1) + s
|
||
i2 = r * (segments + 1) + (s + 1)
|
||
i3 = (r + 1) * (segments + 1) + s
|
||
i4 = (r + 1) * (segments + 1) + (s + 1)
|
||
|
||
# 添加两个三角形
|
||
indices.extend([i1, i3, i2])
|
||
indices.extend([i2, i3, i4])
|
||
|
||
# 写入顶点数据
|
||
for i, (x, y, z) in enumerate(vertices):
|
||
vertex.addData3(x, y, z)
|
||
# 默认天空颜色
|
||
color.addData4(0.4, 0.6, 1.0, 1.0)
|
||
|
||
# 创建几何体
|
||
geom = Geom(vdata)
|
||
prim = GeomTriangles(Geom.UHStatic)
|
||
|
||
# 添加索引
|
||
for idx in indices:
|
||
prim.addVertex(idx)
|
||
prim.closePrimitive()
|
||
|
||
geom.addPrimitive(prim)
|
||
|
||
# 创建节点
|
||
node = GeomNode('sky_dome')
|
||
node.addGeom(geom)
|
||
|
||
# 创建节点路径
|
||
self.sky_dome = self.world.render.attachNewNode(node)
|
||
|
||
# 设置渲染属性
|
||
self.sky_dome.setBin("background", 0)
|
||
self.sky_dome.setDepthWrite(False)
|
||
self.sky_dome.setDepthTest(False)
|
||
self.sky_dome.setLightOff()
|
||
self.sky_dome.setFogOff()
|
||
|
||
# 设置位置在相机中心
|
||
self.sky_dome.setCompass() # 跟随相机旋转但不移动
|
||
|
||
print("创建天空穹顶")
|
||
|
||
except Exception as e:
|
||
print(f"创建天空穹顶时出错: {e}")
|
||
|
||
def _create_sky_box(self):
|
||
"""
|
||
创建天空盒
|
||
"""
|
||
# 简化实现,实际项目中应该加载立方体贴图
|
||
print("创建天空盒(简化实现)")
|
||
pass
|
||
|
||
def _create_procedural_sky(self):
|
||
"""
|
||
创建程序化天空
|
||
"""
|
||
# 简化实现,实际项目中应该使用着色器生成程序化天空
|
||
print("创建程序化天空(简化实现)")
|
||
pass
|
||
|
||
def simulate_weather_cycle(self, duration=3600.0, cycle_pattern=None):
|
||
"""
|
||
模拟天气循环(增强版)
|
||
"""
|
||
try:
|
||
# 创建天气变化序列
|
||
if cycle_pattern is None:
|
||
# 默认循环模式
|
||
cycle_pattern = ['sunny', 'cloudy', 'rainy', 'stormy', 'snowy', 'foggy']
|
||
|
||
# 可以实现定时改变天气
|
||
print(f"开始天气循环模拟,持续时间: {duration}秒")
|
||
print(f"循环模式: {cycle_pattern}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"模拟天气循环时出错: {e}")
|
||
return False
|
||
|
||
def get_environment_stats(self):
|
||
"""
|
||
获取环境统计信息(增强版)
|
||
"""
|
||
stats = {
|
||
'current_weather': self.current_weather,
|
||
'time_of_day': self.time_of_day,
|
||
'current_season': self.current_season,
|
||
'weather_enabled': self.weather_enabled,
|
||
'particle_systems': len(self.particle_systems),
|
||
'fog_density': self.fog.getExpDensity() if self.fog else 0.0,
|
||
'wind_strength': self.wind_strength,
|
||
'wind_vector': (self.wind_vector.getX(), self.wind_vector.getY(), self.wind_vector.getZ()),
|
||
'ambient_light': self.lighting_system['ambient']['node'].getColor() if 'ambient' in self.lighting_system else Vec4(0,0,0,0),
|
||
'directional_light': self.lighting_system['directional']['node'].getColor() if 'directional' in self.lighting_system else Vec4(0,0,0,0),
|
||
'moon_light_enabled': self.lighting_system['moon']['enabled'] if 'moon' in self.lighting_system else False,
|
||
'sky_dome_exists': self.sky_dome is not None and not self.sky_dome.isEmpty(),
|
||
'performance': {
|
||
'last_update_time': self.performance_stats['last_update_time'],
|
||
'avg_update_time': self.performance_stats['avg_update_time'],
|
||
'update_count': self.performance_stats['update_count']
|
||
}
|
||
}
|
||
|
||
return stats
|
||
|
||
def save_environment_data(self, output_path):
|
||
"""
|
||
保存环境数据(增强版)
|
||
"""
|
||
try:
|
||
# 收集环境数据
|
||
environment_data = {
|
||
'current_weather': self.current_weather,
|
||
'time_of_day': self.time_of_day,
|
||
'current_season': self.current_season,
|
||
'weather_conditions': self.weather_conditions,
|
||
'lighting': {
|
||
'ambient': list(self.lighting_system['ambient']['node'].getColor()) if 'ambient' in self.lighting_system else [],
|
||
'directional': list(self.lighting_system['directional']['node'].getColor()) if 'directional' in self.lighting_system else [],
|
||
'moon_enabled': self.lighting_system['moon']['enabled'] if 'moon' in self.lighting_system else False
|
||
},
|
||
'fog': {
|
||
'color': list(self.fog.getColor()) if self.fog else [],
|
||
'density': self.fog.getExpDensity() if self.fog else 0.0
|
||
},
|
||
'wind': {
|
||
'strength': self.wind_strength,
|
||
'vector': [self.wind_vector.getX(), self.wind_vector.getY(), self.wind_vector.getZ()]
|
||
}
|
||
}
|
||
|
||
# 确保输出目录存在
|
||
output_dir = os.path.dirname(output_path)
|
||
if not os.path.exists(output_dir):
|
||
os.makedirs(output_dir)
|
||
|
||
# 写入JSON文件
|
||
with open(output_path, 'w', encoding='utf-8') as f:
|
||
json.dump(environment_data, f, indent=2, ensure_ascii=False)
|
||
|
||
print(f"环境数据保存成功: {output_path}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"保存环境数据时出错: {e}")
|
||
return False
|
||
|
||
def load_environment_data(self, input_path):
|
||
"""
|
||
加载环境数据(增强版)
|
||
"""
|
||
try:
|
||
if not os.path.exists(input_path):
|
||
print(f"环境数据文件不存在: {input_path}")
|
||
return False
|
||
|
||
# 读取JSON文件
|
||
with open(input_path, 'r', encoding='utf-8') as f:
|
||
environment_data = json.load(f)
|
||
|
||
# 恢复时间
|
||
if 'time_of_day' in environment_data:
|
||
self.time_of_day = environment_data['time_of_day']
|
||
|
||
# 恢复季节
|
||
if 'current_season' in environment_data:
|
||
self.current_season = environment_data['current_season']
|
||
|
||
# 恢复天气条件
|
||
if 'weather_conditions' in environment_data:
|
||
self.weather_conditions = environment_data['weather_conditions']
|
||
|
||
# 恢复当前天气
|
||
if 'current_weather' in environment_data:
|
||
self.set_weather(environment_data['current_weather'], transition_time=0)
|
||
|
||
# 恢复光照
|
||
if 'lighting' in environment_data:
|
||
lighting = environment_data['lighting']
|
||
if 'ambient' in lighting and len(lighting['ambient']) == 4:
|
||
if 'ambient' in self.lighting_system:
|
||
light_node = self.lighting_system['ambient']['node']
|
||
light_node.setColor(Vec4(*lighting['ambient']))
|
||
if 'directional' in lighting and len(lighting['directional']) == 4:
|
||
if 'directional' in self.lighting_system:
|
||
light_node = self.lighting_system['directional']['node']
|
||
light_node.setColor(Vec4(*lighting['directional']))
|
||
if 'moon_enabled' in lighting:
|
||
if lighting['moon_enabled'] and not self.lighting_system['moon']['enabled']:
|
||
self.world.render.setLight(self.moon_light_np)
|
||
self.lighting_system['moon']['enabled'] = True
|
||
elif not lighting['moon_enabled'] and self.lighting_system['moon']['enabled']:
|
||
self.world.render.clearLight(self.moon_light_np)
|
||
self.lighting_system['moon']['enabled'] = False
|
||
|
||
# 恢复雾效
|
||
if 'fog' in environment_data:
|
||
fog_data = environment_data['fog']
|
||
if 'color' in fog_data and len(fog_data['color']) == 4:
|
||
self.fog.setColor(*fog_data['color'])
|
||
if 'density' in fog_data:
|
||
self.fog.setExpDensity(fog_data['density'])
|
||
|
||
# 恢复风效
|
||
if 'wind' in environment_data:
|
||
wind_data = environment_data['wind']
|
||
if 'strength' in wind_data:
|
||
self.wind_strength = wind_data['strength']
|
||
if 'vector' in wind_data and len(wind_data['vector']) == 3:
|
||
self.wind_vector = Vec3(*wind_data['vector'])
|
||
|
||
# 更新光照和天空
|
||
self._update_celestial_positions()
|
||
self._update_lighting_colors()
|
||
self._update_sky_color()
|
||
|
||
print(f"环境数据加载成功: {input_path}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"加载环境数据时出错: {e}")
|
||
return False
|
||
|
||
def set_weather_enabled(self, enabled):
|
||
"""
|
||
启用或禁用天气系统
|
||
"""
|
||
self.weather_enabled = enabled
|
||
print(f"天气系统已{'启用' if enabled else '禁用'}")
|
||
|
||
def clear_all_environment_effects(self):
|
||
"""
|
||
清除所有环境效果(增强版)
|
||
"""
|
||
try:
|
||
# 清除粒子效果
|
||
self._clear_particle_effects()
|
||
|
||
# 重置为晴天
|
||
self.set_weather('sunny', transition_time=0)
|
||
|
||
# 清除雾效
|
||
if self.fog:
|
||
self.fog.setExpDensity(0.0)
|
||
|
||
# 重置时间
|
||
self.set_time_of_day(12, 0)
|
||
|
||
# 重置季节
|
||
self.set_season('summer')
|
||
|
||
print("清除所有环境效果")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"清除所有环境效果时出错: {e}")
|
||
return False
|
||
|
||
def create_weather_zone(self, position, radius, weather_type, transition_time=2.0):
|
||
"""
|
||
创建局部天气区域(增强版)
|
||
"""
|
||
try:
|
||
# 创建局部天气区域
|
||
# 可以实现球形或盒形的局部天气效果
|
||
weather_zone = {
|
||
'position': position,
|
||
'radius': radius,
|
||
'weather_type': weather_type,
|
||
'transition_time': transition_time,
|
||
'node': None, # 可视化节点
|
||
'creation_time': self.world.globalClock.getFrameTime(),
|
||
'active': True
|
||
}
|
||
|
||
# 可以创建一个可视化表示
|
||
cm = CardMaker('weather_zone')
|
||
cm.setFrame(-radius, radius, -radius, radius)
|
||
zone_node = self.world.render.attachNewNode(cm.generate())
|
||
zone_node.setPos(position)
|
||
zone_node.setBin("fixed", 10)
|
||
zone_node.setDepthWrite(False)
|
||
zone_node.setDepthTest(False)
|
||
zone_node.setColor(1, 1, 1, 0.2) # 半透明
|
||
zone_node.hide() # 默认隐藏
|
||
|
||
weather_zone['node'] = zone_node
|
||
|
||
print(f"创建局部天气区域: {weather_type} at {position}")
|
||
return weather_zone
|
||
|
||
except Exception as e:
|
||
print(f"创建局部天气区域时出错: {e}")
|
||
return None
|
||
|
||
def add_weather_event(self, event_type, duration, intensity=1.0):
|
||
"""
|
||
添加天气事件(如突然的阵雨、雷暴等)
|
||
"""
|
||
try:
|
||
weather_event = {
|
||
'type': event_type,
|
||
'duration': duration,
|
||
'intensity': intensity,
|
||
'start_time': self.world.globalClock.getFrameTime(),
|
||
'active': True
|
||
}
|
||
|
||
# 根据事件类型应用效果
|
||
if event_type == 'sudden_rain':
|
||
# 增加雨天粒子效果
|
||
self._create_rain_effect()
|
||
elif event_type == 'thunderstorm':
|
||
# 增加闪电和雨天效果
|
||
self._create_lightning_effect()
|
||
self._create_rain_effect()
|
||
elif event_type == 'gust_of_wind':
|
||
# 增加风力
|
||
self.wind_strength *= (1.0 + intensity)
|
||
|
||
print(f"添加天气事件: {event_type}, 持续时间: {duration}秒")
|
||
return weather_event
|
||
|
||
except Exception as e:
|
||
print(f"添加天气事件时出错: {e}")
|
||
return None |