# -*- coding:utf-8 -*- # title :从地球上看天空 # description :从地球上看天空 # author :Python超人 # date :2023-12-19 # link :https://gitcode.net/pythoncr/ # python_version :3.9 # ============================================================================== from ursina import camera from bodies import Sun, Earth from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, AU from sim_scenes.func import ursina_run, camera_look_at, create_sphere_sky from sim_scenes.science.earth_season_func import create_important_pos_earths, get_solar_terms_angles, create_earth, \ get_earth_pos_vel_by_term_name from sim_scenes.universe_sim_scenes import UniverseSimScenes from simulators.ursina.entities.body_timer import TimeData, BodyTimer from simulators.ursina.entities.entity_utils import create_foreground from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent from common.func import find_file class LookAtSkyOnEarth(UniverseSimScenes): def __init__(self, show_sphere_sky=True, # look_at_earth=True, show_china=False, exit_at_total_days=375, earth_cn_size_factor=1.001, earth_clouds_size_factor=1.01, show_name=False, look_point=None): # self.sun = Sun(size_scale=2e1, texture="sun_light.jpg") # self.sun.glows = (0, 1.005, 0.1) self.sun = Sun(size_scale=2e1, texture="transparent.png") self.sun.glows = None self.show_sphere_sky = show_sphere_sky self.look_point = look_point # -1:北半球, 1:南半球, 0:赤道 # self.look_at_earth = look_at_earth self.show_china = show_china self.show_name = show_name self.exit_at_total_days = exit_at_total_days earth_transparent = look_point is not None self.earth_transparent = earth_transparent if earth_transparent: earth_texture = "transparent.png" # earth_texture = "earth_miller_projection_SW.jpg" clouds_texture = "transparent.png" earth_size_scale = 1 else: earth_texture = "earth_miller_projection_sw.png" # "earth_miller_projection_SW.jpg" clouds_texture = "transparent_clouds.png" earth_size_scale = 6e3 # 运动的地球 self.earth, self.earth_clouds, self.earth_cn = create_earth(earth_texture=earth_texture, earth_size_scale=earth_size_scale, earth_cn_texture=None, clouds_texture=None, with_clouds=True, earth_rotation_speed=4, clouds_rotation_speed=4, earth_cn_size_factor=earth_cn_size_factor, earth_clouds_size_factor=earth_clouds_size_factor) self.earth.set_resolution(200) # # 地球立春的位置和速度 # self.earth.init_position = [-9.1507536e+07, 0.0000000e+00, 1.1907757e+08] # self.earth.init_velocity = [-23.550875, 0., -18.05398] self.earth_clouds.init_position = [-9.1507536e+07, 0.0000000e+00, 1.1907757e+08] self.earth_clouds.init_velocity = [-23.550875, 0., -18.05398] self.earth.rotate_axis_color = (255, 255, 50) self.earth.rotate_axis_scale = 0.65 pos_vel = get_earth_pos_vel_by_term_name("春分") if pos_vel is not None: self.earth.init_position = pos_vel["pos"] self.earth.init_velocity = pos_vel["vel"] self.bodies = [ self.sun, self.earth #, self.earth_clouds ] if self.show_china: self.bodies += [self.earth_cn] self.wait_days = 10 self.wait_days_count = self.wait_days # 中国农历24节气表,数据为 节气名称 和 camera.rotation_y 的角度范围值 self.solar_terms_angles = get_solar_terms_angles() def on_ready(self): self.earth.planet.rotation_y -= 180 # 一开始就正对太阳 self.earth.planet.alpha = 0.9 # self.earth_cn.planet.rotation_y -= 185 # 一开始就正对太阳 if hasattr(self.earth_clouds, "planet"): self.earth_clouds.planet.rotation_y -= 50 # 一开始就正对太阳 if self.show_name: font = find_file("fonts/DroidSansFallback.ttf", UrsinaConfig.CN_FONT) from ursina import color text_scale = self.earth.name_text.scale * 2 self.earth.name_text.scale = text_scale self.earth.name_text.font = font self.earth.name_text.color = color.yellow if hasattr(self.earth_clouds, "name_text"): self.earth_clouds.name_text.enabled = False if self.show_china: if hasattr(self.earth_cn, "name_text"): self.earth_cn.name_text.enabled = False cn_planet = self.earth_cn.planet origin_update = cn_planet.update cn_planet.alpha_inc = 0.01 cn_planet.alpha_direct = -1 alpha_range = [0.3, 0.7] cn_planet.alpha = alpha_range[1] def cn_blink(): origin_update() alpha = cn_planet.alpha alpha += cn_planet.alpha_direct * cn_planet.alpha_inc if cn_planet.alpha_direct < 0 and alpha < alpha_range[0]: alpha = alpha_range[0] cn_planet.alpha_direct = 1 elif cn_planet.alpha_direct > 0 and alpha > alpha_range[1]: alpha = alpha_range[1] cn_planet.alpha_direct = -1 cn_planet.alpha = alpha # print(cn_planet.alpha) if self.wait_days_count <= 0: self.earth_cn.planet.alpha = alpha_range[1] cn_planet.update = origin_update cn_planet.update = cn_blink from ursina import application, invoke if self.show_sphere_sky: self.sky = create_sphere_sky(scale=8000, texture="eso0932a.jpg") # self.sky.rotation_x = -50 # self.sky.rotation_z = 90 self.sky.rotation_x = 50 self.sky.rotation_z = 50 # if self.look_point == 1: if self.look_point is not None: camera.rotation_x = 50 * self.look_point # camera.rotation_x = 50 # 1 南半球 # if self.look_at_earth: if self.look_point is None: # 摄像机始终看向移动的地球 camera_look_at(self.earth, rotation_z=0) # camera.fov = 120 # 默认:60 # camera.parent = self.sun.planet else: camera.parent = self.earth.planet camera.rotation_z = 90 camera.fov = 75 # 默认:60 camera.clip_plane_near = 10 camera.clip_plane_far = 1000000 def delay_app_start(): import time # time.sleep(8.0 / self.speed_factor) self.wait_days_count = 0 application.paused = False import threading application.paused = True threading.Thread(target=delay_app_start).start() # invoke(lambda: app_start, delay=3.0) if self.look_point is not None: # self.sun.planet.glow_circle.look_at(camera) create_foreground(f"armazonesdusk_{self.look_point + 2}.png") def on_timer_changed(self, time_data: TimeData): pass # if self.show_china and self.wait_days_count > 0: # self.wait_days_count = self.wait_days - time_data.total_days # # if time_data.total_days > self.exit_at_total_days: # exit(0) # if self.look_at_earth: # # 摄像机始终看向移动的地球 # camera_look_at(self.earth, rotation_z=0) # # 根据角度范围判断,显示中国农历24节气 # for info in self.solar_terms_angles: # if info[1] <= camera.rotation_y < info[2]: # term_name = info[0] # # 控制4个透明地球文本是否显示,防止地球文字的叠加 # self.earth_text_display(term_name) # # 地球名称文字显示为相应的节气 # if hasattr(self.earth, "name_text"): # self.earth.name_text.text = term_name # # if term_name == "立春": # 找到立春的位置和速度 # # print("position", earth.position) # # print("velocity", earth.velocity) # # # print(camera.rotation_y) def run(self, init_position=(0, 0, 0), speed_factor=1.0): self.speed_factor = speed_factor # 订阅事件后,上面2个函数功能才会起作用 # 运行前会触发 on_ready UrsinaEvent.on_ready_subscription(self.on_ready) # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) # 设置计时器的最小时间单位为天 BodyTimer().min_unit = BodyTimer.MIN_UNIT_DAYS # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(self.bodies, SECONDS_PER_HOUR * speed_factor, position=init_position, # 摄像机和太阳是相同位置 show_name=self.show_name, show_grid=False, cosmic_bg='', # show_timer=True, timer_enabled=True) if __name__ == '__main__': """ 摄像机以太阳的视角看地球(四季和24节气) """ # -1:北半球 Northern Hemisphere, 1:南半球 Southern Hemisphere, 0:赤道 Equator sim = LookAtSkyOnEarth() sim.run()