diff --git a/sim_scenes/earth/earth_satellites.py b/sim_scenes/earth/earth_satellites.py index e97453d4f9b02e2259c8014ce0e88c2aac0a6b70..a0cf1bc35a838874a7227f98f838f0238672732a 100644 --- a/sim_scenes/earth/earth_satellites.py +++ b/sim_scenes/earth/earth_satellites.py @@ -10,98 +10,19 @@ from bodies import Moon, Earth, Body from objs import Satellite, Satellite2 from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from sim_scenes.func import mayavi_run, ursina_run, camera_look_at -import math -import random - -# def calculate_satellite_velocity(earth: Earth, altitude): -# """ -# -# @param earth_raduis: -# @param altitude: -# @return: -# """ -# # 地球引力常数 -# G = 6.67430e-11 -# # 地球质量 -# M = earth.mass # 5.97e24 -# # 地球半径 -# R = earth.raduis + altitude -# # 地球表面的线速度 -# v_surface = math.sqrt(G * M / R) -# # 地球卫星轨道速度 -# v_satellite = math.sqrt(G * M / (R + altitude)) -# return v_satellite - v_surface - -import random - -import random -import math - from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent - -# def get_satellite_position_velocity(earth_mass, earth_position, earth_radius, altitude): -# # 万有引力常数 -# G = 6.6743 * 10 ** (-11) -# # 地球质量 -# M = earth_mass -# # 地球半径+海拔高度 -# R = earth_radius + altitude -# -# # 随机生成卫星的位置,确保在球面上 -# phi = random.uniform(0, 2 * math.pi) -# costheta = random.uniform(-1, 1) -# u = random.uniform(0, 1) -# -# theta = math.acos(costheta) -# r = R * (u ** (1 / 3)) -# -# x = r * math.sin(theta) * math.cos(phi) -# y = r * math.sin(theta) * math.sin(phi) -# z = r * math.cos(theta) -# -# # 计算速度的方向 -# # 位置矢量 -# r_vec = [x, y, z] -# # 速度方向和位置矢量垂直,采用向量叉积的性质 -# v_dir = [-y, x, 0] -# # 归一化 -# v_dir_norm = [v / math.sqrt(x ** 2 + y ** 2) for v in v_dir] -# -# # 计算速度大小 -# v = math.sqrt(G * M / R) -# -# # 计算速度矢量 -# v_vec = [v * dir for dir in v_dir_norm] -# -# # 计算卫星的位置和速度 -# position = [earth_position[0] + x, earth_position[1] + y, earth_position[2] + z] -# velocity = v_vec -# -# return tuple(position), [0, 0, 0] -# -# -# def generate_satellite_coordinates(earth_radius, altitude): -# theta = random.uniform(0, 2 * math.pi) # 在0~2π内随机生成一个角度 -# phi = random.uniform(0, math.pi) # 在0~π内随机生成一个角度 -# r = earth_radius + altitude # 地球半径+海拔高度 -# x = r * math.sin(phi) * math.cos(theta) # 计算x坐标 -# y = r * math.sin(phi) * math.sin(theta) # 计算y坐标 -# z = r * math.cos(phi) # 计算z坐标 -# -# return [x, y, z] - - if __name__ == '__main__': """ - 地球、6个月球 + 地球和卫星模拟 """ # 地球在中心位置 earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0]) - # 北斗卫星高度为2.13-2.15万千米。GPS卫星平均轨道高度2.02万千米。 + bodies = [earth] + # 卫星位置和初始速度信息 satellite_infos = [ {"position": [0, 0, 10002], "velocity": [6.3, 0, 0]}, {"position": [0, 0, -12000], "velocity": [5.75, 0, 0]}, @@ -111,9 +32,6 @@ if __name__ == '__main__': {"position": [0, 0, -10000], "velocity": [0, 6.3, 0]}, ] for i, info in enumerate(satellite_infos): - # altitude = random.randint(4000, 10000) - # position, velocity = get_satellite_position_velocity(earth.mass, earth.init_position, earth.raduis, altitude) - satellite = Satellite(name=f'卫星{i + 1}', mass=4.4e10, size_scale=2e2, color=(255, 200, 0), init_position=info["position"], init_velocity=info["velocity"]) @@ -127,6 +45,7 @@ if __name__ == '__main__': UrsinaConfig.trail_type = "line" pass + def on_timer_changed(time_data: TimeData): for info in satellite_infos: info["satellite"].planet.look_at(earth.planet) diff --git a/sim_scenes/fiction/earth_rocks.py b/sim_scenes/fiction/earth_rocks.py index 0ecf4720d58ef7a8642cc1f3d1557f44e7c21380..311e1d99f925f8ce6823aa9864ac850eaaa60db0 100644 --- a/sim_scenes/fiction/earth_rocks.py +++ b/sim_scenes/fiction/earth_rocks.py @@ -6,13 +6,10 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Moon, Earth, Body +from bodies import Earth, Body from objs import RockSnow, Rock, create_rock -from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH -from sim_scenes.func import mayavi_run, ursina_run, camera_look_at, two_bodies_colliding -import math -import random - +from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY +from sim_scenes.func import ursina_run, camera_look_at, two_bodies_colliding from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent @@ -22,18 +19,20 @@ if __name__ == '__main__': 岩石坠落地球 """ # 地球在中心位置 - earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0]) + earth = Earth(init_position=[0, 0, 0], init_velocity=[0, 0, 0], + rotation_speed=0, size_scale=1, texture="earth_hd.jpg") bodies = [earth] + # 岩石位置和初始速度信息 infos = [ - {"position": [0, 0, 10002], "velocity": [2.3, 0, 0]}, - {"position": [0, 0, -12000], "velocity": [1.75, 0, 0]}, - {"position": [0, 8000, 0], "velocity": [1.05, 0, 0]}, - {"position": [0, -12002, 0], "velocity": [1.75, 0, 0]}, - {"position": [0, 18000, 0], "velocity": [1.05, 0, 0]}, - {"position": [0, -22002, 0], "velocity": [1.75, 0, 0]}, - {"position": [0, 0, 8002], "velocity": [0, 1.05, 0]}, - {"position": [0, 0, -10000], "velocity": [0, 1.3, 0]}, + {"position": [0, 0, 10002], "velocity": [4.5, 0, 0]}, + {"position": [0, 0, -12000], "velocity": [3.5, 0, 0]}, + {"position": [0, 8000, 0], "velocity": [4.5, 0, 0]}, + {"position": [0, -12002, 0], "velocity": [3.5, 0, 0]}, + {"position": [0, 18000, 0], "velocity": [3.0, 0, 0]}, + {"position": [-20000, 0, 0], "velocity": [0, -2.0, 0]}, + {"position": [0, 0, 18002], "velocity": [0, 2.5, 0]}, + {"position": [0, 0, -10000], "velocity": [0, 3.3, 0]}, ] for i, info in enumerate(infos): rock = create_rock(no=i % 7 + 1, name=f'岩石{i + 1}', mass=4.4e10, size_scale=5e2, color=(255, 200, 0), diff --git a/sim_scenes/func.py b/sim_scenes/func.py index d06aad525b4b457132583c1ba9187a67a1f623c5..c623e136cdadd8c7b9cf571844d4f8637903397d 100644 --- a/sim_scenes/func.py +++ b/sim_scenes/func.py @@ -59,17 +59,29 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK, mlab.show() -def camera_look_at(body, rotation_x=None, rotation_y=None, rotation_z=None): +def set_camera_parent(target): + from ursina import camera + if hasattr(target, "planet"): + camera.parent = target.planet.main_entity + else: + camera.parent = target + + +def camera_look_at(target, rotation_x=None, rotation_y=None, rotation_z=None): """ 让摄像机看向指定天体 - @param body: 天体 + @param target: 天体 @param rotation_x: x轴旋转角度(None表示不旋转) @param rotation_y: y轴旋转角度(None表示不旋转) @param rotation_z: z轴旋转角度(None表示不旋转) @return: """ from ursina import camera - camera.look_at(body.planet) + if hasattr(target, "planet"): + camera.look_at(target.planet.main_entity) + else: + camera.look_at(target) + if rotation_x is not None: camera.rotation_x = rotation_x if rotation_y is not None: @@ -199,7 +211,7 @@ def create_solar_system_bodies(ignore_mass=False, init_velocity=None): Jupiter(name="木星", size_scale=0.3e3), # 木星放大 300 倍,距离保持不变 Saturn(name="土星", size_scale=0.3e3), # 土星放大 300 倍,距离保持不变 Uranus(name="天王星", size_scale=0.4e3), # 天王星放大 400 倍,距离保持不变 - Neptune(name="海王星", size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 + Neptune(name="海王星", size_scale=1e3), # 海王星放大 800 倍,距离保持不变 Pluto(name="冥王星", size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) ] diff --git a/sim_scenes/solar_system/speed_of_light_init.py b/sim_scenes/solar_system/speed_of_light_init.py index e904d1559f8b821d254308cd91ba82d89ca0a0ae..9687810c47de472d9c37f3d9a873fe61913fdb31 100644 --- a/sim_scenes/solar_system/speed_of_light_init.py +++ b/sim_scenes/solar_system/speed_of_light_init.py @@ -43,8 +43,8 @@ class SpeedOfLightInit: self.camera_position = (AU / 5, 0, 0) self.show_trail = True self.light_size_scale = 2e6 - self.light_init_position = [AU, 0, 0] - self.auto_control_speed = True + self.light_init_position = [AU, AU / 20, 0] + # self.auto_control_speed = True elif self.__camera_follow_light in ["SideViewActualSize"]: # 摄像机位置 = 前-后+、上+下-、左-右+、 # self.camera_position = (0, AU, 0) @@ -58,8 +58,8 @@ class SpeedOfLightInit: self.camera_position = (0, -AU / 25, -AU / 50) self.show_trail = True self.light_size_scale = 2e6 - self.light_init_position = [AU / 12, 0, 0] - # self.auto_control_speed = True + self.light_init_position = [AU / 8, AU / 10, 0] + self.auto_control_speed = True else: # 摄像机位置 = 左-右+、上+下-、前+后- self.camera_position = (0, AU, -6 * AU) @@ -155,7 +155,7 @@ class SpeedOfLightInit: camera.rotation_z = -90 camera.rotation_y = -85 elif self.__camera_follow_light in ["ForwardView"]: - camera.rotation_x = -75 + camera.rotation_x = -72 elif self.__camera_follow_light in ["SideViewActualSize"]: self.light_ship.planet.rotation_x = 0 # camera.rotation_z = -90 @@ -196,22 +196,22 @@ class SpeedOfLightInit: run_speed_maps = [ {"au": 0., "secs": 1}, {"au": 0.008, "secs": 1}, - {"au": "?", "secs": SECONDS_PER_MINUTE * 10}, + {"au": "?", "secs": SECONDS_PER_MINUTE * 5}, {"au": 0.386, "secs": 1}, {"au": 0.3865, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU - {"au": "?", "secs": SECONDS_PER_MINUTE * 10}, + {"au": "?", "secs": SECONDS_PER_MINUTE * 5}, {"au": 0.721, "secs": 1}, - {"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU - {"au": "?", "secs": SECONDS_PER_MINUTE * 10}, + {"au": 0.724, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU + {"au": "?", "secs": SECONDS_PER_MINUTE * 5}, {"au": 1.0, "secs": 1}, {"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU - {"au": "?", "secs": SECONDS_PER_MINUTE * 10}, + {"au": "?", "secs": SECONDS_PER_MINUTE * 5}, {"au": 1.52, "secs": 1}, {"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU - {"au": "?", "secs": SECONDS_PER_MINUTE * 30}, + {"au": "?", "secs": SECONDS_PER_MINUTE * 25}, {"au": 5.19, "secs": 1}, {"au": 5.20, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU - {"au": "?", "secs": SECONDS_PER_MINUTE * 30}, + {"au": "?", "secs": SECONDS_PER_MINUTE * 25}, {"au": 9.5, "secs": 1}, {"au": 9.51, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU {"au": "?", "secs": SECONDS_PER_MINUTE * 30}, diff --git a/sim_scenes/solar_system/transit_of_venus_mercury.py b/sim_scenes/solar_system/transit_of_venus_mercury.py index b931b6951078ad966d67b9e23423358dee7cb645..05c950b6302d789a8009db10003a3d584bc30b37 100644 --- a/sim_scenes/solar_system/transit_of_venus_mercury.py +++ b/sim_scenes/solar_system/transit_of_venus_mercury.py @@ -8,15 +8,17 @@ # ============================================================================== from bodies import Sun, Mercury, Venus, Earth from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HOUR, AU -from sim_scenes.func import mayavi_run, ursina_run, camera_look_at +from sim_scenes.func import ursina_run, set_camera_parent from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.ursina_event import UrsinaEvent if __name__ == '__main__': # 水星、金星凌日 + # 以地球的视角看水星、金星凌日 earth = Earth( name="地球", - rotation_speed=0, + rotate_angle=0, # 不倾斜 + rotation_speed=0, # 不旋转 texture="transparent.png" # 地球纹理透明,不会挡住摄像机视线 ) sun = Sun(name="太阳", size_scale=5e1) # 太阳放大 50 倍 @@ -40,7 +42,7 @@ if __name__ == '__main__': def on_ready(): from ursina import camera # 摄像机跟随地球(模拟在地球上看到的效果) - camera.parent = earth.planet + set_camera_parent(earth) if hasattr(camera, "sky"): # 摄像机跟随地球后,需要对深空背景进行调整,否则看到的是黑色背景 @@ -52,8 +54,7 @@ if __name__ == '__main__': def on_timer_changed(time_data: TimeData): # 时时刻刻的让地球看向太阳(摄像机跟随地球看向太阳) - earth.planet.look_at(sun.planet) - earth.planet.rotation_z = 0 + earth.look_at(sun, rotation_z=0) UrsinaEvent.on_ready_subscription(on_ready) diff --git a/simulators/ursina_simulator.py b/simulators/ursina_simulator.py index 183f02fdeb907dfe3a425a4613b0499debea96ba..e3f54efd906a271c298714f1a026acdbca369074 100644 --- a/simulators/ursina_simulator.py +++ b/simulators/ursina_simulator.py @@ -53,6 +53,7 @@ class UrsinaSimulator(Simulator): for i, view in enumerate(self.body_views): # pos = tuple(body.position) # ursina_view = UrsinaView(body) + self.bind_event(view.body) view.update() self.ursina_views.append(view) # planets.append(newPlanet) @@ -60,6 +61,28 @@ class UrsinaSimulator(Simulator): self.adjust_system_motion_params() UrsinaEvent.on_searching_bodies_subscription(type(self).__name__, self.on_searching_bodies) + def bind_event(self, body): + + def body_look_at(target, rotation_x=None, rotation_y=None, rotation_z=None): + """ + 让 body 看向 target 目标天体 + @param target: 目标天体 + @param rotation_x: x轴旋转角度(None表示不旋转) + @param rotation_y: y轴旋转角度(None表示不旋转) + @param rotation_z: z轴旋转角度(None表示不旋转) + @return: + """ + if hasattr(target, "planet") and hasattr(body, "planet"): + body.planet.main_entity.look_at(target.planet.main_entity) + if rotation_x is not None: + body.planet.rotation_x = rotation_x + if rotation_y is not None: + body.planet.rotation_y = rotation_y + if rotation_z is not None: + body.planet.rotation_z = rotation_z + + body.look_at = body_look_at + # def get_bodies_max_distance(self, body_views): # max_distance = 0 # for b1 in body_views: