Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Python_超人
太阳系三体模拟器
提交
dbb7ae8f
太阳系三体模拟器
项目概览
Python_超人
/
太阳系三体模拟器
通知
1075
Star
131
Fork
128
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
太阳系三体模拟器
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
dbb7ae8f
编写于
3月 10, 2023
作者:
三月三net
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
太阳系三体模拟器
上级
56260282
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
14 addition
and
275 deletion
+14
-275
simulators/ursina_simulator.py
simulators/ursina_simulator.py
+6
-83
simulators/views/ursina_view.py
simulators/views/ursina_view.py
+8
-192
未找到文件。
simulators/ursina_simulator.py
浏览文件 @
dbb7ae8f
...
...
@@ -12,94 +12,12 @@ from ursina.prefabs.first_person_controller import FirstPersonController
from
simulators.views.ursina_view
import
UrsinaView
,
UrsinaPlayer
# # -------------------------------------------------------------------------------
# app = Ursina()
# # window.fullscreen = True
# window.color = color.black
#
# planets = []
#
#
# class Planet(Entity):
# def __init__(self, _type, pos, texture, scale=2):
# self.angle = rd.uniform(0.0005, 0.01)
# self.fastMode = 0
# self.rotation = (rd.randint(0, 360) for i in range(3))
# self.rotspeed = rd.uniform(0.25, 1.5)
# self.rotMode = rd.choice(["x", "y", "z"])
# self._type = _type
# # texture = eval(f"{_type}_texture")
# texture = load_texture(texture)
# super().__init__(model="sphere",
# scale=scale,
# texture=texture,
# color=color.white,
# position=pos)
#
# def turn(self, angle):
# # if self._type != "sun":
# # if self.fastMode:
# # angle *= 200
# # self.x = self.x * cos(radians(angle)) - self.y * sin(radians(angle))
# # self.y = self.x * sin(radians(angle)) + self.y * cos(radians(angle))
# exec(f"self.rotation_{self.rotMode}+=self.rotspeed")
# #
# def input(self, key):
# if key == "enter":
# self.fastMode = 1 - self.fastMode
#
#
#
#
#
# def update():
# global planets, player
# for planet in planets:
# planet.turn(planet.angle)
# player._update()
#
# # os.chdir("../")
#
#
# # sun_texture = load_texture(texture_root + "sun.png")
# # mercury_texture = load_texture(texture_root + "mercury.png")
# # venus_texture = load_texture(texture_root + "venus.png")
# # earth_texture = load_texture(texture_root + "earth.png")
# # mars_texture = load_texture(texture_root + "mars.png")
# # jupiter_texture = load_texture(texture_root + "jupiter.png")
# # saturn_texture = load_texture(texture_root + "saturn.png")
# # uranus_texture = load_texture(texture_root + "uranus.png")
# # neptune_texture = load_texture(texture_root + "neptune.png")
#
# texture_root = "../textures/"
# ps = ["sun", "mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune"]
# cp = [200, 15, 35, 42, 20, 160, 145, 90, 80] # 大小缩放
# x, y, z = 0, 0, 0
# for i, p in enumerate(ps):
# # _type, pos, texture, scale=2
# newPlanet = Planet(p, (x, y, z),texture_root+f"{p}.png", cp[i])
# planets.append(newPlanet)
# x += cp[i] * 10
#
# player = Player(planets)
#
# if __name__ == '__main__':
# # os.chdir("../")
# # sun_texture = os.path.join(texture_root, "sun.png")
# # print(os.path.exists(sun_texture))
# app.run()
#
# # ---------------------------------------------------------------------------
from
simulators.simulator
import
Simulator
from
common.system
import
System
import
time
import
datetime
from
ursina
import
EditorCamera
,
PointLight
,
SpotLight
,
AmbientLight
player
=
None
class
UrsinaSimulator
(
Simulator
):
def
__init__
(
self
,
bodies_sys
:
System
):
...
...
@@ -134,6 +52,11 @@ class UrsinaSimulator(Simulator):
super
().
evolve
(
self
.
evolve_dt
)
def
cosmic_background
(
self
,
texture
=
'../textures/cosmic1.jpg'
):
"""
加入宇宙背景
:param texture:
:return:
"""
# Add skybox
from
ursina
import
Sky
Sky
(
texture
=
texture
)
...
...
@@ -207,7 +130,7 @@ if __name__ == '__main__':
Earth
(
init_position
=
[
1.12
*
AU
,
0
,
0
],
init_velocity
=
[
0
,
29.79
,
0
],
size_scale
=
4e3
,
distance_scale
=
1.3
),
# 地球放大 4000 倍,距离放大 1.3 倍
Moon
(
init_position
=
[
363104
+
1.12
*
AU
,
0
,
0
],
init_velocity
=
[
-
9
,
29.79
+
1.023
,
0
],
size_scale
=
4e3
,
distance_scale
=
1.3
),
init_velocity
=
[
-
9
,
29.79
+
1.023
,
0
],
size_scale
=
4e3
,
distance_scale
=
1.3
),
Mars
(
size_scale
=
4e3
,
distance_scale
=
1.3
),
# 火星放大 4000 倍,距离放大 1.3 倍
Jupiter
(
size_scale
=
0.68e3
,
distance_scale
=
0.65
),
# 木星放大 680 倍,距离缩小到真实距离的 0.65
Saturn
(
size_scale
=
0.68e3
,
distance_scale
=
0.52
),
# 土星放大 680 倍,距离缩小到真实距离的 0.52
...
...
simulators/views/ursina_view.py
浏览文件 @
dbb7ae8f
...
...
@@ -21,72 +21,17 @@ import random
from
simulators.views.body_view
import
BodyView
import
numpy
as
np
import
math
from
math
import
sin
,
cos
,
radians
import
os
import
matplotlib.pyplot
as
plt
SCALE_FACTOR
=
1e-6
class
Ring
(
Entity
):
def
__init__
(
self
,
thickness
=
0.2
,
inner_radius
=
0.5
,
outer_radius
=
3
,
texture
=
None
,
position
=
None
,
**
kwargs
):
super
().
__init__
(
**
kwargs
)
inner_circle
=
Entity
(
parent
=
self
,
model
=
'circle'
,
texture
=
texture
,
scale
=
inner_radius
,
position
=
position
)
outer_circle
=
Entity
(
parent
=
self
,
model
=
'circle'
,
texture
=
texture
,
scale
=
outer_radius
,
position
=
position
)
self
.
children
.
append
(
inner_circle
)
self
.
children
.
append
(
outer_circle
)
inner_circle
.
parent
=
self
outer_circle
.
parent
=
self
inner_circle
.
set_light_off
()
outer_circle
.
set_light_off
()
# inner_circle.y += thickness / 2
# outer_circle.y -= thickness / 2
# self.scale_y = thickness
# 创建 TorusMesh
class
TorusMesh
(
Mesh
):
def
__init__
(
self
,
radius
=
1
,
thickness
=
.
25
,
radial_segments
=
16
,
tubular_segments
=
32
):
super
().
__init__
()
self
.
radius
=
radius
self
.
thickness
=
thickness
self
.
radial_segments
=
radial_segments
self
.
tubular_segments
=
tubular_segments
self
.
vertices
=
[]
self
.
triangles
=
[]
for
j
in
range
(
radial_segments
):
for
i
in
range
(
tubular_segments
):
a
=
i
/
tubular_segments
*
math
.
pi
*
2
b
=
j
/
radial_segments
*
math
.
pi
*
2
x
=
(
radius
+
thickness
*
math
.
cos
(
b
))
*
math
.
cos
(
a
)
y
=
(
radius
+
thickness
*
math
.
cos
(
b
))
*
math
.
sin
(
a
)
z
=
thickness
*
math
.
sin
(
b
)
u
=
i
/
tubular_segments
v
=
j
/
radial_segments
self
.
vertices
.
append
((
x
,
y
,
z
))
self
.
uvs
.
append
((
u
,
v
))
for
j
in
range
(
radial_segments
):
for
i
in
range
(
tubular_segments
):
a
=
i
b
=
j
c
=
(
i
+
1
)
%
tubular_segments
d
=
(
j
+
1
)
%
radial_segments
self
.
triangles
.
append
((
a
+
b
*
tubular_segments
,
b
+
d
*
tubular_segments
,
c
+
b
*
tubular_segments
))
self
.
triangles
.
append
((
c
+
b
*
tubular_segments
,
b
+
d
*
tubular_segments
,
c
+
d
*
tubular_segments
))
class
UrsinaPlayer
(
FirstPersonController
):
"""
"""
class
UrsinaPlayer
(
FirstPersonController
):
def
__init__
(
self
,
position
,
targets
=
None
):
# global planets
super
().
__init__
()
# pos = planets[0].position
camera
.
fov
=
100
camera
.
rotation_y
=
90
self
.
planets
=
None
...
...
@@ -116,51 +61,6 @@ class UrsinaPlayer(FirstPersonController):
self
.
on_enable
()
self
.
rotation_speed
=
80
# def space_callback(self):
# best_camera_position = self.best_camera_position()
# if best_camera_position is None:
# return
# best_pos = np.array(best_camera_position[0]) * SCALE_FACTOR
# camera.position, camera.rotation = best_pos, best_camera_position[1]
#
# def best_camera_position(self):
# if self.planets is None:
# return None
#
# min_x, max_x, min_y, max_y, min_z, max_z = None, None, None, None, None, None
# for planet in self.planets:
# if min_x is None or planet.x < min_x:
# min_x = planet.x
# if max_x is None or planet.x > max_x:
# max_x = planet.x
# if min_y is None or planet.y < min_y:
# min_y = planet.y
# if max_y is None or planet.y > max_y:
# max_y = planet.y
# if min_z is None or planet.z < min_z:
# min_z = planet.z
# if max_z is None or planet.z > max_z:
# max_z = planet.z
# x = (min_x + max_x) / 2
# y = (min_y + max_y) / 2
# z = (min_z + max_z) / 2
# distance = max(max_x - min_x, max_y - min_y, max_z - min_z) * 1.5
# return (x, y + distance, z - distance), (0, -90, 0)
# def camera_adj(self, targets):
# # 创建一些物体
# # targets = []
# # for i in range(10):
# # targets.append(Entity(model='cube', color=color.random_color(), position=(i * 2 - 10, i % 2 * 2 - 1, 0)))
#
# # 计算所有物体的平均位置
# avg_pos = sum(np.array([target.position for target in targets]))/ len(targets)
#
# # 创建一个OrthographicCamera,使其位于所有目标的中心位置,并面向下方
# # camera = OrthographicCamera()
# camera.position = avg_pos + (0, 0, 20)
# camera.rotation_x = -90
def
input
(
self
,
key
):
if
key
==
"escape"
:
if
mouse
.
locked
:
...
...
@@ -168,55 +68,11 @@ class UrsinaPlayer(FirstPersonController):
else
:
sys
.
exit
()
return
super
().
input
(
key
)
# elif key == "space":
# self.space_callback()
# Input.bind('space', space_callback)
# def _update(self):
# # # {'left mouse': 0, 'left': 0, 'left shift': 0, 'space': 1, 'w': 0, 's': 0, 'd': 0, 'a': 0, 'shift': 0})
# # if held_keys["left mouse"]:
# # self.on_enable()
# # if held_keys["left shift"]:
# # self.y -= self.vspeed
# # if held_keys["space"]:
# # self.y += self.vspeed
# # WASD keys
#
# if held_keys['f']:
# camera.fov += 1
# if held_keys['r']:
# camera.fov -= 1
# # camera.position
# # self.rotation_y += held_keys['d'] * self.rotation_speed * time.dt
# # self.rotation_y -= held_keys['a'] * self.rotation_speed * time.dt
# # self.rotation_x += held_keys['w'] * self.rotation_speed * time.dt
# # self.rotation_x -= held_keys['s'] * self.rotation_speed * time.dt
#
# forward = self.forward * (held_keys['w'] - held_keys['s'])
# right = self.right * (held_keys['d'] - held_keys['a'])
#
# self.position += (forward + right) * self.speed * time.dt
# # if held_keys['w']:
# # camera.position += camera.forward * time.dt
# # if held_keys['s']:
# # camera.position -= camera.forward * time.dt
# # if held_keys['a']:
# # camera.position -= camera.right * time.dt
# # if held_keys['d']:
# # camera.position += camera.right * time.dt
# #
# # # Mouse control
# # camera.rotation_y += held_keys['right mouse'] * mouse.velocity[0] * 20
# # camera.rotation_x -= held_keys['right mouse'] * mouse.velocity[1] * 20
# # camera.rotation_x = clamp(camera.rotation_x, -90, 90)
class
Planet
(
Entity
):
def
__init__
(
self
,
body_view
:
BodyView
):
self
.
body_view
=
body_view
# self.angle = 0 # random.uniform(0.0005, 0.01)
# self.fastMode = 0
# self.rotation = (random.randint(0, 360) for i in range(3))
# 旋转速度和大小成反比(未使用真实数据)
self
.
rotspeed
=
30000
/
self
.
body_view
.
raduis
# random.uniform(1.0, 2.0)
self
.
rotMode
=
'x'
# random.choice(["x", "y", "z"])
...
...
@@ -225,18 +81,12 @@ class Planet(Entity):
pos
=
body_view
.
position
*
body_view
.
body
.
distance_scale
*
SCALE_FACTOR
scale
=
body_view
.
body
.
diameter
*
body_view
.
body
.
size_scale
*
SCALE_FACTOR
# texture = eval(f"{_type}_texture")
# e = os.path.exists(texture)
# texture = self.__set_texture(body_view.texture)
if
hasattr
(
body_view
,
"texture"
):
texture
=
load_texture
(
body_view
.
texture
)
else
:
texture
=
None
# 将贴图旋转90度C:\ProgramData\Anaconda3\envs\tf_gpu\Lib\site-packages\ursina\models_compressed\diamond.ursinamesh
super
().
__init__
(
# model=TorusMesh(radius=1e20, thickness=1.25e20, radial_segments=16, tubular_segments=32),
# model="sky_dome",
model
=
"sphere"
,
scale
=
scale
,
texture
=
texture
,
...
...
@@ -244,30 +94,7 @@ class Planet(Entity):
position
=
pos
,
rotation
=
(
0
,
0
,
0
))
# def __set_texture(self, image_file):
# """
# 设置纹理图片到天体
# :param image_file:
# :return:
# """
# outfile = image_file.replace('.png', '_rotate.png').replace('.jpg', '_rotate.jpg')
# from PIL import Image
# # 打开原始图片
# image = Image.open(image_file)
# # 顺时针旋转90度
# rotated_image = image.rotate(90, expand=True)
#
# # 保存旋转后的图片
# rotated_image.save(outfile)
#
# return outfile
def
turn
(
self
):
# if self.name != "sun":
# if self.fastMode:
# angle *= 200
# self.x = self.x * cos(radians(angle)) - self.y * sin(radians(angle))
# self.y = self.x * sin(radians(angle)) + self.y * cos(radians(angle))
pos
=
self
.
body_view
.
position
*
SCALE_FACTOR
self
.
x
=
-
pos
[
1
]
...
...
@@ -289,35 +116,26 @@ class UrsinaView(BodyView):
def
__init__
(
self
,
body
:
Body
):
BodyView
.
__init__
(
self
,
body
)
self
.
velocity
=
body
.
velocity
# 将列表元素往后移动一位,最后一位变为第一位
# a1 = a[1:] + [a[0]]
# self.velocity = np.concatenate((body.velocity[1:], [body.velocity[0]]))
# 将列表元素往前移动一位,第一位变为最后一位
# a2 = [a[-1]] + a[:-1]
# self.velocity = np.concatenate((np.array([body.velocity[-1]]), body.velocity[0:2]))
self
.
planet
=
Planet
(
self
)
if
body
.
has_rings
:
self
.
create_rings
()
# self.planet.clear_light()
if
self
.
body
.
is_fixed_star
:
# 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
self
.
planet
.
set_light_off
()
def
create_rings
(
self
):
from
ursina
import
Cylinder
"""
创建星环(使用土星贴图)
:return:
"""
scale
=
3
*
self
.
body
.
diameter
*
self
.
body
.
size_scale
*
SCALE_FACTOR
pos
=
self
.
planet
.
position
# self.ring = Entity(model='sphere', texture='textures/saturnRings.jpg', scale=scale, position=pos,double_sided=True)
self
.
ring
=
Entity
(
model
=
"circle"
,
texture
=
'../textures/saturnRings.jpg'
,
scale
=
scale
,
position
=
pos
,
rotation
=
(
70
,
0
,
0
),
double_sided
=
True
)
# self.ring2 = Entity(model="circle", texture='../textures/saturnRings.jpg', scale=scale, position=pos,
# rotation=(180 + 70, 0, 0))
# 假设星环自身会发光
self
.
ring
.
set_light_off
()
# self.ring2.set_light_off()
def
update
(
self
):
self
.
planet
.
turn
()
...
...
@@ -325,8 +143,6 @@ class UrsinaView(BodyView):
self
.
light
.
position
=
Vec3
(
self
.
planet
.
x
,
self
.
planet
.
y
,
self
.
planet
.
z
)
if
hasattr
(
self
,
"ring"
):
self
.
ring
.
position
=
Vec3
(
self
.
planet
.
x
,
self
.
planet
.
y
,
self
.
planet
.
z
)
# if hasattr(self, "ring2"):
# self.ring2.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
def
appear
(
self
):
pass
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录