提交 047aa3ce 编写于 作者: 三月三net's avatar 三月三net

太阳系三体模拟器

上级 5d2f1f56
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon 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 from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_YEAR, AU
from scenes.func import mayavi_run, ursina_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
...@@ -19,21 +19,24 @@ if __name__ == '__main__': ...@@ -19,21 +19,24 @@ if __name__ == '__main__':
# ===================================================================== # =====================================================================
# 以下展示的效果为太阳系真实的距离 # 以下展示的效果为太阳系真实的距离
# 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大 # 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大
sun = Sun(name="太阳", size_scale=0.8e2) # 太阳放大 80 倍,距离保持不变
bodies = [ bodies = [
Sun(size_scale=0.8e2), # 太阳放大 80 倍,距离保持不变 sun,
Mercury(size_scale=4e3), # 水星放大 4000 倍,距离保持不变 Mercury(name="水星", size_scale=4e3), # 水星放大 4000 倍,距离保持不变
Venus(size_scale=4e3), # 金星放大 4000 倍,距离保持不变 Venus(name="金星", size_scale=4e3), # 金星放大 4000 倍,距离保持不变
Earth(size_scale=4e3), # 地球放大 4000 倍,距离保持不变 Earth(name="地球", size_scale=4e3), # 地球放大 4000 倍,距离保持不变
Mars(size_scale=4e3), # 火星放大 4000 倍,距离保持不变 Mars(name="火星", size_scale=4e3), # 火星放大 4000 倍,距离保持不变
Jupiter(size_scale=0.8e3), # 木星放大 800 倍,距离保持不变 Asteroids(name="小行星群", size_scale=3.2e2,
Saturn(size_scale=0.8e3), # 土星放大 800 倍,距离保持不变 parent=sun), # 小行星群模拟(仅 ursina 模拟器支持)
Uranus(size_scale=0.8e3), # 天王星放大 800 倍,距离保持不变 Jupiter(name="木星", size_scale=0.8e3), # 木星放大 800 倍,距离保持不变
Neptune(size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 Saturn(name="土星", size_scale=0.8e3), # 土星放大 800 倍,距离保持不变
Pluto(size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) Uranus(name="天王星", size_scale=0.8e3), # 天王星放大 800 倍,距离保持不变
Neptune(name="海王星", size_scale=1e3), # 海王星放大 1000 倍,距离保持不变
Pluto(name="冥王星", size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除)
] ]
# 使用 mayavi 查看的运行效果 # 使用 mayavi 查看的运行效果
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 0, 0)) ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 5 * AU, -10 * AU)) # position=左-右+、上+下-、前+后-
\ No newline at end of file
...@@ -149,15 +149,57 @@ class UrsinaUI: ...@@ -149,15 +149,57 @@ class UrsinaUI:
else: else:
UrsinaConfig.show_trail = False UrsinaConfig.show_trail = False
def move_camera_to_entity(self, camera_pos: Vec3, entity_pos: Vec3, _distance: float) -> Vec3:
# 计算摄像机到实体的向量
direction = entity_pos - camera_pos
# 计算当前距离
current_distance = direction.length()
# 如果当前距离已经小于等于要求的距离,则直接返回实体坐标
if current_distance <= _distance:
return camera_pos
# 计算需要移动的距离
_distance = current_distance - _distance
# 根据需要移动的距离计算移动向量
move_vector = direction.normalized() * _distance
# 返回摄像机移动后的坐标
return camera_pos + move_vector
def move_camera_to_entity(self,entity,d):
import math
# print("before",camera.position, entity.position)
camera.position = entity.position #- Vec3(0, 0, d) # 设置摄像机位置
camera.world_position = entity.position
# camera.rotation = (0, 0, 0) # 重置摄像机旋转角度
# print("after",camera.position,entity.position)
# # 获取相机和实体之间的向量
# target_vector = entity.position - camera.position
# target_vector.y = 0 # 假设实体在 x-z 平面上,将 y 坐标设为 0
#
# # 计算旋转角度
# angle = math.degrees(math.atan2(target_vector.z, target_vector.x))
# camera.rotation_y = angle # 旋转相机
# camera.look_at(entity.position) # 对准指定实体
def bodies_button_list_click(self, item): def bodies_button_list_click(self, item):
if item is not None: if item is not None:
# TODO: 先找到位置,确定摄像机的位置 # TODO: 先找到位置,确定摄像机的位置
# print("select->", item) # print("select->", item)
# UrsinaConfig.SCALE_FACTOR # UrsinaConfig.SCALE_FACTOR
x = item.planet.scale_x * 10 # import copy
camera.position = item.planet.position + Vec3(-x, 0, 0) # camera_rotation = copy.deepcopy(camera.rotation)
camera.look_at(item.planet) d = item.planet.scale_x * 20
camera.rotation = (0, 90, 0) self.move_camera_to_entity(item.planet, d)
# d = distance(camera.position, item.planet.position)
# camera.look_at(item.planet)
# if d > 1.5 * x:
# move_to = self.move_camera_to_entity(camera.position, item.planet.position, x)
# camera.position = move_to
# camera_rotation = copy.deepcopy(camera.rotation)
# camera.rotation = (camera_rotation[0], camera_rotation[1], 0)
# camera.forward = (1, 0, 0) # 设置相机的方向向量为x轴方向 # camera.forward = (1, 0, 0) # 设置相机的方向向量为x轴方向
destroy(self.bodies_button_list) destroy(self.bodies_button_list)
...@@ -193,11 +235,14 @@ class UrsinaUI: ...@@ -193,11 +235,14 @@ class UrsinaUI:
name = f"{body.name}\t距离:{d:.4f}天文单位" name = f"{body.name}\t距离:{d:.4f}天文单位"
button_dict[name] = callback_action button_dict[name] = callback_action
else: else:
if hasattr(self, "bodies_button_list"):
destroy(self.bodies_button_list)
name = f"{body.name}\t距离太远,找不到了" name = f"{body.name}\t距离太远,找不到了"
button_dict[name] = lambda: self.bodies_button_list_click(None) button_dict[name] = lambda: self.bodies_button_list_click(None)
if hasattr(self, "bodies_button_list"): if hasattr(self, "bodies_button_list"):
destroy(self.bodies_button_list) destroy(self.bodies_button_list)
self.bodies_button_list = ButtonList(button_dict, font=UrsinaConfig.CN_FONT, button_height=1.5) self.bodies_button_list = ButtonList(button_dict, font=UrsinaConfig.CN_FONT, button_height=1.5)
# self.bodies_button_list.input = self.bodies_button_list_input # self.bodies_button_list.input = self.bodies_button_list_input
...@@ -235,11 +280,11 @@ class UrsinaUI: ...@@ -235,11 +280,11 @@ class UrsinaUI:
def on_slider_run_speed_changed(self): def on_slider_run_speed_changed(self):
UrsinaConfig.run_speed_factor = self.slider_run_speed_factor.value UrsinaConfig.run_speed_factor = self.slider_run_speed_factor.value
def show_text_time_scale_info(self): # def show_text_time_scale_info(self):
if self.text_time_scale_info is not None: # if self.text_time_scale_info is not None:
self.text_time_scale_info.disable() # self.text_time_scale_info.disable()
text_time_scale = "控制倍率:" + str(application.time_scale).ljust(4, " ") # text_time_scale = "控制倍率:" + str(application.time_scale).ljust(4, " ")
text_time_scale_info = Text(text=text_time_scale, position=(-0.8, 0.5), origin=(-1, 1), background=True) # text_time_scale_info = Text(text=text_time_scale, position=(-0.8, 0.5), origin=(-1, 1), background=True)
# def show_button(self): # def show_button(self):
# b = Button(scale=(0, .25), text='zzz') # b = Button(scale=(0, .25), text='zzz')
......
...@@ -168,6 +168,14 @@ class UrsinaSimulator(Simulator): ...@@ -168,6 +168,14 @@ class UrsinaSimulator(Simulator):
def run(self, dt, **kwargs): def run(self, dt, **kwargs):
window.title = '宇宙模拟器' window.title = '宇宙模拟器'
# 设置 camera 的裁剪面和位置
# camera.clip_plane_near = 0.00000009
# camera.fov = 120
# camera.clip_plane_far = 1000
# camera.position = (0, 10, -20)
# camera.rotation_x = -30
# 设定时间间隔为0.01秒 # 设定时间间隔为0.01秒
interval = 0.01 interval = 0.01
self.evolve_dt = dt * interval self.evolve_dt = dt * interval
...@@ -194,12 +202,6 @@ class UrsinaSimulator(Simulator): ...@@ -194,12 +202,6 @@ class UrsinaSimulator(Simulator):
if cosmic_bg is not None and os.path.exists(cosmic_bg): if cosmic_bg is not None and os.path.exists(cosmic_bg):
self.cosmic_background(cosmic_bg) self.cosmic_background(cosmic_bg)
# 设置 camera 的裁剪面和位置
camera.clip_plane_near = 0.1
# camera.clip_plane_far = 1000
# camera.position = (0, 10, -20)
# camera.rotation_x = -30
ui = UrsinaUI() ui = UrsinaUI()
EditorCamera(ignore_paused=True) EditorCamera(ignore_paused=True)
# 防止打开中文输入法 # 防止打开中文输入法
......
...@@ -47,7 +47,7 @@ class UrsinaPlayer(FirstPersonController): ...@@ -47,7 +47,7 @@ class UrsinaPlayer(FirstPersonController):
# #
# camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20))) # camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20)))
pos = np.array(position) * UrsinaConfig.SCALE_FACTOR pos = np.array(position) * UrsinaConfig.SCALE_FACTOR
# self.position = Vec3(pos[0], pos[1], pos[2]) self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机位置设置为 x=0、y=1、z=0 的位置 # 将摄像机位置设置为 x=0、y=1、z=0 的位置
camera.position = Vec3(pos[0], pos[1], pos[2]) camera.position = Vec3(pos[0], pos[1], pos[2])
# self.position = Vec3(pos[0], pos[1], pos[2]) # self.position = Vec3(pos[0], pos[1], pos[2])
...@@ -95,7 +95,7 @@ class Planet(Entity): ...@@ -95,7 +95,7 @@ class Planet(Entity):
if hasattr(self.body_view.body, "torus_stars"): if hasattr(self.body_view.body, "torus_stars"):
# 创建一个星环小天体群(主要模拟小行星群,非一个天体) # 创建一个星环小天体群(主要模拟小行星群,非一个天体)
model = create_torus(0.86, 1.02, 64, 4) model = create_torus(0.75, 1.10, 64, 1)
rotation = (90, 0, 0) rotation = (90, 0, 0)
else: else:
# 创建一个天体 # 创建一个天体
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册