# -*- coding:utf-8 -*- # title :模拟场景 # description :模拟场景 # author :Python超人 # date :2024-03-20 # link :https://gitcode.net/pythoncr/ # python_version :3.9 # ============================================================================== from ursina import Ursina, camera, EditorCamera, Sky, Entity, load_model, color from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, \ get_reality_orbit_points from common.consts import SECONDS_PER_DAY, AU from bodies.body import Body from bodies import * from sim_scenes.func import create_sphere_sky, ursina_run from sim_scenes.universe_sim_scenes import UniverseSimScenes 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 simulators.ursina.ursina_mesh import create_orbit_by_points from 引力世界.数据.天体数据 import get_body_pos_vel class 模拟场景(UniverseSimScenes): def __init__(self): # self.app = Ursina() # # self.sky = create_sphere_sky(scale=80000) self.造物() # # EditorCamera() def 获取天体列表(self): for p in vars(self): f = getattr(self, p) if isinstance(f, Body): yield f def 获取坐标和速度(self, 天体名称): pos, vel = get_body_pos_vel(天体名称) return pos, vel def 造物(self): pass def 摄像机看向(self, 物体): camera.look_at(物体) camera.rotation_z = 0 def on_ready(self): from ursina import application, window # application.time_scale = 0.0001 window_size = (int(1920/2), int(1079/2)) UniverseSimScenes.set_window_size(window_size, False) window.borderless = False window.position = (20, 20) # 运行前触发 self.sky = create_sphere_sky(texture="bg_pan2.jpg", scale=500000, rotation_x=20, rotation_y=160, rotation_z=20) # UrsinaConfig.trail_type = "line" # UrsinaConfig.trail_length = 91 # UrsinaConfig.trail_type = "line" UrsinaConfig.trail_length = 420 # UrsinaConfig.trail_length = 1000 UrsinaConfig.trail_factor = 3 UrsinaConfig.trail_thickness_factor = 3 camera.clip_plane_near = 0.1 camera.clip_plane_far = 51000000 # camera.position=[1000,1000,-1000] # from sim_scenes.func import create_sphere_sky # create_sphere_sky(scale=500000) # # # 为了较好的立体效果,可以增加太阳光线,光线指向木星(target=jupiter) # create_directional_light(position=(10.5e3, -1e3, -175e3), light_num=1, target=moon, look_at_target_always=True) def 运行(self, 全屏=False): # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- bodies = list(self.获取天体列表()) UrsinaEvent.on_ready_subscription(self.on_ready) # UrsinaEvent.on_timer_changed_subscription(on_timer_changed) ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, -2*AU), cosmic_bg="", view_closely=0.001) # self.app.run() class 太阳系模拟场景(模拟场景): def __init__(self): self.造物() def create_orbit_line(self,center_body, body, start_time, alpha=0.2): import math if not hasattr(body, "orbital_days"): return None orbital_days = int(math.ceil(body.orbital_days)) points = get_reality_orbit_points(type(body).__name__.lower(), start_time=start_time, days=orbital_days, segments=100) # print(points) orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color, alpha=alpha) return orbit_line def create_orbit_lines(self): """ 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外) @return: """ self.orbit_lines = [] for body in self.bodies: if isinstance(body, Sun): continue if isinstance(body, Earth): alpha = 0.5 else: alpha = 0.2 orbit_line = self.create_orbit_line(self.太阳, body, self.start_time, alpha=alpha) if orbit_line is not None: self.orbit_lines.append(orbit_line) 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, True, self.地月距离放大倍数) def on_ready(self): super(太阳系模拟场景, self).on_ready() self.create_orbit_lines() def show_clock(self, time_data): """ 显示时钟 @param dt: 时间 datetime @return: """ # if self.clock_position_center: # position, origin = (0, .25), (0, 0), # else: from ursina import window dt = time_data.get_datetime(self.start_time) aspect_ratio = window.aspect_ratio position, origin = (0.5 * aspect_ratio - 0.15, -0.45), (-0.05, 0.1), ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d'), position=position, origin=origin, # font="verdana.ttf", font="fonts/Digital-7Mono.TTF", font_scale=2, font_color=(0, 255, 0), close_time=-1) def on_timer_changed(self, time_data: TimeData): """ @param time_data: @return: """ dt = time_data.get_datetime(str(self.start_time)) year = dt.strftime("%Y") self.set_bodies_position(time_data) self.show_clock(time_data) def 运行(self, 运行时间=None, 全屏=False): # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- self.地月距离放大倍数 = 10 if isinstance(运行时间, str): self.start_time = conv_to_astropy_time(运行时间) else: self.start_time = 运行时间 if self.start_time is None: from astropy.time import Time self.start_time = Time.now() self.bodies = list(self.获取天体列表()) UrsinaEvent.on_ready_subscription(self.on_ready) UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) ursina_run(self.bodies, SECONDS_PER_DAY, position=(0, 0, -2 * AU), cosmic_bg="", gravity_works=False, timer_enabled=True, show_grid=False, show_camera_info=False, view_closely=0.001)