From fa9e1779f66e84dd1e9b45de37b2a68dc7a61360 Mon Sep 17 00:00:00 2001 From: march3 Date: Mon, 25 Mar 2024 11:03:29 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_scenes/featured/solar_system_2149.py | 262 ++++++++++++++++++ sim_scenes/featured/solar_system_explorer.py | 8 +- .../solar_system/solar_system_reality.py | 5 +- simulators/ursina/entities/entity_utils.py | 4 + simulators/ursina/entities/video_recorder.py | 15 +- textures/bg_white.png | Bin 0 -> 5029 bytes 6 files changed, 281 insertions(+), 13 deletions(-) create mode 100644 sim_scenes/featured/solar_system_2149.py create mode 100644 textures/bg_white.png diff --git a/sim_scenes/featured/solar_system_2149.py b/sim_scenes/featured/solar_system_2149.py new file mode 100644 index 0000000..97e037c --- /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 6bb3f89..eb87090 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 f783294..b7f9d7b 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 f02b642..86b6911 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 313d430..50ca689 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 GIT binary patch literal 5029 zcmeHLXHZky7TyHVgf1-<>4F82?nRU$hy)GAAR&lIlU}8VCW}q4bznb_t?So zXG1M!&|8!=00+H!+l!zejsc|aGS~spc?xXJ&!glZ#Cnj6*OA=IL@Z&5w0x{=0Ew(& z27&Py9H)*gh)ma&YX#!!5TGZ@)5a){WXx6Usv9n{@rfoN7yyx!(w26tONEz^@=7RZ zes*|NVzl0)OxF&+o689{E}4~^ETXP zy(P6I=7u(^uR)jqmvINR&t_txhta2rp){b*y~qmmp@GZLvb9P-EcYbKtB~bbtooXc zXwEIu=7S>JSy)+Tr0s9jD2~NyeN`Fp9*&Jz+WflFA2JKhX6U3B6Z50i&)RtfmZ0Lv zBqm)YFB(~Dqbd5_di?IrQPr|ja(q|kFjoksl15F~C#b~35-lmC+*9Y2=fqOiVM#&k z0DsAZX#9BVBa#O(;u8ZTmIKoj2y`MA_CIT*JRb?yonMgGe4zb&ESch!~@gSG(mhs5#EVl$w4+)+i zYV(}Y8%4r>$n&;jrR3WMv`8cnz^Vo*~e-M5(-XXG6iNopIJG)cY zF6-M~!3fDT@jFal)X)iP4kDP}0{MiAId)X&4oGYy&ouP(MXq{}3pkts28q$TD?Ke$ z!CeKlfJI$Ys^2M@bl0RpI)r<H38vdOm37l|?;UR|%6S957o&0Wq@ibSps9k{d_PYe#1w#c31u6v<(vf$V zU#F!vpHO_OES&CqgY$;BIcCq&o-n?|m)t2DDd?1l6!N_j=6>ed-Pn7qC+?eb-am~F zzjMU=q3Ku=><$0@?jjNMr$zfp+EGEM1k;Y=Hu<$S>laoW*vl_PAIZIh$Uosw`9d&G zg8zlG;~Yk}#}~~=k#oOcWN%fzJdF%wUKI{h2t}Id`Q3BEJ0&`0Po8aK;CN9sJiGs0 z*3ou}cJ}sAc}96{`LZ6jVyEJW;@|p0`fB^^XMAV)XDEHt0H17~Y`N@34NnbP0IX_X z)$yw6s{VkEk6N!CDA+03;>$&jsliTzMbFRqi|~)s9%`r9Z;GnWeKei!+NG0y8~_ct?2?c6aSw zH1q0HnqHe`na-HrGP8flZb^E{bE!k5bvw66&jJ4fVZQzWt$`js)s%t})#pVGMbD=! zoQ0il`DHJt!S5Wyk+{gtkrluz^PmLCjS!9ljjSyL*rFy}cigSD5*q z^{2`8;KwajoonLf5{j-pIneL+*f-D_@8*H>aG1^{L=x^1&Ie!qqCc0$?a#9VHgjdX zp|?Tv%9tO7?2)08HJ))I)!(6HVj%Acd~&LtloNE&Qq2+R6)RG zqR`7oglGO@X0(ZZZC+g7@v=(7(Sz3~v(YI_>VpTu^;TRinH&jtp#n2O$zl@)uRoDm zFhU>hd5`aSclMq9{^YFWtb7!^Yifn;TgA#xu0-^?S@{P)n)5gbTDb@@8VKul?Q$p#(UP7?t+^}Sw z{!@ObSTlIgUL|W()tO+|*{*Ps3#mMH-EZ+(Pmy z`F!$;1D{>W8FQ*zTDKMY+#Yy}4c-TTx8zId5yIrCg|SU{*do@mukZcQ%9k?~1f_uD zg{N88Jvdt9cBuQ+rCIi3;kmd8VH?k*@BMFuxGl!FRkXcqV^p(Ko3UzrjPIYnwJ(1u zB>S8-3B6u?zq0n7OkYpkU{L4+N0bQPf%nwp>FP(a!4~c{`r(USU7s!tCJ5OJSJh2M z3=#~2Od4|%LT`s|UDBsg-2A;g1|HPamBTzy`{G0q8a@-5k=}ioGZ{gTd`|A+s6RCE zZ0FFOu+TBn54YN%4?J%hNEoLe5hkTh0!rZ6YlSX=W=`T&-OTuXPiK5kv(tk;pF4fp?qthAxE zEW9TtSkG4be3qoy_e)nEE7mO0G>Gt7A3;2@@}@Y_NHZ1(OZ-0@Q4VxcU!PlXBX;|} z{qlCN^-XLI^~JPsrI*a$c7k-(;+Mds8F&!OC***2NJ8*~wc5V*k6TwbKc1`DD03uw z4u7#F+IBp*#0$^3eL|>ah;YTJJ3Da%@Lk3ASj#mwLbGfku;5lUQ{-R&(yoT5)@SIF&%H8fvN$ zOW(Dovthc>x#G}N_{xN)MGo6oQ=na3Se5R&sj@k3iaQ`sMgW9J0}vSn!1CA4_Y?pD ziU54H1wi8l0C4Z?HjPIBfOZ)kK6E0uZ@Ncm+vci4kyuA=Vroi8e0XELImr$P!T@07 z2a(SpKoJ9gfE)l(%)qu3{Jz}63W&B0zb}6U^eyHuGtq(msQ&Neehm79;&)E}9T50l z{X20wPITqyL3E02hW<5(PLa*fKgsl~pl_zp5vSusmx&Ja&Dmc8(P{hVhvHX3blQFk zrQ<}Gi4H`k?YG^(1ko$9d76Km>6bxtvi(o|rgQ0=cXZ``Y^8wQ-@W_&==|S#xoI9f zr=RfhCk&_Slb^b)>H6gF-u;PN;KwfgPptgAcmFwL{EN8%@v