From 9d507a796edf786fc042e6fa421d76a45baa16a7 Mon Sep 17 00:00:00 2001 From: march3 Date: Mon, 4 Mar 2024 12:13:49 +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_explorer.py | 323 ++++++++++++++++++ .../solar_system/solar_system_gen_pos.py | 69 ++++ 2 files changed, 392 insertions(+) create mode 100644 sim_scenes/featured/solar_system_explorer.py create mode 100644 sim_scenes/solar_system/solar_system_gen_pos.py diff --git a/sim_scenes/featured/solar_system_explorer.py b/sim_scenes/featured/solar_system_explorer.py new file mode 100644 index 0000000..908406b --- /dev/null +++ b/sim_scenes/featured/solar_system_explorer.py @@ -0,0 +1,323 @@ +# -*- coding:utf-8 -*- +# title :遨游太阳系 +# description :遨游太阳系 +# author :Python超人 +# date :2024-03-04 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== + +from ursina import camera, application, lerp, Vec3 +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto +from common.celestial_data_service import init_bodies_reality_pos_vels, conv_to_astropy_time, \ + set_solar_system_celestial_position, init_bodies_pos_vels, get_init_pos_vels_2 +from common.consts import SECONDS_PER_YEAR,SECONDS_PER_MINUTE,SECONDS_PER_HOUR, AU +from common.func import calculate_distance +from bodies import Earth +from objs import QuadObj, CircleObj, Obj, CoreValagaClas +from sim_scenes.func import create_text_panel, camera_look_at, get_run_speed_factor, \ + camera_move_update, camera_move_to_target_update, camera_move_control, two_bodies_colliding +from sim_scenes.func import ursina_run, create_sphere_sky +from sim_scenes.solar_system.halley_comet_lib import HalleyCometSimBase, HalleyCometParams, \ + create_halley_comet, create_orbit_line +from sim_scenes.universe_sim_scenes import UniverseSimScenes +from simulators.func import ext_fun_for_method +from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.entities.entity_utils import get_value_direction_vectors +from simulators.ursina.ui.control_ui import ControlUI +from simulators.ursina.ursina_config import UrsinaConfig +from simulators.ursina.ursina_event import UrsinaEvent +from simulators.ursina.ursina_mesh import create_label +import time + + +class SolarSystemExplorer(UniverseSimScenes): + """ + 遨游太阳系 + """ + + def build_solar_system(self): + # region 构建太阳系 + show_trail = False + self.SIZE_FACTOR = 0.01 + self.init_pos = [2 * AU, 2 * AU, -10 * AU] + self.sun = Sun(size_scale=20e2*self.SIZE_FACTOR, show_trail=show_trail, + # color=(255, 250, 245), + # texture="", + texture="sun_light.jpg" + ) + self.sun.glows = (24, 1.008, 0.04) + self.sun.set_resolution(200) + self.mercury = Mercury(size_scale=2e3*self.SIZE_FACTOR, distance_scale=1.6, show_trail=show_trail) + self.venus = Venus(size_scale=2e3*self.SIZE_FACTOR, distance_scale=1.5, show_trail=show_trail) + self.earth = Earth(size_scale=2e3*self.SIZE_FACTOR, distance_scale=1.5, rotate_angle=0, show_trail=show_trail) + self.mars = Mars(size_scale=2e3*self.SIZE_FACTOR, distance_scale=1.4, show_trail=show_trail) + self.jupiter = Jupiter(size_scale=0.3e3*self.SIZE_FACTOR, distance_scale=0.7, show_trail=show_trail) + self.saturn = Saturn(size_scale=0.3e3*self.SIZE_FACTOR, distance_scale=0.52, show_trail=show_trail) + self.uranus = Uranus(size_scale=0.8e3*self.SIZE_FACTOR, distance_scale=0.34, show_trail=show_trail) + self.neptune = Neptune(size_scale=0.8e3*self.SIZE_FACTOR, distance_scale=0.25, show_trail=show_trail) + self.pluto = Pluto(size_scale=1e4*self.SIZE_FACTOR, distance_scale=0.23, show_trail=show_trail) + D = AU / 10 + self.camera_target = CoreValagaClas(name="摄像机镜头", mass=1e30, color=(111, 140, 255), + # init_position=[0, 0, 0], + init_position=self.init_pos, + init_velocity=[0, 0, 0], + size_scale=1e3*self.SIZE_FACTOR).set_ignore_gravity(True) + + self.bodies = [ + self.sun, # 太阳 + self.mercury, # 水星 + self.venus, # 金星 + self.earth, # 地球 + self.mars, # 火星 + self.jupiter, # 木星 + self.saturn, # 土星 + self.uranus, # 天王星 + self.neptune, # 海王星 + self.pluto, # 冥王星 + self.camera_target + ] + + init_bodies_pos_vels(self.bodies, init_pos_vels_fun=self.get_init_pos_vels) + + def get_init_pos_vels(self): + init_pos_vels = {} + init_pos_vels['sun'] = {} + init_pos_vels['sun']['pos'] = [-23.205570220947266, 0.0, 494.46502685546875] + init_pos_vels['sun']['vel'] = [-3.617262336774729e-05, 0.0, 0.000522326270584017] + init_pos_vels['mercury'] = {} + init_pos_vels['mercury']['pos'] = [-56858320.0, 0.0, -237695.5] + init_pos_vels['mercury']['vel'] = [0.5191680788993835, 0.0, -48.36161804199219] + init_pos_vels['venus'] = {} + init_pos_vels['venus']['pos'] = [-61601512.0, 0.0, 88374768.0] + init_pos_vels['venus']['vel'] = [-28.69715118408203, 0.0, -20.112533569335938] + init_pos_vels['earth'] = {} + init_pos_vels['earth']['pos'] = [-54543052.0, 0.0, 139275888.0] + init_pos_vels['earth']['vel'] = [-27.743507385253906, 0.0, -10.863121032714844] + init_pos_vels['mars'] = {} + init_pos_vels['mars']['pos'] = [-44924356.0, 0.0, 222884576.0] + init_pos_vels['mars']['vel'] = [-23.654102325439453, 0.0, -4.7799787521362305] + init_pos_vels['asteroids'] = {} + init_pos_vels['asteroids']['pos'] = [0.0, 0.0, 0.0] + init_pos_vels['asteroids']['vel'] = [0.0, 0.0, 0.0] + init_pos_vels['jupiter'] = {} + init_pos_vels['jupiter']['pos'] = [-24472074.0, 0.0, 776025472.0] + init_pos_vels['jupiter']['vel'] = [-13.053510665893555, 0.0, -0.4124884009361267] + init_pos_vels['saturn'] = {} + init_pos_vels['saturn']['pos'] = [-18066134.0, 0.0, 1421063552.0] + init_pos_vels['saturn']['vel'] = [-9.6392240524292, 0.0, -0.12374488264322281] + init_pos_vels['uranus'] = {} + init_pos_vels['uranus']['pos'] = [-12762774.0, 0.0, 2872276736.0] + init_pos_vels['uranus']['vel'] = [-6.809953689575195, 0.0, -0.030240831896662712] + init_pos_vels['neptune'] = {} + init_pos_vels['neptune']['pos'] = [-10176475.0, 0.0, 4592654848.0] + init_pos_vels['neptune']['vel'] = [-5.429999828338623, 0.0, -0.011822682805359364] + init_pos_vels['pluto'] = {} + init_pos_vels['pluto']['pos'] = [-8808451.0, 0.0, 5916595712.0] + init_pos_vels['pluto']['vel'] = [-4.699999809265137, 0.0, -0.007128323893994093] + return init_pos_vels + + + + def build(self): + """ + 构建太阳系系统以及哈雷彗星 + @return: + """ + self.build_solar_system() + + def init_settings(self): + """ + 初始化设置 + @return: + """ + from ursina import color + # 创建天空 + create_sphere_sky(texture="bg_pan2.jpg", scale=50000, rotation_x=200, rotation_y=None, rotation_z=45) + # UrsinaConfig.trail_type = "curve_line" + # UrsinaConfig.trail_length = 300 + UrsinaConfig.trail_type = "line" + # UrsinaConfig.trail_length = 152 # 尾巴数量刚刚好 + UrsinaConfig.trail_length = 130 + UrsinaConfig.trail_thickness_factor = 3 + + # UrsinaConfig.trail_length = 180 + UrsinaConfig.trail_factor = 3 + + # camera.clip_plane_near = 0.1 + camera.clip_plane_far = 51000 + + application.time_scale = 0.001 + # camera.fov = 60 + # self.current_stage = self.stage_01 + + def s_f(self, value=1): + if value == 0: + return 0 + return get_run_speed_factor() * value + + def camera_move(self, time_data): + """ + 摄像机移动控制 + @param dt: + @return: + """ + # 摄像机移动控制数据 + camera_move_infos = [ + # 条件:年份 + # 移动的信息: + # 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳) + # 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下 + (0, {"f": 5.758}), + # (1983, {"to": {"ct_id": 1, "t": 10}}), + (11, {"f": 1.8}), + (14, {"f": 2}), + (18, {"f": 2}), + (25, {"f": 1}), + (28, {"f": 0.2}), + # (30, {"f": 0.5}), + # (40, {"f": 0.6}), + (33, {"b": 2}), + (50, {"f": 0.2}), + (65, {"f": 2}), + (69, {"f": 3}), + (70, {"f": 4}), + (75, {"f": 5}), + (90, {"f": 3}), + (200, {}), + # (2000, {"exit": True}), + # (1989, {"z": -8, "f": -5}), + # (1993, {"z": -8, "f": -3}), + # (1995, {"z": -8}), + # (2000, {"z": -8, "y": -0.2}), + # (2013, {}), + # (2048, {"f": 3}), + # (2062, {"y": -3}), + # (2063, {"y": -10, "z": 2}), + # (2181, {}), + # (2082, {"exit": True}) + (250, {"exit": True}), + ] + + if time_data.total_days > 120: + # self.two_way_foil_circle.planet.enabled = False + self.two_way_foil.scale_factor = 0.5 + + if 100 > time_data.total_days > 28: + self.two_way_foil.scale_factor -= 1.5e-3 + + def cond_cb(ps): + return ps["next_cond"] > time_data.total_days >= ps["cond"] + + camera_move_control(camera_move_infos, + cond_cb=cond_cb, + value_conv=self.s_f, smooth=1) + + def get_target(self): + for body in self.bodies: + if hasattr(body, "is_arrived"): + continue + return body + return None + + def last_target(self): + return self.sun + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 初始化设置 + self.init_settings() + + # self.set_window_size((int(1920 * r), int(1080 * r)), False) + # 最大分辨率的高度-1,保证不全屏 + # self.set_window_size((1920, 1079), False) + application.time_scale = 0.00001 + camera.speed = 4e2 + self.camera_target.planet.update = lambda: None + # 显示网格以及坐标线 + # self.show_grid_axises() + + def go_target(self): + from ursina import distance + target = self.get_target() + + target_scale = target.planet.scale_x + target_pos = target.planet.position + Vec3(0, target_scale * (3 / 5), 0) + + self.camera_target.planet.look_at(target_pos) + + dd = distance(self.camera_target.planet.position, target_pos) + + if not hasattr(target, "distance"): + target.distance = dd + self.camera_target.planet.position = lerp(self.camera_target.planet.position, target_pos, + camera.speed * time.dt * target.distance) + + camera_target_pos =self.camera_target.planet.position + dd2 = distance(camera.position, camera_target_pos) + camera.position = lerp(camera.position, camera_target_pos, + camera.speed * 0.99 * time.dt * target.distance) + + if dd < target_scale * 3 and dd2 < target_scale*3: + if target is not None: + target.is_arrived = True + + camera_look_at(self.camera_target, rotation_z=0) + + + # print(camera.position) + print(target.name, target_scale, dd, self.camera_target.planet.position) + # print(dd) + + def on_timer_changed(self, time_data): + """ + + @param time_data: + @return: + """ + self.go_target() + # self.camera_move(time_data) + # self.current_stage() + + +if __name__ == '__main__': + """ + + """ + + # params = TwoWayFoilSim() + + sim = SolarSystemExplorer() + # window_size = (1920, 1079) + # UniverseSimScenes.set_window_size(window_size, False) + sim.build() + + # 订阅事件后,上面2个函数功能才会起作用 + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(sim.on_ready) + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(sim.bodies, + # SECONDS_PER_YEAR / 48 * get_run_speed_factor(), + SECONDS_PER_MINUTE, + # position=(0, 2 * AU, -11 * AU), + # position=(0, 0.5 * AU, -5 * AU), + # position=(2 * AU, -5 * AU, -20 * AU), + position=sim.init_pos, + cosmic_bg='', + # show_trail=True, + # bg_music='sounds/no_glory.mp3', + show_camera_info=False, + # video_recoder=True, + show_control_info=False, + # save_cube_map=True, + timer_enabled=True, + # show_timer=True, + show_grid=False + ) diff --git a/sim_scenes/solar_system/solar_system_gen_pos.py b/sim_scenes/solar_system/solar_system_gen_pos.py new file mode 100644 index 0000000..3f80a89 --- /dev/null +++ b/sim_scenes/solar_system/solar_system_gen_pos.py @@ -0,0 +1,69 @@ +# -*- coding:utf-8 -*- +# title :太阳系场景位置生成器 +# description :太阳系场景位置生成器 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon, Asteroids +from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_YEAR, AU, SECONDS_PER_MONTH +from sim_scenes.func import mayavi_run, ursina_run +from simulators.ursina.ursina_event import UrsinaEvent + +if __name__ == '__main__': + # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) + # 排列顺序 + # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 + # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 + # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + # ===================================================================== + # 以下展示的效果为太阳系真实的距离 + # 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大 + sun = Sun(name="太阳", size_scale=0.8e2) # 太阳放大 80 倍,距离保持不变 + bodies = [ + sun, + Mercury(name="水星", size_scale=4e3), # 水星放大 4000 倍,距离保持不变 + Venus(name="金星", size_scale=4e3), # 金星放大 4000 倍,距离保持不变 + Earth(name="地球", size_scale=4e3), # 地球放大 4000 倍,距离保持不变 + Mars(name="火星", size_scale=4e3), # 火星放大 4000 倍,距离保持不变 + Asteroids(name="小行星群", size_scale=1e2, + parent=sun), # 小行星群模拟(仅 ursina 模拟器支持) + Jupiter(name="木星", size_scale=0.8e3), # 木星放大 800 倍,距离保持不变 + Saturn(name="土星", size_scale=0.8e3), # 土星放大 800 倍,距离保持不变 + Uranus(name="天王星", size_scale=0.8e3), # 天王星放大 800 倍,距离保持不变 + Neptune(name="海王星", size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 + Pluto(name="冥王星", size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) + ] + + + def on_timer_changed(time_data): + init_pos_vels = """ +---------------------------------------------- +def get_init_pos_vels(): + init_pos_vels = {}""" + for body in bodies: + body_name = body.__class__.__name__.lower() + pos = body.position + vel = body.velocity + init_pos_vels += f""" + init_pos_vels['{body_name}'] = {{}} + init_pos_vels['{body_name}']['pos'] = [{pos[0]}, {pos[1]}, {pos[2]}] + init_pos_vels['{body_name}']['vel'] = [{vel[0]}, {vel[1]}, {vel[2]}]""" + + init_pos_vels += """ + return init_pos_vels""" + print(init_pos_vels) + + def on_ready(): + pass + + UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(on_ready) + + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(bodies, SECONDS_PER_MONTH/10, position=(0, 2 * AU, -11 * AU), + timer_enabled=True) -- GitLab