From 04ddaea28c86392f05d6b80e149ff5a1ab738328 Mon Sep 17 00:00:00 2001 From: march3 Date: Fri, 22 Dec 2023 15:38:47 +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/look_at_sky_on_earth.py | 64 ++-- .../featured/look_at_sky_on_earth_move.py | 324 ++++++++++++++++++ 2 files changed, 364 insertions(+), 24 deletions(-) create mode 100644 sim_scenes/featured/look_at_sky_on_earth_move.py diff --git a/sim_scenes/featured/look_at_sky_on_earth.py b/sim_scenes/featured/look_at_sky_on_earth.py index c63773f..0853a2e 100644 --- a/sim_scenes/featured/look_at_sky_on_earth.py +++ b/sim_scenes/featured/look_at_sky_on_earth.py @@ -45,6 +45,8 @@ class LookAtSkyOnEarth(UniverseSimScenes): self.show_name = show_name self.exit_at_total_days = exit_at_total_days self.angle = 55 + self.angle_d = -1 + self.angle_s = 0.01 earth_transparent = look_point is not None @@ -92,9 +94,9 @@ class LookAtSkyOnEarth(UniverseSimScenes): self.target = self.create_camera_target() self.target.size_scale = 1e4 ep = self.earth.init_position - self.target.init_position = [ep[0]+4e7,ep[1],ep[2]-4e7] + self.target.init_position = [ep[0] + 4e7, ep[1], ep[2] - 4e7] self.bodies = [ - self.sun, self.earth #, self.target # , self.earth_core # , self.earth_clouds + self.sun, self.earth # , self.target # , self.earth_core # , self.earth_clouds ] @@ -142,6 +144,40 @@ class LookAtSkyOnEarth(UniverseSimScenes): y=-y, x=-x, z=z, color=color.blue) # y=-y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.blue) + def sky_watchers_move(self): + + self.angle += self.angle_d * self.angle_s + if self.angle_d<0 and self.angle<16: + self.angle = 16 + self.angle_d = 1 + elif self.angle_d>0 and self.angle>90: + self.angle = 90 + self.angle_d = -1 + # print(self.angle) + if self.look_point is not None: + camera.rotation_x = self.angle * self.look_point + + r = 0.5 + x_y_angle = math.pi * self.angle / 180 + xr = r * math.cos(x_y_angle) + y = r * math.sin(x_y_angle) + # z = pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5) + x_z_angle = math.pi * 45 / 180 + x = r * math.cos(x_z_angle) + z = r * math.sin(x_z_angle) + # if self.look_point is None or self.look_point == 0: + # self.watcher_e.position = [-x, 0.0, z] + # y=0.0, x=x-0.17, z=pow(pow(r, 2) - pow(x-0.17, 2), 0.5), color=color.green) + x = xr * math.cos(x_z_angle) + z = xr * math.sin(x_z_angle) + if self.look_point is None or self.look_point == -1: + self.watcher_n.position = [-x, y, z] + + # y=y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.red) + if self.look_point is None or self.look_point == 1: + self.watcher_s.position = [-x, -y, z] + # y=-y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.blue) + def on_ready(self): self.create_sky_watchers() @@ -252,28 +288,8 @@ class LookAtSkyOnEarth(UniverseSimScenes): if abs(self.earth.planet.init_rotation_y - self.earth.planet.rotation_y) > 380: exit(0) - # 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) + # self.sky_watchers_move() + def run(self, init_position=(0, 0, 0), speed_factor=1.0): self.speed_factor = speed_factor diff --git a/sim_scenes/featured/look_at_sky_on_earth_move.py b/sim_scenes/featured/look_at_sky_on_earth_move.py new file mode 100644 index 0000000..ac0e216 --- /dev/null +++ b/sim_scenes/featured/look_at_sky_on_earth_move.py @@ -0,0 +1,324 @@ +# -*- coding:utf-8 -*- +# title :从地球上看天空 +# description :从地球上看天空 +# author :Python超人 +# date :2023-12-19 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== +import math + +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.earth_core = Sun(size_scale=2e-1, texture="sun.png", rotation_speed=0).set_ignore_gravity(True) + self.earth_core.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 + self.angle = 90 + self.angle_d = -1 + self.angle_s = 0.1 + + 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_trans.png" # "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.set_ignore_gravity(True) + self.earth.set_light_disable(True) + + # # 地球立春的位置和速度 + # 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.earth.init_velocity = [0, 0, 0] + + self.target = self.create_camera_target() + self.target.size_scale = 1e4 + ep = self.earth.init_position + self.target.init_position = [ep[0] + 4e7, ep[1], ep[2] - 4e7] + self.bodies = [ + self.sun, self.earth # , self.target # , self.earth_core # , 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 create_sky_watchers(self): + from simulators.ursina.ursina_mesh import create_sphere + from ursina import Entity, color + r = 0.5 + scale = 0.05 + model = 'diamond' + model = "sphere" + # subdivisions = 16 + x_y_angle = math.pi * self.angle / 180 + xr = r * math.cos(x_y_angle) + y = r * math.sin(x_y_angle) + # z = pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5) + x_z_angle = math.pi * 45 / 180 + x = r * math.cos(x_z_angle) + z = r * math.sin(x_z_angle) + # if self.look_point is None or self.look_point == 0: + # self.watcher_e = Entity(parent=self.earth.planet, + # model=model, # create_sphere(r, subdivisions), + # scale=scale, + # y=0.0, x=-x, z=z, color=color.red) + # y=0.0, x=x-0.17, z=pow(pow(r, 2) - pow(x-0.17, 2), 0.5), color=color.green) + x = xr * math.cos(x_z_angle) + z = xr * math.sin(x_z_angle) + if self.look_point is None or self.look_point == -1: + self.watcher_n = Entity(parent=self.earth.planet, + model=model, # create_sphere(r, subdivisions), + scale=scale, + y=y, x=-x, z=z, color=color.green) + # y=y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.red) + # if self.look_point is None or self.look_point == 1: + # self.watcher_s = Entity(parent=self.earth.planet, + # model=model, # create_sphere(r, subdivisions), + # scale=scale, + # y=-y, x=-x, z=z, color=color.blue) + # y=-y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.blue) + + def sky_watchers_move(self): + + self.angle += self.angle_d * self.angle_s + # if self.angle_d<0 and self.angle<16: + # self.angle = 16 + # self.angle_d = 1 + # elif self.angle_d>0 and self.angle>90: + # self.angle = 90 + # self.angle_d = -1 + # print(self.angle) + if self.look_point is not None: + camera.rotation_x = self.angle * self.look_point + + r = 0.5 + x_y_angle = math.pi * self.angle / 180 + xr = r * math.cos(x_y_angle) + y = r * math.sin(x_y_angle) + # z = pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5) + x_z_angle = math.pi * 45 / 180 + x = r * math.cos(x_z_angle) + z = r * math.sin(x_z_angle) + # if self.look_point is None or self.look_point == 0: + # self.watcher_e.position = [-x, 0.0, z] + # y=0.0, x=x-0.17, z=pow(pow(r, 2) - pow(x-0.17, 2), 0.5), color=color.green) + x = xr * math.cos(x_z_angle) + z = xr * math.sin(x_z_angle) + if self.look_point is None or self.look_point == -1: + self.watcher_n.position = [-x, y, z] + + # y=y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.red) + # if self.look_point is None or self.look_point == 1: + # self.watcher_s.position = [-x, -y, z] + # y=-y, x=x, z=pow(pow(r, 2) - pow(x, 2) - pow(y, 2), 0.5), color=color.blue) + + def on_ready(self): + self.create_sky_watchers() + + self.earth.planet.rotation_y -= 180 # 一开始就正对太阳 + # self.earth.planet.alpha = 0.8 + # self.earth_cn.planet.rotation_y -= 185 # 一开始就正对太阳 + if hasattr(self.earth_clouds, "planet"): + self.earth_clouds.planet.rotation_y -= 50 # 一开始就正对太阳 + + self.earth.planet.init_rotation_y = self.earth.planet.rotation_y + + 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 = self.angle * 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: + if self.look_point == 0: + camera.parent = self.watcher_e + elif self.look_point == -1: + camera.parent = self.watcher_n + elif self.look_point == 1: + camera.parent = self.watcher_s + # camera.parent = self.earth.planet + + camera.rotation_z = 90 + camera.fov = 75 # 默认:60 + + camera.clip_plane_near = 10 + camera.clip_plane_far = 100000000 + if hasattr(self.earth_core, "planet"): + self.earth_core.planet.parent = self.earth.planet + self.earth_core.planet.alpha = 1 + + 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") + + # if self.look_point is None: + + def on_timer_changed(self, time_data: TimeData): + if abs(self.earth.planet.init_rotation_y - self.earth.planet.rotation_y) > 380: + exit(0) + + self.sky_watchers_move() + + + 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(speed_factor=0.75) + + sim = LookAtSkyOnEarth(look_point=-1) + sim.run(speed_factor=0.7000) -- GitLab