diff --git a/sim_scenes/featured/solar_system_2149.py b/sim_scenes/featured/solar_system_2149.py new file mode 100644 index 0000000000000000000000000000000000000000..97e037cd7eebe1beb706abba425eec8276faa628 --- /dev/null +++ b/sim_scenes/featured/solar_system_2149.py @@ -0,0 +1,262 @@ +# -*- coding:utf-8 -*- +# title :模拟太阳系给天体真实时间和位置 +# description :模拟太阳系给天体真实时间和位置 +# author :Python超人 +# date :2023-07-23 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== + +import numpy as np + +from bodies import Sun, Mercury, Venus, Earth, Mars, Asteroids, Jupiter, Saturn, Uranus, Neptune, Moon, Pluto +from common.celestial_data_service import get_body_posvel, recalc_moon_position, calc_solar_acceleration, \ + set_solar_system_celestial_position, set_earth_rotation +from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HOUR, AU +from sim_scenes.func import ursina_run +from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.ui.control_ui import ControlUI +from simulators.ursina.ursina_config import UrsinaConfig +from simulators.ursina.ursina_event import UrsinaEvent +from ursina import camera, application + + +class SolarSystemRealitySim: + def __init__(self): + """ + + @param debug_mode: 是否为调试模式 + """ + self.show_asteroids = False + self.clock_position_center = False + self.show_earth_clouds = False + self.debug_mode = False + self.recalc_moon_pos = True + + def create_bodies(self): + """ + 创建太阳系的天体 + @return: + """ + # 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大 + # 太阳缩放比例 + self.sun_size_scale = 0.04e2 if self.debug_mode else 0.4e2 + + # 地月缩放比例 + # 为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变),重新计算位置后,地球和月球可以放大1000倍以上 + if self.recalc_moon_pos: # 重新计算月球位置 + self.earth_size_scale = 10e3 if self.debug_mode else 1e3 + self.moon_size_scale = 2e3 + else: + # 不重新计算,则地月的距离相对整个太阳系会非常近,因此,月球只放大了10倍 + self.earth_size_scale = 1e1 + self.moon_size_scale = 1e1 + + self.sun = Sun(name="太阳", size_scale=self.sun_size_scale*1.5) # 太阳 + self.mercury = Mercury(name="水星", size_scale=6e3*1.2) # 水星 + self.venus = Venus(name="金星", size_scale=3e3) # 金星 + self.earth = Earth(name="地球", texture="earth_hd.jpg", + rotate_angle=3.44, + size_scale=self.earth_size_scale*3) # 地球 + self.earth_clouds = Earth(name="地球云层", texture="transparent_clouds.png", show_trail=False, + rotate_angle=3.44, + size_scale=self.earth_size_scale * 1.01) # 地球云层 + self.moon = Moon(name="月球", size_scale=self.moon_size_scale) # 月球 + self.mars = Mars(name="火星", size_scale=4e3*1.5) # 火星 + self.asteroids = Asteroids(size_scale=1e2, parent=self.sun, rotate_angle=-20) # 模拟的小行星带 + self.jupiter = Jupiter(name="木星", size_scale=4e2*1.5) # 木星 + self.saturn = Saturn(name="土星", size_scale=4e2*1.5) # 土星 + self.uranus = Uranus(name="天王星", size_scale=10e2*1.5) # 天王星 + self.neptune = Neptune(name="海王星", size_scale=10e2*1.5) # 海王星 + self.pluto = Pluto(size_scale=1e5) + + # 行星 + self.planets = [self.mercury, self.venus, self.earth, self.mars, + self.jupiter, self.saturn, self.uranus, self.neptune, self.pluto] + # 所有天体 + self.bodies = [self.sun] + self.planets # + [self.moon] + + # for body in self.bodies: + # body.texture = '' + + if self.show_earth_clouds: + self.bodies += [self.earth_clouds] + + if self.show_asteroids: + self.bodies += [self.asteroids] + + def init_earth(self): + """ + 初始化地球 + @return: + """ + # 让地球显示自转轴线 + # self.earth.rotate_axis_color = (255, 255, 50) + # 如果为调试模式,则太阳光对地球无效,方便查看 + if self.debug_mode: + self.earth.set_light_disable(True) + + def show_clock(self, dt): + """ + 显示时钟 + @param dt: 时间 datetime + @return: + """ + if self.clock_position_center: + position, origin = (0, .25), (0, 0), + else: + from ursina import window + aspect_ratio = window.aspect_ratio + position, origin = (0.5 * aspect_ratio - 0.3, -0.465), (-0.5, 0.5), + # position, origin = (0.60, -0.465), (-0.5, 0.5), + + ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d %H:%M:%S'), + position=position, + origin=origin, + font="verdana.ttf", + close_time=-1) + + def set_bodies_position(self, time_data: TimeData): + """ + 设置天体的位置(包含速度和加速度的信息) + @param time_data: + @return: + """ + t = self.start_time + time_data.total_days + set_solar_system_celestial_position(self.bodies, t, self.recalc_moon_pos) + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 运行前触发 + + # if self.sky_texture is not None: + # from simulators.ursina.entities.sphere_sky import SphereSky + # SphereSky(texture=self.sky_texture).scale = 80000 + + camera.clip_plane_near = 0.1 + camera.clip_plane_far = 100000 + + camera.look_at(self.sun.planet) + + for body in self.bodies: + body.planet.set_light_off(True) + + # camera.rotation_z = -20 + if self.debug_mode: + camera.fov = 30 # 调试时,拉近摄像机距离 + + # 需要按照时间和日期来控制地球的自转,所以删除控制地球自转的属性 + delattr(self.earth.planet, "rotation_speed") + delattr(self.earth.planet, "rotspeed") + + # 设置后,可以调整鼠标键盘的控制速度 + application.time_scale = 1 + + def on_timer_changed(self, time_data: TimeData): + """ + 事件绑定后,时时刻刻都会触发 + @param time_data: + @return: + """ + dt = time_data.get_datetime(str(self.start_time)) + # 设置天体的位置(包含速度和加速度的信息) + self.set_bodies_position(time_data) + # 保证地球的自转和北京时间同步 + set_earth_rotation(self.earth, dt) + # 显示时钟 + # self.show_clock(dt) + + def bind_events(self): + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(self.on_ready) + + def run(self, + debug_mode=False, + start_time=None, + dt=None, + show_asteroids=False, + show_earth_clouds=False, + recalc_moon_pos=True, + clock_position_center=False): + """ + 模拟运行 + @param debug_mode: 是否调试模式 + @param start_time: 运行的开始时间 + @param dt: 运行速度(dt的值为秒数,表示1秒相当于dt的秒数) + @param show_asteroids: 是否显示小行星带 + @param show_earth_clouds: 地球是否显示云层(图片效果,不是真实的云层) + @param recalc_moon_pos: 为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变) + @param clock_position_center: 时钟是否显示在中间 + @return: + """ + self.recalc_moon_pos = recalc_moon_pos + self.debug_mode = debug_mode + self.clock_position_center = clock_position_center + self.show_asteroids = show_asteroids + self.show_earth_clouds = show_earth_clouds + # 创建太阳系天体 + self.create_bodies() + # glows = (glow_num:10, glow_scale:1.03 glow_alpha:0.1~1) + # self.sun.glows = (4, 1.005, 0.1) + + # 对地球进行初始化 + self.init_earth() + # 绑定事件 + self.bind_events() + + from astropy.time import Time + from datetime import datetime + # 开始时间为空,则默认为当前时间 + if start_time is None: + self.start_time = Time.now() # 获取默认开始时间为当前时间 + elif isinstance(start_time, str): + self.start_time = Time(datetime.strptime(start_time + '+0800', '%Y-%m-%d %H:%M:%S%z'), + format='datetime') + + from common.image_utils import find_texture + self.sky_texture = find_texture("bg_white.png", None) + if self.sky_texture is None: + cosmic_bg = None + else: + cosmic_bg = '' + if dt is None: + dt = 1 # 1秒=1秒 + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(self.bodies, dt, + # position=(0, 0.2 * AU, -3 * AU), + position=(0, 0, -20 * AU), + gravity_works=False, # 关闭万有引力的计算 + show_grid=False, + cosmic_bg=cosmic_bg, + show_camera_info=False, + show_control_info=False, + timer_enabled=True) + + +if __name__ == '__main__': + # 以下展示的效果为太阳系真实的时间和位置 + sim = SolarSystemRealitySim() + sim.run( + # debug_mode=True, # 是否调试模式 + # dt=SECONDS_PER_DAY , # 1秒=1天 + dt=1, + # dt=SECONDS_PER_HOUR, # 1秒=1小时 + # start_time='2023-10-24 00:00:00', + # start_time='2050-01-01 12:00:00', # 指定运行的开始时间,不指定为当前时间 + # 网上没有找到精确的日期,宇宙模拟器展示大概2040年8、9月份 + # start_time='2040-08-15 12:00:00', # 金木水火土五星连珠的时间 # https://baijiahao.baidu.com/s?id=1776120995339598449 + # start_time='2049-01-01 12:00:00', # 九星连珠的时间 # https://988892.com/qiwenyishi/2023061960711.html + # start_time='2149-12-10 12:00:00', # 九星连珠的时间 # https://baijiahao.baidu.com/s?id=1654160345900112362 + start_time='2149-02-14 13:14:00', + # show_asteroids=True, # 是否显示小行星带(图片模拟) + show_earth_clouds=True, # 地球是否显示云层(图片效果,不是真实的云层) + # recalc_moon_pos=False, # 为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变) + clock_position_center=True # 时钟是否显示在中间 + ) diff --git a/sim_scenes/featured/solar_system_explorer.py b/sim_scenes/featured/solar_system_explorer.py index 6bb3f89b1c9ebf729346e3413338d92b0810dc02..eb8709078fafc4228be5783fdd1a4f3482d21ad1 100644 --- a/sim_scenes/featured/solar_system_explorer.py +++ b/sim_scenes/featured/solar_system_explorer.py @@ -288,8 +288,8 @@ class SolarSystemExplorer(UniverseSimScenes): self.camera_target.planet.update = lambda: None # 显示网格以及坐标线 # self.show_grid_axises(scale_factor=50) - target = self.get_target() - camera_look_at(self.saturn, rotation_z=0) + # target = self.get_target() + # camera_look_at(self.saturn, rotation_z=0) def go_target(self): from ursina import distance @@ -355,7 +355,7 @@ if __name__ == '__main__': # 订阅事件后,上面2个函数功能才会起作用 # 运行中,每时每刻都会触发 on_timer_changed - UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) + # UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) # 运行前会触发 on_ready UrsinaEvent.on_ready_subscription(sim.on_ready) # 使用 ursina 查看的运行效果 @@ -375,7 +375,7 @@ if __name__ == '__main__': # video_recoder=True, show_control_info=False, # save_cube_map=True, - timer_enabled=True, + # timer_enabled=True, # show_timer=True, show_grid=False ) diff --git a/sim_scenes/solar_system/solar_system_reality.py b/sim_scenes/solar_system/solar_system_reality.py index f7832944c26b2f7d2333c222b2e7936674ccfbcf..b7f9d7b20dcedbdae5a27804cc4f7ed44b143d44 100644 --- a/sim_scenes/solar_system/solar_system_reality.py +++ b/sim_scenes/solar_system/solar_system_reality.py @@ -52,7 +52,7 @@ class SolarSystemRealitySim: self.earth_size_scale = 1e1 self.moon_size_scale = 1e1 - self.sun = Sun(name="太阳", size_scale=self.sun_size_scale, color=(255, 250, 245), texture="") # 太阳 + self.sun = Sun(name="太阳", size_scale=self.sun_size_scale) # 太阳 self.mercury = Mercury(name="水星", size_scale=1.5e3) # 水星 self.venus = Venus(name="金星", size_scale=1e3) # 金星 self.earth = Earth(name="地球", texture="earth_hd.jpg", @@ -192,7 +192,7 @@ class SolarSystemRealitySim: # 创建太阳系天体 self.create_bodies() # glows = (glow_num:10, glow_scale:1.03 glow_alpha:0.1~1) - self.sun.glows = (4, 1.005, 0.1) + # self.sun.glows = (4, 1.005, 0.1) # 对地球进行初始化 self.init_earth() @@ -241,6 +241,7 @@ if __name__ == '__main__': # start_time='2040-08-15 12:00:00', # 金木水火土五星连珠的时间 # https://baijiahao.baidu.com/s?id=1776120995339598449 # start_time='2049-01-01 12:00:00', # 九星连珠的时间 # https://988892.com/qiwenyishi/2023061960711.html # start_time='2149-12-10 12:00:00', # 九星连珠的时间 # https://baijiahao.baidu.com/s?id=1654160345900112362 + start_time='2149-02-14 13:14:00', # show_asteroids=True, # 是否显示小行星带(图片模拟) show_earth_clouds=True, # 地球是否显示云层(图片效果,不是真实的云层) # recalc_moon_pos=False, # 为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变) diff --git a/simulators/ursina/entities/entity_utils.py b/simulators/ursina/entities/entity_utils.py index f02b642bab29df445baa6f7c5a345fd442eddd18..86b6911f2f8682945a1e2c1b9c850eeae722baca 100644 --- a/simulators/ursina/entities/entity_utils.py +++ b/simulators/ursina/entities/entity_utils.py @@ -291,7 +291,11 @@ def create_trail_curve_line(parent, pos): thickness=UrsinaConfig.trail_thickness_factor), color=parent.trail_color, alpha=0.5) trail.set_light_off() + else: + pass parent.last_trail = trail + else: + pass parent.trail_last_pos = pos return trail diff --git a/simulators/ursina/entities/video_recorder.py b/simulators/ursina/entities/video_recorder.py index 313d43053ea9c45c6816d003228e8663afd35f7f..50ca6892c9bfd9dc489bd3775dc539a0e1f99da8 100644 --- a/simulators/ursina/entities/video_recorder.py +++ b/simulators/ursina/entities/video_recorder.py @@ -38,13 +38,14 @@ class CubeMapVideoRecorder(Entity): def screenshot(self): self.t += time.dt - if self.t >= 1 / self.fps: - base.saveCubeMap( - namePrefix=f'\\{self.temp_dir}\\cmap_' + str(self.i).zfill(self.sd) + '_#.jpg', - size=8196 # 最大分辨率,用于图片 - # size=4096 # 建议动态视频用这个 - # namePrefix = 'cube_map_#.png' - ) + # if self.t >= 1 / self.fps: + base.saveCubeMap( + namePrefix=f'\\{self.temp_dir}\\cmap_' + str(self.i).zfill(self.sd) + '_#.jpg', + # size=8196 # 最大分辨率,用于图片 + # size=4096 # 建议动态视频用这个 + size = 512 # 建议动态视频用这个 + # namePrefix = 'cube_map_#.png' + ) self.t = 0 self.i += 1 diff --git a/textures/bg_white.png b/textures/bg_white.png new file mode 100644 index 0000000000000000000000000000000000000000..56e4e879532fc7d7381efaab81c887d97d071481 Binary files /dev/null and b/textures/bg_white.png differ