提交 645f0e10 编写于 作者: 三月三net's avatar 三月三net

太阳系三体模拟器

上级 e2a28818
...@@ -55,22 +55,37 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK, ...@@ -55,22 +55,37 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
def ursina_run(bodies, def ursina_run(bodies,
dt=SECONDS_PER_HALF_DAY, dt=SECONDS_PER_HALF_DAY,
position=(4000000, 800000000, 4000000), position=(4000000, 800000000, 4000000),
# view_azimuth=0,
light=True, light=True,
cosmic_bg=None, cosmic_bg=None,
show_grid=True): show_grid=True):
""" """
:param bodies: :param bodies: 天体
:param dt: :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
:param position: 摄像头位置
:param view_azimuth: 摄像头观测方位角,可选,float类型(以度为单位,0-360)
:param light: 使用灯光效果
:param cosmic_bg: 宇宙背景图片
:param show_grid: 是否显示空间网格
:return: :return:
""" """
from simulators.ursina_simulator import UrsinaSimulator, UrsinaPlayer from simulators.ursina_simulator import UrsinaSimulator, UrsinaPlayer
from ursina import application, Sequence, camera, held_keys, time, clamp,Entity,Text from ursina import application, Sequence, camera, held_keys, time, clamp, Entity, Text, color
from ursina.prefabs.first_person_controller import FirstPersonController
body_sys = System(bodies) body_sys = System(bodies)
simulator = UrsinaSimulator(body_sys) simulator = UrsinaSimulator(body_sys)
view_azimuth = 0 # 暂时未用
player = UrsinaPlayer(position, simulator.ursina_views) player = UrsinaPlayer(position, view_azimuth, simulator.ursina_views)
# # player = FirstPersonController(model='cube', y=-1e20, color=color.orange, origin_y=-5000, speed=8)
# # player.on_disable()
# # player.position = position
#
# player = FirstPersonController()
# cube = Entity(model='cube', color=color.red, scale=2)
# player.parent = cube # 设置 FirstPersonController 的父实体为 cube
# cube.position = position # 修改父实体的位置,从而间接地修改 FirstPersonController 的位置
# # 创建一个实体(在屏幕中央)和一个摄像机 # # 创建一个实体(在屏幕中央)和一个摄像机
# TODO: 未使用 # TODO: 未使用
......
...@@ -39,4 +39,5 @@ if __name__ == '__main__': ...@@ -39,4 +39,5 @@ if __name__ == '__main__':
# 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, 5 * AU, -10 * AU)) # position=左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 2 * AU, -11 * AU))
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Asteroids from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Asteroids
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_MONTH, SECONDS_PER_YEAR from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_MONTH, 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__':
...@@ -42,4 +42,5 @@ if __name__ == '__main__': ...@@ -42,4 +42,5 @@ if __name__ == '__main__':
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2]) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2])
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 0, 0)) # position = 左-右+、上+下-、前+后-
\ No newline at end of file ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 2 * AU, -11 * AU))
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, AU
from scenes.func import mayavi_run, ursina_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
...@@ -23,4 +23,5 @@ if __name__ == '__main__': ...@@ -23,4 +23,5 @@ if __name__ == '__main__':
# 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_WEEK, position=(0, 0, 0)) # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_WEEK, position=(0, AU, -3 * AU))
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth, Jupiter from bodies import Sun, Earth, Jupiter
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, AU
from scenes.func import mayavi_run, ursina_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
...@@ -24,4 +24,5 @@ if __name__ == '__main__': ...@@ -24,4 +24,5 @@ if __name__ == '__main__':
# 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_WEEK, position=(0, 0, 0)) # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_WEEK, position=(0, AU, -3 * AU))
...@@ -20,17 +20,28 @@ if __name__ == '__main__': ...@@ -20,17 +20,28 @@ if __name__ == '__main__':
sun = Sun(init_position=[AU, 0, 0], size_scale=2e1) # 太阳放大 20 倍 sun = Sun(init_position=[AU, 0, 0], size_scale=2e1) # 太阳放大 20 倍
# 忽略质量的引力 # 忽略质量的引力
sun.ignore_mass = True sun.ignore_mass = True
# 观看月相变化的过程:分别是 新月、蛾眉月、上弦月、盈凸、满月、亏凸、下弦月、残月
# TODO: 月球在摄像机的前方(从 “新月” 开始)
moon_pos, moon_vel = [384400, 0, 0], [0, EARTH_INIT_VELOCITY + 1.023, 0]
# TODO: 月球在摄像机的右方(从 “下弦月” 开始),将会出现
# moon_pos, moon_vel = [0, -384400, 0], [1.023, EARTH_INIT_VELOCITY, 0]
# TODO: 月月球在摄像机的左方(从 “上弦月” 开始)
# moon_pos, moon_vel = [0, 384400, 0], [-1.023, EARTH_INIT_VELOCITY, 0]
bodies = [ bodies = [
sun, sun,
Earth(init_position=[0, 0, 0], Earth(init_position=[0, 0, 0],
init_velocity=[0, EARTH_INIT_VELOCITY, 0], init_velocity=[0, EARTH_INIT_VELOCITY, 0],
size_scale=1e1), # 地球放大 10 倍,距离保持不变 size_scale=1e1), # 地球放大 10 倍,距离保持不变
Moon(init_position=[0, 384400, 0], # 距地距离约: 363104 至 405696 km Moon(init_position=moon_pos, # 距地距离约: 363104 至 405696 km
init_velocity=[-1.023, EARTH_INIT_VELOCITY, 0], init_velocity=moon_vel,
size_scale=2e1) # 月球放大 20 倍,距离保持不变 size_scale=2e1) # 月球放大 20 倍,距离保持不变
] ]
# 使用 mayavi 查看的运行效果 # 使用 mayavi 查看的运行效果
# mayavi_run(bodies, SECONDS_PER_HALF_DAY / 2, view_azimuth=-45) # mayavi_run(bodies, SECONDS_PER_HALF_DAY / 2, view_azimuth=-45)
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
# position = 左-右+、上+下-、前+后-
# position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0)) ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, AU
from scenes.func import mayavi_run, ursina_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
...@@ -32,4 +32,5 @@ if __name__ == '__main__': ...@@ -32,4 +32,5 @@ if __name__ == '__main__':
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0)) # position = 左-右+、上+下-、前+后-
\ No newline at end of file ursina_run(bodies, SECONDS_PER_DAY, position=(3 * AU, AU, -4 * AU))
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_YEAR from common.consts import SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_YEAR, AU
from scenes.func import mayavi_run, mpl_run, ursina_run from scenes.func import mayavi_run, mpl_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
...@@ -57,4 +57,5 @@ if __name__ == '__main__': ...@@ -57,4 +57,5 @@ if __name__ == '__main__':
# mpl_run(bodies, SECONDS_PER_WEEK) # mpl_run(bodies, SECONDS_PER_WEEK)
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 0, 0)) # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_YEAR, position=(3 * AU, 3 * AU, -20 * AU))
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_YEAR, AU
from scenes.func import mayavi_run from scenes.func import mayavi_run, mpl_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
""" """
...@@ -28,4 +28,8 @@ if __name__ == '__main__': ...@@ -28,4 +28,8 @@ if __name__ == '__main__':
] ]
# 使用 mayavi 查看的运行效果 # 使用 mayavi 查看的运行效果
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
# 使用 ursina 查看的运行效果
# position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_YEAR, position=(0, 2 * AU, -5 * AU))
\ No newline at end of file
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
class UrsinaConfig: class UrsinaConfig:
# 常量定义 # 常量定义
# 天体缩放的因子(不能太大,否则无法容得下大数量级的天体)调整 5e-7 最佳 # 天体缩放的因子(不能太大,否则无法容得下大数量级的天体)调整 5e-7 最佳
SCALE_FACTOR = 5e-7 __SCALE_FACTOR = 5e-7
auto_scale_factor = 1.0 # __SCALE_FACTOR 不能满足,需要自动进行调整
# 旋转因子为1,则为正常的转速 # 旋转因子为1,则为正常的转速
ROTATION_SPEED_FACTOR = 1.0 ROTATION_SPEED_FACTOR = 1.0
# ROTATION_SPEED_FACTOR = 0.01 # ROTATION_SPEED_FACTOR = 0.01
...@@ -34,7 +35,7 @@ class UrsinaConfig: ...@@ -34,7 +35,7 @@ class UrsinaConfig:
show_trail = False show_trail = False
# 拖尾球体的数量 # 拖尾球体的数量
trail_length = 200 trail_length = 100
# 默认秒数(0表示默认) # 默认秒数(0表示默认)
seconds_per = 0 seconds_per = 0
# # 控制摄像机动作速度(天体越大,速度越快,天体越小,速度越慢) # # 控制摄像机动作速度(天体越大,速度越快,天体越小,速度越慢)
...@@ -42,6 +43,25 @@ class UrsinaConfig: ...@@ -42,6 +43,25 @@ class UrsinaConfig:
__body_size_factor = 1.0 __body_size_factor = 1.0
@classmethod
def init(cls):
# 初始化
cls.run_speed_factor = 1.0
cls.body_spin_factor = 1.0
cls.body_size_factor = 1.0
# 天体缩放的因子(不能太大,否则无法容得下大数量级的天体)调整 5e-7 最佳
cls.SCALE_FACTOR = 5e-7
@property
@classmethod
def SCALE_FACTOR(cls):
return cls.__SCALE_FACTOR * cls.auto_scale_factor
@SCALE_FACTOR.setter
@classmethod
def SCALE_FACTOR(cls, value):
cls.__SCALE_FACTOR = value
@property @property
@classmethod @classmethod
def run_speed_factor(cls): def run_speed_factor(cls):
...@@ -82,10 +102,7 @@ class UrsinaConfig: ...@@ -82,10 +102,7 @@ class UrsinaConfig:
f() f()
# 初始化 UrsinaConfig.init()
UrsinaConfig.run_speed_factor = 1.0
UrsinaConfig.body_spin_factor = 1.0
UrsinaConfig.body_size_factor = 1.0
if __name__ == '__main__': if __name__ == '__main__':
UrsinaConfig.run_speed_factor = 2.0 UrsinaConfig.run_speed_factor = 2.0
......
...@@ -29,9 +29,9 @@ class UrsinaUI: ...@@ -29,9 +29,9 @@ class UrsinaUI:
# application.time_scale = 0.5 # application.time_scale = 0.5
self.slider_body_spin_factor = UiSlider(text='自转速度', min=0.01, max=30, default=1) self.slider_body_spin_factor = UiSlider(text='自转速度', min=0.01, max=30, default=1)
self.slider_body_size_factor = UiSlider(text='天体缩放', min=0.1, max=100, default=1) self.slider_body_size_factor = UiSlider(text='天体缩放', min=0.1, max=100, step=0.1, default=1)
self.slider_run_speed_factor = UiSlider(text="运行速度", min=0.01, max=80, default=1) self.slider_run_speed_factor = UiSlider(text="运行速度", min=0.01, max=80, default=1)
self.slider_control_speed_factor = UiSlider(text="控制速度", min=0.01, max=50, default=application.time_scale) self.slider_control_speed_factor = UiSlider(text="控制速度", min=0.01, max=20, default=application.time_scale)
self.slider_trail_length = UiSlider(text="拖尾长度", min=30, max=500, step=10, default=UrsinaConfig.trail_length) self.slider_trail_length = UiSlider(text="拖尾长度", min=30, max=500, step=10, default=UrsinaConfig.trail_length)
self.slider_body_size_factor.on_value_changed = self.on_slider_body_size_changed self.slider_body_size_factor.on_value_changed = self.on_slider_body_size_changed
...@@ -98,7 +98,7 @@ class UrsinaUI: ...@@ -98,7 +98,7 @@ class UrsinaUI:
) )
self.sec_per_time_switch.x = -0.4 self.sec_per_time_switch.x = -0.4
self.on_off_switch.x = 0.2 self.on_off_switch.x = 0.2
self.on_off_trail.x = -0.4 self.on_off_trail.x = 0.2 # -0.4
wp.y = 0.5 # wp.panel.scale_y / 2 * wp.scale_y # center the window panel wp.y = 0.5 # wp.panel.scale_y / 2 * wp.scale_y # center the window panel
wp.x = 0.6 # wp.scale_x + 0.1 wp.x = 0.6 # wp.scale_x + 0.1
# wp.x = 0#wp.panel.scale_x / 2 * wp.scale_x # wp.x = 0#wp.panel.scale_x / 2 * wp.scale_x
......
...@@ -57,10 +57,10 @@ class UrsinaSimulator(Simulator): ...@@ -57,10 +57,10 @@ class UrsinaSimulator(Simulator):
self.ursina_views.append(view) self.ursina_views.append(view)
# planets.append(newPlanet) # planets.append(newPlanet)
# x += cp[i] * 10 # x += cp[i] * 10
self.adj_application_time_scale() self.adj_run_params()
UrsinaEvent.on_searching_bodies_subscription(type(self).__name__, self.on_searching_bodies) UrsinaEvent.on_searching_bodies_subscription(type(self).__name__, self.on_searching_bodies)
def adj_application_time_scale(self): def adj_run_params(self):
max_distance = 0 max_distance = 0
for b1 in self.body_views: for b1 in self.body_views:
for b2 in self.body_views: for b2 in self.body_views:
...@@ -71,10 +71,12 @@ class UrsinaSimulator(Simulator): ...@@ -71,10 +71,12 @@ class UrsinaSimulator(Simulator):
max_distance = d max_distance = d
# UrsinaConfig.control_camera_speed = round(max_distance * 10, 2) # UrsinaConfig.control_camera_speed = round(max_distance * 10, 2)
time_scale = round(pow(max_distance, 1 / 3), 2) time_scale = round(pow(max_distance, 1 / 4), 2)
if time_scale < 0.01: if time_scale < 0.01:
time_scale = 0.01 time_scale = 0.01
application.time_scale = time_scale application.time_scale = time_scale
# UrsinaConfig.auto_scale_factor = 1.0e-9
def on_searching_bodies(self, **kwargs): def on_searching_bodies(self, **kwargs):
views = [] views = []
......
...@@ -28,9 +28,9 @@ class UrsinaPlayer(FirstPersonController): ...@@ -28,9 +28,9 @@ class UrsinaPlayer(FirstPersonController):
""" """
""" """
body_rotation_speed_control = 1.0 # body_rotation_speed_control = 1.0
def __init__(self, position, targets=None): def __init__(self, position, view_azimuth=0, targets=None):
super().__init__() super().__init__()
# camera.fov = 2000 # 100 # camera.fov = 2000 # 100
# camera.rotation_y = 90 # camera.rotation_y = 90
...@@ -50,18 +50,21 @@ class UrsinaPlayer(FirstPersonController): ...@@ -50,18 +50,21 @@ class UrsinaPlayer(FirstPersonController):
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.x = 90
# self.position = Vec3(pos[0], pos[1], pos[2]) # self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度 # 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度
# camera.rotation = Vec3(45, 90, 0) # self.rotation = Vec3(45, 90, 0)
camera.rotation = Vec3(0, 0, 0) # camera.look_at(Vec3(0, 0, 0))
# camera.world_rotation = Vec3(0, 190, 190)
# camera.enabled = True
# self.gravity = 0 # self.gravity = 0
# self.vspeed = 400 # self.vspeed = 400
# self.speed = 1000 # self.speed = 1000
# self.mouse_sensitivity = Vec2(160, 160) # self.mouse_sensitivity = Vec2(160, 160)
# self.on_enable() # self.on_enable()
# self.rotation_speed = 80 # self.rotation_speed = 80
self.on_disable()
self.on_disable() # 防止鼠标被窗口锁定
# def input(self, key): # def input(self, key):
# if key == "escape": # if key == "escape":
...@@ -95,7 +98,7 @@ class Planet(Entity): ...@@ -95,7 +98,7 @@ class Planet(Entity):
if hasattr(self.body_view.body, "torus_stars"): if hasattr(self.body_view.body, "torus_stars"):
# 创建一个星环小天体群(主要模拟小行星群,非一个天体) # 创建一个星环小天体群(主要模拟小行星群,非一个天体)
model = create_torus(0.75, 1.10, 64, 1) model = create_torus(0.83, 1.05, 64, 1)
rotation = (90, 0, 0) rotation = (90, 0, 0)
else: else:
# 创建一个天体 # 创建一个天体
...@@ -112,11 +115,12 @@ class Planet(Entity): ...@@ -112,11 +115,12 @@ class Planet(Entity):
color=color.white, color=color.white,
position=pos, position=pos,
rotation=rotation # ,double_sided=True rotation=rotation # ,double_sided=True
) )
if hasattr(self.body_view.body, "torus_stars"): if hasattr(self.body_view.body, "torus_stars"):
# 星环小天体群(主要模拟小行星群,非一个天体) # 星环小天体群(主要模拟小行星群,非一个天体)
self.set_light_off() self.set_light_off()
self.double_sided = True
else: else:
# 一个天体 # 一个天体
# 拖尾球体的初始化 # 拖尾球体的初始化
...@@ -195,8 +199,12 @@ class Planet(Entity): ...@@ -195,8 +199,12 @@ class Planet(Entity):
:param pos: :param pos:
:return: :return:
""" """
trail = Entity(model="sphere", color=self.trail_color, scale=self.trail_scale, position=pos) # sphere = create_sphere(1,6) diamond sphere
trail = Entity(model='sphere', color=self.trail_color, scale=self.trail_scale, position=pos)
trail.set_light_off() trail.set_light_off()
# trail.set_color_off()
# trail.set_color_scale_off()
# trail.enabled = False
return trail return trail
def turn(self): def turn(self):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册